fix: structural ref resolution for record-using interfaces#21
Merged
Conversation
Records inside an interface block were previously hashed by path string on the handler side and rejected outright by the actor-side pack_types! parser, so handlers using records (e.g. theater-handler-podman) couldn't agree on an interface hash with their actors. - src/metadata.rs: hash_type_in resolves Type::Ref against in-scope typedefs and hashes the underlying record/variant structurally; cycle- safe via a name stack returning HASH_SELF_REF. - src/interface_impl.rs: removed the duplicate ref-hashing path; FuncSignature delegates to metadata::hash_type_in. InterfaceImpl::from_pact now captures pact.types so refs in function signatures resolve. - crates/pack-guest-macros/src/lib.rs: parse_func_sigs_into accepts record /variant/enum/flags/type-alias decls inside an interface block, scoped locally so sibling interfaces don't share resolution. - tests/handler_actor_hash_convergence.rs: cross-crate convergence test using the podman.pact shape — parse_pact + InterfaceImpl::from_pact produces byte-identical hash to direct packr-abi primitives.
5ea3855 to
f68ec37
Compare
This was referenced May 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Handlers that declare records inside an
interface name { ... }block (e.g.theater-handler-podman) could not agree on an interface hash with their actors. Two root causes:Type::Ref(path)nominally (sha256("ref:" + path_str)), while the actor side hashed records structurally. Even when the actor-side type defs were in scope, the two sides produced different bytes.imports { iface { ... } }blocks, so actors couldn't declare matching type defs at all — the only escape hatch was placing records at top level of the.typesfile, which still mismatched (see point 1).This unblocks
agentry-actorand any future actor calling a record-using handler.Changes
src/metadata.rs: newhash_type_in(ty, types)resolvesType::Refagainst in-scope typedefs and hashes the underlying record/variant structurally. Cycle-safe via a name stack returningHASH_SELF_REF.hash_typebecomes a thin wrapper overhash_type_in(ty, &[]).compute_interface_hashthreadsarena.typesthrough.src/interface_impl.rs: removed the duplicate ref-hashing path intype_to_hash(it shadowed the metadata.rs logic and would have diverged again).FuncSignaturenow hashash_in(types); the oldhash()delegates with no types in scope.InterfaceImplcarries atypesfield, andfrom_pactcapturespact.types(plus type-style exports). This is the path theater actually uses.crates/pack-guest-macros/src/lib.rs:parse_func_sigs_intoacceptsrecord/variant/enum/flags/typedeclarations at the top of an interface block. Declarations are scoped locally so sibling interfaces don't share resolution.crates/pack-guest-macros/src/metadata.rs: added an explanatory comment about theresult<_, E>→ Bool/String convention shared withpact.rs::parse_result.Tests
src/metadata.rs: ref resolves structurally, unresolved ref falls back to path hash, recursive types terminate cleanly,compute_interface_hashmatches a hand-computed structural hash.pack-guest-macros: parser accepts records inside imports/interface blocks, scopes don't leak between sibling interfaces, top-level typedefs reach into blocks,result<_, E>convention.tests/handler_actor_hash_convergence.rsusing the actualpodman.pactshape:parse_pact+InterfaceImpl::from_pactproduces a byte-identical hash topackr-abiprimitives applied directly. This is the test that would have failed before the fix and catches future regressions.Test plan
cargo test --workspace— all 252 tests passhandler_actor_hash_convergence) explicitly mirrors the user-reportedtheater-handler-podmanscenario🤖 Generated with Claude Code