Handle flow via imports and exports in Unsubtyping#8439
Conversation
We previously upated Unsubtyping so that any subtype of the result of a JS-called function would keep its descriptor if that descriptor could configure a JS prototype. But configured prototypes can also become visible indirectly because they flow out of the module via imported or exported functions, globals, or tables. Handle these cases of values flowing in from or out to JS.
| (func $test (export "test") (param (ref $super)) (result anyref) | ||
| (local $sub (ref null $sub)) | ||
| ;; $super flowing in from JS means it is cast from any. Since $sub flows out | ||
| ;; via any, it could be flowing back in and must remain a subtype of $super. |
There was a problem hiding this comment.
Must we assume any export is called by JS? Can we consider exports not marked with js.called to be called from wasm?
There was a problem hiding this comment.
Yes, I think that would be nice eventually. Right now we do treat every export as being called from JS by virtue of the --fuzz-exec interpreter pretending to be JS.
| ) | ||
|
|
||
| ;; $super flows out via the exported global and also flows back in because the | ||
| ;; global is immutable. |
There was a problem hiding this comment.
This sounds wrong? Should immutable be mutable? But the global is immutable...
There was a problem hiding this comment.
Oh yes, copy-paste error. Disregard copies of this below as well. I will fix them.
There was a problem hiding this comment.
Sg. Then I am not sure what this module is testing, though - that we export an immutable super (which has subtypes) does not constrain us..?
There was a problem hiding this comment.
The key result for this one is that $sub-in is optimized to no longer be a subtype of $super. That's only possible because $super does not flow in from JS.
There was a problem hiding this comment.
Got it, thanks. So the comment on this test could say this?
;; Exported immutable global flows out, but not in. As a result, sub-in can be unsubtyped.
| ;; CHECK-NEXT: ) | ||
| (func $test-in (result anyref) | ||
| (local $sub-in (ref null $sub-in)) | ||
| ;; This requires that $sub-in is a subtype of $any. If $super flows in from |
There was a problem hiding this comment.
| ;; This requires that $sub-in is a subtype of $any. If $super flows in from | |
| ;; This requires that $sub-in is a subtype of any. If $super flows in from |
| ) | ||
|
|
||
| ;; $super flows out via the exported global and also flows back in because the | ||
| ;; global is immutable. |
There was a problem hiding this comment.
Got it, thanks. So the comment on this test could say this?
;; Exported immutable global flows out, but not in. As a result, sub-in can be unsubtyped.
kripken
left a comment
There was a problem hiding this comment.
lgtm aside from comment improvements
| (func $test-out (result (ref null $super)) | ||
| (local $sub-out (ref null $sub-out)) | ||
| ;; This requires that $sub-out is a subtype of $super. If $super flows out | ||
| ;; to JS, $sub-out will have to keep its descriptor. |
There was a problem hiding this comment.
It would be good not to repeat these comments in each testcase. Or to specialize them for each, alternatively.
We previously upated Unsubtyping so that any subtype of the result of a
JS-called function would keep its descriptor if that descriptor could
configure a JS prototype. But configured prototypes can also become
visible indirectly because they flow out of the module via imported or
exported functions, globals, or tables. Handle these cases of values
flowing in from or out to JS.