Skip to content

Project IReference of TypeName/HResult as Type/Exception#2461

Draft
Sergio0694 wants to merge 3 commits into
staging/3.0from
sergio0694-ireference-typename-projection
Draft

Project IReference of TypeName/HResult as Type/Exception#2461
Sergio0694 wants to merge 3 commits into
staging/3.0from
sergio0694-ireference-typename-projection

Conversation

@Sergio0694

Copy link
Copy Markdown
Member

Summary

Fix the C# projection of IReference<T> for the two Windows Runtime value types that map to .NET reference types: Windows.UI.Xaml.Interop.TypeName -> System.Type and Windows.Foundation.HResult -> System.Exception. These now project to Type / Exception instead of the invalid System.Nullable<Type> / System.Nullable<Exception>.

Motivation

IReference<T> normally projects to System.Nullable<T>, which is correct for value-type inners. But TypeName and HResult are Windows Runtime value types that project to the .NET reference types System.Type and System.Exception. Nullable<Type> / Nullable<Exception> are not valid C# (the type argument of Nullable<T> must be a non-nullable value type), so any metadata containing IReference<TypeName> or IReference<HResult> produced a projection that failed to compile. A reference type is already nullable, so the projection should simply be the inner type. This mirrors the equivalent CsWinRT 2.x fix (#2103).

The marshalling itself was already fully supported by the runtime (TypeMarshaller / ExceptionMarshaller BoxToUnmanaged / UnboxToManaged via IID_IReferenceOfType / IID_IReferenceOfException); only the projected type name was wrong.

Changes

  • src/WinRT.Projection.Writer/Helpers/TypedefNameWriter.cs: when projecting Windows.Foundation.IReference<T>, detect inners whose projection is a .NET reference type (TypeName -> Type, HResult -> Exception, plus a literal System.Type) and emit the inner type directly instead of wrapping it in System.Nullable<>.
  • src/Tests/TestComponentCSharp/ (TestComponentCSharp.idl, Class.h, Class.cpp): add scalar IReference<TypeName> and IReference<HResult> members - a native-boxed property (BoxedTypeName / BoxedHResult) and a round-trip method (RoundtripTypeName / RoundtripHResult).
  • src/Tests/UnitTest/TestComponentCSharp_Tests.cs: add ReferenceTypeNameProjectsAsType and ReferenceHResultProjectsAsException, covering both marshalling directions and the null case.

Notes

The test members and the projection-writer fix are committed separately so CI can demonstrate the tests failing to build (invalid Nullable<Type> / Nullable<Exception>) before the fix lands, then passing afterward. Collections of these types (IVector<IReference<TypeName>> etc.) are intentionally out of scope: since Type / Exception are reference types there is no distinct Nullable<> managed shape, so such a collection is indistinguishable from IVector<TypeName> / IVector<HResult> at the interop layer.

@Sergio0694 Sergio0694 added bug Something isn't working CsWinRT 3.0 labels Jun 20, 2026
@Sergio0694 Sergio0694 requested a review from manodasanW June 20, 2026 00:49
@Sergio0694 Sergio0694 force-pushed the sergio0694-ireference-typename-projection branch from 0e19ee7 to 2b39a90 Compare June 20, 2026 01:27
@Sergio0694 Sergio0694 marked this pull request as draft June 20, 2026 01:46
Add members to TestComponentCSharp exercising the scalar IReference<T>
projection for the two WinRT value types that map to .NET reference types:
IReference<Windows.UI.Xaml.Interop.TypeName> -> System.Type and
IReference<Windows.Foundation.HResult> -> System.Exception.

Each adds a native-boxed property (BoxedTypeName / BoxedHResult) and a
round-trip method (RoundtripTypeName / RoundtripHResult), with matching
UnitTest coverage including the null case.

These tests fail to build until the projection writer stops emitting the
invalid Nullable<Type> / Nullable<Exception> for these instantiations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Sergio0694 Sergio0694 force-pushed the sergio0694-ireference-typename-projection branch from 2b39a90 to a8db136 Compare June 20, 2026 02:02
Sergio0694 and others added 2 commits June 19, 2026 19:34
…able<>

Windows.UI.Xaml.Interop.TypeName and Windows.Foundation.HResult are Windows
Runtime value types that project to the .NET reference types System.Type and
System.Exception. IReference<T> of those must project to the inner type
directly (Type / Exception), not the invalid System.Nullable<Type/Exception>
(the type argument of Nullable<T> must be a non-nullable value type).

Generalize the TypedefNameWriter IReference special-case to drop the
Nullable<> wrapper whenever the inner argument projects to a .NET reference
type (TypeName -> Type, HResult -> Exception, or a literal System.Type). The
runtime marshalling was already in place (TypeMarshaller / ExceptionMarshaller
BoxToUnmanaged / UnboxToManaged); only the projected type name was wrong.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add IVector<IReference<TypeName>> and IVector<IReference<HResult>> members to
TestComponentCSharp (return and parameter, exercised in isolation) plus matching
UnitTest coverage, to verify the generic projection compiles and to capture the
runtime round-trip behavior.

The public type collapses to IList<Type> / IList<Exception> via the scalar fix,
while the ABI marshaller keeps the Nullable<T> element marker and so targets the
IVector<IReference<T>> IID with per-element box/unbox.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working CsWinRT 3.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant