diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 3a04a9dee77c4158afb09badb96829ae46a5221e..0491ce5f3a1cc75e7a1d7d920ddb77404b85611a 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -4242,11 +4242,11 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo } if (m_class_get_byval_arg (klass)->type == MONO_TYPE_FNPTR) { - /* - * if both klass and oklass are fnptr, and they're equal, we would have returned at the - * beginning. - */ - /* Is this right? or do we need to look at signature compatibility? */ + if (mono_metadata_signature_equal (klass_byval_arg->data.method, oklass_byval_arg->data.method)) { + *result = TRUE; + return; + } + *result = FALSE; return; } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index bca051413a6a8d416505e92658c3c4376ab239d5..5ab899e032d0ebf518cf29bd0d479e433ae16343 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -4693,6 +4693,8 @@ is_monomorphic_array (MonoClass *klass) return FALSE; element_class = m_class_get_element_class (klass); + if (m_class_get_byval_arg (element_class)->type == MONO_TYPE_FNPTR) + return FALSE; return mono_class_is_sealed (element_class) || m_class_is_valuetype (element_class); } diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.cs b/src/tests/Loader/classloader/Casting/Functionpointer.cs new file mode 100644 index 0000000000000000000000000000000000000000..95d7bf33b1303c78cd3f0f312e4a6b08cdb2b1ff --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.cs @@ -0,0 +1,46 @@ +using System; +using System.Runtime.InteropServices; + +namespace TestFunctionPointer +{ + unsafe class TestThings + { + public static delegate* managed[][] Functions = { + new delegate* managed[] + { + &Function, + }, + }; + + public static int Function() => 100; + + public static delegate* unmanaged[][] Functions1 = { + new delegate* unmanaged[] + { + &Function1, + }, + }; + + [UnmanagedCallersOnly] + public static int Function1() => 100; + + public static delegate* managed[][] Functions2 = { + new delegate* managed[] + { + &Function2, + }, + }; + + public static int Function2(int a) { + return a; + } + } + + unsafe class Program + { + public static int Main() + { + return TestThings.Functions2[0][0](TestThings.Functions[0][0]()); + } + } +} \ No newline at end of file diff --git a/src/tests/Loader/classloader/Casting/Functionpointer.csproj b/src/tests/Loader/classloader/Casting/Functionpointer.csproj new file mode 100644 index 0000000000000000000000000000000000000000..51f7075c49c8158c321033d7a606f261932d9194 --- /dev/null +++ b/src/tests/Loader/classloader/Casting/Functionpointer.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + \ No newline at end of file