smarcd edited PR #14128.
smarcd updated PR #14128.
smarcd commented on PR #14128:
Done: title renamed, doc comment trimmed, test moved to
tests/all/func.rsand simplified to fetch-multiple-ways equality (name,exports(), table).One flag:
Eqdoesn't hold across an import/export boundary between two instances (each instance copies its ownVMFunctionImportrecord, so the pointer differs even though it calls the same code). Left the test scoped to one instance. Let me know if cross-instance identity was actually expected (can compare through to the underlying code/vmctx pointer instead if so).
cfallin commented on PR #14128:
Hmm, that's actually somewhat surprising API behavior, IMHO -- equality (and hashing) should hold when a
Funcrefers to the same function within a store, regardless how it's reached.I think this means we need to take a
Storeborrow so we can safely reach inside the raw pointers. That means we can't implement theEqandHashtraits literally -- we need to provide separate methods on theFuncfor this. I'd imagine something likeFunc::is_same(&store, &f1, &f2)or similar. cc @alexcrichton for thoughts on this as well since it's a fairly conspicuous API surface...
smarcd updated PR #14128.
smarcd commented on PR #14128:
Agreed, and that tracks with what I found — pushed
Func::is_same(store, a, b)andFunc::identity_key(store)in place of the trait impls.Both take a store borrow and dereference into the
VMFuncRef's own identity (vmctx,wasm_call,array_call) rather than comparing the wrapper pointer's own address, so they see through the import/export copy: the underlying entry points andvmctxare identical across instances even though each instance holds its ownVMFunctionImportrecord at a different address.identity_keyreturns an opaqueHash + Eqvalue forHashMapuse, consistent withis_same.Extended the test to cover the case that broke last time: a function imported into a second instance and re-exported from there now correctly reports
is_sameand equalidentity_key.
alexcrichton commented on PR #14128:
This seems reasonable to me, yeah, thanks! I'd probably go ahead and throw the type index into the hashed key as well to be safe, although it's probably not strictly necessary either
:memo: cfallin submitted PR review:
Thanks @smarcd -- another nit below, and see Alex's point. If you can address those and get the CI green, I'm happy to approve and merge.
:speech_balloon: cfallin created PR review comment:
It's probably sufficient to return just the
wasm_callfield here: each exported function will have the two entry points but either one will uniquely identify the function.
smarcd updated PR #14128.
smarcd commented on PR #14128:
Checked
wasm_callbefore committing to it: it'sNonefor a hostFunc::wrapuntil thatFuncis later paired with a module that has a matching trampoline, and it's filled in in place at that point (confirmed with a throwaway probe:Nonebefore instantiation,Some(..)after).That's two problems for using it alone as the key:
- Two never-imported host functions both read
wasm_call = None, so they'd collide.- Even a single
Func's key would change over the store's lifetime as it flipsNone → Some, which breaksHashMapuse outright, not just an occasional collision.
array_calldoesn't have either issue (always present, never mutates), so I kept(vmctx, array_call)and folded intype_indexper Alex - droppedwasm_callinstead of keeping only it.Also fixed the regression test along the way: it wrapped two different
|| {}closures to check that distinct host functions aren'tis_same, but two separate closure expressions are two distinct Rust types, so that assertion happened to pass for the wrong reason (differentarray_call, not differentvmctx). Now wraps the same closure value twice, soarray_callis shared and onlyvmctxdiscriminates, plus a new test assertingidentity_keyis stable across thewasm_calltransition.
smarcd updated PR #14128.
:speech_balloon: cfallin created PR review comment:
No need for the narrative comment here (which bits are exported, etc) -- that's also something we can easily change if needed.
Better to explain why we choose these keys. We include vmctx to disambiguate statically-same functions from different instances of its module; we include the array-call pointer because it's always present and there is one per separate function; and we include the type-index as insurance to ensure that we disambiguate functions based on their Wasm-level signatures.
:thumbs_up: cfallin submitted PR review:
Thanks -- just one nit then I'm happy to merge.
smarcd updated PR #14128.
smarcd commented on PR #14128:
Done.
:thumbs_up: cfallin submitted PR review.
cfallin has enabled auto merge for PR #14128.
cfallin added PR #14128 feat: implement PartialEq/Eq/Hash for Func to the merge queue.
github-merge-queue[bot] removed PR #14128 feat: implement PartialEq/Eq/Hash for Func from the merge queue.
Last updated: Aug 30 2026 at 09:07 UTC