Skip to content

Add [WindowsRuntimeType] marker and centralize WinRT metadata mapping#2467

Draft
Sergio0694 wants to merge 5 commits into
user/sergiopedri/smoke-testsfrom
user/sergiopedri/type-attribute-opt
Draft

Add [WindowsRuntimeType] marker and centralize WinRT metadata mapping#2467
Sergio0694 wants to merge 5 commits into
user/sergiopedri/smoke-testsfrom
user/sergiopedri/type-attribute-opt

Conversation

@Sergio0694

Copy link
Copy Markdown
Member

Summary

Splits the dual-purpose [WindowsRuntimeMetadata("contract")] attribute into a parameterless [WindowsRuntimeType] marker placed on every projected/proxy type, plus a single centralized, fully-trimmable ABI.WindowsRuntimeMetadataTypes lookup type that carries the type -> source .winmd mapping (one [WindowsRuntimeMetadata(typeof(T), "stem")] entry per type). This mirrors how ABI.WindowsRuntimeDefaultInterfaces already centralizes default-interface metadata.

Motivation

The old [WindowsRuntimeMetadata] attribute did two unrelated jobs at once: it acted as the "this is a Windows Runtime type" marker, and it also carried the source .winmd module name (the "contract"/"stem") as a string on every single projected type. That string is never read at runtime — the runtime only ever checks for the presence of the attribute. The stem is needed only by build-time tooling (the interop and WinMD generators), and now that reference projections exist, those generators already have to recover that information through a lookup against the implementation projection.

Given that, carrying a per-type string everywhere is pure overhead. Moving to a parameterless marker removes a string from the metadata of every projected type, and relocating the type -> stem mapping onto one dedicated lookup type means the entire mapping is dead-code-eliminated by ILLink/ILC whenever it isn't needed. The net result is smaller metadata with no loss of functionality.

Changes

  • src/WinRT.Runtime2/Attributes/: add the new parameterless, implementation-only WindowsRuntimeTypeAttribute marker; repurpose WindowsRuntimeMetadataAttribute to a (Type, string), class-targeting, AllowMultiple attribute used only on the centralized lookup type; delete the now-redundant WindowsRuntimeMappedMetadataAttribute.
  • src/WinRT.Runtime2/ (manually-projected types + ABI/ proxy types): replace the per-type [WindowsRuntimeMetadata("...")] / [WindowsRuntimeMappedMetadata("...")] attributes with the parameterless [WindowsRuntimeType] marker across all manually-projected types and custom-mapped proxy types.
  • src/WinRT.Runtime2/InteropServices/TypeMapInfo/: update the runtime lookups (WindowsRuntimeMetadataInfo, WindowsRuntimeMarshallingInfo) to recognize Windows Runtime types via [WindowsRuntimeType], and to distinguish projected vs. proxy types via [WindowsRuntimeMappedType].
  • src/WinRT.Projection.Writer/: emit [WindowsRuntimeType] per projected type, and emit the centralized ABI.WindowsRuntimeMetadataTypes lookup type (implementation projections only) carrying the [WindowsRuntimeMetadata(typeof(T), "stem")] entries, wired through the generator run state, emit context, and finalization step (mirroring the default-interfaces flow).
  • src/WinRT.Projection.Writer/Resources/Additions/ (XAML structs): update the 12 hand-authored full-replacement XAML struct additions (CornerRadius, Duration, GridLength, KeyTime, RepeatBehavior, Matrix3D for both WinUI and UWP XAML) to use [WindowsRuntimeType], placed inside the existing #if !CSWINRT_REFERENCE_PROJECTION block alongside the other implementation-only attributes.
  • src/WinRT.Interop.Generator/: recognize projected types via [WindowsRuntimeType]; read the source .winmd stem from the centralized ABI.WindowsRuntimeMetadataTypes lookup on the resolved implementation projection (new GetWindowsRuntimeMetadataTypesLookup reader); emit the parameterless marker on generated proxy types.
  • src/WinRT.WinMD.Generator/: recognize Windows Runtime types via [WindowsRuntimeType] and recover the assembly/contract name from the centralized lookup type instead of from a per-type attribute.
  • .github/: update copilot-instructions.md and the interop generator skill (SKILL.md + references/name-mangling-scheme.md) to document the new marker and the centralized metadata-types lookup.

Validation

Built every affected project, and validated end-to-end locally by running the projection writer over the Windows SDK union metadata: the full generated Windows SDK projection (including all XAML namespaces and the new lookup type) compiles cleanly against the new runtime. An AsmResolver probe confirmed the consumption-side lookup correctly reads the emitted entries.

Sergio0694 and others added 5 commits June 22, 2026 10:51
The per-type [WindowsRuntimeMetadata("contract")] attribute served two purposes:
marking a type as a Windows Runtime type (presence) and recording the source
.winmd stem (value). The runtime only ever reads the presence; the value is used
exclusively by build-time tooling. Carrying the string on every projected type is
pure metadata overhead at runtime.

Split the two concerns:
- Add a parameterless [WindowsRuntimeType] marker attribute (implementation-only),
  applied to every projected type and to proxy types for custom-mapped types.
- Repurpose [WindowsRuntimeMetadata] into a (Type, string) attribute targeting a
  single class with AllowMultiple, so the type -> .winmd-stem mapping can live on a
  centralized, trimmable lookup type (emitted by the projection generator in a later
  change) instead of on each type.
- Remove [WindowsRuntimeMappedMetadata]; proxy types now use [WindowsRuntimeType].

Update the runtime metadata/marshalling lookups accordingly: presence checks now use
[WindowsRuntimeType], and the projected-vs-proxy distinction (previously inferred from
[WindowsRuntimeMetadata] vs [WindowsRuntimeMappedMetadata]) now uses [WindowsRuntimeMappedType],
which proxy types already carry to point at their public type. The 'System.EventHandler'
proxy intentionally remains unmarked (a pure custom type, not a metadata type).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace the per-type [WindowsRuntimeMetadata("stem")] attribute emitted on every
projected type with the parameterless [WindowsRuntimeType] marker, and move the
type -> source .winmd-stem mapping to a centralized ABI.WindowsRuntimeMetadataTypes
lookup type carrying one [WindowsRuntimeMetadata(typeof(T), "stem")] per projected
type. This mirrors how ABI.WindowsRuntimeDefaultInterfaces centralizes default
interfaces, and lets the (build-time only) metadata be trimmed away when unused.

The mapping is recorded as a side effect of emitting the per-type marker (the single
chokepoint), so the lookup set never drifts from the set of types that actually carry
the marker (e.g. enums are not projected in component mode). Both emission and the
lookup type are skipped in reference-projection mode, where [WindowsRuntimeType] is
stripped along with the rest of the implementation-only surface.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the interop generator for the [WindowsRuntimeType] marker + centralized
metadata mapping:

- IsProjectedWindowsRuntimeType now checks for [WindowsRuntimeType] (the parameterless
  marker) instead of the per-type [WindowsRuntimeMetadata] attribute.
- GetWindowsRuntimeMetadataName now reads the source .winmd stem from the
  ABI.WindowsRuntimeMetadataTypes lookup type in the implementation projection (via a
  new GetWindowsRuntimeMetadataTypesLookup module extension, mirroring
  GetDefaultInterfacesLookup), rather than from a per-type attribute. This works
  uniformly for types resolved from implementation and reference projections, since both
  select the same implementation projection that carries the lookup type.
- Generated proxy types now emit the parameterless [WindowsRuntimeType] marker instead of
  [WindowsRuntimeMappedMetadata("<contract>")]; the runtime only checks for its presence.
- InteropReferences/WellKnownMetadataNames swap the [WindowsRuntimeMetadata]/
  [WindowsRuntimeMappedMetadata] references for [WindowsRuntimeType].

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update the WinMD generator for the [WindowsRuntimeType] marker + centralized metadata
mapping, mirroring the interop generator:

- IsWindowsRuntimeType now checks for the [WindowsRuntimeType] marker.
- WindowsRuntimeAssemblyName now reads the source .winmd contract assembly name from the
  centralized ABI.WindowsRuntimeMetadataTypes lookup type in the type's declaring module
  (via a new GetWindowsRuntimeMetadataTypesLookup module extension), instead of from a
  per-type [WindowsRuntimeMetadata] attribute.

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

Document the split of [WindowsRuntimeMetadata("contract")] into the parameterless
[WindowsRuntimeType] marker plus the centralized, trimmable ABI.WindowsRuntimeMetadataTypes
lookup type: a new subsection in the copilot instructions, the updated type-inclusion and
generated-attribute notes in the interop generator skill, and the rewritten metadata-name
derivation in the name-mangling reference.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Sergio0694 Sergio0694 added performance Related to performance work trimming CsWinRT 3.0 labels Jun 22, 2026
@Sergio0694 Sergio0694 requested a review from manodasanW June 22, 2026 18:41
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/smoke-tests branch 2 times, most recently from 5362e08 to c140feb Compare June 23, 2026 00:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CsWinRT 3.0 performance Related to performance work trimming

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant