Skip to content

Commit 63b613c

Browse files
Always create constructed MethodTable for MdArray & co. (#103696)
Arrays that don't implement generic interface methods can be loaded at runtime without any sort of type loader template (their template is the same thing that we just whack into the right shape and there's no associated code because everything is from `System.Array`). But this means we should never create unconstructed MethodTable for these because we could end up in a situation where a single type has two `MethodTable`s. The regression test demonstrates how that can happen (the `is` check only forces unconstructed form of the `MethodTable`). Ran into this while working on a different PR, but I don't want to clutter that one with this.
1 parent b00d30c commit 63b613c

File tree

2 files changed

+29
-0
lines changed
  • src

2 files changed

+29
-0
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -624,6 +624,19 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact
624624
if (_type.IsInterface)
625625
dependencies.Add(factory.InterfaceUse(_type.GetTypeDefinition()), "Interface is used");
626626

627+
// Array types that don't have generic interface methods can be created out of thin air
628+
// at runtime by the type loader. We should never emit non-constructed forms of these MethodTables.
629+
// There's similar logic for generic types, but that one is a conditional dependency conditioned
630+
// on the presence of the type loader template for the canonical form of the type.
631+
if (_type.IsArrayTypeWithoutGenericInterfaces())
632+
{
633+
IEETypeNode maximallyConstructableType = factory.MaximallyConstructableType(_type);
634+
if (maximallyConstructableType != this)
635+
{
636+
dependencies.Add(maximallyConstructableType, "Type is template-loadable");
637+
}
638+
}
639+
627640
if (EmitVirtualSlots)
628641
{
629642
if (!_type.IsArrayTypeWithoutGenericInterfaces())

src/tests/nativeaot/SmokeTests/Reflection/Reflection.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ private static int Main()
6666
TestGenericMethodOnGenericType.Run();
6767
TestIsValueTypeWithoutTypeHandle.Run();
6868
TestMdArrayLoad.Run();
69+
TestMdArrayLoad2.Run();
6970
TestByRefTypeLoad.Run();
7071
TestGenericLdtoken.Run();
7172
TestAbstractGenericLdtoken.Run();
@@ -2443,6 +2444,21 @@ public static void Run()
24432444
}
24442445
}
24452446

2447+
class TestMdArrayLoad2
2448+
{
2449+
class Atom { }
2450+
2451+
public static object MakeMdArray<T>() => new T[1,1,1];
2452+
2453+
public static void Run()
2454+
{
2455+
var mi = typeof(TestMdArrayLoad2).GetMethod(nameof(MakeMdArray)).MakeGenericMethod(GetAtom());
2456+
if (mi.Invoke(null, Array.Empty<object>()) is not Atom[,,])
2457+
throw new Exception();
2458+
static Type GetAtom() => typeof(Atom);
2459+
}
2460+
}
2461+
24462462
class TestByRefTypeLoad
24472463
{
24482464
class Atom { }

0 commit comments

Comments
 (0)