Skip to content

Commit bd370fc

Browse files
committed
Fixing the GetInterfaceMap tests for mono in the runtime repo.
Addressing 4 issues for GetInterfaceMap and default interface methods Only methods marked as virtual on on interface should be added to the interface map. (no static or instance) If the found target method is ambiguous (a diamond) the target is null. If the found target method's class in an interface, then the target class is the interface class, else it is the class of the RuntimeType (aka this) If the found target method is abstract (reabstraction) then the target is null. https://github.com/dotnet/runtime/blob/6072e4d/src/tests/reflection/DefaultInterfaceMethods/GetInterfaceMapConsumer.cs
1 parent 1e4274e commit bd370fc

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

mono/metadata/icall.c

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2983,10 +2983,36 @@ set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, Mo
29832983

29842984
MONO_HANDLE_ARRAY_SETREF (methods, i, member);
29852985

2986-
MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, m_class_get_vtable (klass) [i + ioffset], klass, error));
2987-
goto_if_nok (error, leave);
2986+
MonoMethod* foundMethod = m_class_get_vtable (klass) [i + ioffset];
2987+
2988+
if (mono_class_has_dim_conflicts (klass) && mono_class_is_interface (foundMethod->klass)) {
2989+
GSList* conflicts = mono_class_get_dim_conflicts (klass);
2990+
GSList* l;
2991+
MonoMethod* decl = method;
29882992

2989-
MONO_HANDLE_ARRAY_SETREF (targets, i, member);
2993+
if (decl->is_inflated)
2994+
decl = ((MonoMethodInflated*)decl)->declaring;
2995+
2996+
gboolean in_conflict = FALSE;
2997+
for (l = conflicts; l; l = l->next) {
2998+
if (decl == l->data) {
2999+
in_conflict = TRUE;
3000+
break;
3001+
}
3002+
}
3003+
if (in_conflict) {
3004+
MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
3005+
goto leave;
3006+
}
3007+
}
3008+
3009+
if (foundMethod->flags & METHOD_ATTRIBUTE_ABSTRACT)
3010+
MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
3011+
else {
3012+
MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, foundMethod, mono_class_is_interface (foundMethod->klass) ? foundMethod->klass : klass, error));
3013+
goto_if_nok (error, leave);
3014+
MONO_HANDLE_ARRAY_SETREF (targets, i, member);
3015+
}
29903016

29913017
leave:
29923018
HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
@@ -3012,20 +3038,30 @@ ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionTypeHandle ref_type, Mo
30123038
if (ioffset == -1)
30133039
return;
30143040

3015-
int len = mono_class_num_methods (iclass);
3041+
MonoMethod* method;
3042+
int i = 0;
3043+
gpointer iter = NULL;
30163044
MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_type);
3017-
MonoArrayHandle targets_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
3045+
3046+
while ((method = mono_class_get_methods(iclass, &iter))) {
3047+
if (method->flags & METHOD_ATTRIBUTE_VIRTUAL)
3048+
i++;
3049+
}
3050+
3051+
MonoArrayHandle targets_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, i, error);
30183052
return_if_nok (error);
30193053
MONO_HANDLE_ASSIGN (targets, targets_arr);
30203054

3021-
MonoArrayHandle methods_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, len, error);
3055+
MonoArrayHandle methods_arr = mono_array_new_handle (domain, mono_defaults.method_info_class, i, error);
30223056
return_if_nok (error);
30233057
MONO_HANDLE_ASSIGN (methods, methods_arr);
30243058

3025-
MonoMethod* method;
3026-
int i = 0;
3027-
gpointer iter = NULL;
3059+
i = 0;
3060+
iter = NULL;
3061+
30283062
while ((method = mono_class_get_methods (iclass, &iter))) {
3063+
if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL))
3064+
continue;
30293065
if (!set_interface_map_data_method_object (domain, method, iclass, ioffset, klass, targets, methods, i, error))
30303066
return;
30313067
i ++;

0 commit comments

Comments
 (0)