Skip to content

Commit 66173b4

Browse files
[release/7.0] [mono] Assert that we don't need to inflate types when applying DIM overrides (#74519)
* do we need to inflate here? it seems like we always get the right class * use member access, not type punning * Add regression test for #70190 * Assert code from #64102 is unreachable In #64102 (comment) we concluded that this branch is never taken. * Assert that overrides are already inflated how we expect * try to enable some disabled DIM tests * remove unused var * Don't assert - code is reachable, there's just nothing to do * Add link to issue for failing tests Co-authored-by: Aleksey Kliger <alklig@microsoft.com> Co-authored-by: Aleksey Kliger <aleksey@lambdageek.org>
1 parent 1a5c7ee commit 66173b4

File tree

3 files changed

+61
-28
lines changed

3 files changed

+61
-28
lines changed

src/mono/mono/metadata/class-setup-vtable.c

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,8 @@ mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
932932
context = mono_class_get_context (klass);
933933
type_token = mono_class_get_generic_class (klass)->container_class->type_token;
934934
} else {
935-
context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
935+
MonoGenericContainer *container = mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
936+
context = container ? &container->context : NULL;
936937
type_token = klass->type_token;
937938
}
938939

@@ -1010,30 +1011,14 @@ apply_override (MonoClass *klass, MonoClass *override_class, MonoMethod **vtable
10101011
MonoMethod *prev_override = (MonoMethod*)g_hash_table_lookup (map, decl);
10111012
MonoClass *prev_override_class = (MonoClass*)g_hash_table_lookup (class_map, decl);
10121013

1014+
g_assert (override_class == override->klass);
1015+
10131016
g_hash_table_insert (map, decl, override);
10141017
g_hash_table_insert (class_map, decl, override_class);
10151018

10161019
/* Collect potentially conflicting overrides which are introduced by default interface methods */
10171020
if (prev_override) {
1018-
ERROR_DECL (error);
1019-
1020-
/*
1021-
* The override methods are part of the generic definition, need to inflate them so their
1022-
* parent class becomes the actual interface/class containing the override, i.e.
1023-
* IFace<T> in:
1024-
* class Foo<T> : IFace<T>
1025-
* This is needed so the mono_class_is_assignable_from_internal () calls in the
1026-
* conflict resolution work.
1027-
*/
1028-
if (mono_class_is_ginst (override_class)) {
1029-
override = mono_class_inflate_generic_method_checked (override, &mono_class_get_generic_class (override_class)->context, error);
1030-
mono_error_assert_ok (error);
1031-
}
1032-
1033-
if (mono_class_is_ginst (prev_override_class)) {
1034-
prev_override = mono_class_inflate_generic_method_checked (prev_override, &mono_class_get_generic_class (prev_override_class)->context, error);
1035-
mono_error_assert_ok (error);
1036-
}
1021+
g_assert (prev_override->klass == prev_override_class);
10371022

10381023
if (!*conflict_map)
10391024
*conflict_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
@@ -1771,10 +1756,9 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
17711756
MonoMethod *override = iface_overrides [i*2 + 1];
17721757
if (mono_class_is_gtd (override->klass)) {
17731758
override = mono_class_inflate_generic_method_full_checked (override, ic, mono_class_get_context (ic), error);
1774-
} else if (decl->is_inflated) {
1775-
override = mono_class_inflate_generic_method_checked (override, mono_method_get_context (decl), error);
1776-
mono_error_assert_ok (error);
1777-
}
1759+
}
1760+
// there used to be code here to inflate decl if decl->is_inflated, but in https://github.com/dotnet/runtime/pull/64102#discussion_r790019545 we
1761+
// think that this does not correspond to any real code.
17781762
if (!apply_override (klass, ic, vtable, decl, override, &override_map, &override_class_map, &conflict_map))
17791763
goto fail;
17801764
}
@@ -1786,6 +1770,18 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
17861770
MonoMethod *decl = overrides [i*2];
17871771
MonoMethod *override = overrides [i*2 + 1];
17881772
if (MONO_CLASS_IS_INTERFACE_INTERNAL (decl->klass)) {
1773+
/*
1774+
* We expect override methods that are part of a generic definition, to have
1775+
* their parent class be the actual interface/class containing the override,
1776+
* i.e.
1777+
*
1778+
* IFace<T> in:
1779+
* class Foo<T> : IFace<T>
1780+
*
1781+
* This is needed so the mono_class_is_assignable_from_internal () calls in the
1782+
* conflict resolution work.
1783+
*/
1784+
g_assert (override->klass == klass);
17891785
if (!apply_override (klass, klass, vtable, decl, override, &override_map, &override_class_map, &conflict_map))
17901786
goto fail;
17911787
}

src/tests/Loader/classloader/DefaultInterfaceMethods/regressions/github61244.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,19 @@
1414
// derived interface contexts, but the order is changed (or different.)
1515
// When this occurs the generic info is incorrect for the inflated method.
1616

17+
// TestClass2 tests a regression due to the fix for the previous
18+
// regression that caused Mono to incorrectly instantiate generic
19+
// interfaces that appeared in the MethodImpl table
20+
1721
class Program
1822
{
1923
static int Main(string[] args)
2024
{
21-
return new TestClass().DoTest();
25+
int result = new TestClass().DoTest();
26+
if (result != 100)
27+
return result;
28+
result = new TestClass2().DoTest();
29+
return result;
2230
}
2331
}
2432

@@ -78,4 +86,33 @@ public int DoTest ()
7886
Console.WriteLine("Passed => 100");
7987
return 100;
8088
}
81-
}
89+
}
90+
91+
public interface IA
92+
{
93+
public int Foo();
94+
}
95+
96+
public interface IB<T> : IA
97+
{
98+
int IA.Foo() { return 104; }
99+
}
100+
101+
public interface IC<H1, H2> : IB<H2>
102+
{
103+
int IA.Foo() { return 105; }
104+
}
105+
106+
public class C<U, V, W> : IC<V, W>
107+
{
108+
int IA.Foo() { return 100; }
109+
}
110+
111+
public class TestClass2
112+
{
113+
public int DoTest()
114+
{
115+
IA c = new C<byte, short, int>();
116+
return c.Foo();
117+
}
118+
}

src/tests/issues.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2019,10 +2019,10 @@
20192019
<Issue>These tests are not supposed to be run with mono.</Issue>
20202020
</ExcludeList>
20212021
<ExcludeList Include="$(XunitTestBinBase)/reflection/DefaultInterfaceMethods/Emit/**">
2022-
<Issue>needs triage</Issue>
2022+
<Issue>https://github.com/dotnet/runtime/issues/36113</Issue>
20232023
</ExcludeList>
20242024
<ExcludeList Include="$(XunitTestBinBase)/reflection/DefaultInterfaceMethods/InvokeConsumer/**">
2025-
<Issue>needs triage</Issue>
2025+
<Issue>https://github.com/dotnet/runtime/issues/36113</Issue>
20262026
</ExcludeList>
20272027
<ExcludeList Include="$(XunitTestBinBase)/reflection/Modifiers/modifiers/**">
20282028
<Issue>needs triage</Issue>

0 commit comments

Comments
 (0)