Closed sebthom closed 7 years ago
Seems like some AST typing issue wrt inlining or analyzer
That compiles fine for me if I call createExample("foo")
. How are you invoking it?
I updated the example above. Basically it happens when the return value is directly assigned to a static variable. Works fine with non-static.
class Main {
static var example = if (Math.random() > 0.5) 1 else 2;
public static function main() {
trace(example);
}
}
Static inits are annoying. From the expression's point of view this is a block-level if
, so having it typed as Void
is correct. It is only due to the fact that the block is assigned to the field that it should be different here.
This leads to back our static_init
discussion from... somewhere else. Right now I'm not even sure how to temp-fix this for hxcpp.
Would it be acceptable to use self-calling-functions as field initialization on targets that have problems with this (C++, HL)?
shouldn't the expression be typed as returning a value in the first place?
Not really because the assignment to the field is implicit.
@hughsando: Do you have an opinion on this (or remember where we talked about it before)?
I think we talked about generating the "static init block" per class (including meta and rtti?), rather than limiting ourselves to a series of field.cf_exprs. Or even just a helper "create_static_init_block." This would avoid code duplication between targets, and allow arbitrary code ordering/tmp variables.
I tried working on this but ran into a problem with DCE or rather post-process order in general. We want to apply all post-process operations to the static inits, but we don't want to do that for statics which would be DCE'd otherwise.
Basically collecting them before DCE subverts DCE, collecting them after misses the required post-processing.
Yep, sounds like fun. I guess the other way to do it would be make the expression an arbitrary void expression (ie, could be a block) which includes (possibly conditional and multiple) "name = value" statements.
Then instead of outputting "name = genExpr(cf_expr)" just generate "genExpr(cf_expr)".
This would be less code per target (unless they optimize somehow?), but would involve changing every target.
I'm don't agree that the AST expression should be Void. Even if the assignment is implicit, we are actually typing it with WithType if there's an explicit type (I think) and with Value either, so it should be typed as an expression which eval to a value.
Sure we type it with WithType, just as we do something like this:
var x = if (e1) e2 else e3
This is transformed:
var x;
if (e1) x = e2
else x = e3
At this stage the if-expression is typed as Void, so we effectively discard the type that originally came from the WithType. Depending on the complexity of e1, e2 and e3 we might then reconstruct the original expression.
Now imagine the same thing without the assignment. We obviously end up with this:
if (e1) e2
else e3
And again the if-expression is typed as Void. This case is indistinguishable from the former, the only difference is the context because the latter is actually assigned to a static field.
I'm using self-calling functions now for Cpp so the regression part of this can be considered resolved. I might look into a better approach in the future, but this should be good enough for 3.3.
Works with HL1.1 and Haxe 3.4.
The following code doesn't compile when targeting HL but throws the error
characters 25-51 : Don't know how to cast void to #Example
.The example contains only the minimum number of statements from my project to reproduce the error.
It compiles if I remove
inline
keyword from thecreateExample
function, orstatic
keyword from theTest.example
field, orcreateExample
functionWhen targeting C# and Java the Compiler Warning
Type Example is being cast to the unrelated type Void
is reported but compilation proceeds and the code works. All dynamic targets work fine too.Targeting CPP fails with