Skip to content

Commit

Permalink
[mono][metadata] Fix overriding of methods from parent variant interf…
Browse files Browse the repository at this point in the history
…aces

As an example from the now enabled test.

```
interface InterfaceScenario2<in T> {
	static abstract int Method ();
}

class BaseScenario2 : InterfaceScenario2<string, InterfaceScenario2<object> {
	public static int Method() {
//		.override method int32 class InterfaceScenario2`1<string>::Method()
		return 2;
	}

	public static int32 Method_Obj() {
//		.override method int32 class InterfaceScenario2`1<object>::Method()
		return 3;
	}
}

class DerivedScenario2 : BaseScenario2 {
	public static int Method () {
//		.override method int32 class InterfaceScenario2`1<object>::Method()
		return 6;
	}
}

public static string Test_Scenario2_1<T, ImplType>() where ImplType : InterfaceScenario2<T> {
	return ImplType.Method ().ToString ();
}

Test_Scenario2_1<string, DerivedScenario2> ());
```

This test calls InterfaceScenario2<string> on DerviedScenario2. This should call DerivedScenario2.Method (not BaseScenario2.Method) because this method overrides (in BaseScenario2) both the obvious slot for InterfaceScenario2<object> as well as the slot for variant compatible interface InterfaceScenario2<string>.
  • Loading branch information
BrzVlad committed Sep 8, 2023
1 parent fac95fb commit 25bd253
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
32 changes: 32 additions & 0 deletions src/mono/mono/metadata/class-setup-vtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,37 @@ apply_override (MonoClass *klass, MonoClass *override_class, MonoMethod **vtable
return TRUE;
}

/*
* Interface method `decl` is overridden in `klass` with `override`. In addition to overriding the method slot
* for this interface method, if parent klass implements a different variant compatible interface, then we also
* need to override the correpsonding method slot in this other interface.
*/
static void
apply_override_variant_interface (MonoClass *klass, MonoMethod *decl, MonoMethod *override, MonoMethod **vtable)
{
MonoClass *parent = klass->parent;

// This handles variant overrides for static virtual methods only
if (!m_method_is_static (decl))
return;

if (mono_class_has_variant_generic_params (decl->klass) && parent) {
for (int k = 0; k < klass->parent->interface_offsets_count; k++) {
MonoClass *impl_itf = parent->interfaces_packed [k];
if (decl->klass != impl_itf &&
mono_class_has_variant_generic_params (impl_itf) &&
mono_class_get_generic_type_definition (impl_itf) == mono_class_get_generic_type_definition (decl->klass)) {
if (mono_class_is_variant_compatible (impl_itf, decl->klass, FALSE)) {
int vt_slot = parent->interface_offsets_packed [k] + decl->slot;
vtable [vt_slot] = override;
TRACE_INTERFACE_VTABLE (printf ("\tvariance override slot %d with method %s\n", vt_slot, mono_method_full_name (override, TRUE)));
break;
}
}
}
}
}

static void
handle_dim_conflicts (MonoMethod **vtable, MonoClass *klass, GHashTable *conflict_map)
{
Expand Down Expand Up @@ -1788,6 +1819,7 @@ mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int o
g_assert (override->klass == klass);
if (!apply_override (klass, klass, vtable, decl, override, &override_map, &override_class_map, &conflict_map))
goto fail;
apply_override_variant_interface (klass, decl, override, vtable);
}
}

Expand Down
3 changes: 0 additions & 3 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -1294,9 +1294,6 @@
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/StaticVirtualMethods/DiamondShape/**">
<Issue>https://github.com/dotnet/runtime/issues/80350</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/StaticVirtualMethods/InterfaceVariance/**">
<Issue>Static virtual methods are not yet implemented in the Mono runtime.</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Loader/classloader/StaticVirtualMethods/NegativeTestCases/**">
<Issue>Static virtual methods are not yet implemented in the Mono runtime.</Issue>
</ExcludeList>
Expand Down

0 comments on commit 25bd253

Please sign in to comment.