-
Notifications
You must be signed in to change notification settings - Fork 695
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Type checking and unreachable blocks #707
Comments
@rossberg-chromium is probably the best to explain this, but I'll try :) They simple way I think of it is that there are two extra types, So in the first example, it validates because the type of the In the second example, the two branches have a float type, because the last expression of the (implicit) block is a |
On Fri, Jun 10, 2016 at 9:01 PM, Ben Smith [email protected] wrote:
Ben's right. This is exactly how type checking works in the V8 validator:
|
One nit: it's not unification but computing the LUB (at least until we decide for #694). (And super-nit: I'd personally avoid the names As for the question why the second example does not type-check: it's a very simple and conventional type system. Like most type systems, it only looks at data flow, not control flow. So whether there is an unconditional branch somewhere in a block does not affect the block's type. |
Ha, I knew I'd mess that up. :) |
Sounds good to me, thanks for the clarification! |
On Mon, Jun 13, 2016 at 12:27 PM, rossberg-chromium <
|
I have run into some issue regarding this from the testsuite. Same goes for function |
@Cellule Consider |
@Cellule oh, and the second example, if the types conflict then the result is the same as for |
Branches, like all unconditional control flow transfer, are simply polymorphic, i.e., they can have any type, in order to e.g. allow exiting from branches whose siblings do yield some value. Same treatment as in all other typed (expression) languages. I suppose we should have an FAQ for that, as this question keeps coming up. ;) The operands to branches are implicitly dropped when the block targeted has type void. Thus, their types can differ in such cases -- they are all implicitly converted to void. There has been a long history of back & forth on this (#179, #180, #227, #271), but this arguably surprising freedom is removed with #694. |
Thanks, On the other hand, I am a little fuzzy as to how to implement
Since Let's say it is valid or we put an I fail to see why any such things should be considered valid. It feels like the equivalent of such a thing in c++ for example would be {
if (ctz(goto label1) + 1.4f) {
int a = return 0;
}
label1:
} Which looks really silly. |
@Cellule The 'unreachable' type does not propagate through typed operators. So the result type of This choice was probably to support top-down typing too. Perhaps the disucussion in #654 would also be of interest in which is it proposed that the |
No, type checking does not consider control flow. Both examples are
Yes, that's valid (though useless). I think there already is a test for
There are infinitely many ways of writing dead or otherwise useless code The reason control flow transfer should be polymorphic (instead of, say,
or more interestingly, (the encoding of) switch cases:
If control flow transfer was typed void then you'd be forced to insert dead IOW, the point of these typing rules is not to prevent dead code, but to FWIW, typing control flow transfer constructs polymorphically is completely |
Since some of these type semantics issues have been confusing multiple people and the only "documentation" of the WASM type system is the spec implementation, would people be interested in a prose explanation of the type system? |
The prose can also go into a discussion of the motivation in attempt to clarify things. |
@rossberg-chromium was the design repo ever updated to clarify this? I don't see a commit but may have missed it. |
I left open #747 on these things |
@jfbastien You're right, I was a bit hasty in closing this. |
@jfbastien, see the description of WebAssembly/spec#345 for the resolution we reached regarding unreachable code. The design repo is generally (and IIUC, somewhat intentionally) very vague about validation, so not sure where specific clarifications would fit in there exactly. I believe we agreed that the written spec will be the appropriate place to lay out the details. But everybody has been busy with catching up to 0xc, so not much progress on that front... |
This is old and has been superseded by more recent discussion. |
Feels like there are some corner cases with type checking, and AFAIK there hasn't really been much discussion on it. Right now I am looking at cases like the following pseudo-code for a function which has been defined with an int result type:
Should this validate? All paths return an int but the if/else doesn't yield a value.
If that should validate, what about this?
Same type of scenario, but now it's arguable whether we consider that the if/else yields float or doesn't yield. If it yields, then I suppose we fail validation, because that (unreachable) path yields a float.
How are you guys handling this type of scenario today?
The text was updated successfully, but these errors were encountered: