Generate CCW vtables for value types implementing WinRT interfaces - #2514
Open
Sergio Pedri (Sergio0694) wants to merge 1 commit into
Open
Generate CCW vtables for value types implementing WinRT interfaces#2514Sergio Pedri (Sergio0694) wants to merge 1 commit into
Sergio Pedri (Sergio0694) wants to merge 1 commit into
Conversation
The AOT source generator only ever considered classes when deciding which
types need a CCW vtable, so value types implementing WinRT interfaces (eg.
'ImmutableArray<T>', which implements 'IReadOnlyList<T>', 'IList<T>' and
'IList') got no vtable entries when boxed. Binding such a collection from
XAML then failed with "Argument 'source' is not a supported vector".
Value types are now handled the same way classes are:
- The '[WinRTExposedType]' attribute generator runs for structs, records
and record structs ('ref struct'-s are skipped, as they can never be
boxed). The generated partial declaration now uses the keyword of the
original declaration instead of always using 'class'.
- CsWinRT1028 and its "Make type partial" code fix now cover those same
type kinds, so the "mark this partial" guidance is reported for them.
- The CCW vtable lookup table covers value types from other assemblies
(which we can't annotate), such as 'ImmutableArray<T>', as well as
generic value types whose instantiations each need their own vtable.
Projected/custom mapped value types keep being marshalled by the
projection itself.
Fixes #2507
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Sergio Pedri (Sergio0694)
marked this pull request as ready for review
August 7, 2026 21:59
Sergio Pedri (Sergio0694)
requested a review
from Manodasan Wignarajah (manodasanW)
August 7, 2026 21:59
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
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 #2507
Problem
Binding an
ImmutableArray<T>from XAML under Native AOT fails with:The AOT source generator only ever considered
TypeKind.Classwhen deciding which types need a CCW vtable.ImmutableArray<T>is a struct, so when it was boxed (e.g. assigned toItemsSource, which isobject) the CCW built for it had none of the vtable entries for the WinRT interfaces it actually implements (IReadOnlyList<T>,IList<T>,IList,IEnumerable). XAML'sQueryInterfaceforIBindableVector/IBindableIterablethen failed.This was not specific to
ImmutableArray<T>— it affected any value type implementing WinRT interfaces, including user-defined ones. Records and record structs were also never handled, sinceRecordDeclarationSyntaxis a sibling ofClassDeclarationSyntax, not a subtype.Fix
Value types now go through the exact same two paths classes already use.
Attribute path (types in the assembly being compiled)
NeedVtableAttributenow matches anyTypeDeclarationSyntax(class, struct, record, record struct) rather than onlyClassDeclarationSyntax.ref struct-s are excluded since they can never be boxed, and interfaces/enums/static/abstract types remain excluded.partial class. It now emits the keyword matching the original declaration (struct,record,record struct), which is required for the partial definitions to match. Nested types already used the correct keyword;VtableAttributenow carriesTypeKind/IsRecordso top-level types do too.WinRTExposedTypeAttributealready allowed structs;WinRTRuntimeClassNameAttributeandGeneratedWinRTExposedTypeAttributenow do as well.Lookup table path (types we can't annotate)
ImmutableArray<T>) and generic value types where each instantiation needs its own vtable.Windows.Foundation.Point,KeyValuePair<TKey, TValue>,Nullable<T>) are explicitly excluded, since the projection marshals those itself.Analyzer + code fix
CsWinRT1028("type is not marked partial") and the "Make type partial" code fix now cover structs, records and record structs, so users get the same guidance for value types they already get for classes.ref struct-s never warn.Runtime
ComWrappersSupport.GetInterfaceTableEntriesnow honours user-providedIMarshal/ICustomPropertyProviderentries for value types too, not just classes.Testing
AotOptimizerTests(16 tests):ImmutableArray<T>boxed viaImmutableArray.Create, a collection expression, and a builder +ToImmutable()all land on the lookup table with the bindable (IBindableVector/IBindableIterable) entries and enumerator adapters; struct/record/record struct/nested types get[WinRTExposedType]with the right keyword; generic value types go on the lookup table;ref struct, non-boxed, no-WinRT-interface and projected value types produce nothing.RunAotOptimizernow also asserts the generated sources compile, which is what catches a mismatched partial keyword (verified: reverting the keyword fix makes those tests fail with CS0261).DiagnosticAnalyzerTests(6 new): CsWinRT1028 fires for non-partial struct/record/record struct, and does not for partial types,ref struct, or types with no WinRT interfaces.WinRTAotCodeFixerTests(new file, 5 tests): the code fix produces a correctpartialdeclaration for class, struct, record, record struct and nested types.FunctionalTests/Collections(Native AOT end-to-end): round-trips a boxedImmutableArray<string>throughBindableIterableProperty, and exercises the nativeIIterable<IInspectable>QI + enumeration path (what XAML does) for arrays built viaCreate, a collection expression, and a builder, plus a same-assemblypartial structandpartial record struct.All 91 source generator tests pass.