Skip to content

Fix typed select pushing Type::Any instead of expected type#2707

Merged
sbc100 merged 2 commits into
WebAssembly:mainfrom
sumleo:fix/typed-select-pushes-any
Feb 27, 2026
Merged

Fix typed select pushing Type::Any instead of expected type#2707
sbc100 merged 2 commits into
WebAssembly:mainfrom
sumleo:fix/typed-select-pushes-any

Conversation

@sumleo

@sumleo sumleo commented Feb 26, 2026

Copy link
Copy Markdown
Contributor

Summary

  • The typed select instruction's type checker validates operands against the expected type but forgets to set result_type, leaving it as Type::Any.
  • Fix adds result_type = expected[0] in the typed select branch.

Details

In TypeChecker::OnSelect (type-checker.cc), result_type is initialized to Type::Any. The untyped select path (when expected is empty) correctly sets result_type = type1 on line 1012. However, the typed select path (when expected is non-empty) validates both operands against expected[0] but never assigns result_type.

The typed select instruction (select t) exists specifically to provide precise type information for cases where the operand types alone are insufficient (e.g., reference types). Pushing Type::Any as the result type defeats this purpose and can cause downstream type checking to be less precise than intended.

The fix adds result_type = expected[0] after the CheckType calls in the typed select branch, mirroring the pattern used in the untyped path.

Tests

  • typed-select-result-type.txt: Verifies that typed select with funcref/externref annotations properly propagates the result type, allowing the result to be used in contexts expecting that specific reference type (e.g., global.set to a funcref global, return from an externref function).
  • bad-typed-select-type-mismatch.txt: Verifies that using a typed select (result funcref) where externref is expected correctly produces a type mismatch error.

In OnSelect, when expected is non-empty (typed select instruction),
the code validates type1 and type2 against expected[0] but never
assigns result_type. It stays as Type::Any from initialization,
defeating the purpose of the typed select which exists to provide
precise type information for reference types.
@zherczeg

Copy link
Copy Markdown
Collaborator

This looks valid. Even without GC there are some reference types, so it is possible to add a test for this. With GC, unknown reference types in dead code could be an interesting test as well.

@sbc100

sbc100 commented Feb 26, 2026

Copy link
Copy Markdown
Member

@zherczeg should we land this now or ask for a test for be added?

Add a positive test verifying that typed select with funcref/externref
annotations properly propagates the result type, allowing the result
to be used in contexts expecting that specific reference type.

Add a negative test verifying that using a typed select result where
a different reference type is expected correctly produces a type
mismatch error.
@sumleo

sumleo commented Feb 27, 2026

Copy link
Copy Markdown
Contributor Author

Added two tests:

  • test/typecheck/typed-select-result-type.txt — positive test that typed select with funcref and externref annotations properly propagates the result type (e.g., storing the result in a (mut funcref) global, returning it from an externref function).
  • test/typecheck/bad-typed-select-type-mismatch.txt — negative test that using a typed select (result funcref) where externref is expected correctly produces a type mismatch error.

@sbc100 sbc100 merged commit dbd22f8 into WebAssembly:main Feb 27, 2026
17 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.

3 participants