From: Thays Grazia Date: Wed, 30 Oct 2019 17:47:15 +0000 (-0300) Subject: [dim][regression] Explicit interface override (mono/mono#17583) X-Git-Tag: submit/tizen/20210909.063632~10331^2~5^2~264 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cf207e2c9cde4c1ec4ff5e3a10e94c91ce4c633a;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [dim][regression] Explicit interface override (mono/mono#17583) * Precedence order: -> Override interface method in class -> Method in class -> DIM Commit migrated from https://github.com/mono/mono/commit/fffb1201bdd14e18e19a3c61d0afe25a91a2d501 --- diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 0cebac9..1d13536 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -3100,7 +3100,6 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o // Loop on all interface methods... int mcount = mono_class_get_method_count (ic); for (im_index = 0; im_index < mcount; im_index++) { - gboolean foundOverrideInClassOrParent = FALSE; MonoMethod *im = ic->methods [im_index]; int im_slot = ic_offset + im->slot; MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL; @@ -3110,41 +3109,17 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1))); - int cm_index; - MonoMethod *cm; - - // First look for a suitable method among the class methods - for (l = virt_methods; l; l = l->next) { - cm = (MonoMethod *)l->data; - TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))); - if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) { - TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING")); - vtable [im_slot] = cm; - foundOverrideInClassOrParent = TRUE; - /* Why do we need this? */ - if (cm->slot < 0) { - cm->slot = im_slot; - } - if (conflict_map) - g_hash_table_remove(conflict_map, im); - } - TRACE_INTERFACE_VTABLE (printf ("\n")); - if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/ - goto fail; - } - - // If the slot is still empty, look in all the inherited virtual methods... - if ((vtable [im_slot] == NULL) && klass->parent != NULL) { - MonoClass *parent = klass->parent; - // Reverse order, so that last added methods are preferred - for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) { - cm = parent->vtable [cm_index]; - - TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name)); - if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) { - TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING")); + if (override_im == NULL || (override_im && MONO_CLASS_IS_INTERFACE_INTERNAL(override_im->klass))) { + int cm_index; + MonoMethod *cm; + + // First look for a suitable method among the class methods + for (l = virt_methods; l; l = l->next) { + cm = (MonoMethod *)l->data; + TRACE_INTERFACE_VTABLE (printf (" For slot %d ('%s'.'%s':'%s'), trying method '%s'.'%s':'%s'... [EXPLICIT IMPLEMENTATION = %d][SLOT IS NULL = %d]", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))); + if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) { + TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING")); vtable [im_slot] = cm; - foundOverrideInClassOrParent = TRUE; /* Why do we need this? */ if (cm->slot < 0) { cm->slot = im_slot; @@ -3157,17 +3132,39 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/ goto fail; } - } + + // If the slot is still empty, look in all the inherited virtual methods... + if ((vtable [im_slot] == NULL) && klass->parent != NULL) { + MonoClass *parent = klass->parent; + // Reverse order, so that last added methods are preferred + for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) { + MonoMethod *cm = parent->vtable [cm_index]; + + TRACE_INTERFACE_VTABLE ((cm != NULL) && printf (" For slot %d ('%s'.'%s':'%s'), trying (ancestor) method '%s'.'%s':'%s'... ", im_slot, ic->name_space, ic->name, im->name, cm->klass->name_space, cm->klass->name, cm->name)); + if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) { + TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING")); + vtable [im_slot] = cm; + /* Why do we need this? */ + if (cm->slot < 0) { + cm->slot = im_slot; + } + break; + } + if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/ + goto fail; + TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n")); + } + } - if (vtable [im_slot] == NULL) { - if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) { - TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1))); - vtable [im_slot] = im; + if (vtable [im_slot] == NULL) { + if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) { + TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1))); + vtable [im_slot] = im; + } } - } - - if (override_im != NULL && !foundOverrideInClassOrParent) + } else { g_assert (vtable [im_slot] == override_im); + } } } diff --git a/src/mono/mono/tests/Makefile.am b/src/mono/mono/tests/Makefile.am index 6330eff..45871d6 100755 --- a/src/mono/mono/tests/Makefile.am +++ b/src/mono/mono/tests/Makefile.am @@ -383,6 +383,7 @@ TESTS_CS_SRC= \ params.cs \ reflection.cs \ interface.cs \ + interface-2.cs \ iface.cs \ iface2.cs \ iface3.cs \ diff --git a/src/mono/mono/tests/interface-2.cs b/src/mono/mono/tests/interface-2.cs new file mode 100644 index 0000000..185d2a7 --- /dev/null +++ b/src/mono/mono/tests/interface-2.cs @@ -0,0 +1,97 @@ +using System; + +public interface I1 +{ + int M1() + { + return 100; + } +} + +public interface I2 : I1 { int I1.M1() { return 200; } } + +public interface I3 : I1 { int I1.M1() { return 300; } } + +public interface I4 : I1 { int I1.M1() { return 400; } } + +class Test10 : I1, I2, I3, I4 { + //void I1.M1() { System.Console.WriteLine("I1.I1.M1"); } + public int M1() { return 0; } +} + +public interface I1t +{ + int M1t() + { + return 100; + } +} + +public interface I2t : I1t { int I1t.M1t() { return 200; } } + +public interface I3t : I1t { int I1t.M1t() { return 300; } } + +public interface I4t : I1t { int I1t.M1t() { return 400; } } + +class Test10t : I1t, I2t, I3t, I4t +{ + int I1t.M1t() { return 0; } + public int M1t() { return 10; } +} + + +public interface IName +{ + string Name { get; } +} +public interface IOther +{ + T other { get; } + string Name { get; } +} +public class Name1 : IName +{ + public string Name { get { return "ClassName"; } } + string IName.Name { get { return "InterfaceName"; } } +} +public class Name2 : IName, IOther +{ + public string Name { get { return "ClassName"; } } + string IName.Name { get { return "InterfaceName"; } } + public int other { get { return 43; } } +} + +public class Test +{ + public static int test_0_override() + { + var name1 = new Name1(); + var name2 = new Name2(); + IName iName1 = name1; + IName iName2 = name2; + if (!iName1.Name.Equals("InterfaceName")) + return 10; + if (!iName2.Name.Equals("InterfaceName")) + return 20; + if (!name1.Name.Equals("ClassName")) + return 30; + if (!name2.Name.Equals("ClassName")) + return 40; + return 0; + } + + public static int test_0_dim_override() + { + I1 var = new Test10(); + if (var.M1() != 0) + return var.M1(); + + I1t var2 = new Test10t(); + return var2.M1t(); + } + + public static int Main (string[] args) { + return TestDriver.RunTests (typeof (Test), args); + } + +}