Open nadako opened 4 years ago
I was thinking that we need the notion of a Haxe compilation being "self-contained". Perhaps we can even assume this when there is a -main
, and then have a define to switch the behavior off (or on in absence of -main
).
I feel like there's a better word for that though which eludes me right now.
Clearly that's a "final" compilation. ;)
I actually kinda like that, but there's probably some established term for it.
standalone?
But what about the complication server? First compilation - no overrides. Second compilation - an override is added, but the parent entity is reused from cache.
Final inference itself can work around that. But yes, if there's an optimization depending on it we would have to reverse-invalidate for sure...
This might then require field-level invalidation first in order to not be a big problem. And that in turn probably requires redesigning the compilation server. :(
While I read this thread, I was searching for a duplicate of a proposal I wanted to make for the Haxe compiler. I will put it there because I feel it is relevant on what you are discussing about:
What about making this final not infered, but suggested by the compiler?
For example, given this code:
class Main {
public static function main() {
var message = "Hello world";
trace(message);
}
}
The compiler could see that the variable message
is never reassigned in the scope of the public static function main()
method, and warns that it should better be a final message = "Hello world";
instead.
Same would go for classes that are never extended.
I hope it would help not forcing the compiler to make the choice of assuming such class should be final and risk to run into issues mentioned above.
If such a feature is added, it has to be opt-in and maybe a diagnostic in the IDE only. Otherwise there would be thousands of such suggestions in any project or library that I have seen.
Perhaps related, I think structure fields should also infer final or at least delay "locking in" the accessors. In the following case, if we can delay locking in the accessor to be (default, default) then it should be able to unify.
class Main {
static function main() {
final o = {x: 1}
foo(o); // error: Cannot unify final and non-final fields
}
static function foo(obj:{final x:Int;}) {
trace(obj.x);
}
}
@kevinresol I think this is unrelated to the original issue, but it looks sensible to do what you propose, could you create a separate issue?
We currently disable some optimizations such as tail recusion elimination and purity inference for non-final instance methods based on the fact that we cannot make assumptions about them, since they can be overriden later by users of haxe-generated code.
While this is a safe bet, I believe it is actually rare when Haxe code is used like that, and it would be more beneficial to actually infer and set
final
for both classes and methods. It would enable both Haxe and target-native optimizations and would still be safe to use from outside (if target language supports checking forfinal
). It would also benefit code that does not use inheritance much.Of course, it should be opt-in, so how about
-D infer-final
?