Repository navigation
Handle ternary, switch, and cast expressions in AOT CCW discovery - #2480
Merged
Manodasan Wignarajah (manodasanW) merged 3 commits intoJul 15, 2026
Merged
Manodasan Wignarajah (manodasanW) merged 3 commits into
Manodasan Wignarajah (manodasanW) merged 3 commits into
Conversation
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>
There was a problem hiding this comment.
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.GetVtableAttributesToAddOnLookupTableto route expression-based sites through a newAddVtableAttributesForExpressionhelper 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 expectedIVector<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.
Manodasan Wignarajah (manodasanW)
approved these changes
Jul 15, 2026
Manodasan Wignarajah (manodasanW)
deleted the
user/sergiopedri/fix-aot-analyzer-ternary
branch
July 15, 2026 02:32
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.
Fixes #1947.
Problem
The AOT source generator's CCW lookup table discovery (
GetVtableAttributesToAddOnLookupTableinAotOptimizer.cs) calledGetTypeInfodirectly on the initializer / assignment / return / argument expressions it inspects. For a conditional (ternary) or switch expression,GetTypeInfoonly yields the common target type of all branches (typicallyobjector 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.Fix
Add an
AddVtableAttributesForExpressionhelper 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>)valuediscovery is preserved while the operand ((object)new List<string>()) is now also discovered.Testing
src/Tests/SourceGeneratorTest/AotOptimizerTests.cs): runWinRTAotSourceGeneratorover 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.src/Tests/FunctionalTests/CCW/Program.cs): boxList<T>instances only reachable through a ternary or switch expression and validate, under Native AOT, that their CCWs expose the expectedIVector<T>vtable via the reported runtime class name.Verified locally:
SourceGeneratorTest(68 tests) andDiagnosticTests(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.