Don't block specific generic types in field marshalling scenarios.
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
- // * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios
+ // * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for interop scenarios
+ // We can't block these types for field scenarios for back-compat reasons.
- if (type.HasInstantiation && (!isBlittable
+ if (type.HasInstantiation && !isField && (!isBlittable
|| InteropTypes.IsSystemByReference(context, type)
+ || InteropTypes.IsSystemSpan(context, type)
+ || InteropTypes.IsSystemReadOnlySpan(context, type)
|| InteropTypes.IsSystemNullable(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector64T(context, type)
|| InteropTypes.IsSystemRuntimeIntrinsicsVector128T(context, type)
return IsCoreNamedType(context, type, "System", "ByReference`1");
}
+ public static bool IsSystemSpan(TypeSystemContext context, TypeDesc type)
+ {
+ return IsCoreNamedType(context, type, "System", "Span`1");
+ }
+
+ public static bool IsSystemReadOnlySpan(TypeSystemContext context, TypeDesc type)
+ {
+ return IsCoreNamedType(context, type, "System", "ReadOnlySpan`1");
+ }
+
public static bool IsSystemNullable(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Nullable`1");
// * Vector64<T>: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128<T>: Represents the __m128 ABI primitive which requires currently unimplemented handling
// * Vector256<T>: Represents the __m256 ABI primitive which requires currently unimplemented handling
- // * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for inteorp scenarios
-
- if (m_pMT->HasInstantiation() && (!m_pMT->IsBlittable()
- || m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
- || m_pMT->HasSameTypeDefAs(g_pNullableClass)
- || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
- || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
- || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
+ // * Vector<T>: Has a variable size (either __m128 or __m256) and isn't readily usable for interop scenarios
+ // We can't block these types for field scenarios for back-compat reasons.
+ if (m_pMT->HasInstantiation() && !IsFieldScenario()
+ && (!m_pMT->IsBlittable()
+ || (m_pMT->HasSameTypeDefAs(g_pNullableClass)
+ || m_pMT->HasSameTypeDefAs(g_pByReferenceClass)
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__SPAN))
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__READONLY_SPAN))
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR64T))
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR128T))
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTOR256T))
#ifndef CROSSGEN_COMPILE
- // Crossgen scenarios block Vector<T> from even being loaded
- || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
+ // Crossgen scenarios block Vector<T> from even being loaded
+ || m_pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__VECTORT))
#endif // !CROSSGEN_COMPILE
- ))
+ )))
{
m_resID = IDS_EE_BADMARSHAL_GENERICS_RESTRICTION;
IfFailGoto(E_FAIL, lFail);
AssertExtensions.Throws<ArgumentNullException>("structure", () => Marshal.SizeOf<string>(null));
}
+ [Fact]
+ public void SizeOf_Struct_With_GenericValueTypeField_ReturnsExpected()
+ {
+ Assert.Equal(8, Marshal.SizeOf<TestStructWithGenericStructField>());
+ Assert.Equal(8, Marshal.SizeOf<TestStructWithNullable>());
+ Assert.Equal(8, Marshal.SizeOf<TestStructWithVector64>());
+ }
+
public static IEnumerable<object[]> SizeOf_InvalidType_TestData()
{
yield return new object[] { typeof(int).MakeByRefType(), null };
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.LPStr, SizeConst = 0)]
public string[] Arr;
}
+
+ public struct GenericStruct<T>
+ {
+ public T t;
+ public bool b;
+ }
+
+ public struct TestStructWithGenericStructField
+ {
+ public GenericStruct<int> i;
+ }
+
+ public struct TestStructWithNullable
+ {
+ public int? i;
+ }
+
+ public struct TestStructWithVector64
+ {
+ public System.Runtime.Intrinsics.Vector64<double> v;
+ }
}
}