diff --git a/src/mono/mono/metadata/class-setup-vtable.c b/src/mono/mono/metadata/class-setup-vtable.c index a0b7128ce0705d..a7452c6a9f5b3f 100644 --- a/src/mono/mono/metadata/class-setup-vtable.c +++ b/src/mono/mono/metadata/class-setup-vtable.c @@ -1742,11 +1742,11 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o for (int i = 0; i < iface_onum; i++) { MonoMethod *decl = iface_overrides [i*2]; MonoMethod *override = iface_overrides [i*2 + 1]; - if (decl->is_inflated) { + if (mono_class_is_gtd (override->klass)) { + override = mono_class_inflate_generic_method_full_checked (override, ic, mono_class_get_context (ic), error); + } else if (decl->is_inflated) { override = mono_class_inflate_generic_method_checked (override, mono_method_get_context (decl), error); mono_error_assert_ok (error); - } else if (mono_class_is_gtd (override->klass)) { - override = mono_class_inflate_generic_method_full_checked (override, ic, mono_class_get_context (ic), error); } if (!apply_override (klass, ic, vtable, decl, override, &override_map, &override_class_map, &conflict_map)) goto fail; diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.cs b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.cs new file mode 100644 index 00000000000000..ae08369177388d --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.cs @@ -0,0 +1,81 @@ +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +// In GH issue 61244 the mono runtime aborted when inflating the default +// interface method because the context used was from the base interface. + +// The OneArgBaseInterface portion of this test handles the original bug +// where the base interface has less generic arguments than the derived +// interface and the runtime aborts. + +// The SecondInterface portion of this test handles an additional scenario +// where the number of generic arguments are the same in the base and +// derived interface contexts, but the order is changed (or different.) +// When this occurs the generic info is incorrect for the inflated method. + +class Program +{ + static int Main(string[] args) + { + return new TestClass().DoTest(); + } +} + +public interface OneArgBaseInterface +{ + int SomeFunc1(T1 someParam1, Type someParam1Type); +} + +public interface TwoArgBaseInterface +{ + int SomeFunc1(T1 someParam1, T2 someParam2, Type someParam1Type, Type someParam2Type); +} + +public interface SecondInterface : OneArgBaseInterface, TwoArgBaseInterface +{ + int OneArgBaseInterface.SomeFunc1(TParam1Type someParam1, Type someParam1Type) + { + if (typeof(TParam1Type) != someParam1Type) + { + Console.WriteLine("Failed => 101"); + return 101; + } + + return 100; + } + + int TwoArgBaseInterface.SomeFunc1(TParam1Type someParam1, TParam2Type someParam2, Type someParam1Type, Type someParam2Type) + { + if (typeof(TParam1Type) != someParam1Type) + { + Console.WriteLine("Failed => 102"); + return 102; + } + + if (typeof(TParam2Type) != someParam2Type) + { + Console.WriteLine("Failed => 103"); + return 103; + } + + return 100; + } +} + +public class TestClass : SecondInterface +{ + public int DoTest () + { + int ret = (this as OneArgBaseInterface).SomeFunc1("test string", typeof(string)); + if (ret != 100) + return ret; + + ret = (this as TwoArgBaseInterface).SomeFunc1("test string", 0, typeof(string), typeof(int)); + if (ret != 100) + return ret; + + Console.WriteLine("Passed => 100"); + return 100; + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.csproj b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.csproj new file mode 100644 index 00000000000000..42c7a9e8ffc90f --- /dev/null +++ b/src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.csproj @@ -0,0 +1,9 @@ + + + true + Exe + + + + +