Skip to content
3 changes: 3 additions & 0 deletions src/coreclr/vm/dllimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3316,8 +3316,11 @@ BOOL NDirect::MarshalingRequired(
FALLTHROUGH;

case ELEMENT_TYPE_VALUETYPE:
case ELEMENT_TYPE_GENERICINST:
{
TypeHandle hndArgType = arg.GetTypeHandleThrowing(pModule, &emptyTypeContext);
if(!hndArgType.IsValueType())
return true;

if (hndArgType.GetMethodTable()->IsInt128OrHasInt128Fields())
{
Expand Down
24 changes: 24 additions & 0 deletions src/tests/Interop/UnmanagedCallersOnly/UnmanagedCallersOnlyTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public static int Main(string[] args)
NegativeTest_FromInstantiatedGenericClass();
TestUnmanagedCallersOnlyViaUnmanagedCalli();
TestPInvokeMarkedWithUnmanagedCallersOnly();
TestUnmanagedCallersOnlyWithGeneric();

// Exception handling is only supported on CoreCLR Windows.
if (TestLibrary.Utilities.IsWindows && !TestLibrary.Utilities.IsMonoRuntime)
Expand Down Expand Up @@ -217,4 +218,27 @@ public static void TestPInvokeMarkedWithUnmanagedCallersOnly()
int n = 1234;
Assert.Throws<NotSupportedException>(() => ((delegate* unmanaged<int, int>)&CallingUnmanagedCallersOnlyDirectly.PInvokeMarkedWithUnmanagedCallersOnly)(n));
}

public static void TestUnmanagedCallersOnlyWithGeneric()
{
Assert.Equal(0, ((delegate* unmanaged<Blittable<nint>, int>)&BlittableGenericStruct)(new Blittable<nint>()));

Assert.Equal(0, ((delegate* unmanaged<MaybeBlittable<nint>, int>)&MaybeBlittableGenericStruct)(new MaybeBlittable<nint>()));
}

internal struct Blittable<T> where T : unmanaged
{
T Value;
}

internal struct MaybeBlittable<T>
{
T Value;
}

[UnmanagedCallersOnly]
internal static int BlittableGenericStruct(Blittable<nint> param) => 0;

[UnmanagedCallersOnly]
internal static int MaybeBlittableGenericStruct(MaybeBlittable<nint> param) => 0;
}