-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Background and motivation
In .NET 8 we've added the Unsafe.BitCast API as a less-unsafe alternative to Unsafe.As when casting between compatible structs.
One justification was that this would let us avoid codegen pessimization for values marked as address-taken in some cases. Example from the original API proposal: #81334 (comment)
Due to the TFrom : struct constraint, we can't use this API in places like the span.IndexOf* helpers.
I propose we drop the generic constraint while keeping the runtime behavior the same.
With the constraint removed, I was able to confirm that we're able to flow the constness of values through for this case: MihaZupan@65c8054.
Quoting the conclusion from the initial API review:
... we should try having it constrained, and if we run into problems then get rid of them. They're easier to remove than add.
API Proposal
namespace System.Runtime.CompilerServices;
public static class Unsafe
{
public static TTo BitCast<TFrom, TTo>(TFrom value)
- where TFrom : struct
where TTo : struct;
}API Usage
public static unsafe int IndexOf<T>(this Span<T> span, T value)
where T : IEquatable<T>?
{
if (RuntimeHelpers.IsBitwiseEquatable<T>() && sizeof(T) == sizeof(short))
{
return IndexOfValueType(
ref Unsafe.As<T, short>(ref MemoryMarshal.GetReference(span)),
Unsafe.BitCast<T, short>(value0), // <--- This is now legal
span.Length);
}
// ...
}
private static unsafe int IndexOfValueType<T>(ref T searchSpace, T value, int length)
where T : struct, INumber<T> => 42;Alternative Designs
We could drop the constraint on TTo as well while we're at it?
Risks
Some erroneous usages move from being compile-time errors to run-time exceptions.
But this is an Unsafe API for a reason :)