fix: key resource-import fallback by name, eliminate sentinel (closes #99)#115
Merged
Merged
Conversation
Replace the `(0u32, prefix)` sentinel slot in `build_resource_type_to_import` with a per-resource name-keyed fallback index. The previous design collapsed every `[resource-rep]` / `[resource-new]` import onto a single map slot whenever a component imported resources without canonical entries — silently overwriting all but the first when more than one resource was imported. Changes: - New `ResourceImportMap` struct with two indices: `by_type_id` (canonical type-id → import) and `by_name` (resource short-name → import). The canonical lookup path is unchanged; the import-only fallback now lives in `by_name`, keyed per-resource. - `resolve_resource_positions` uses the new combined `resolve()` helper, which tries the type-id index first then translates the type id to a resource short-name (via `ParsedComponent:: resolve_resource_type`) for the name fallback. The legacy `used_sentinel` gate is gone — its job (marking imported-resource matches as "callee does not define") is now driven by whether the match came from the name fallback. - `resolve_inner_resource_imports` / `resolve_one_layout` updated to take the parsed component for the same name-fallback path. - All call sites in `resolver.rs` updated to pass the component alongside the resource map. - Four new unit tests pin down the multi-resource case, the single-resource case (now keyed by name, not by sentinel), the empty case, and the per-name disambiguation property. Test results: 181 lib unit tests pass (was 177 + 4 new); 73 `wit_bindgen_runtime` tests stay green; clippy `-D warnings` clean. Closes #99. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
avrabe
added a commit
that referenced
this pull request
Apr 29, 2026
V&V-hardening minor release. Closes 5 issues: - #98 — semver-correct compare_version (PR #113) - #99 — resource-import fallback name-keyed, sentinel eliminated (PR #115) - #102 — Kani + proptest harnesses for parser/merger/resolver (PR #116) - #104 — cargo-fuzz scaffolding with 4 targets (PR #114) - #112 — Mythos v0.4 follow-up: items 4, 5, 6 confirmed and fixed (PR #117) New approved STPA loss scenarios: LS-R-10, LS-CP-3. Pre-release Mythos delta pass (tier-5 + tier-4 changed since v0.3.0): merger.rs and resolver.rs scanned; **no confirmed findings**. The cargo-fuzz scaffolding immediately surfaced a real parser panic on truncated component-section input — tracked as #118 for v0.4.1 / v0.5. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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
Closes #99.
build_resource_type_to_importpreviously had a fallback branch thatcollapsed every
[resource-rep]/[resource-new]core import onto asingle map slot keyed
(0u32, prefix)whenever a component importedresources without canonical entries. That sentinel was intentional for
the single-resource case but is a known foot-gun for any future code
path that writes multiple resources into it.
Approach: option (b) — key by resource name
Per the issue's two options for hardening, this PR implements option
(b): key the import-only fallback by the resource short-name extracted
from the import field (e.g.,
[resource-rep]frequency→ key("frequency", "[resource-rep]")). The sentinel is gone, and so is thedownstream
used_sentinelgate inresolve_resource_positions.Why option (b) over (a):
preserving it with safe keying is preferable to asserting a
single-resource invariant that future work could legitimately need to
break.
resolved entries as "callee does not define this resource"; with the
sentinel removed, that signal becomes "matched via the name index"
rather than "matched via type-id 0", which is a cleaner predicate.
Concrete changes
ResourceImportMapstruct with two indices:by_type_id: HashMap<(u32, &'static str), (String, String)>—populated from canonical
ResourceRep/ResourceNewentries plusStep-5 missing-op inference and Step-6 alias propagation. Identical
semantics to the pre-existing primary map.
by_name: HashMap<(String, &'static str), (String, String)>—populated by scanning core module imports for
[resource-rep]<rn>/
[resource-new]<rn>. Replaces the sentinel slot.ResourceImportMap::resolve(component, type_id, prefix)returnsOption<(&entry, matched_via_name_fallback: bool)>. Tryby_type_idfirst; on miss, translate the type id to a resource short-name via
ParsedComponent::resolve_resource_typeand look up inby_name.resolve_resource_positions— drops theused_sentinelgate. Theflag now reads "did this match come from the name index?", which is
the same logical condition without the sentinel.
resolve_inner_resource_imports/resolve_one_layout— extended totake the parsed component so they can use the name fallback for
inner-list resource borrows.
resolver.rsupdated; no signatures outside themodule changed.
Test plan
cargo test --lib -p meld-core— 181 unit tests pass (was 177 +4 new for issue Design: resource-fallback sentinel in build_resource_type_to_import #99).
cargo test --release --test wit_bindgen_runtime— 73 testspass.
cargo test --release— full workspace green.cargo fmt --all -- --checkclean.cargo clippy --workspace --all-targets -- -D warningsclean.New tests
meld-core/src/resolver.rs:test_issue_99_multi_resource_import_only_no_collapse— hand-builtParsedComponentwith two distinct[resource-rep]and two[resource-new]imports; asserts 4 distinct entries inby_name,and that
xandyresolve to different module/field tuples.test_issue_99_single_resource_import_only_keyed_by_name—single-resource case keys by the actual resource name, not by an
empty-string sentinel.
test_issue_99_no_resources_produces_empty_map— empty fallbackcase is genuinely empty.
test_issue_99_get_by_name_disambiguates_resources— directget_by_nameon two resources from different interfaces returnsthe correct per-resource entries.
🤖 Generated with Claude Code