-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[API Proposal]: update API signatures to leverage ref readonly parameters #85911
Comments
This isn't actionable at present. |
Yup, same as #85910, needs Roslyn changes first (I mentioned this in the introduction paragraph as well). I just had the list already from working on the language proposal, so figured I'd open this for tracking and to have a central place where we could start adding any APIs that'd need changes, so when the Roslyn changes go online we have the list ready for API review 🙂 |
I don't think we should use |
AFAIR, there was a fairly decent discussion in API review when That being said, going from Going from |
Tagging subscribers to this area: @dotnet/area-system-runtime-compilerservices Issue DetailsBackground and motivation
This issue tracks updating the signatures of all methods that can benefit from either the new API Proposalnamespace System
{
public static class Nullable
{
- public static ref readonly T GetValueRefOrDefaultRef<T>(in T? nullable) where T : struct;
+ public static ref readonly T GetValueRefOrDefaultRef<T>(ref readonly T? nullable) where T : struct;
}
public readonly ref struct ReadOnlySpan<T>
{
- public ReadOnlySpan(in T reference);
+ public ReadOnlySpan(ref readonly T reference);
}
}
namespace System.Runtime.CompilerServices
{
public static class Unsafe
{
- public static bool AreSame<T>(ref T left, ref T right);
+ public static bool AreSame<T>(ref readonly T left, ref readonly T right);
- public static ref T AsRef<T>(in T source);
+ public static ref T AsRef<T>(ref readonly T source);
- public static nint ByteOffset<T>(ref T origin, ref T target);
+ public static nint ByteOffset<T>(ref readonly T origin, ref readonly T target);
- public static void Copy<T>(void* destination, ref T source);
+ public static void Copy<T>(void* destination, ref readonly T source);
- public static void CopyBlock(ref byte destination, ref byte source, uint byteCount);
+ public static void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount);
- public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount);
+ public static void CopyBlockUnaligned(ref byte destination, ref readonly byte source, uint byteCount);
- public static bool IsAddressGreaterThan<T>(ref T left, ref T right);
+ public static bool IsAddressGreaterThan<T>(ref readonly T left, ref readonly T right);
- public static bool IsAddressLessThan<T>(ref T left, ref T right);
+ public static bool IsAddressLessThan<T>(ref readonly T left, ref readonly T right);
- public static bool IsNullRef<T>(ref T source);
+ public static bool IsNullRef<T>(ref readonly T source);
- public static T ReadUnaligned<T>(ref byte source);
+ public static T ReadUnaligned<T>(ref readonly byte source);
}
}
namespace namespace System.Runtime.InteropServices
{
public static class Marshal
{
- public static int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv);
+ public static int QueryInterface(IntPtr pUnk, in Guid iid, out IntPtr ppv);
}
public static class MemoryMarshal
{
- public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref T reference, int length);
+ public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref readonly T reference, int length);
- public static unsafe void Write<T>(Span<byte> destination, ref T value) where T : struct;
+ public static unsafe void Write<T>(Span<byte> destination, in T value) where T : struct;
- public static unsafe bool TryWrite<T>(Span<byte> destination, ref T value) where T : struct;
+ public static unsafe bool TryWrite<T>(Span<byte> destination, in T value) where T : struct;
}
}
namespace System.Threading
{
public static class Volatile
{
- public static bool Read(ref bool location);
+ public static bool Read(ref readonly bool location);
- public static byte Read(ref byte location);
+ public static byte Read(ref readonly byte location);
- public static double Read(ref double location);
+ public static double Read(ref readonly double location);
- public static short Read(ref short location);
+ public static short Read(ref readonly short location);
- public static int Read(ref int location);
+ public static int Read(ref readonly int location);
- public static long Read(ref long location);
+ public static long Read(ref readonly long location);
- public static IntPtr Read(ref IntPtr location);
+ public static IntPtr Read(ref readonly IntPtr location);
- public static sbyte Read(ref sbyte location);
+ public static sbyte Read(ref readonly sbyte location);
- public static float Read(ref float location);
+ public static float Read(ref readonly float location);
- public static ushort Read(ref ushort location);
+ public static ushort Read(ref readonly ushort location);
- public static uint Read(ref uint location);
+ public static uint Read(ref readonly uint location);
- public static ulong Read(ref ulong location);
+ public static ulong Read(ref readonly ulong location);
- public static UIntPtr Read(ref UIntPtr location);
+ public static UIntPtr Read(ref readonly UIntPtr location);
- public static T Read<T>(ref T location) where T : class?;
+ public static T Read<T>(ref readonly T location) where T : class?;
}
public static class Interlocked
{
- public static ulong Read(ref ulong location);
+ public static ulong Read(ref readonly ulong location);
- public static long Read(ref long location);
+ public static long Read(ref readonly long location);
}
}
namespace System.Numerics
{
public static class Vector
{
- public static Vector<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
}
namespace System.Runtime.Intrinsics
{
public static class Vector64
{
- public static Vector64<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector64<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector64<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector64<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector128
{
- public static Vector128<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector128<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector128<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector128<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector256
{
- public static Vector256<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector256<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector256<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector256<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector512
{
- public static Vector512<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector512<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector512<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector512<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
} API UsageFor instance, easy QI with immediate values: IntPtr pUnknown = GetPtr();
Marshal.ThrowExceptionForHR(Marshal.QueryInterface(pUnknown, new Guid("3718BE5F-F5A1-40CF-AF09-C4ECFD858A47"), out IntPtr pObject)); Or, writing immediates into spans: Span<byte> bytes = GetSpan();
MemoryMarshal.Write(bytes, 128UL); Or, loading vectors from readonly spans directly: ReadOnlySpan<int> span = GetSpan();
Vector128<int> vector = Vector128.LoadUnsafe(in span[0]); There's of course lots more examples (see API changes above).
|
It shouldn't be source breaking, given that |
It's source breaking because
|
@tannergooding It's a warning in the current spec. It's like this to allow it to be changed without any issues (other than a warning on likely unintended use). Doesn't necessarily mean we should use it for ROS's ctor, but it doesn't cause any issues other than a new warning, so it should be about whether we want it to take rvalues or not without a warning (I personally would think no, but that's up to API review). |
Marking as ready for review given the general syntax questions on the language side seem to have been resolved. As with the corresponding attribute (#85910), keeping in future until the language feature gets closer to completion. We can push update the milestone and push forward as/when needed. |
namespace System
{
public static class Nullable
{
- public static ref readonly T GetValueRefOrDefaultRef<T>(in T? nullable) where T : struct;
+ public static ref readonly T GetValueRefOrDefaultRef<T>(ref readonly T? nullable) where T : struct;
}
public readonly ref struct ReadOnlySpan<T>
{
- public ReadOnlySpan(in T reference);
+ public ReadOnlySpan(ref readonly T reference);
}
}
namespace System.Runtime.CompilerServices
{
public static class Unsafe
{
- public static bool AreSame<T>(ref T left, ref T right);
+ public static bool AreSame<T>(ref readonly T left, ref readonly T right);
- public static ref T AsRef<T>(in T source);
+ public static ref T AsRef<T>(ref readonly T source);
- public static nint ByteOffset<T>(ref T origin, ref T target);
+ public static nint ByteOffset<T>(ref readonly T origin, ref readonly T target);
- public static void Copy<T>(void* destination, ref T source);
+ public static void Copy<T>(void* destination, ref readonly T source);
- public static void CopyBlock(ref byte destination, ref byte source, uint byteCount);
+ public static void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount);
- public static void CopyBlockUnaligned(ref byte destination, ref byte source, uint byteCount);
+ public static void CopyBlockUnaligned(ref byte destination, ref readonly byte source, uint byteCount);
- public static bool IsAddressGreaterThan<T>(ref T left, ref T right);
+ public static bool IsAddressGreaterThan<T>(ref readonly T left, ref readonly T right);
- public static bool IsAddressLessThan<T>(ref T left, ref T right);
+ public static bool IsAddressLessThan<T>(ref readonly T left, ref readonly T right);
- public static bool IsNullRef<T>(ref T source);
+ public static bool IsNullRef<T>(ref readonly T source);
- public static T ReadUnaligned<T>(ref byte source);
+ public static T ReadUnaligned<T>(ref readonly byte source);
}
}
namespace namespace System.Runtime.InteropServices
{
public static class Marshal
{
- public static int QueryInterface(IntPtr pUnk, ref Guid iid, out IntPtr ppv);
+ public static int QueryInterface(IntPtr pUnk, in Guid iid, out IntPtr ppv);
}
public static class MemoryMarshal
{
- public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref T reference, int length);
+ public static ReadOnlySpan<T> CreateReadOnlySpan<T>(scoped ref readonly T reference, int length);
- public static unsafe void Write<T>(Span<byte> destination, ref T value) where T : struct;
+ public static unsafe void Write<T>(Span<byte> destination, in T value) where T : struct;
- public static unsafe bool TryWrite<T>(Span<byte> destination, ref T value) where T : struct;
+ public static unsafe bool TryWrite<T>(Span<byte> destination, in T value) where T : struct;
}
}
namespace System.Threading
{
public static class Volatile
{
- public static bool Read(ref bool location);
+ public static bool Read(ref readonly bool location);
- public static byte Read(ref byte location);
+ public static byte Read(ref readonly byte location);
- public static double Read(ref double location);
+ public static double Read(ref readonly double location);
- public static short Read(ref short location);
+ public static short Read(ref readonly short location);
- public static int Read(ref int location);
+ public static int Read(ref readonly int location);
- public static long Read(ref long location);
+ public static long Read(ref readonly long location);
- public static IntPtr Read(ref IntPtr location);
+ public static IntPtr Read(ref readonly IntPtr location);
- public static sbyte Read(ref sbyte location);
+ public static sbyte Read(ref readonly sbyte location);
- public static float Read(ref float location);
+ public static float Read(ref readonly float location);
- public static ushort Read(ref ushort location);
+ public static ushort Read(ref readonly ushort location);
- public static uint Read(ref uint location);
+ public static uint Read(ref readonly uint location);
- public static ulong Read(ref ulong location);
+ public static ulong Read(ref readonly ulong location);
- public static UIntPtr Read(ref UIntPtr location);
+ public static UIntPtr Read(ref readonly UIntPtr location);
- public static T Read<T>(ref T location) where T : class?;
+ public static T Read<T>(ref readonly T location) where T : class?;
}
public static class Interlocked
{
- public static ulong Read(ref ulong location);
+ public static ulong Read(ref readonly ulong location);
- public static long Read(ref long location);
+ public static long Read(ref readonly long location);
}
}
namespace System.Numerics
{
public static class Vector
{
- public static Vector<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
}
namespace System.Runtime.Intrinsics
{
public static class Vector64
{
- public static Vector64<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector64<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector64<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector64<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector128
{
- public static Vector128<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector128<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector128<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector128<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector256
{
- public static Vector256<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector256<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector256<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector256<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
public static class Vector512
{
- public static Vector512<T> LoadUnsafe<T>(ref T source) where T : struct;
+ public static Vector512<T> LoadUnsafe<T>(ref readonly T source) where T : struct;
- public static Vector512<T> LoadUnsafe<T>(ref T source, nuint elementOffset) where T : struct;
+ public static Vector512<T> LoadUnsafe<T>(ref readonly T source, nuint elementOffset) where T : struct;
}
} |
Background and motivation
This issue tracks updating the signatures of all methods that can benefit from either the new
ref readonly
parameters (see dotnet/csharplang#6010), as well as the additional flexibility from the compiler allowing changes in ref-ness for method parameters without it being a breaking change (also see speclet at dotnet/csharplang#7165). Needs Roslyn changes first.API Proposal
API Usage
For instance, easy QI with immediate values:
Or, writing immediates into spans:
Or, loading vectors from readonly spans directly:
There's of course lots more examples (see API changes above).
The text was updated successfully, but these errors were encountered: