diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs index f2c31155d5f45..d1c85bb48ddfe 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs @@ -559,7 +559,7 @@ static List BuildVTable(NodeFactory factory, TypeDesc currentType, T if (currentType == null) return vtable; - BuildVTable(factory, currentType.BaseType?.ConvertToCanonForm(CanonicalFormKind.Specific), implType, vtable); + BuildVTable(factory, currentType.BaseType, implType, vtable); IReadOnlyList slice = factory.VTable(currentType).Slots; foreach (MethodDesc decl in slice) @@ -571,19 +571,19 @@ static List BuildVTable(NodeFactory factory, TypeDesc currentType, T return vtable; } - baseType = canonType.BaseType?.ConvertToCanonForm(CanonicalFormKind.Specific); - if (!canonType.IsArray && baseType != null) + baseType = type.BaseType; + if (!type.IsArray && baseType != null) { if (!vtables.TryGetValue(baseType, out List baseVtable)) vtables.Add(baseType, baseVtable = BuildVTable(factory, baseType, baseType, new List())); - if (!vtables.TryGetValue(canonType, out List vtable)) - vtables.Add(canonType, vtable = BuildVTable(factory, canonType, canonType, new List())); + if (!vtables.TryGetValue(type, out List vtable)) + vtables.Add(type, vtable = BuildVTable(factory, type, type, new List())); for (int i = 0; i < baseVtable.Count; i++) { if (baseVtable[i] != vtable[i]) - _overridenMethods.Add(baseVtable[i]); + _overridenMethods.Add(baseVtable[i].GetCanonMethodTarget(CanonicalFormKind.Specific)); } } } diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs index c69c013150941..a44cb6ffc0722 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Devirtualization.cs @@ -12,6 +12,7 @@ class Devirtualization internal static int Run() { RegressionBug73076.Run(); + RegressionGenericHierarchy.Run(); DevirtualizationCornerCaseTests.Run(); DevirtualizeIntoUnallocatedGenericType.Run(); @@ -53,6 +54,36 @@ public static void Run() } } + class RegressionGenericHierarchy + { + class Base + { + public virtual string Print() => "Base"; + } + + class Mid : Base + { + public override string Print() => "Mid"; + public override string ToString() => Print(); + } + + class Derived : Mid + { + public override string Print() => "Derived"; + } + + class Atom { } + + public static void Run() + { + if (Get().ToString() != "Derived") + throw new Exception(); + + [MethodImpl(MethodImplOptions.NoInlining)] + static object Get() => new Derived(); + } + } + class DevirtualizationCornerCaseTests { interface IIntf1