Skip to content

wasmprinter: fix outer aliases that print unparsable or shadowed identifiers - #2795

Merged
alexcrichton merged 2 commits into
bytecodealliance:mainfrom
jrandolf:wasmprinter-outer-alias-names
Oct 27, 2026
Merged

alexcrichton merged 2 commits into
bytecodealliance:mainfrom
jrandolf:wasmprinter-outer-alias-names

Conversation

@jrandolf

@jrandolf jrandolf commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Outer aliases now print the same identifier as the header of the component they refer to, or the alias's count when a scope in between has the same identifier. In three cases, the printed text of a valid component didn't parse or referred to the wrong scope:

  • When a component's name can't be its identifier, such as an empty name, the alias printed the synthetic identifier with its (@name ...) annotation, which only parses where the component is defined. (component (@name "") (type u8) (alias outer 0 0 (type))) printed (alias outer $"#component0 " (@name "") 0 (type)).
  • A nested component's header uses the name its parent gives it, but the alias used the component's own name from its component-name section, so it could refer to an identifier that nothing defines.
  • An inner scope could have the same identifier, which the alias then resolved to instead. A component and its first nested component can both have the synthetic identifier $"#component0 ", for example.

These were found by the grammar-based component fuzzer in #2796.

@jrandolf
jrandolf requested a review from a team as a code owner October 23, 2026 21:54
@jrandolf
jrandolf requested review from alexcrichton and removed request for a team October 23, 2026 21:54
Outer aliases now print the same identifier as the header of the
component they refer to, or its count when a scope in between has the
same identifier. They printed the target's name with its `(@name ...)`
annotation, which only parses where the component is defined; they used
a nested component's own name from its `component-name` section, while
its header uses the name its parent gives it; and they printed
identifiers that an inner scope shadows, such as the synthetic
`$"#component0 "` of both a component and its first nested component,
so the printed text didn't parse or referred to the wrong scope.

    (component (@name "") (type u8) (alias outer 0 0 (type)))

printed `(alias outer $"#component0 " (@name "") 0 (type))`.
@jrandolf
jrandolf force-pushed the wasmprinter-outer-alias-names branch from 6f556a1 to a949791 Compare October 23, 2026 23:52

@alexcrichton alexcrichton left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused by this PR - the title says that this prints the identifier outer aliases refer to, but it looks like that was already done since outer.name.as_ref() was already inspected. Is the change in this PR primarily to handle the shadowing problem? Or handle the case that outer.name wasn't set by looking at the component name sections?

Comment thread crates/wasmprinter/src/lib.rs Outdated
Comment on lines +539 to +551
// Outer aliases refer to a nested component by the name
// printed above, which its parent gives it.
#[cfg(feature = "component-model")]
if let [.., parent, state] = &mut states[..] {
if state.encoding == Encoding::Component {
state.name = parent
.component
.component_names
.index_to_name
.get(&parent.component.components)
.cloned();
}
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be part of read_names since that seems most readily applicable to what's going on here.

For example this'd go well inside register_component_names perhaps

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've moved this into read_names. It can't go in register_component_names, because that only runs when the nested component has its own component-name section, and the parent's name needs to apply either way.

@alexcrichton

Copy link
Copy Markdown
Member

Oh, also, this should likely have some tests one way or another.

Sets a nested component's name from its parent's name for it in
read_names, and adds a test for each case where an outer alias printed
text that didn't parse or referred to the wrong component.
@jrandolf

jrandolf commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor Author

This fixes three separate problems, not only the shadowing. The old code did print outer.name, but:

  1. For names that can't be identifiers, such as an empty name, it printed the (@name ...) annotation along with the identifier, and that annotation only parses in the component's header.
  2. For a nested component, it used the name from the component's own component-name section. The component's header uses the name its parent gives it, so the alias could name something that doesn't exist.
  3. An inner component with the same identifier could shadow it.

I've added tests/cli/component-model/outer-alias-names.wast with one case for each. All three fail to roundtrip on main.

@jrandolf
jrandolf requested a review from alexcrichton October 26, 2026 16:41
@jrandolf jrandolf changed the title wasmprinter: print the identifier that outer aliases refer to wasmprinter: fix outer aliases that print unparsable or shadowed identifiers Oct 26, 2026
@alexcrichton
alexcrichton added this pull request to the merge queue Oct 27, 2026
Merged via the queue into bytecodealliance:main with commit 24de91c Oct 27, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants