Closed titzer closed 8 months ago
Update: it appears that the reference interpreter has just changed to use constant initializers (ref.func
in init expressions). I guess this is intended as having been "referenced" since all such element sections can appear before bodies? If so, I'll close this issue.
I don't know what the intention is here. I don't recall ever having discussed it 😅
IIRC we explicitly decided that the occurrence of a function index in a global/table initialiser, active/passive elem segment, or export would also (in addition to the "normal" declarative elem segment case) count as "referencing" for the purposes of allowing ref.func
in code. This is reflected in the live spec, but I'll try to dig up a meeting or issue where this decision was recorded.
I remember @rossberg being against this relaxing at the time :)
https://github.com/WebAssembly/reference-types/issues/31 https://github.com/WebAssembly/reference-types/issues/76
See @lukewagner's comment towards the end, which I think pretty much sums up the eventual decision
@rossberg What I proposed is that, in your example, since the ref.global is outside the code section, it doesn't need to have been declared. Implementation-wise, everything before the code section is effectively one big declaration for the code section, so there's no practical benefit in your example requiring the ref.global to have already been declared.
@conrad-watt Thanks for doing the legwork to dig this up. It seems the most consistent that all element segments behave the same (counting as a reference), regardless of whether they were function indexes or ref.func
s. Looks like we just didn't have a test for that case yet until recently here.
It seems the most consistent that all element segments behave the same (counting as a reference), regardless of whether they were function indexes or
ref.func
s
agree - especially since we previously said that occurrences of ref.func $i
in global initialisers should cause $i
to be counted as "declared".
Right, IIRC, it was the group's sentiment to count every occurrence of a function reference outside a function body to be sufficient as a "forward declaration". That's what spec and interpreter implement. (This forward declaration thing probably is one of Wasm's biggest hacks.)
Legacy element segments with just function indices are desugared into reference instructions by the spec, so they naturally behave consistently.
FWIW re the OP: the text format never implies hidden forward declarations. What you see is what you get when converting to binary.
@rossberg Thanks, I think we can close this now.
The current reference interpreter passes this test (excerpted from
type-equivalence.wast
):However, when translating it to
.bin.wast
, it does not pre-refer to the functions in the table. IIUC this is a change from previous behavior. Do we still require functions to be pre-declared (in elements) to be used withref.func
?