Skip to content

Handle ternary, switch, and cast expressions in AOT CCW discovery - #2480

Merged
Manodasan Wignarajah (manodasanW) merged 3 commits into
masterfrom
user/sergiopedri/fix-aot-analyzer-ternary
Jul 15, 2026
Merged

Manodasan Wignarajah (manodasanW) merged 3 commits into
masterfrom
user/sergiopedri/fix-aot-analyzer-ternary

Conversation

@Sergio0694

Copy link
Copy Markdown
Member

Fixes #1947.

Problem

The AOT source generator's CCW lookup table discovery (GetVtableAttributesToAddOnLookupTable in AotOptimizer.cs) called GetTypeInfo directly on the initializer / assignment / return / argument expressions it inspects. For a conditional (ternary) or switch expression, GetTypeInfo only yields the common target type of all branches (typically object or an interface), and for a cast expression it yields the cast target type. So the concrete types actually being boxed or cast were never discovered and got no CCW vtable entries or generic instantiations, failing at runtime under Native AOT.

// Nothing here was discovered: 'List<int>' and 'List<string>' both got no CCW vtable
object obj = GetFlag() ? new List<int>() : (object)new List<string>();

Fix

Add an AddVtableAttributesForExpression helper that looks through parenthesized, cast, conditional (ternary), and switch expressions to reach the concrete leaf expressions that flow into the target, and route every expression-based call site through it. For casts the target type is still processed directly, so existing (List<int>)value discovery is preserved while the operand ((object)new List<string>()) is now also discovered.

Testing

  • Source generator unit tests (src/Tests/SourceGeneratorTest/AotOptimizerTests.cs): run WinRTAotSourceGenerator over ternary, switch, and cast boxing and assert the concrete types are registered in the generated CCW vtable lookup table. The three positive tests fail without the fix and pass with it; a control test guards against discovering types that aren't actually boxed.
  • AOT CCW functional test (src/Tests/FunctionalTests/CCW/Program.cs): box List<T> instances only reachable through a ternary or switch expression and validate, under Native AOT, that their CCWs expose the expected IVector<T> vtable via the reported runtime class name.

Verified locally: SourceGeneratorTest (68 tests) and DiagnosticTests (364 tests) pass, and both the Roslyn 4.8 and Roslyn 4.12 generator variants build cleanly.

Grouped as three commits: the generator fix, the AOT functional test, and the unit tests.

Copilot AI added 3 commits July 2, 2026 14:41
The AOT source generator's CCW lookup table discovery ('GetVtableAttributesToAddOnLookupTable') called 'GetTypeInfo' directly on the initializer / assignment / return / argument expressions. For a conditional (ternary) or switch expression this only yields the common target type (typically 'object' or an interface), and for a cast expression it yields the cast target type, so the concrete branch/operand types being boxed or cast (eg. 'List<int>' in 'object o = flag ? new List<int>() : ...') were never discovered and got no CCW vtable entries or generic instantiations, failing at runtime under Native AOT.

Add an 'AddVtableAttributesForExpression' helper that looks through parenthesized, cast, conditional, and switch expressions to reach the concrete leaf expressions, and route all expression-based call sites through it. For casts the target type is still processed directly to preserve existing '(List<int>)value' detection.

Fixes #1947

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Boxes 'List<T>' instances that are only reachable through a conditional (ternary) or switch expression (mirroring issue #1947) and validates, under Native AOT, that their CCWs expose the expected 'IVector<T>' vtable via the reported runtime class name. Without the generator fix these types get no CCW vtable entries and the runtime class name check fails.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ion discovery

Run the 'WinRTAotSourceGenerator' over conditional (ternary), switch, and cast expressions that box generic types, and assert the discovered concrete types are registered in the generated CCW vtable lookup table. These fail without the generator fix (the boxed types are never discovered) and pass with it, and a control test guards against discovering types that aren't actually boxed. Fixes #1947.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes Native AOT CCW lookup-table discovery in the WinRT AOT source generator by ensuring it can “see through” ternary, switch, parenthesized, and cast expressions to the concrete leaf expressions that actually produce boxed values. This addresses issue #1947 where only the common/converted type (often object or an interface) was observed, causing missing CCW vtable entries and runtime failures under Native AOT.

Changes:

  • Updated AotOptimizer.GetVtableAttributesToAddOnLookupTable to route expression-based sites through a new AddVtableAttributesForExpression helper that recursively inspects ternary/switch/cast/parenthesized expressions.
  • Added generator unit tests validating discovery for ternary, switch, and cast scenarios (plus a control test to prevent over-eager discovery).
  • Added a functional CCW regression test validating List<T> CCWs expose the expected IVector<T> vtable under Native AOT when the lists are only reachable through ternary/switch expressions.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Authoring/WinRT.SourceGenerator/AotOptimizer.cs Adds an expression-walking helper to discover concrete boxed/cast types in ternary/switch/cast/parenthesized expressions for CCW vtable lookup generation.
src/Tests/SourceGeneratorTest/AotOptimizerTests.cs Adds source generator regression tests asserting concrete generic types are discovered in generated CCW lookup table sources.
src/Tests/FunctionalTests/CCW/Program.cs Adds Native AOT functional regression coverage ensuring CCWs created from values boxed via ternary/switch expose expected IVector<T> runtime class names.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@manodasanW
Manodasan Wignarajah (manodasanW) merged commit 0c2379e into master Jul 15, 2026
14 checks passed
@manodasanW
Manodasan Wignarajah (manodasanW) deleted the user/sergiopedri/fix-aot-analyzer-ternary branch July 15, 2026 02:32
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.

AOT analyzer misses ternary expressions

4 participants