Skip to content

Commit b74596d

Browse files
MichalStrehovskymikelle-rogers
authored andcommitted
Fix obtaining type handles of IDynamicInterfaceCastableImplementation (dotnet#109875)
Fixes dotnet#109496. We try to optimize away type handles (MethodTables) of types that are only needed due to metadata. Trying to grab type handle of such type throws. This fixes it by unconditionally generating type handles of IDynamicInterfaceCastableImplementation.
1 parent a5b9847 commit b74596d

2 files changed

Lines changed: 67 additions & 0 deletions

File tree

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataNode.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
132132
default:
133133
Debug.Assert(type.IsDefType);
134134

135+
// We generally postpone creating MethodTables until absolutely needed.
136+
// IDynamicInterfaceCastableImplementation is special in the sense that just obtaining a System.Type
137+
// (by e.g. browsing custom attribute metadata) gives the user enough to pass this to runtime APIs
138+
// that need a MethodTable. We don't have a legitimate type handle without the MethodTable. Other
139+
// kinds of APIs that expect a MethodTable have enough dataflow annotation to trigger warnings.
140+
// There's no dataflow annotations on the IDynamicInterfaceCastable.GetInterfaceImplementation API.
141+
if (type.IsInterface && ((MetadataType)type).IsDynamicInterfaceCastableImplementation())
142+
{
143+
dependencies ??= new DependencyList();
144+
dependencies.Add(nodeFactory.ReflectedType(type), "Reflected IDynamicInterfaceCastableImplementation");
145+
}
146+
135147
TypeDesc typeDefinition = type.GetTypeDefinition();
136148
if (typeDefinition != type)
137149
{

src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Text;
66
using System.Collections.Generic;
7+
using System.Reflection;
78
using System.Runtime.CompilerServices;
89
using System.Runtime.InteropServices;
910
using System.Diagnostics.CodeAnalysis;
@@ -60,6 +61,7 @@ public static int Run()
6061
TestDefaultDynamicStaticNonGeneric.Run();
6162
TestDefaultDynamicStaticGeneric.Run();
6263
TestDynamicStaticGenericVirtualMethods.Run();
64+
TestRuntime109496Regression.Run();
6365

6466
return Pass;
6567
}
@@ -1890,4 +1892,57 @@ public static void Run()
18901892
Console.WriteLine(s_entry.Enter1<SimpleCallStruct<object>>("One"));
18911893
}
18921894
}
1895+
1896+
class TestRuntime109496Regression
1897+
{
1898+
class CastableThing : IDynamicInterfaceCastable
1899+
{
1900+
RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType)
1901+
=> Type.GetTypeFromHandle(interfaceType).GetCustomAttribute<TypeAttribute>().TheType.TypeHandle;
1902+
bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
1903+
=> Type.GetTypeFromHandle(interfaceType).IsDefined(typeof(TypeAttribute));
1904+
}
1905+
1906+
[Type(typeof(IMyInterfaceImpl))]
1907+
interface IMyInterface
1908+
{
1909+
int Method();
1910+
}
1911+
1912+
[DynamicInterfaceCastableImplementation]
1913+
interface IMyInterfaceImpl : IMyInterface
1914+
{
1915+
int IMyInterface.Method() => 42;
1916+
}
1917+
1918+
[Type(typeof(IMyGenericInterfaceImpl<int>))]
1919+
interface IMyGenericInterface
1920+
{
1921+
int Method();
1922+
}
1923+
1924+
[DynamicInterfaceCastableImplementation]
1925+
interface IMyGenericInterfaceImpl<T> : IMyGenericInterface
1926+
{
1927+
int IMyGenericInterface.Method() => typeof(T).Name.Length;
1928+
}
1929+
1930+
class TypeAttribute : Attribute
1931+
{
1932+
public Type TheType { get; }
1933+
1934+
public TypeAttribute(Type t) => TheType = t;
1935+
}
1936+
1937+
public static void Run()
1938+
{
1939+
object o = new CastableThing();
1940+
1941+
if (((IMyInterface)o).Method() != 42)
1942+
throw new Exception();
1943+
1944+
if (((IMyGenericInterface)o).Method() != 5)
1945+
throw new Exception();
1946+
}
1947+
}
18931948
}

0 commit comments

Comments
 (0)