Skip to content

Commit d9855f2

Browse files
Fix obtaining type handles of IDynamicInterfaceCastableImplementation (#109875)
Fixes #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 245897a commit d9855f2

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

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)