Skip to content

Commit e13eb14

Browse files
[release/9.0-staging] Fix obtaining type handles of IDynamicInterfaceCastableImplementation (#109909)
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 8abd404 commit e13eb14

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
@@ -130,6 +130,18 @@ public static void GetMetadataDependencies(ref DependencyList dependencies, Node
130130
default:
131131
Debug.Assert(type.IsDefType);
132132

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

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
}
@@ -1780,4 +1782,57 @@ public static void Run()
17801782
Console.WriteLine(s_entry.Enter1<SimpleCallStruct<object>>("One"));
17811783
}
17821784
}
1785+
1786+
class TestRuntime109496Regression
1787+
{
1788+
class CastableThing : IDynamicInterfaceCastable
1789+
{
1790+
RuntimeTypeHandle IDynamicInterfaceCastable.GetInterfaceImplementation(RuntimeTypeHandle interfaceType)
1791+
=> Type.GetTypeFromHandle(interfaceType).GetCustomAttribute<TypeAttribute>().TheType.TypeHandle;
1792+
bool IDynamicInterfaceCastable.IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented)
1793+
=> Type.GetTypeFromHandle(interfaceType).IsDefined(typeof(TypeAttribute));
1794+
}
1795+
1796+
[Type(typeof(IMyInterfaceImpl))]
1797+
interface IMyInterface
1798+
{
1799+
int Method();
1800+
}
1801+
1802+
[DynamicInterfaceCastableImplementation]
1803+
interface IMyInterfaceImpl : IMyInterface
1804+
{
1805+
int IMyInterface.Method() => 42;
1806+
}
1807+
1808+
[Type(typeof(IMyGenericInterfaceImpl<int>))]
1809+
interface IMyGenericInterface
1810+
{
1811+
int Method();
1812+
}
1813+
1814+
[DynamicInterfaceCastableImplementation]
1815+
interface IMyGenericInterfaceImpl<T> : IMyGenericInterface
1816+
{
1817+
int IMyGenericInterface.Method() => typeof(T).Name.Length;
1818+
}
1819+
1820+
class TypeAttribute : Attribute
1821+
{
1822+
public Type TheType { get; }
1823+
1824+
public TypeAttribute(Type t) => TheType = t;
1825+
}
1826+
1827+
public static void Run()
1828+
{
1829+
object o = new CastableThing();
1830+
1831+
if (((IMyInterface)o).Method() != 42)
1832+
throw new Exception();
1833+
1834+
if (((IMyGenericInterface)o).Method() != 5)
1835+
throw new Exception();
1836+
}
1837+
}
17831838
}

0 commit comments

Comments
 (0)