Background and motivation
Wrapper structs with a single field are popular in many codebases, for SIMD, generics and interop purposes. A common issue with them is that such wrapper types either cause less optimal calling conventions in the 1st case, have issues around wrapping managed types in 2nd, or are not guaranteed to match ABI wise for 3rd.
As such, I'd like to propose exposing support for user defineable value types that guarantee to match the ABI properties of the type they wrap.
This would be enforced both in managed and native calls and would potentially also impact how the JIT treats them for promotion and such.
The runtime would throw TypeLoadException if such type contains more than 1 field.
This was previously discussed in #100896 and was left for future discussion AFAIU.
This is already internally implemented in a limited capacity for CLong`CULong\NFloat`, with public API those could be switched to it from special handling.
For prior art on this, Rust provides this with #[repr(transparent)].
cc @tannergooding @jkoritzinsky @jkotas as you were all involved in previous discussions on this.
API Proposal
namespace System.Runtime.InteropServices;
public enum ExtendedLayoutKind
{
+ Transparent
}
API Usage
// non interop
[ExtendedLayout(ExtendedLayoutKind.Transparent)]
public readonly struct CustomVector
{
public readonly Vector128<float> Vector;
}
public static void Method(CustomVector v)
{
// passed via SIMD reg, not stack like normal struct.
}
[ExtendedLayout(ExtendedLayoutKind.Transparent)]
public readonly struct EquatableWrapper<T> : IEquatable<EquatableWrapper<T>>
{
public readonly T Value;
public EquatableWrapper(T value) => Value = value;
public bool Equals(EquatableWrapper<T> other) => EqualityComparer<T>.Default.Equals(Value, other.Value);
// rest of IEquatable
}
// layouts guaranteed to match
Unsafe.BitCast<ReadOnlySpan<object>, ReadOnlySpan<EquatableWrapper<object>>>(a).Contains(new EquatableWrapper<object>(o))
// interop
[ExtendedLayout(ExtendedLayoutKind.Transparent)]
public readonly struct Handle
{
public readonly void* Value;
}
// guaranteed to be safe
[DllImport("Kernel32")]
public static extern int CloseHandle(Handle handle);
Alternative Designs
For interop purposes this can be solved with custom LibraryImport marshallers but that doesn't help with blittable PInvokes, function pointers and non interop uses.
Risks
No response
Background and motivation
Wrapper structs with a single field are popular in many codebases, for SIMD, generics and interop purposes. A common issue with them is that such wrapper types either cause less optimal calling conventions in the 1st case, have issues around wrapping managed types in 2nd, or are not guaranteed to match ABI wise for 3rd.
As such, I'd like to propose exposing support for user defineable value types that guarantee to match the ABI properties of the type they wrap.
This would be enforced both in managed and native calls and would potentially also impact how the JIT treats them for promotion and such.
The runtime would throw
TypeLoadExceptionif such type contains more than 1 field.This was previously discussed in #100896 and was left for future discussion AFAIU.
This is already internally implemented in a limited capacity for
CLong`CULong\NFloat`, with public API those could be switched to it from special handling.For prior art on this, Rust provides this with
#[repr(transparent)].cc @tannergooding @jkoritzinsky @jkotas as you were all involved in previous discussions on this.
API Proposal
namespace System.Runtime.InteropServices; public enum ExtendedLayoutKind { + Transparent }API Usage
Alternative Designs
For interop purposes this can be solved with custom LibraryImport marshallers but that doesn't help with blittable PInvokes, function pointers and non interop uses.
Risks
No response