Remove the TypeKey concept as the primary user for the concept is unable to use it...
authorJeremy Koritzinsky <jekoritz@microsoft.com>
Thu, 19 Jan 2023 01:09:52 +0000 (17:09 -0800)
committerGitHub <noreply@github.com>
Thu, 19 Jan 2023 01:09:52 +0000 (17:09 -0800)
13 files changed:
docs/design/libraries/ComInterfaceGenerator/VTableStubs.md
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ManagedToNativeVTableMethodGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Marshallers/NativeToManagedThisMarshallerFactory.cs
src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs
src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs
src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/IUnmanagedVirtualMethodTableProvider.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/ImplicitThisTests.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/NoImplicitThisTests.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/VTableGCHandlePair.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CallingConventionForwarding.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/CodeSnippets.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/IVirtualMethodIndexSignatureProvider.cs
src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Unit.Tests/NativeInterfaceShape.cs

index 21a1086..3f5514d 100644 (file)
@@ -80,26 +80,29 @@ public readonly ref struct VirtualMethodTableInfo
     }
 }
 
-public interface IUnmanagedVirtualMethodTableProvider<T> where T : IEquatable<T>
+public interface IUnmanagedVirtualMethodTableProvider
 {
-    protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey);
+    protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type);
 
     public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey<TUnmanagedInterfaceType>()
-        where TUnmanagedInterfaceType : IUnmanagedInterfaceType<T>
+        where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
     {
-        return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey);
+        // Dispatch from a non-virtual generic to a virtual non-generic with System.Type
+        // to avoid generic virtual method dispatch, which is very slow.
+        return GetVirtualMethodTableInfoForKey(typeof(TUnmanagedInterfaceType));
     }
 }
 
-public interface IUnmanagedInterfaceType<T> where T : IEquatable<T>
+public interface IUnmanagedInterfaceType<TUnmanagedInterfaceType> where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
 {
-    public abstract static T TypeKey { get; }
 }
 ```
 
 ## Required API Shapes
 
-The user will be required to implement `IUnmanagedVirtualMethodTableProvider<T>` on the type that provides the method tables, and `IUnmanagedInterfaceType<T>` on the type that defines the unmanaged interface. The `T` types must match between the two interfaces. This mechanism is designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`.
+The user will be required to implement `IUnmanagedVirtualMethodTableProvider` on the type that provides the method tables, and `IUnmanagedInterfaceType<TUnmanagedInterfaceType>` on the type that defines the unmanaged interface. The `TUnmanagedInterfaceType` follows the same design principles as the generic math designs as somewhat of a "self" type to enable us to use the derived interface type in any additional APIs we add to support unmanaged-to-managed stubs.
+
+Previously, each of these interface types were also generic on another type `T`. The `T` types were required to match between the two interfaces. This mechanism was designed to enable each native API platform to provide their own casting key, for example `IID`s in COM, without interfering with each other or requiring using reflection-based types like `System.Type`. However, practical implementation showed that providing just a "type key" was not enough information to cover any non-trivial scenarios (like COM) efficiently without effectively forcing a two-level lookup model or hard-coding type support in the `IUnmanagedVirtualMethodTableProvider<T>` implementation. Additionally, we determined that using reflection to get to attributes is considered "okay" and using generic attributes would enable APIs that build on this model like COM to effectively retrieve information from the `System.Type` instance without causing additional problems.
 
 ## Example Usage
 
@@ -160,11 +163,8 @@ using System.Runtime.InteropServices;
 [assembly:DisableRuntimeMarshalling]
 
 // Define the interface of the native API
-partial interface INativeAPI : IUnmanagedInterfaceType<NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {
-    // There is no concept of casting for this API, but providing a type key is still required by the generator.
-    // Use an empty readonly record struct to provide a type that implements IEquatable<T> but contains no data.
-    static NoCasting IUnmanagedInterfaceType.TypeKey => default;
 
     [VirtualMethodIndex(0, ImplicitThisParameter = false, Direction = CustomTypeMarshallerDirection.In)]
     int GetVersion();
@@ -176,11 +176,8 @@ partial interface INativeAPI : IUnmanagedInterfaceType<NoCasting>
     int Multiply(int x, int y);
 }
 
-// Define the key for native "casting" support for our scenario
-readonly record struct NoCasting {}
-
 // Define our runtime wrapper type for the native interface.
-unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativeAPI.Native
+unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native
 {
     private CNativeAPI* _nativeAPI;
 
@@ -192,7 +189,7 @@ unsafe class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativ
         }
     }
 
-    VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableInfoForKey(NoCasting _)
+    VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(Type _)
     {
         return new(IntPtr.Zero, MemoryMarshal.Cast<CNativeAPI, IntPtr>(new ReadOnlySpan<CNativeAPI>(_nativeAPI, 1)));
     }
@@ -229,7 +226,7 @@ partial interface INativeAPI
     {
         int INativeAPI.GetVersion()
         {
-            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
             int retVal;
             retVal = ((delegate* unmanaged<int>)vtable[0])();
             return retVal;
@@ -242,7 +239,7 @@ partial interface INativeAPI
     {
         int INativeAPI.Add(int x, int y)
         {
-            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
             int retVal;
             retVal = ((delegate* unmanaged<int, int, int>)vtable[1])(x, y);
             return retVal;
@@ -255,7 +252,7 @@ partial interface INativeAPI
     {
         int INativeAPI.Multiply(int x, int y)
         {
-            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider<NoCasting>)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
+            var (_, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<INativeAPI>();
             int retVal;
             retVal = ((delegate* unmanaged<int, int, int>)vtable[2])(x, y);
             return retVal;
@@ -266,7 +263,7 @@ partial interface INativeAPI
 // LibraryImport-generated code omitted for brevity
 ```
 
-As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider<T>` with a `T` matching the `TypeKey` type of the native interface.
+As this generator is primarily designed to provide building blocks for future work, it has a larger requirement on user-written code. In particular, this generator does not provide any support for authoring a runtime wrapper object that stores the native pointers for the underlying object or the virtual method table. However, this lack of support also provides significant flexibility for developers. The only requirement for the runtime wrapper object type is that it implements `IUnmanagedVirtualMethodTableProvider`.
 
 The emitted interface implementation can be used in two ways:
 
@@ -290,10 +287,8 @@ struct IUnknown
 using System;
 using System.Runtime.InteropServices;
 
-interface IUnknown: IUnmanagedInterfaceType<Guid>
+interface IUnknown: IUnmanagedInterfaceType<IUnknown>
 {
-    static Guid IUnmanagedTypeInterfaceType<Guid>.TypeKey => Guid.Parse("00000000-0000-0000-C000-000000000046");
-
     [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall), typeof(CallConvMemberFunction) })]
     [VirtualMethodIndex(0)]
     int QueryInterface(in Guid riid, out IntPtr ppvObject);
@@ -307,7 +302,7 @@ interface IUnknown: IUnmanagedInterfaceType<Guid>
     uint Release();
 }
 
-class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider<Guid>, IDynamicInterfaceCastable
+class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider, IDynamicInterfaceCastable
 {
     private IntPtr _unknownPtr;
 
@@ -316,9 +311,9 @@ class BaseIUnknownComObject : IUnmanagedVirtualMethodTableProvider<Guid>, IDynam
         _unknownPtr = unknown;
     }
 
-    unsafe VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider<Guid>.GetVirtualMethodTableInfoForKey(Guid iid)
+    unsafe VirtualMethodTableInfo IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableInfoForKey(Type type)
     {
-        if (iid == IUnknown.TypeKey)
+        if (type == typeof(IUnknown))
         {
             return new VirtualMethodTableInfo(_unknownPtr, new ReadOnlySpan<IntPtr>(**(IntPtr***)_unknownPtr), 3);
         }
@@ -358,7 +353,7 @@ partial interface IUnknown
     {
         int IUnknown.QueryInterface(in Guid riid, out IntPtr ppvObject)
         {
-            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
             int retVal;
             fixed (Guid* riid__gen_native = &riid)
             fixed (IntPtr* ppvObject__gen_native = &ppvObject)
@@ -375,7 +370,7 @@ partial interface IUnknown
     {
         uint IUnknown.AddRef()
         {
-            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
             uint retVal;
             retVal = ((delegate* unmanaged[Stdcall, MemberFunction]<IntPtr, uint>)vtable[1])(thisPtr);
             return retVal;
@@ -388,7 +383,7 @@ partial interface IUnknown
     {
         uint IUnknown.Release()
         {
-            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider<Guid>)this).GetVirtualMethodTableInfoForKey<IUnknown>();
+            var (thisPtr, vtable) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<IUnknown>();
             uint retVal;
             retVal = ((delegate* unmanaged[Stdcall, MemberFunction]<IntPtr, uint>)vtable[2])(thisPtr);
             return retVal;
index cc7b913..1b9c1b4 100644 (file)
@@ -97,11 +97,11 @@ namespace Microsoft.Interop
         /// <remarks>
         /// The generated code assumes it will be in an unsafe context.
         /// </remarks>
-        public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv, TypeSyntax containingTypeName, ManagedTypeInfo typeKeyType)
+        public BlockSyntax GenerateStubBody(int index, ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv, TypeSyntax containingTypeName)
         {
             var setupStatements = new List<StatementSyntax>
             {
-                // var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider<<typeKeyType>>)this).GetVirtualMethodTableInfoForKey<<containingTypeName>>();
+                // var (<thisParameter>, <virtualMethodTable>) = ((IUnmanagedVirtualMethodTableProvider)this).GetVirtualMethodTableInfoForKey<<containingTypeName>>();
                 ExpressionStatement(
                     AssignmentExpression(
                         SyntaxKind.SimpleAssignmentExpression,
@@ -119,11 +119,7 @@ namespace Microsoft.Interop
                                 SyntaxKind.SimpleMemberAccessExpression,
                                 ParenthesizedExpression(
                                     CastExpression(
-                                        GenericName(
-                                            Identifier(TypeNames.IUnmanagedVirtualMethodTableProvider))
-                                        .WithTypeArgumentList(
-                                            TypeArgumentList(
-                                                SingletonSeparatedList(typeKeyType.Syntax))),
+                                        ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
                                         ThisExpression())),
                                 GenericName(
                                     Identifier("GetVirtualMethodTableInfoForKey"),
index 3655ed6..345986b 100644 (file)
@@ -9,7 +9,10 @@ using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
 
 namespace Microsoft.Interop
 {
-    internal sealed record NativeThisInfo(ManagedTypeInfo TypeKeyType) : MarshallingInfo;
+    internal sealed record NativeThisInfo : MarshallingInfo
+    {
+        public static readonly NativeThisInfo Instance = new();
+    }
 
     internal sealed class NativeToManagedThisMarshallerFactory : IMarshallingGeneratorFactory
     {
@@ -20,14 +23,10 @@ namespace Microsoft.Interop
         }
 
         public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context)
-            => info.MarshallingAttributeInfo is NativeThisInfo(ManagedTypeInfo typeKeyType) ? new Marshaller(typeKeyType) : _inner.Create(info, context);
+            => info.MarshallingAttributeInfo is NativeThisInfo ? new Marshaller() : _inner.Create(info, context);
 
         private sealed class Marshaller : IMarshallingGenerator
         {
-            private readonly ManagedTypeInfo _typeKeyType;
-
-            public Marshaller(ManagedTypeInfo typeKeyType) => _typeKeyType = typeKeyType;
-
             public ManagedTypeInfo AsNativeType(TypePositionInfo info) => new PointerTypeInfo("void*", "void*", false);
             public IEnumerable<StatementSyntax> Generate(TypePositionInfo info, StubCodeContext context)
             {
@@ -44,10 +43,7 @@ namespace Microsoft.Interop
                     IdentifierName(managedIdentifier),
                         InvocationExpression(
                             MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression,
-                                GenericName(Identifier(TypeNames.IUnmanagedVirtualMethodTableProvider),
-                                    TypeArgumentList(
-                                        SingletonSeparatedList(
-                                            _typeKeyType.Syntax))),
+                               ParseTypeName(TypeNames.IUnmanagedVirtualMethodTableProvider),
                                 GenericName(Identifier("GetObjectForUnmanagedWrapper"),
                                     TypeArgumentList(
                                         SingletonSeparatedList(
index c92244d..6be7b39 100644 (file)
@@ -30,7 +30,6 @@ namespace Microsoft.Interop
             MarshallingInfo ExceptionMarshallingInfo,
             MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> ManagedToUnmanagedGeneratorFactory,
             MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> UnmanagedToManagedGeneratorFactory,
-            ManagedTypeInfo TypeKeyType,
             ManagedTypeInfo TypeKeyOwner,
             SequenceEqualImmutableArray<Diagnostic> Diagnostics);
 
@@ -348,20 +347,15 @@ namespace Microsoft.Interop
 
             ImmutableArray<FunctionPointerUnmanagedCallingConventionSyntax> callConv = GenerateCallConvSyntaxFromAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute);
 
-            var typeKeyOwner = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
-            ManagedTypeInfo typeKeyType = SpecialTypeInfo.Byte;
+            var interfaceType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol.ContainingType);
 
-            INamedTypeSymbol? iUnmanagedInterfaceTypeInstantiation = symbol.ContainingType.AllInterfaces.FirstOrDefault(iface => SymbolEqualityComparer.Default.Equals(iface.OriginalDefinition, iUnmanagedInterfaceTypeType));
-            if (iUnmanagedInterfaceTypeInstantiation is null)
+            INamedTypeSymbol expectedUnmanagedInterfaceType = iUnmanagedInterfaceTypeType.Construct(symbol.ContainingType);
+
+            bool implementsIUnmanagedInterfaceOfSelf = symbol.ContainingType.AllInterfaces.Any(iface => SymbolEqualityComparer.Default.Equals(iface, expectedUnmanagedInterfaceType));
+            if (!implementsIUnmanagedInterfaceOfSelf)
             {
                 // TODO: Report invalid configuration
             }
-            else
-            {
-                // The type key is the second generic type parameter, so we need to get the info for the
-                // second argument.
-                typeKeyType = ManagedTypeInfo.CreateTypeInfoForTypeSymbol(iUnmanagedInterfaceTypeInstantiation.TypeArguments[1]);
-            }
 
             MarshallingInfo exceptionMarshallingInfo = CreateExceptionMarshallingInfo(virtualMethodIndexAttr, symbol, environment.Compilation, generatorDiagnostics, virtualMethodIndexData);
 
@@ -375,8 +369,7 @@ namespace Microsoft.Interop
                 exceptionMarshallingInfo,
                 ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.ManagedToUnmanaged),
                 ComInterfaceGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.UnmanagedToManaged),
-                typeKeyType,
-                typeKeyOwner,
+                interfaceType,
                 new SequenceEqualImmutableArray<Diagnostic>(generatorDiagnostics.Diagnostics.ToImmutableArray()));
         }
 
@@ -442,8 +435,7 @@ namespace Microsoft.Interop
             BlockSyntax code = stubGenerator.GenerateStubBody(
                 methodStub.VtableIndexData.Index,
                 methodStub.CallingConvention.Array,
-                methodStub.TypeKeyOwner.Syntax,
-                methodStub.TypeKeyType);
+                methodStub.TypeKeyOwner.Syntax);
 
             return (
                 methodStub.ContainingSyntaxContext.AddContainingSyntax(
@@ -518,7 +510,7 @@ namespace Microsoft.Interop
 
             var elements = ImmutableArray.CreateBuilder<TypePositionInfo>(originalElements.Length + 2);
 
-            elements.Add(new TypePositionInfo(methodStub.TypeKeyOwner, new NativeThisInfo(methodStub.TypeKeyType))
+            elements.Add(new TypePositionInfo(methodStub.TypeKeyOwner, NativeThisInfo.Instance)
             {
                 InstanceIdentifier = ThisParameterIdentifier,
                 NativeIndex = 0,
index 9b4effb..60c3f39 100644 (file)
@@ -38,7 +38,7 @@ namespace Microsoft.Interop
 
         public const string IUnmanagedVirtualMethodTableProvider = "System.Runtime.InteropServices.IUnmanagedVirtualMethodTableProvider";
 
-        public const string IUnmanagedInterfaceType_Metadata = "System.Runtime.InteropServices.IUnmanagedInterfaceType`2";
+        public const string IUnmanagedInterfaceType_Metadata = "System.Runtime.InteropServices.IUnmanagedInterfaceType`1";
 
         public const string System_Span_Metadata = "System.Span`1";
         public const string System_Span = "System.Span";
index b0c3a1f..99e4309 100644 (file)
@@ -48,17 +48,17 @@ namespace System.Runtime.InteropServices
     }
 
     /// <summary>
-    /// This interface allows an object to provide information about a virtual method table for a managed interface that implements <see cref="IUnmanagedInterfaceType{TInterface, T}"/> to enable invoking methods in the virtual method table.
+    /// This interface allows an object to provide information about a virtual method table for a managed interface that implements <see cref="IUnmanagedInterfaceType{TInterface}"/> to enable invoking methods in the virtual method table.
     /// </summary>
     /// <typeparam name="T">The type to use to represent the the identity of the unmanaged type.</typeparam>
-    public unsafe interface IUnmanagedVirtualMethodTableProvider<T> where T : IEquatable<T>
+    public unsafe interface IUnmanagedVirtualMethodTableProvider
     {
         /// <summary>
-        /// Get the information about the virtual method table for a given unmanaged interface type represented by <paramref name="typeKey"/>.
+        /// Get the information about the virtual method table for a given unmanaged interface type represented by <paramref name="type"/>.
         /// </summary>
-        /// <param name="typeKey">The object that represents the identity of the unmanaged interface.</param>
+        /// <param name="type">The managed type for the unmanaged interface.</param>
         /// <returns>The virtual method table information for the unmanaged interface.</returns>
-        protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(T typeKey);
+        protected VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type);
 
         /// <summary>
         /// Get the information about the virtual method table for the given unmanaged interface type.
@@ -66,9 +66,9 @@ namespace System.Runtime.InteropServices
         /// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
         /// <returns>The virtual method table information for the unmanaged interface.</returns>
         public sealed VirtualMethodTableInfo GetVirtualMethodTableInfoForKey<TUnmanagedInterfaceType>()
-            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
         {
-            return GetVirtualMethodTableInfoForKey(TUnmanagedInterfaceType.TypeKey);
+            return GetVirtualMethodTableInfoForKey(typeof(TUnmanagedInterfaceType));
         }
 
         /// <summary>
@@ -77,7 +77,7 @@ namespace System.Runtime.InteropServices
         /// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
         /// <returns>The length of the virtual method table for the unmanaged interface.</returns>
         public static int GetVirtualMethodTableLength<TUnmanagedInterfaceType>()
-            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
         {
             return TUnmanagedInterfaceType.VirtualMethodTableLength;
         }
@@ -88,7 +88,7 @@ namespace System.Runtime.InteropServices
         /// <typeparam name="TUnmanagedInterfaceType">The managed interface type that represents the unmanaged interface.</typeparam>
         /// <returns>A pointer to the virtual method table  of managed implementations of the unmanaged interface type</returns>
         public static void* GetVirtualMethodTableManagedImplementation<TUnmanagedInterfaceType>()
-            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
         {
             return TUnmanagedInterfaceType.VirtualMethodTableManagedImplementation;
         }
@@ -100,7 +100,7 @@ namespace System.Runtime.InteropServices
         /// <param name="obj">The managed object that implements the unmanaged interface.</param>
         /// <returns>A pointer-sized value that can be passed to unmanaged code that represents <paramref name="obj"/></returns>
         public static void* GetUnmanagedWrapperForObject<TUnmanagedInterfaceType>(TUnmanagedInterfaceType obj)
-            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
         {
             return TUnmanagedInterfaceType.GetUnmanagedWrapperForObject(obj);
         }
@@ -112,7 +112,7 @@ namespace System.Runtime.InteropServices
         /// <param name="ptr">A pointer-sized value returned by <see cref="GetUnmanagedWrapperForObject{TUnmanagedInterfaceType}(TUnmanagedInterfaceType)"/> or <see cref="IUnmanagedInterfaceType{TInterface, TKey}.GetUnmanagedWrapperForObject(TInterface)"/>.</param>
         /// <returns>The object wrapped by <paramref name="ptr"/>.</returns>
         public static TUnmanagedInterfaceType GetObjectForUnmanagedWrapper<TUnmanagedInterfaceType>(void* ptr)
-            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType, T>
+            where TUnmanagedInterfaceType : IUnmanagedInterfaceType<TUnmanagedInterfaceType>
         {
             return TUnmanagedInterfaceType.GetObjectForUnmanagedWrapper(ptr);
         }
@@ -123,9 +123,8 @@ namespace System.Runtime.InteropServices
     /// </summary>
     /// <typeparam name="TInterface">The managed interface.</typeparam>
     /// <typeparam name="TKey">The type of a value that can represent types from the corresponding unmanaged type system.</typeparam>
-    public unsafe interface IUnmanagedInterfaceType<TInterface, TKey>
-        where TInterface : IUnmanagedInterfaceType<TInterface, TKey>
-        where TKey : IEquatable<TKey>
+    public unsafe interface IUnmanagedInterfaceType<TInterface>
+        where TInterface : IUnmanagedInterfaceType<TInterface>
     {
         /// <summary>
         /// Get the length of the virtual method table for the given unmanaged interface type.
@@ -152,10 +151,5 @@ namespace System.Runtime.InteropServices
         /// <param name="ptr">A pointer-sized value returned by <see cref="IUnmanagedVirtualMethodTableProvider{TKey}.GetUnmanagedWrapperForObject{IUnmanagedInterfaceType{TInterface, TKey}}(IUnmanagedInterfaceType{TInterface, TKey})"/> or <see cref="GetUnmanagedWrapperForObject(TInterface)"/>.</param>
         /// <returns>The object wrapped by <paramref name="ptr"/>.</returns>
         public static abstract TInterface GetObjectForUnmanagedWrapper(void* ptr);
-
-        /// <summary>
-        /// The value that represents the unmanaged type's identity in the corresponding unmanaged type system.
-        /// </summary>
-        public static abstract TKey TypeKey { get; }
     }
 }
index a325169..55174ae 100644 (file)
@@ -13,35 +13,32 @@ namespace ComInterfaceGenerator.Tests
     {
         internal partial class ImplicitThis
         {
-            public readonly record struct NoCasting;
-
-            internal partial interface INativeObject : IUnmanagedInterfaceType<INativeObject, NoCasting>
+            internal partial interface INativeObject : IUnmanagedInterfaceType<INativeObject>
             {
-                static int IUnmanagedInterfaceType<INativeObject, NoCasting>.VirtualMethodTableLength => 2;
+                static int IUnmanagedInterfaceType<INativeObject>.VirtualMethodTableLength => 2;
 
-                static NoCasting IUnmanagedInterfaceType<INativeObject, NoCasting>.TypeKey => default;
 
-                private static void** s_vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(INativeObject), sizeof(void*) * IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<INativeObject>());
-                static void* IUnmanagedInterfaceType<INativeObject, NoCasting>.VirtualMethodTableManagedImplementation
+                private static void** s_vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(INativeObject), sizeof(void*) * IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<INativeObject>());
+                static void* IUnmanagedInterfaceType<INativeObject>.VirtualMethodTableManagedImplementation
                 {
                     get
                     {
                         if (s_vtable[0] == null)
                         {
-                            Native.PopulateUnmanagedVirtualMethodTable(new Span<IntPtr>(s_vtable, IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<INativeObject>()));
+                            Native.PopulateUnmanagedVirtualMethodTable(new Span<IntPtr>(s_vtable, IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<INativeObject>()));
                         }
                         return s_vtable;
                     }
                 }
 
-                static void* IUnmanagedInterfaceType<INativeObject, NoCasting>.GetUnmanagedWrapperForObject(INativeObject obj)
+                static void* IUnmanagedInterfaceType<INativeObject>.GetUnmanagedWrapperForObject(INativeObject obj)
                 {
-                    return VTableGCHandlePair<INativeObject, NoCasting>.Allocate(obj);
+                    return VTableGCHandlePair<INativeObject>.Allocate(obj);
                 }
 
-                static INativeObject IUnmanagedInterfaceType<INativeObject, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr)
+                static INativeObject IUnmanagedInterfaceType<INativeObject>.GetObjectForUnmanagedWrapper(void* ptr)
                 {
-                    return VTableGCHandlePair<INativeObject, NoCasting>.GetObject(ptr);
+                    return VTableGCHandlePair<INativeObject>.GetObject(ptr);
                 }
 
                 [VirtualMethodIndex(0, ImplicitThisParameter = true)]
@@ -51,7 +48,7 @@ namespace ComInterfaceGenerator.Tests
             }
 
             [NativeMarshalling(typeof(NativeObjectMarshaller))]
-            public class NativeObject : INativeObject.Native, IUnmanagedVirtualMethodTableProvider<NoCasting>, IDisposable
+            public class NativeObject : INativeObject.Native, IUnmanagedVirtualMethodTableProvider, IDisposable
             {
                 private readonly void* _pointer;
 
@@ -60,7 +57,11 @@ namespace ComInterfaceGenerator.Tests
                     _pointer = pointer;
                 }
 
-                public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => new VirtualMethodTableInfo((IntPtr)_pointer, new ReadOnlySpan<IntPtr>(*(void**)_pointer, 2));
+                public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type)
+                {
+                    Assert.Equal(typeof(INativeObject), type);
+                    return new VirtualMethodTableInfo((IntPtr)_pointer, new ReadOnlySpan<IntPtr>(*(void**)_pointer, 2));
+                }
 
                 public void Dispose()
                 {
@@ -112,7 +113,7 @@ namespace ComInterfaceGenerator.Tests
 
             ManagedObjectImplementation impl = new ManagedObjectImplementation(startingValue);
 
-            void* wrapper = IUnmanagedVirtualMethodTableProvider<NativeExportsNE.ImplicitThis.NoCasting>.GetUnmanagedWrapperForObject<NativeExportsNE.ImplicitThis.INativeObject>(impl);
+            void* wrapper = IUnmanagedVirtualMethodTableProvider.GetUnmanagedWrapperForObject<NativeExportsNE.ImplicitThis.INativeObject>(impl);
 
             Assert.Equal(startingValue, NativeExportsNE.ImplicitThis.GetNativeObjectData(wrapper));
             NativeExportsNE.ImplicitThis.SetNativeObjectData(wrapper, newValue);
@@ -120,7 +121,7 @@ namespace ComInterfaceGenerator.Tests
             // Verify that we actually updated the managed instance.
             Assert.Equal(newValue, impl.GetData());
 
-            VTableGCHandlePair<NativeExportsNE.ImplicitThis.INativeObject, NativeExportsNE.ImplicitThis.NoCasting>.Free(wrapper);
+            VTableGCHandlePair<NativeExportsNE.ImplicitThis.INativeObject>.Free(wrapper);
         }
 
         class ManagedObjectImplementation : NativeExportsNE.ImplicitThis.INativeObject
index 5d382cb..fd0d0a4 100644 (file)
@@ -12,18 +12,14 @@ namespace ComInterfaceGenerator.Tests
     {
         internal partial class NoImplicitThis
         {
-            public readonly record struct NoCasting;
-
-            internal partial interface IStaticMethodTable : IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>
+            internal partial interface IStaticMethodTable : IUnmanagedInterfaceType<IStaticMethodTable>
             {
-                static int IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.VirtualMethodTableLength => 2;
-                static void* IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.VirtualMethodTableManagedImplementation => null;
-
-                static void* IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.GetUnmanagedWrapperForObject(IStaticMethodTable obj) => null;
+                static int IUnmanagedInterfaceType<IStaticMethodTable>.VirtualMethodTableLength => 2;
+                static void* IUnmanagedInterfaceType<IStaticMethodTable>.VirtualMethodTableManagedImplementation => null;
 
-                static IStaticMethodTable IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
+                static void* IUnmanagedInterfaceType<IStaticMethodTable>.GetUnmanagedWrapperForObject(IStaticMethodTable obj) => null;
 
-                static NoCasting IUnmanagedInterfaceType<IStaticMethodTable, NoCasting>.TypeKey => default;
+                static IStaticMethodTable IUnmanagedInterfaceType<IStaticMethodTable>.GetObjectForUnmanagedWrapper(void* ptr) => null;
 
                 [VirtualMethodIndex(0, Direction = MarshalDirection.ManagedToUnmanaged, ImplicitThisParameter = false)]
                 int Add(int x, int y);
@@ -32,7 +28,7 @@ namespace ComInterfaceGenerator.Tests
             }
 
             [NativeMarshalling(typeof(StaticMethodTableMarshaller))]
-            public class StaticMethodTable : IStaticMethodTable.Native, IUnmanagedVirtualMethodTableProvider<NoCasting>
+            public class StaticMethodTable : IStaticMethodTable.Native, IUnmanagedVirtualMethodTableProvider
             {
                 private readonly void* _vtableStart;
 
@@ -41,8 +37,11 @@ namespace ComInterfaceGenerator.Tests
                     _vtableStart = vtableStart;
                 }
 
-                public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) =>
-                    new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan<IntPtr>(_vtableStart, IUnmanagedVirtualMethodTableProvider<NoCasting>.GetVirtualMethodTableLength<IStaticMethodTable>()));
+                public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(Type type)
+                {
+                    Assert.Equal(typeof(IStaticMethodTable), type);
+                    return new VirtualMethodTableInfo(IntPtr.Zero, new ReadOnlySpan<IntPtr>(_vtableStart, IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<IStaticMethodTable>()));
+                }
             }
 
             [CustomMarshaller(typeof(StaticMethodTable), MarshalMode.ManagedToUnmanagedOut, typeof(StaticMethodTableMarshaller))]
index a5653fb..c6ee2cd 100644 (file)
@@ -1,22 +1,16 @@
 ï»¿// Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using System.Runtime.InteropServices;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace ComInterfaceGenerator.Tests
 {
-    public static unsafe class VTableGCHandlePair<TUnmanagedInterface, TKey>
-        where TUnmanagedInterface : IUnmanagedInterfaceType<TUnmanagedInterface, TKey>
-        where TKey : IEquatable<TKey>
+    public static unsafe class VTableGCHandlePair<TUnmanagedInterface>
+        where TUnmanagedInterface : IUnmanagedInterfaceType<TUnmanagedInterface>
     {
         public static void* Allocate(TUnmanagedInterface obj)
         {
-            void** unmanaged = (void**)NativeMemory.Alloc((nuint)sizeof(void*) * (nuint)IUnmanagedVirtualMethodTableProvider<TKey>.GetVirtualMethodTableLength<TUnmanagedInterface>());
+            void** unmanaged = (void**)NativeMemory.Alloc((nuint)sizeof(void*) * (nuint)IUnmanagedVirtualMethodTableProvider.GetVirtualMethodTableLength<TUnmanagedInterface>());
             unmanaged[0] = TUnmanagedInterface.VirtualMethodTableManagedImplementation;
             unmanaged[1] = (void*)GCHandle.ToIntPtr(GCHandle.Alloc(obj));
             return unmanaged;
index 5357157..d8033b5 100644 (file)
@@ -23,10 +23,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [VirtualMethodIndex(0)]
                     void Method();
                 }
@@ -50,10 +49,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [SuppressGCTransitionAttribute]
                     [VirtualMethodIndex(0)]
                     void Method();
@@ -78,10 +76,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [UnmanagedCallConv]
                     [VirtualMethodIndex(0)]
                     void Method();
@@ -106,10 +103,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
                     [VirtualMethodIndex(0)]
                     void Method();
@@ -134,10 +130,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })]
                     [VirtualMethodIndex(0)]
                     void Method();
@@ -168,10 +163,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [SuppressGCTransition]
                     [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl), typeof(CallConvMemberFunction) })]
                     [VirtualMethodIndex(0)]
index da20a1a..ef02fb3 100644 (file)
@@ -10,26 +10,25 @@ namespace ComInterfaceGenerator.Unit.Tests
     {
         public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]";
         public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;";
-        public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl = $$"""
+        public const string INativeAPI_IUnmanagedInterfaceTypeImpl = $$"""
             partial interface INativeAPI
             {
-                {{INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                {{INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
             }
             """;
 
-        public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl = """
-                static int IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableLength => 1;
-                static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableManagedImplementation => null;
-                static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
-                static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
-                static NoCasting IUnmanagedInterfaceType<INativeAPI, NoCasting>.TypeKey => default;
+        public const string INativeAPI_IUnmanagedInterfaceTypeMethodImpl = """
+                static int IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableLength => 1;
+                static unsafe void* IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableManagedImplementation => null;
+                static unsafe void* IUnmanagedInterfaceType<INativeAPI>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
+                static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI>.GetObjectForUnmanagedWrapper(void* ptr) => null;
             """;
 
         public static string NativeInterfaceUsage() => @"
 // Try using the generated native interface
-sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativeAPI.Native
+sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider, INativeAPI.Native
 {
-    public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(NoCasting typeKey) => throw null;
+    public VirtualMethodTableInfo GetVirtualMethodTableInfoForKey(System.Type type) => throw null;
 }
 ";
 
@@ -37,31 +36,28 @@ sealed class NativeAPI : IUnmanagedVirtualMethodTableProvider<NoCasting>, INativ
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {
     [VirtualMethodIndex(0)]
     void Method();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public static readonly string SpecifiedMethodIndexNoExplicitParametersNoImplicitThis = @"
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {
     [VirtualMethodIndex(0, ImplicitThisParameter = false)]
     void Method();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public static readonly string SpecifiedMethodIndexNoExplicitParametersCallConvWithCallingConventions = @"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 
-readonly record struct NoCasting {}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {
 
     [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })]
@@ -84,7 +80,7 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
     [SuppressGCTransition]
     [VirtualMethodIndex(4)]
     void Method4();
-}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         public static string BasicParametersAndModifiers(string typeName, string preDeclaration = "") => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -93,12 +89,11 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0)]
     {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         public static string BasicParametersAndModifiersManagedToUnmanaged(string typeName, string preDeclaration = "") => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -107,12 +102,11 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, Direction = MarshalDirection.ManagedToUnmanaged)]
     {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         public static string BasicParametersAndModifiers<T>() => BasicParametersAndModifiers(typeof(T).FullName!);
         public static string BasicParametersAndModifiersNoRef(string typeName, string preDeclaration = "") => $@"
 using System.Runtime.CompilerServices;
@@ -122,23 +116,21 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0)]
     {typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         public static string BasicParametersAndModifiersNoImplicitThis(string typeName) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = false)]
     {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public static string BasicParametersAndModifiersNoImplicitThis<T>() => BasicParametersAndModifiersNoImplicitThis(typeof(T).FullName!);
         public static string MarshalUsingCollectionCountInfoParametersAndModifiers<T>() => MarshalUsingCollectionCountInfoParametersAndModifiers(typeof(T).ToString());
@@ -148,8 +140,7 @@ using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0)]
     [return:MarshalUsing(ConstantElementCount=10)]
@@ -160,7 +151,7 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
         [MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef,
         [MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut,
         out int pOutSize);
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public static string BasicReturnTypeComExceptionHandling(string typeName, string preDeclaration = "") => $@"
 using System.Runtime.CompilerServices;
@@ -168,12 +159,11 @@ using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 {preDeclaration}
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ExceptionMarshalling = ExceptionMarshalling.Com)]
     {typeName} Method();
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public static string BasicReturnTypeCustomExceptionHandling(string typeName, string customExceptionType, string preDeclaration = "") => $@"
 using System.Runtime.CompilerServices;
@@ -181,12 +171,11 @@ using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 {preDeclaration}
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, CustomExceptionMarshallingType = typeof({customExceptionType}))]
     {typeName} Method();
-}}" + NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         public class ManagedToUnmanaged : IVirtualMethodIndexSignatureProvider<ManagedToUnmanaged>
         {
@@ -211,7 +200,7 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
             public static bool ImplicitThisParameter => true;
 
             // Unmanaged-to-managed-only stubs don't provide implementations for the interface, so we don't want to try to use the generated nested interface
-            // since it won't have managed implementations for the meth
+            // since it won't have managed implementations for the methods
             public static string NativeInterfaceUsage() => string.Empty;
         }
         public class Bidirectional : IVirtualMethodIndexSignatureProvider<Bidirectional>
index 544e87c..8ad0d29 100644 (file)
@@ -19,19 +19,18 @@ namespace ComInterfaceGenerator.Unit.Tests
 
         public static readonly string DisableRuntimeMarshalling = "[assembly:System.Runtime.CompilerServices.DisableRuntimeMarshalling]";
         public static readonly string UsingSystemRuntimeInteropServicesMarshalling = "using System.Runtime.InteropServices.Marshalling;";
-        public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl = $$"""
+        public const string INativeAPI_IUnmanagedInterfaceTypeImpl = $$"""
             partial interface INativeAPI
             {
-                {{INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                {{INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
             }
             """;
 
-        public const string INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl = """
-                static int IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableLength => 1;
-                static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.VirtualMethodTableManagedImplementation => null;
-                static unsafe void* IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
-                static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI, NoCasting>.GetObjectForUnmanagedWrapper(void* ptr) => null;
-                static NoCasting IUnmanagedInterfaceType<INativeAPI, NoCasting>.TypeKey => default;
+        public const string INativeAPI_IUnmanagedInterfaceTypeMethodImpl = """
+                static int IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableLength => 1;
+                static unsafe void* IUnmanagedInterfaceType<INativeAPI>.VirtualMethodTableManagedImplementation => null;
+                static unsafe void* IUnmanagedInterfaceType<INativeAPI>.GetUnmanagedWrapperForObject(INativeAPI obj) => null;
+                static unsafe INativeAPI IUnmanagedInterfaceType<INativeAPI>.GetObjectForUnmanagedWrapper(void* ptr) => null;
             """;
 
         public static abstract string NativeInterfaceUsage();
@@ -43,12 +42,11 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     {typeName} Method({typeName} value, in {typeName} inValue, ref {typeName} refValue, out {typeName} outValue);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.BasicParametersAndModifiersNoRef(string typeName, string preDeclaration) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -57,12 +55,11 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     {typeName} Method({typeName} value, in {typeName} inValue, out {typeName} outValue);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         static string ICustomMarshallingSignatureTestProvider.BasicParameterByValue(string typeName, string preDeclaration) => $@"
 using System.Runtime.CompilerServices;
@@ -70,12 +67,11 @@ using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 {preDeclaration}
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     void Method({typeName} value);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         static string ICustomMarshallingSignatureTestProvider.BasicParameterWithByRefModifier(string modifier, string typeName, string preDeclaration) => $@"
 using System.Runtime.CompilerServices;
@@ -85,32 +81,29 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     void Method({modifier} {typeName} value);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.BasicReturnType(string typeName, string preDeclaration) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 {preDeclaration}
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     {typeName} Method();
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingParametersAndModifiers(string typeName, string marshallerTypeName, string preDeclaration) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 {preDeclaration}
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     [return: MarshalUsing(typeof({marshallerTypeName}))]
@@ -119,15 +112,14 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
         [MarshalUsing(typeof({marshallerTypeName}))] in {typeName} pIn,
         [MarshalUsing(typeof({marshallerTypeName}))] ref {typeName} pRef,
         [MarshalUsing(typeof({marshallerTypeName}))] out {typeName} pOut);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Runtime.InteropServices.Marshalling;
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     [return:MarshalUsing(ConstantElementCount=10)]
@@ -138,7 +130,7 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
         [MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef,
         [MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut,
         out int pOutSize);
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -146,8 +138,7 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     [return:MarshalUsing(typeof({marshallerType}), ConstantElementCount=10)]
@@ -159,7 +150,7 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
         [MarshalUsing(typeof({marshallerType}), CountElementName = ""pOutSize"")] out {collectionType} pOut,
         out int pOutSize
         );
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -167,14 +158,13 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     int Method(
         [MarshalUsing(typeof({marshallerType}), CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out {collectionType} pOut
         );
-}}" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+}}" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
 
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionOutConstantLength(string collectionType, string predeclaration) => $@"
 using System.Runtime.CompilerServices;
@@ -184,15 +174,14 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     int Method(
         [MarshalUsing(ConstantElementCount = 10)] out {collectionType} pOut
         );
 }}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.MarshalUsingCollectionReturnConstantLength(string collectionType, string predeclaration) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -201,14 +190,13 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     [return:MarshalUsing(ConstantElementCount = 10)]
     {collectionType} Method();
 }}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
         static string ICustomMarshallingSignatureTestProvider.CustomElementMarshalling(string collectionType, string elementMarshaller, string predeclaration) => $@"
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
@@ -217,8 +205,7 @@ using System.Runtime.InteropServices.Marshalling;
 
 [assembly:DisableRuntimeMarshalling]
 
-readonly record struct NoCasting {{}}
-partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
 {{
     [VirtualMethodIndex(0, ImplicitThisParameter = {TProvider.ImplicitThisParameter.ToString().ToLowerInvariant()}, Direction = MarshalDirection.{TProvider.Direction})]
     [return:MarshalUsing(ConstantElementCount=10)]
@@ -232,6 +219,6 @@ partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
         out int pOutSize
         );
 }}
-" + TProvider.NativeInterfaceUsage() + INativeAPI_NoCasting_IUnmanagedInterfaceTypeImpl;
+" + TProvider.NativeInterfaceUsage() + INativeAPI_IUnmanagedInterfaceTypeImpl;
     }
 }
index 548eb70..6fa6406 100644 (file)
@@ -23,10 +23,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [VirtualMethodIndex(0)]
                     void Method();
                 }
@@ -50,10 +49,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [VirtualMethodIndex(0)]
                     void Method();
                 }
@@ -77,10 +75,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [VirtualMethodIndex(0)]
                     void Method();
                 }
@@ -109,10 +106,9 @@ namespace ComInterfaceGenerator.Unit.Tests
                 using System.Runtime.InteropServices;
                 using System.Runtime.InteropServices.Marshalling;
 
-                readonly record struct NoCasting {}
-                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI, NoCasting>
+                partial interface INativeAPI : IUnmanagedInterfaceType<INativeAPI>
                 {
-                    {{CodeSnippets.INativeAPI_NoCasting_IUnmanagedInterfaceTypeMethodImpl}}
+                    {{CodeSnippets.INativeAPI_IUnmanagedInterfaceTypeMethodImpl}}
                     [VirtualMethodIndex(0)]
                     void Method();
                 }