Skip to content

Commit ea4c511

Browse files
authored
Merge pull request #1462 from Unity-Technologies/default-interface-methods-upstream-update-21-7
pick upstream mono path for GetInterfaceMap
2 parents 598af7a + 49be953 commit ea4c511

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

mono/metadata/class-inlines.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,29 @@ m_class_is_private (MonoClass *klass)
200200
return (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NOT_PUBLIC;
201201
}
202202

203+
static inline gboolean
204+
m_method_is_static (MonoMethod *method)
205+
{
206+
return (method->flags & METHOD_ATTRIBUTE_STATIC) != 0;
207+
}
208+
static inline gboolean
209+
m_method_is_virtual (MonoMethod *method)
210+
{
211+
return (method->flags & METHOD_ATTRIBUTE_VIRTUAL) != 0;
212+
}
213+
214+
static inline gboolean
215+
m_method_is_abstract (MonoMethod *method)
216+
{
217+
return (method->flags & METHOD_ATTRIBUTE_ABSTRACT) != 0;
218+
}
219+
220+
static inline gboolean
221+
m_method_is_final (MonoMethod *method)
222+
{
223+
return (method->flags & METHOD_ATTRIBUTE_FINAL) != 0;
224+
}
225+
203226
static inline gboolean
204227
m_method_is_icall (MonoMethod *method)
205228
{

mono/metadata/icall.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2973,6 +2973,23 @@ ves_icall_RuntimeType_GetInterfaces (MonoReflectionTypeHandle ref_type, MonoErro
29732973
return NULL_HANDLE_ARRAY;
29742974
}
29752975

2976+
static gboolean
2977+
method_is_reabstracted (MonoMethod *method)
2978+
{
2979+
/* only on interfaces */
2980+
/* method is marked "final abstract" */
2981+
/* FIXME: we need some other way to detect reabstracted methods. "final" is an incidental detail of the spec. */
2982+
return m_method_is_final (method) && m_method_is_abstract (method);
2983+
}
2984+
2985+
static gboolean
2986+
method_is_dim (MonoMethod *method)
2987+
{
2988+
/* only valid on interface methods*/
2989+
/* method is marked "virtual" but not "virtual abstract" */
2990+
return m_method_is_virtual (method) && !m_method_is_abstract (method);
2991+
}
2992+
29762993
static gboolean
29772994
set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, MonoClass *iclass, int ioffset, MonoClass *klass, MonoArrayHandle targets, MonoArrayHandle methods, int i, MonoError *error)
29782995
{
@@ -3006,9 +3023,25 @@ set_interface_map_data_method_object (MonoDomain *domain, MonoMethod *method, Mo
30063023
}
30073024
}
30083025

3009-
if (foundMethod->flags & METHOD_ATTRIBUTE_ABSTRACT)
3026+
/*
3027+
* if the iterface method is reabstracted, and either the found implementation method is abstract, or the found
3028+
* implementation method is from another DIM (meaning neither klass nor any of its ancestor classes implemented
3029+
* the method), then say the target method is null.
3030+
*/
3031+
if (method_is_reabstracted (method) &&
3032+
(m_method_is_abstract (foundMethod) ||
3033+
(mono_class_is_interface (foundMethod->klass) && method_is_dim (foundMethod))))
30103034
MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
3011-
else {
3035+
else if (mono_class_is_interface (foundMethod->klass) && method_is_reabstracted (foundMethod) && !m_class_is_abstract (klass)) {
3036+
/* if the method we found is a reabstracted DIM method, but the class isn't abstract, return NULL */
3037+
/*
3038+
* (C# doesn't seem to allow constructing such types, it requires the whole class to be abstract - in
3039+
* which case we are supposed to return the reabstracted interface method. But in IL we can make a
3040+
* non-abstract class with reabstracted interface methods - which is supposed to fail with an
3041+
* EntryPointNotFoundException at invoke time, but does not prevent the class from loading.)
3042+
*/
3043+
MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE);
3044+
} else {
30123045
MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (domain, foundMethod, mono_class_is_interface (foundMethod->klass) ? foundMethod->klass : klass, error));
30133046
goto_if_nok (error, leave);
30143047
MONO_HANDLE_ARRAY_SETREF (targets, i, member);

0 commit comments

Comments
 (0)