diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 43ddbfecf006fa..edbaabbf7de363 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -224,6 +224,7 @@ public static object GetUninitializedObject( /// true if given type is reference type or value type that contains references [Intrinsic] public static bool IsReferenceOrContainsReferences() + // where T : allows ref struct // TODO https://github.com/dotnet/runtime/issues/102847 { // The body of this function will be replaced by the EE with unsafe code!!! // See getILIntrinsicImplementationForRuntimeHelpers for how this happens. diff --git a/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs b/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs index 6c2b09321b7f96..84c5c0212de2b2 100644 --- a/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs +++ b/src/libraries/System.Collections.Concurrent/ref/System.Collections.Concurrent.cs @@ -101,13 +101,13 @@ public ConcurrentDictionary(int concurrencyLevel, int capacity, System.Collectio public System.Collections.Generic.ICollection Values { get { throw null; } } public TValue AddOrUpdate(TKey key, System.Func addValueFactory, System.Func updateValueFactory) { throw null; } public TValue AddOrUpdate(TKey key, TValue addValue, System.Func updateValueFactory) { throw null; } - public TValue AddOrUpdate(TKey key, System.Func addValueFactory, System.Func updateValueFactory, TArg factoryArgument) { throw null; } + public TValue AddOrUpdate(TKey key, System.Func addValueFactory, System.Func updateValueFactory, TArg factoryArgument) where TArg : allows ref struct { throw null; } public void Clear() { } public bool ContainsKey(TKey key) { throw null; } public System.Collections.Generic.IEnumerator> GetEnumerator() { throw null; } public TValue GetOrAdd(TKey key, System.Func valueFactory) { throw null; } public TValue GetOrAdd(TKey key, TValue value) { throw null; } - public TValue GetOrAdd(TKey key, System.Func valueFactory, TArg factoryArgument) { throw null; } + public TValue GetOrAdd(TKey key, System.Func valueFactory, TArg factoryArgument) where TArg : allows ref struct { throw null; } void System.Collections.Generic.ICollection>.Add(System.Collections.Generic.KeyValuePair keyValuePair) { } bool System.Collections.Generic.ICollection>.Contains(System.Collections.Generic.KeyValuePair keyValuePair) { throw null; } void System.Collections.Generic.ICollection>.CopyTo(System.Collections.Generic.KeyValuePair[] array, int index) { } diff --git a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs index e6ae682a9c8536..bf48ef7f5a18ce 100644 --- a/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs +++ b/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs @@ -1201,6 +1201,7 @@ public TValue GetOrAdd(TKey key, Func valueFactory) /// key is already in the dictionary, or the new value for the key as returned by valueFactory /// if the key was not in the dictionary. public TValue GetOrAdd(TKey key, Func valueFactory, TArg factoryArgument) + where TArg : allows ref struct { if (key is null) { @@ -1279,6 +1280,7 @@ public TValue GetOrAdd(TKey key, TValue value) /// absent) or the result of updateValueFactory (if the key was present). public TValue AddOrUpdate( TKey key, Func addValueFactory, Func updateValueFactory, TArg factoryArgument) + where TArg : allows ref struct { if (key is null) { diff --git a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs index bf180cfb33dbc0..8e452d7e1d1e3f 100644 --- a/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs +++ b/src/libraries/System.Collections.Immutable/ref/System.Collections.Immutable.cs @@ -200,8 +200,16 @@ public static partial class ImmutableArray public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Generic.IEnumerable items) { throw null; } public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, System.Func selector) { throw null; } public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, int start, int length, System.Func selector) { throw null; } - public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, System.Func selector, TArg arg) { throw null; } - public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, int start, int length, System.Func selector, TArg arg) { throw null; } + public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, System.Func selector, TArg arg) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif + { throw null; } + public static System.Collections.Immutable.ImmutableArray CreateRange(System.Collections.Immutable.ImmutableArray items, int start, int length, System.Func selector, TArg arg) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif + { throw null; } public static System.Collections.Immutable.ImmutableArray Create() { throw null; } public static System.Collections.Immutable.ImmutableArray Create(System.Collections.Immutable.ImmutableArray items, int start, int length) { throw null; } public static System.Collections.Immutable.ImmutableArray Create(T item) { throw null; } @@ -672,7 +680,11 @@ public static partial class ImmutableInterlocked public static void Enqueue(ref System.Collections.Immutable.ImmutableQueue location, T value) { } public static TValue GetOrAdd(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, System.Func valueFactory) where TKey : notnull { throw null; } public static TValue GetOrAdd(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, TValue value) where TKey : notnull { throw null; } - public static TValue GetOrAdd(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, System.Func valueFactory, TArg factoryArgument) where TKey : notnull { throw null; } + public static TValue GetOrAdd(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, System.Func valueFactory, TArg factoryArgument) where TKey : notnull +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif + { throw null; } public static System.Collections.Immutable.ImmutableArray InterlockedCompareExchange(ref System.Collections.Immutable.ImmutableArray location, System.Collections.Immutable.ImmutableArray value, System.Collections.Immutable.ImmutableArray comparand) { throw null; } public static System.Collections.Immutable.ImmutableArray InterlockedExchange(ref System.Collections.Immutable.ImmutableArray location, System.Collections.Immutable.ImmutableArray value) { throw null; } public static bool InterlockedInitialize(ref System.Collections.Immutable.ImmutableArray location, System.Collections.Immutable.ImmutableArray value) { throw null; } @@ -683,9 +695,17 @@ public static void Push(ref System.Collections.Immutable.ImmutableStack lo public static bool TryRemove(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value) where TKey : notnull { throw null; } public static bool TryUpdate(ref System.Collections.Immutable.ImmutableDictionary location, TKey key, TValue newValue, TValue comparisonValue) where TKey : notnull { throw null; } public static bool Update(ref T location, System.Func transformer) where T : class? { throw null; } - public static bool Update(ref T location, System.Func transformer, TArg transformerArgument) where T : class? { throw null; } + public static bool Update(ref T location, System.Func transformer, TArg transformerArgument) where T : class? +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif + { throw null; } public static bool Update(ref System.Collections.Immutable.ImmutableArray location, Func, System.Collections.Immutable.ImmutableArray> transformer) { throw null; } - public static bool Update(ref System.Collections.Immutable.ImmutableArray location, Func, TArg, System.Collections.Immutable.ImmutableArray> transformer, TArg transformerArgument) { throw null; } + public static bool Update(ref System.Collections.Immutable.ImmutableArray location, Func, TArg, System.Collections.Immutable.ImmutableArray> transformer, TArg transformerArgument) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif + { throw null; } } public static partial class ImmutableList { diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs index 8f244bc8305bd5..15de249335b8f3 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableArray.cs @@ -337,6 +337,9 @@ public static ImmutableArray CreateRange(ImmutableArr /// the source array. /// public static ImmutableArray CreateRange(ImmutableArray items, Func selector, TArg arg) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif { Requires.NotNull(selector, nameof(selector)); @@ -370,6 +373,9 @@ public static ImmutableArray CreateRange(Immuta /// included in the resulting array. /// public static ImmutableArray CreateRange(ImmutableArray items, int start, int length, Func selector, TArg arg) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif { int itemsLength = items.Length; diff --git a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableInterlocked.cs b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableInterlocked.cs index 397ae8338b9b57..573d2764266f35 100644 --- a/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableInterlocked.cs +++ b/src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableInterlocked.cs @@ -76,6 +76,9 @@ public static bool Update(ref T location, Func transformer) where T : c /// invocation of returned the existing value. /// public static bool Update(ref T location, Func transformer, TArg transformerArgument) where T : class? +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif { Requires.NotNull(transformer, nameof(transformer)); @@ -162,6 +165,9 @@ public static bool Update(ref ImmutableArray location, Func returned the existing value. /// public static bool Update(ref ImmutableArray location, Func, TArg, ImmutableArray> transformer, TArg transformerArgument) +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif { Requires.NotNull(transformer, nameof(transformer)); @@ -241,7 +247,11 @@ public static bool InterlockedInitialize(ref ImmutableArray location, Immu /// The function to execute to obtain the value to insert into the dictionary if the key is not found. /// The argument to pass to the value factory. /// The value obtained from the dictionary or if it was not present. - public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) where TKey : notnull + public static TValue GetOrAdd(ref ImmutableDictionary location, TKey key, Func valueFactory, TArg factoryArgument) + where TKey : notnull +#if NET9_0_OR_GREATER + where TArg : allows ref struct +#endif { Requires.NotNull(valueFactory, nameof(valueFactory)); diff --git a/src/libraries/System.Linq/src/System/Linq/Sum.cs b/src/libraries/System.Linq/src/System/Linq/Sum.cs index 7eb2dc855dc67b..481997b8f82633 100644 --- a/src/libraries/System.Linq/src/System/Linq/Sum.cs +++ b/src/libraries/System.Linq/src/System/Linq/Sum.cs @@ -60,11 +60,11 @@ private static TResult Sum(ReadOnlySpan span) if (typeof(T) == typeof(long)) { - return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast(span)); + return (TResult)(object)SumSignedIntegersVectorized(Unsafe.BitCast, ReadOnlySpan>(span)); } if (typeof(T) == typeof(int)) { - return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast(span)); + return (TResult)(object)SumSignedIntegersVectorized(Unsafe.BitCast, ReadOnlySpan>(span)); } } diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Helpers.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Helpers.cs index 1ddabb93dd0ea4..5e4e89b61742d0 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Helpers.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/TensorPrimitives.Helpers.cs @@ -36,7 +36,11 @@ private static void ValidateInputOutputSpanNonOverlapping(ReadOnlySpan inp private static unsafe Span Rename(Span span) { Debug.Assert(sizeof(TFrom) == sizeof(TTo)); +#if NET9_0_OR_GREATER + return Unsafe.BitCast, Span>(span); +#else return *(Span*)(&span); +#endif } /// Creates a span of from a when they're the same type. @@ -48,7 +52,11 @@ private static unsafe Span Rename(Span span) private static unsafe ReadOnlySpan Rename(ReadOnlySpan span) { Debug.Assert(sizeof(TFrom) == sizeof(TTo)); +#if NET9_0_OR_GREATER + return Unsafe.BitCast, ReadOnlySpan>(span); +#else return *(ReadOnlySpan*)(&span); +#endif } /// Mask used to handle alignment elements before vectorized handling of the input. diff --git a/src/libraries/System.Private.CoreLib/src/System/Action.cs b/src/libraries/System.Private.CoreLib/src/System/Action.cs index dacc4fa7cc5b7b..9c78bed630e036 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Action.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Action.cs @@ -6,37 +6,196 @@ namespace System { public delegate void Action(); - public delegate void Action(T obj); - public delegate void Action(T1 arg1, T2 arg2); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + + public delegate void Action(T obj) + where T : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2) + where T1 : allows ref struct + where T2 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where T16 : allows ref struct; // This should probably technically be T? rather than T to match `IComparer`. However, the use cases are generally different, // with Comparison typically being used via a lambda, with the T inferred from the type of the collection being sorted, // and forcing nullable warnings onto all such usage leads to many spurious warnings. - public delegate int Comparison(T x, T y); + public delegate int Comparison(T x, T y) + where T : allows ref struct; - public delegate TOutput Converter(TInput input); + public delegate TOutput Converter(TInput input) + where TInput : allows ref struct + where TOutput : allows ref struct; - public delegate bool Predicate(T obj); + public delegate bool Predicate(T obj) + where T : allows ref struct; } namespace System.Buffers { - public delegate void SpanAction(Span span, TArg arg); - public delegate void ReadOnlySpanAction(ReadOnlySpan span, TArg arg); + public delegate void SpanAction(Span span, TArg arg) + where TArg : allows ref struct; + + public delegate void ReadOnlySpanAction(ReadOnlySpan span, TArg arg) + where TArg : allows ref struct; internal delegate TResult SpanFunc(Span span, T1 arg1, T2 arg2, T3 arg3); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerable.cs index 097c31d12679da..bf7dcf51416c06 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerable.cs @@ -8,6 +8,9 @@ namespace System.Collections.Generic /// Exposes an enumerator that provides asynchronous iteration over values of a specified type. /// The type of values to enumerate. public interface IAsyncEnumerable +#if NET9_0_OR_GREATER + where T : allows ref struct +#endif { /// Returns an enumerator that iterates asynchronously through the collection. /// A that may be used to cancel the asynchronous iteration. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerator.cs index fc1a9d5e1d93b2..f5249067de14ca 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IAsyncEnumerator.cs @@ -8,6 +8,9 @@ namespace System.Collections.Generic /// Supports a simple asynchronous iteration over a generic collection. /// The type of objects to enumerate. public interface IAsyncEnumerator : IAsyncDisposable +#if NET9_0_OR_GREATER + where T : allows ref struct +#endif { /// Advances the enumerator asynchronously to the next element of the collection. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs index 096f0d9dfff401..1cdfaeb34a0f85 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs @@ -9,6 +9,7 @@ namespace System.Collections.Generic { // Implement this interface if you need to support foreach semantics. public interface IEnumerable : IEnumerable + where T : allows ref struct { // Returns an IEnumerator for this enumerable Object. The enumerator provides // a simple way to access all the contents of a collection. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerator.cs index 45693471642276..8d32647af98a5e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerator.cs @@ -6,6 +6,7 @@ namespace System.Collections.Generic // Base interface for all generic enumerators, providing a simple approach // to iterating over a collection. public interface IEnumerator : IDisposable, IEnumerator + where T : allows ref struct { // Returns the current element of the enumeration. The returned value is // undefined before the first call to MoveNext and following a @@ -16,5 +17,10 @@ public interface IEnumerator : IDisposable, IEnumerator { get; } + + // NOTE: An implementation of an enumerator using a ref struct T will + // not be able to implement IEnumerator.Current to return that T (as + // doing so would require boxing). It should throw a NotSupportedException + // from that property implementation. } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Function.cs b/src/libraries/System.Private.CoreLib/src/System/Function.cs index 519d1cd82e4b06..a8554896437dfb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Function.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Function.cs @@ -3,21 +3,190 @@ namespace System { - public delegate TResult Func(); - public delegate TResult Func(T arg); - public delegate TResult Func(T1 arg1, T2 arg2); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); + public delegate TResult Func() + where TResult : allows ref struct; + + public delegate TResult Func(T arg) + where T : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2) + where T1 : allows ref struct + where T2 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where T16 : allows ref struct + where TResult : allows ref struct; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index db12f89bf2dd18..5192820e1a4d5b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -763,12 +763,12 @@ private static void AppendString(ref ValueListBuilder result, scop { if (typeof(TChar) == typeof(char)) { - result.Append(MemoryMarshal.Cast(s)); + result.Append(Unsafe.BitCast, ReadOnlySpan>(s)); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - Encoding.UTF8.GetBytes(s, MemoryMarshal.Cast(result.AppendSpan(Encoding.UTF8.GetByteCount(s)))); + Encoding.UTF8.GetBytes(s, Unsafe.BitCast, Span>(result.AppendSpan(Encoding.UTF8.GetByteCount(s)))); } } @@ -777,8 +777,8 @@ internal static void FormatFraction(ref ValueListBuilder result, i Span chars = stackalloc TChar[11]; int charCount; bool formatted = typeof(TChar) == typeof(char) ? - fraction.TryFormat(MemoryMarshal.Cast(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) : - fraction.TryFormat(MemoryMarshal.Cast(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture); + fraction.TryFormat(Unsafe.BitCast, Span>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) : + fraction.TryFormat(Unsafe.BitCast, Span>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture); Debug.Assert(charCount != 0); result.Append(chars.Slice(0, charCount)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs index e87960b61792d4..f2b99e5a81b3b5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs @@ -358,8 +358,8 @@ internal ReadOnlySpan AMDesignatorTChar() where TChar : unmanaged, { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(AMDesignator) : - MemoryMarshal.Cast(amDesignatorUtf8 ??= Encoding.UTF8.GetBytes(AMDesignator)); + Unsafe.BitCast, ReadOnlySpan>(AMDesignator) : + Unsafe.BitCast, ReadOnlySpan>(amDesignatorUtf8 ??= Encoding.UTF8.GetBytes(AMDesignator)); } public Calendar Calendar @@ -607,8 +607,8 @@ internal ReadOnlySpan DateSeparatorTChar() where TChar : unmanaged { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(DateSeparator) : - MemoryMarshal.Cast(dateSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DateSeparator)); + Unsafe.BitCast, ReadOnlySpan>(DateSeparator) : + Unsafe.BitCast, ReadOnlySpan>(dateSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DateSeparator)); } public DayOfWeek FirstDayOfWeek @@ -810,8 +810,8 @@ internal ReadOnlySpan PMDesignatorTChar() where TChar : unmanaged, { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(PMDesignator) : - MemoryMarshal.Cast(pmDesignatorUtf8 ??= Encoding.UTF8.GetBytes(PMDesignator)); + Unsafe.BitCast, ReadOnlySpan>(PMDesignator) : + Unsafe.BitCast, ReadOnlySpan>(pmDesignatorUtf8 ??= Encoding.UTF8.GetBytes(PMDesignator)); } public string RFC1123Pattern => rfc1123Pattern; @@ -992,8 +992,8 @@ internal ReadOnlySpan TimeSeparatorTChar() where TChar : unmanaged { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(TimeSeparator) : - MemoryMarshal.Cast(timeSeparatorUtf8 ??= Encoding.UTF8.GetBytes(TimeSeparator)); + Unsafe.BitCast, ReadOnlySpan>(TimeSeparator) : + Unsafe.BitCast, ReadOnlySpan>(timeSeparatorUtf8 ??= Encoding.UTF8.GetBytes(TimeSeparator)); } public string UniversalSortableDateTimePattern => universalSortableDateTimePattern; @@ -1731,8 +1731,8 @@ internal ReadOnlySpan DecimalSeparatorTChar() where TChar : unmana { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(DecimalSeparator) : - MemoryMarshal.Cast(_decimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DecimalSeparator)); + Unsafe.BitCast, ReadOnlySpan>(DecimalSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_decimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DecimalSeparator)); } // Positive TimeSpan Pattern diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs index 0424b678e4b182..60882f7aaaa0ee 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -269,8 +269,8 @@ internal ReadOnlySpan CurrencyDecimalSeparatorTChar() where TChar { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_currencyDecimalSeparator) : - MemoryMarshal.Cast(_currencyDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyDecimalSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_currencyDecimalSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_currencyDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyDecimalSeparator)); } public bool IsReadOnly => _isReadOnly; @@ -361,8 +361,8 @@ internal ReadOnlySpan CurrencyGroupSeparatorTChar() where TChar : { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_currencyGroupSeparator) : - MemoryMarshal.Cast(_currencyGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyGroupSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_currencyGroupSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_currencyGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyGroupSeparator)); } public string CurrencySymbol @@ -383,8 +383,8 @@ internal ReadOnlySpan CurrencySymbolTChar() where TChar : unmanage { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_currencySymbol) : - MemoryMarshal.Cast(_currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol)); + Unsafe.BitCast, ReadOnlySpan>(_currencySymbol) : + Unsafe.BitCast, ReadOnlySpan>(_currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol)); } internal byte[]? CurrencySymbolUtf8 => _currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol); @@ -429,8 +429,8 @@ internal ReadOnlySpan NaNSymbolTChar() where TChar : unmanaged, IU { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_nanSymbol) : - MemoryMarshal.Cast(_nanSymbolUtf8 ??= Encoding.UTF8.GetBytes(_nanSymbol)); + Unsafe.BitCast, ReadOnlySpan>(_nanSymbol) : + Unsafe.BitCast, ReadOnlySpan>(_nanSymbolUtf8 ??= Encoding.UTF8.GetBytes(_nanSymbol)); } public int CurrencyNegativePattern @@ -514,8 +514,8 @@ internal ReadOnlySpan NegativeInfinitySymbolTChar() where TChar : { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_negativeInfinitySymbol) : - MemoryMarshal.Cast(_negativeInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_negativeInfinitySymbol)); + Unsafe.BitCast, ReadOnlySpan>(_negativeInfinitySymbol) : + Unsafe.BitCast, ReadOnlySpan>(_negativeInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_negativeInfinitySymbol)); } public string NegativeSign @@ -537,8 +537,8 @@ internal ReadOnlySpan NegativeSignTChar() where TChar : unmanaged, { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_negativeSign) : - MemoryMarshal.Cast(_negativeSignUtf8 ??= Encoding.UTF8.GetBytes(_negativeSign)); + Unsafe.BitCast, ReadOnlySpan>(_negativeSign) : + Unsafe.BitCast, ReadOnlySpan>(_negativeSignUtf8 ??= Encoding.UTF8.GetBytes(_negativeSign)); } public int NumberDecimalDigits @@ -573,8 +573,8 @@ internal ReadOnlySpan NumberDecimalSeparatorTChar() where TChar : { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_numberDecimalSeparator) : - MemoryMarshal.Cast(_numberDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberDecimalSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_numberDecimalSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_numberDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberDecimalSeparator)); } public string NumberGroupSeparator @@ -594,8 +594,8 @@ internal ReadOnlySpan NumberGroupSeparatorTChar() where TChar : un { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_numberGroupSeparator) : - MemoryMarshal.Cast(_numberGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberGroupSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_numberGroupSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_numberGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberGroupSeparator)); } public int CurrencyPositivePattern @@ -631,8 +631,8 @@ internal ReadOnlySpan PositiveInfinitySymbolTChar() where TChar : { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_positiveInfinitySymbol) : - MemoryMarshal.Cast(_positiveInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_positiveInfinitySymbol)); + Unsafe.BitCast, ReadOnlySpan>(_positiveInfinitySymbol) : + Unsafe.BitCast, ReadOnlySpan>(_positiveInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_positiveInfinitySymbol)); } public string PositiveSign @@ -654,8 +654,8 @@ internal ReadOnlySpan PositiveSignTChar() where TChar : unmanaged, { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_positiveSign) : - MemoryMarshal.Cast(_positiveSignUtf8 ??= Encoding.UTF8.GetBytes(_positiveSign)); + Unsafe.BitCast, ReadOnlySpan>(_positiveSign) : + Unsafe.BitCast, ReadOnlySpan>(_positiveSignUtf8 ??= Encoding.UTF8.GetBytes(_positiveSign)); } public int PercentDecimalDigits @@ -690,8 +690,8 @@ internal ReadOnlySpan PercentDecimalSeparatorTChar() where TChar : { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_percentDecimalSeparator) : - MemoryMarshal.Cast(_percentDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentDecimalSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_percentDecimalSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_percentDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentDecimalSeparator)); } public string PercentGroupSeparator @@ -711,8 +711,8 @@ internal ReadOnlySpan PercentGroupSeparatorTChar() where TChar : u { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_percentGroupSeparator) : - MemoryMarshal.Cast(_percentGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentGroupSeparator)); + Unsafe.BitCast, ReadOnlySpan>(_percentGroupSeparator) : + Unsafe.BitCast, ReadOnlySpan>(_percentGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentGroupSeparator)); } public string PercentSymbol @@ -732,8 +732,8 @@ internal ReadOnlySpan PercentSymbolTChar() where TChar : unmanaged { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_percentSymbol) : - MemoryMarshal.Cast(_percentSymbolUtf8 ??= Encoding.UTF8.GetBytes(_percentSymbol)); + Unsafe.BitCast, ReadOnlySpan>(_percentSymbol) : + Unsafe.BitCast, ReadOnlySpan>(_percentSymbolUtf8 ??= Encoding.UTF8.GetBytes(_percentSymbol)); } public string PerMilleSymbol @@ -754,8 +754,8 @@ internal ReadOnlySpan PerMilleSymbolTChar() where TChar : unmanage { Debug.Assert(typeof(TChar) == typeof(char) || typeof(TChar) == typeof(byte)); return typeof(TChar) == typeof(char) ? - MemoryMarshal.Cast(_perMilleSymbol) : - MemoryMarshal.Cast(_perMilleSymbolUtf8 ??= Encoding.UTF8.GetBytes(_perMilleSymbol)); + Unsafe.BitCast, ReadOnlySpan>(_perMilleSymbol) : + Unsafe.BitCast, ReadOnlySpan>(_perMilleSymbolUtf8 ??= Encoding.UTF8.GetBytes(_perMilleSymbol)); } public string[] NativeDigits diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs index 2a89bf96385294..031641204e5b00 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -853,7 +853,7 @@ private static bool TryCopyTo(string source, Span destination, out if (typeof(TChar) == typeof(char)) { - if (source.TryCopyTo(MemoryMarshal.Cast(destination))) + if (source.TryCopyTo(Unsafe.BitCast, Span>(destination))) { charsWritten = source.Length; return true; @@ -864,7 +864,7 @@ private static bool TryCopyTo(string source, Span destination, out } else { - return Encoding.UTF8.TryGetBytes(source, MemoryMarshal.Cast(destination), out charsWritten); + return Encoding.UTF8.TryGetBytes(source, Unsafe.BitCast, Span>(destination), out charsWritten); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs index 852b979492c2d5..070b563b57cb5c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs @@ -883,16 +883,16 @@ internal static bool SpanStartsWith(ReadOnlySpan span, ReadOnlySpa { if (typeof(TChar) == typeof(char)) { - ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); - ReadOnlySpan typedValue = MemoryMarshal.Cast(value); + ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); + ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); return typedSpan.StartsWith(typedValue, comparisonType); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); - ReadOnlySpan typedValue = MemoryMarshal.Cast(value); + ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); + ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); return typedSpan.StartsWithUtf8(typedValue, comparisonType); } } @@ -903,13 +903,13 @@ internal static ReadOnlySpan SpanTrim(ReadOnlySpan span) { if (typeof(TChar) == typeof(char)) { - return MemoryMarshal.Cast(MemoryMarshal.Cast(span).Trim()); + return Unsafe.BitCast, ReadOnlySpan>(Unsafe.BitCast, ReadOnlySpan>(span).Trim()); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - return MemoryMarshal.Cast(MemoryMarshal.Cast(span).TrimUtf8()); + return Unsafe.BitCast, ReadOnlySpan>(Unsafe.BitCast, ReadOnlySpan>(span).TrimUtf8()); } } @@ -919,16 +919,16 @@ internal static bool SpanEqualsOrdinalIgnoreCase(ReadOnlySpan span { if (typeof(TChar) == typeof(char)) { - ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); - ReadOnlySpan typedValue = MemoryMarshal.Cast(value); + ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); + ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); return typedSpan.EqualsOrdinalIgnoreCase(typedValue); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); - ReadOnlySpan typedValue = MemoryMarshal.Cast(value); + ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); + ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); return typedSpan.EqualsOrdinalIgnoreCaseUtf8(typedValue); } } @@ -1041,7 +1041,7 @@ internal static void ThrowFormatException(ReadOnlySpan value) // It's possible after we check the bytes for validity that they could be concurrently // mutated, but if that's happening, all bets are off, anyway, and it simply impacts // which exception is thrown. - ReadOnlySpan bytes = MemoryMarshal.Cast(value); + ReadOnlySpan bytes = Unsafe.BitCast, ReadOnlySpan>(value); errorMessage = Utf8.IsValid(bytes) ? SR.Format(SR.Format_InvalidStringWithValue, Encoding.UTF8.GetString(bytes)) : SR.Format_InvalidString; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs index 9f0129aef0a728..286435be8cc0f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs @@ -33,6 +33,7 @@ public static unsafe partial class Unsafe [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void* AsPointer(ref T value) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -51,6 +52,7 @@ public static unsafe partial class Unsafe [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int SizeOf() + where T : allows ref struct { return sizeof(T); } @@ -102,6 +104,7 @@ public static ref TTo As(ref TFrom source) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Add(ref T source, int elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -128,6 +131,7 @@ public static ref T Add(ref T source, int elementOffset) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Add(ref T source, IntPtr elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -155,6 +159,7 @@ public static ref T Add(ref T source, IntPtr elementOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void* Add(void* source, int elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -181,6 +186,7 @@ public static ref T Add(ref T source, IntPtr elementOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Add(ref T source, nuint elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -208,6 +214,7 @@ public static ref T Add(ref T source, nuint elementOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T AddByteOffset(ref T source, nuint byteOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -232,6 +239,7 @@ public static ref T AddByteOffset(ref T source, nuint byteOffset) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool AreSame([AllowNull] ref readonly T left, [AllowNull] ref readonly T right) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -250,6 +258,8 @@ public static bool AreSame([AllowNull] ref readonly T left, [AllowNull] ref r [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static TTo BitCast(TFrom source) + where TFrom : allows ref struct + where TTo : allows ref struct { if (sizeof(TFrom) != sizeof(TTo) || default(TFrom) is null || default(TTo) is null) { @@ -267,6 +277,7 @@ public static TTo BitCast(TFrom source) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Copy(void* destination, ref readonly T source) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -286,6 +297,7 @@ public static void Copy(void* destination, ref readonly T source) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Copy(ref T destination, void* source) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -388,6 +400,7 @@ public static void CopyBlockUnaligned(ref byte destination, ref readonly byte so [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsAddressGreaterThan([AllowNull] ref readonly T left, [AllowNull] ref readonly T right) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -411,6 +424,7 @@ public static bool IsAddressGreaterThan([AllowNull] ref readonly T left, [All [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsAddressLessThan([AllowNull] ref readonly T left, [AllowNull] ref readonly T right) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -516,6 +530,7 @@ public static void InitBlockUnaligned(ref byte startAddress, byte value, uint by [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T ReadUnaligned(void* source) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -539,7 +554,8 @@ public static T ReadUnaligned(void* source) // Mono:ReadUnaligned [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static T ReadUnaligned(ref readonly byte source) + public static T ReadUnaligned(scoped ref readonly byte source) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -565,6 +581,7 @@ public static T ReadUnaligned(ref readonly byte source) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteUnaligned(void* destination, T value) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -590,6 +607,7 @@ public static void WriteUnaligned(void* destination, T value) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WriteUnaligned(ref byte destination, T value) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); // Type token used by the actual method body @@ -615,6 +633,7 @@ public static void WriteUnaligned(ref byte destination, T value) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T AddByteOffset(ref T source, IntPtr byteOffset) + where T : allows ref struct { // This method is implemented by the toolchain throw new PlatformNotSupportedException(); @@ -633,6 +652,7 @@ public static ref T AddByteOffset(ref T source, IntPtr byteOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Read(void* source) + where T : allows ref struct { return *(T*)source; } @@ -645,6 +665,7 @@ public static T Read(void* source) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Write(void* destination, T value) + where T : allows ref struct { *(T*)destination = value; } @@ -657,6 +678,7 @@ public static void Write(void* destination, T value) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T AsRef(void* source) + where T : allows ref struct { return ref *(T*)source; } @@ -672,6 +694,7 @@ public static ref T AsRef(void* source) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T AsRef(scoped ref readonly T source) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -689,6 +712,7 @@ public static ref T AsRef(scoped ref readonly T source) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static IntPtr ByteOffset([AllowNull] ref readonly T origin, [AllowNull] ref readonly T target) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -707,6 +731,7 @@ public static IntPtr ByteOffset([AllowNull] ref readonly T origin, [AllowNull [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T NullRef() + where T : allows ref struct { return ref AsRef(null); @@ -727,6 +752,7 @@ public static ref T NullRef() [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNullRef(ref readonly T source) + where T : allows ref struct { return AsPointer(ref Unsafe.AsRef(in source)) == null; @@ -747,6 +773,7 @@ public static bool IsNullRef(ref readonly T source) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void SkipInit(out T value) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -761,6 +788,7 @@ public static void SkipInit(out T value) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Subtract(ref T source, int elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -787,6 +815,7 @@ public static ref T Subtract(ref T source, int elementOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void* Subtract(void* source, int elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -812,6 +841,7 @@ public static ref T Subtract(ref T source, int elementOffset) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Subtract(ref T source, IntPtr elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -837,6 +867,7 @@ public static ref T Subtract(ref T source, IntPtr elementOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T Subtract(ref T source, nuint elementOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); @@ -861,6 +892,7 @@ public static ref T Subtract(ref T source, nuint elementOffset) [NonVersionable] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T SubtractByteOffset(ref T source, IntPtr byteOffset) + where T : allows ref struct { throw new PlatformNotSupportedException(); @@ -879,6 +911,7 @@ public static ref T SubtractByteOffset(ref T source, IntPtr byteOffset) [CLSCompliant(false)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref T SubtractByteOffset(ref T source, nuint byteOffset) + where T : allows ref struct { #if CORECLR typeof(T).ToString(); diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index d20d5d23649014..4ea9b5b37b67f5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -320,6 +320,7 @@ private static unsafe string Ctor(ReadOnlySpan value) } public static string Create(int length, TState state, SpanAction action) + where TState : allows ref struct { if (action is null) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Version.cs b/src/libraries/System.Private.CoreLib/src/System/Version.cs index 99c26d59a91439..607a72d03fb9aa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Version.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Version.cs @@ -249,8 +249,8 @@ static void ThrowArgumentException(string failureUpperBound) => int valueCharsWritten; bool formatted = typeof(TChar) == typeof(char) ? - ((uint)value).TryFormat(MemoryMarshal.Cast(destination), out valueCharsWritten) : - ((uint)value).TryFormat(MemoryMarshal.Cast(destination), out valueCharsWritten, default, CultureInfo.InvariantCulture); + ((uint)value).TryFormat(Unsafe.BitCast, Span>(destination), out valueCharsWritten) : + ((uint)value).TryFormat(Unsafe.BitCast, Span>(destination), out valueCharsWritten, default, CultureInfo.InvariantCulture); if (!formatted) { diff --git a/src/libraries/System.Private.Uri/src/System/UriHelper.cs b/src/libraries/System.Private.Uri/src/System/UriHelper.cs index fbdfd0314a3ee2..3b45b59c03debb 100644 --- a/src/libraries/System.Private.Uri/src/System/UriHelper.cs +++ b/src/libraries/System.Private.Uri/src/System/UriHelper.cs @@ -12,13 +12,11 @@ internal static class UriHelper { public static unsafe string SpanToLowerInvariantString(ReadOnlySpan span) { -#pragma warning disable CS8500 // takes address of managed type - return string.Create(span.Length, (IntPtr)(&span), static (buffer, spanPtr) => + return string.Create(span.Length, span, static (buffer, span) => { - int charsWritten = (*(ReadOnlySpan*)spanPtr).ToLowerInvariant(buffer); + int charsWritten = span.ToLowerInvariant(buffer); Debug.Assert(charsWritten == buffer.Length); }); -#pragma warning restore CS8500 } // http://host/Path/Path/File?Query is the base of @@ -618,12 +616,10 @@ internal static unsafe string StripBidiControlCharacters(ReadOnlySpan strT return backingString ?? new string(strToClean); } -#pragma warning disable CS8500 // takes address of managed type - ReadOnlySpan tmpStrToClean = strToClean; // avoid address exposing the span and impacting the other code in the method that uses it - return string.Create(tmpStrToClean.Length - charsToRemove, (IntPtr)(&tmpStrToClean), static (buffer, strToCleanPtr) => + return string.Create(strToClean.Length - charsToRemove, strToClean, static (buffer, strToClean) => { int destIndex = 0; - foreach (char c in *(ReadOnlySpan*)strToCleanPtr) + foreach (char c in strToClean) { if (!IsBidiControlCharacter(c)) { @@ -632,7 +628,6 @@ internal static unsafe string StripBidiControlCharacters(ReadOnlySpan strT } Debug.Assert(buffer.Length == destIndex); }); -#pragma warning restore CS8500 } } } diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs index 8d6b7abbfdbd9b..a62190ee40d933 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/Complex.cs @@ -2241,8 +2241,8 @@ private bool TryFormatCore(Span destination, out int charsWritten, { int realChars; if (typeof(TChar) == typeof(char) ? - m_real.TryFormat(MemoryMarshal.Cast(destination.Slice(1)), out realChars, format, provider) : - m_real.TryFormat(MemoryMarshal.Cast(destination.Slice(1)), out realChars, format, provider)) + m_real.TryFormat(Unsafe.BitCast, Span>(destination.Slice(1)), out realChars, format, provider) : + m_real.TryFormat(Unsafe.BitCast, Span>(destination.Slice(1)), out realChars, format, provider)) { destination[0] = TChar.CreateTruncating('<'); destination = destination.Slice(1 + realChars); // + 1 for < @@ -2252,8 +2252,8 @@ private bool TryFormatCore(Span destination, out int charsWritten, { int imaginaryChars; if (typeof(TChar) == typeof(char) ? - m_imaginary.TryFormat(MemoryMarshal.Cast(destination.Slice(2)), out imaginaryChars, format, provider) : - m_imaginary.TryFormat(MemoryMarshal.Cast(destination.Slice(2)), out imaginaryChars, format, provider)) + m_imaginary.TryFormat(Unsafe.BitCast, Span>(destination.Slice(2)), out imaginaryChars, format, provider) : + m_imaginary.TryFormat(Unsafe.BitCast, Span>(destination.Slice(2)), out imaginaryChars, format, provider)) { // We have 1 more character for: > if ((uint)(2 + imaginaryChars) < (uint)destination.Length) diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 0d928378a603f9..0804eaf5354381 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -55,22 +55,174 @@ public AccessViolationException(string? message) { } public AccessViolationException(string? message, System.Exception? innerException) { } } public delegate void Action(); - public delegate void Action(T obj); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); - public delegate void Action(T1 arg1, T2 arg2); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); - public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); + public delegate void Action(T obj) + where T : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2) + where T1 : allows ref struct + where T2 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct; + + public delegate void Action(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where T16 : allows ref struct; + public static partial class Activator { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Type and its constructor could be removed")] @@ -1110,7 +1262,7 @@ public sealed partial class CLSCompliantAttribute : System.Attribute public CLSCompliantAttribute(bool isCompliant) { } public bool IsCompliant { get { throw null; } } } - public delegate int Comparison(T x, T y); + public delegate int Comparison(T x, T y) where T : allows ref struct; public abstract partial class ContextBoundObject : System.MarshalByRefObject { protected ContextBoundObject() { } @@ -1589,7 +1741,7 @@ public static partial class Convert public static bool TryToHexString(System.ReadOnlySpan source, System.Span destination, out int charsWritten) { throw null; } public static bool TryToHexStringLower(System.ReadOnlySpan source, System.Span destination, out int charsWritten) { throw null; } } - public delegate TOutput Converter(TInput input); + public delegate TOutput Converter(TInput input) where TInput : allows ref struct where TOutput : allows ref struct; public readonly partial struct DateOnly : System.IComparable, System.IComparable, System.IEquatable, System.IFormattable, System.IParsable, System.ISpanFormattable, System.ISpanParsable, System.IUtf8SpanFormattable { private readonly int _dummyPrimitive; @@ -2694,23 +2846,193 @@ protected FormattableString() { } public override string ToString() { throw null; } public abstract string ToString(System.IFormatProvider? formatProvider); } - public delegate TResult Func(); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16); - public delegate TResult Func(T arg); - public delegate TResult Func(T1 arg1, T2 arg2); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7); - public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8); + public delegate TResult Func() + where TResult : allows ref struct; + + public delegate TResult Func(T arg) + where T : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2) + where T1 : allows ref struct + where T2 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where TResult : allows ref struct; + + public delegate TResult Func(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16) + where T1 : allows ref struct + where T2 : allows ref struct + where T3 : allows ref struct + where T4 : allows ref struct + where T5 : allows ref struct + where T6 : allows ref struct + where T7 : allows ref struct + where T8 : allows ref struct + where T9 : allows ref struct + where T10 : allows ref struct + where T11 : allows ref struct + where T12 : allows ref struct + where T13 : allows ref struct + where T14 : allows ref struct + where T15 : allows ref struct + where T16 : allows ref struct + where TResult : allows ref struct; + public static partial class GC { public static int MaxGeneration { get { throw null; } } @@ -4635,7 +4957,7 @@ protected PlatformNotSupportedException(System.Runtime.Serialization.Serializati public PlatformNotSupportedException(string? message) { } public PlatformNotSupportedException(string? message, System.Exception? inner) { } } - public delegate bool Predicate(T obj); + public delegate bool Predicate(T obj) where T : allows ref struct; public partial class Progress : System.IProgress { public Progress() { } @@ -5286,7 +5608,7 @@ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, in public void CopyTo(System.Span destination) { } public static string Create(System.IFormatProvider? provider, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("provider")] ref System.Runtime.CompilerServices.DefaultInterpolatedStringHandler handler) { throw null; } public static string Create(System.IFormatProvider? provider, System.Span initialBuffer, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute(new string[]{ "provider", "initialBuffer"})] ref System.Runtime.CompilerServices.DefaultInterpolatedStringHandler handler) { throw null; } - public static string Create(int length, TState state, System.Buffers.SpanAction action) { throw null; } + public static string Create(int length, TState state, System.Buffers.SpanAction action) where TState : allows ref struct { throw null; } public bool EndsWith(char value) { throw null; } public bool EndsWith(string value) { throw null; } public bool EndsWith(string value, bool ignoreCase, System.Globalization.CultureInfo? culture) { throw null; } @@ -7498,7 +7820,7 @@ public enum OperationStatus NeedMoreData = 2, InvalidData = 3, } - public delegate void ReadOnlySpanAction(System.ReadOnlySpan span, TArg arg); + public delegate void ReadOnlySpanAction(System.ReadOnlySpan span, TArg arg) where TArg : allows ref struct; public static partial class SearchValues { public static System.Buffers.SearchValues Create(params System.ReadOnlySpan values) { throw null; } @@ -7510,7 +7832,7 @@ public partial class SearchValues where T : System.IEquatable? internal SearchValues() { } public bool Contains(T value) { throw null; } } - public delegate void SpanAction(System.Span span, TArg arg); + public delegate void SpanAction(System.Span span, TArg arg) where TArg : allows ref struct; } namespace System.Buffers.Text { @@ -7811,11 +8133,11 @@ public partial interface IStructuralEquatable } namespace System.Collections.Generic { - public partial interface IAsyncEnumerable + public partial interface IAsyncEnumerable where T : allows ref struct { System.Collections.Generic.IAsyncEnumerator GetAsyncEnumerator(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)); } - public partial interface IAsyncEnumerator : System.IAsyncDisposable + public partial interface IAsyncEnumerator : System.IAsyncDisposable where T : allows ref struct { T Current { get; } System.Threading.Tasks.ValueTask MoveNextAsync(); @@ -7844,11 +8166,11 @@ public partial interface IDictionary : System.Collections.Generic. bool Remove(TKey key); bool TryGetValue(TKey key, [System.Diagnostics.CodeAnalysis.MaybeNullWhenAttribute(false)] out TValue value); } - public partial interface IEnumerable : System.Collections.IEnumerable + public partial interface IEnumerable : System.Collections.IEnumerable where T : allows ref struct { new System.Collections.Generic.IEnumerator GetEnumerator(); } - public partial interface IEnumerator : System.Collections.IEnumerator, System.IDisposable + public partial interface IEnumerator : System.Collections.IEnumerator, System.IDisposable where T : allows ref struct { new T Current { get; } } @@ -13340,26 +13662,26 @@ public TypeForwardedToAttribute(System.Type destination) { } } public static partial class Unsafe { - public static ref T AddByteOffset(ref T source, System.IntPtr byteOffset) { throw null; } + public static ref T AddByteOffset(ref T source, System.IntPtr byteOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public static ref T AddByteOffset(ref T source, nuint byteOffset) { throw null; } + public static ref T AddByteOffset(ref T source, nuint byteOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static void* Add(void* source, int elementOffset) { throw null; } - public static ref T Add(ref T source, int elementOffset) { throw null; } - public static ref T Add(ref T source, System.IntPtr elementOffset) { throw null; } + public unsafe static void* Add(void* source, int elementOffset) where T : allows ref struct { throw null; } + public static ref T Add(ref T source, int elementOffset) where T : allows ref struct { throw null; } + public static ref T Add(ref T source, System.IntPtr elementOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public static ref T Add(ref T source, nuint elementOffset) { throw null; } - public static bool AreSame([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) { throw null; } + public static ref T Add(ref T source, nuint elementOffset) where T : allows ref struct { throw null; } + public static bool AreSame([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static void* AsPointer(ref T value) { throw null; } + public unsafe static void* AsPointer(ref T value) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static ref T AsRef(void* source) { throw null; } - public static ref T AsRef(scoped ref readonly T source) { throw null; } + public unsafe static ref T AsRef(void* source) where T : allows ref struct { throw null; } + public static ref T AsRef(scoped ref readonly T source) where T : allows ref struct { throw null; } [return: System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute("o")] public static T? As(object? o) where T : class? { throw null; } - public static ref TTo As (ref TFrom source) where TFrom : allows ref struct where TTo : allows ref struct { throw null; } - public static TTo BitCast(TFrom source) { throw null; } - public static System.IntPtr ByteOffset([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T origin, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T target) { throw null; } + public static ref TTo As(ref TFrom source) where TFrom : allows ref struct where TTo : allows ref struct { throw null; } + public static TTo BitCast(TFrom source) where TFrom : allows ref struct where TTo : allows ref struct { throw null; } + public static System.IntPtr ByteOffset([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T origin, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T target) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] public static void CopyBlock(ref byte destination, ref readonly byte source, uint byteCount) { } [System.CLSCompliantAttribute(false)] @@ -13369,9 +13691,9 @@ public static void CopyBlockUnaligned(ref byte destination, ref readonly byte so [System.CLSCompliantAttribute(false)] public unsafe static void CopyBlockUnaligned(void* destination, void* source, uint byteCount) { } [System.CLSCompliantAttribute(false)] - public unsafe static void Copy(void* destination, ref readonly T source) { } + public unsafe static void Copy(void* destination, ref readonly T source) where T : allows ref struct { } [System.CLSCompliantAttribute(false)] - public unsafe static void Copy(ref T destination, void* source) { } + public unsafe static void Copy(ref T destination, void* source) where T : allows ref struct { } [System.CLSCompliantAttribute(false)] public static void InitBlock(ref byte startAddress, byte value, uint byteCount) { } [System.CLSCompliantAttribute(false)] @@ -13380,32 +13702,32 @@ public unsafe static void InitBlock(void* startAddress, byte value, uint byteCou public static void InitBlockUnaligned(ref byte startAddress, byte value, uint byteCount) { } [System.CLSCompliantAttribute(false)] public unsafe static void InitBlockUnaligned(void* startAddress, byte value, uint byteCount) { } - public static bool IsAddressGreaterThan([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) { throw null; } - public static bool IsAddressLessThan([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) { throw null; } - public static bool IsNullRef(ref readonly T source) { throw null; } - public static ref T NullRef() { throw null; } - public static T ReadUnaligned(ref readonly byte source) { throw null; } + public static bool IsAddressGreaterThan([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; } + public static bool IsAddressLessThan([System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T left, [System.Diagnostics.CodeAnalysis.AllowNull] ref readonly T right) where T : allows ref struct { throw null; } + public static bool IsNullRef(ref readonly T source) where T : allows ref struct { throw null; } + public static ref T NullRef() where T : allows ref struct { throw null; } + public static T ReadUnaligned(scoped ref readonly byte source) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static T ReadUnaligned(void* source) { throw null; } + public unsafe static T ReadUnaligned(void* source) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static T Read(void* source) { throw null; } - public static int SizeOf() { throw null; } - public static void SkipInit(out T value) { throw null; } - public static ref T SubtractByteOffset(ref T source, System.IntPtr byteOffset) { throw null; } + public unsafe static T Read(void* source) where T : allows ref struct { throw null; } + public static int SizeOf() where T : allows ref struct { throw null; } + public static void SkipInit(out T value) where T : allows ref struct { throw null; } + public static ref T SubtractByteOffset(ref T source, System.IntPtr byteOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public static ref T SubtractByteOffset(ref T source, nuint byteOffset) { throw null; } + public static ref T SubtractByteOffset(ref T source, nuint byteOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public unsafe static void* Subtract(void* source, int elementOffset) { throw null; } - public static ref T Subtract(ref T source, int elementOffset) { throw null; } - public static ref T Subtract(ref T source, System.IntPtr elementOffset) { throw null; } + public unsafe static void* Subtract(void* source, int elementOffset) where T : allows ref struct { throw null; } + public static ref T Subtract(ref T source, int elementOffset) where T : allows ref struct { throw null; } + public static ref T Subtract(ref T source, System.IntPtr elementOffset) where T : allows ref struct { throw null; } [System.CLSCompliantAttribute(false)] - public static ref T Subtract(ref T source, nuint elementOffset) { throw null; } + public static ref T Subtract(ref T source, nuint elementOffset) where T : allows ref struct { throw null; } public static ref T Unbox(object box) where T : struct { throw null; } - public static void WriteUnaligned(ref byte destination, T value) { } + public static void WriteUnaligned(ref byte destination, T value) where T : allows ref struct { } [System.CLSCompliantAttribute(false)] - public unsafe static void WriteUnaligned(void* destination, T value) { } + public unsafe static void WriteUnaligned(void* destination, T value) where T : allows ref struct { } [System.CLSCompliantAttribute(false)] - public unsafe static void Write(void* destination, T value) { } + public unsafe static void Write(void* destination, T value) where T : allows ref struct { } } [System.AttributeUsageAttribute(System.AttributeTargets.Method, AllowMultiple=false, Inherited=false)] public sealed partial class UnsafeAccessorAttribute : System.Attribute diff --git a/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs index 70d55cd6f69850..8cc4f236af4de4 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs @@ -6,6 +6,8 @@ using System.Runtime.InteropServices; using Xunit; +#pragma warning disable CS8500 // This takes the address of, gets the size of, or declares a pointer to a managed type + namespace System.Runtime.CompilerServices { public class UnsafeTests @@ -19,6 +21,17 @@ public static unsafe void ReadInt32() Assert.Equal(expected, ret); } + [Fact] + public static unsafe void ReadSpan() + { + int i = 42; + Span span = new Span(ref i); + void* address = Unsafe.AsPointer(ref span); // Unsafe.AsPointer is safe since expected is on stack + Span ret = Unsafe.Read>(address); + Assert.Equal(1, ret.Length); + Assert.Equal(42, ret[0]); + } + [Fact] public static unsafe void WriteInt32() { @@ -32,6 +45,20 @@ public static unsafe void WriteInt32() Assert.Equal(expected, Unsafe.Read(address)); } + [Fact] + public static unsafe void WriteSpan() + { + int value = 10; + int value2 = 20; + Span span = new Span(ref value); + Span* address = (Span*)Unsafe.AsPointer(ref span); // Unsafe.AsPointer is safe since value is on stack + Unsafe.Write(address, new Span(ref value2)); + + Assert.Equal(1, span.Length); + Assert.Equal(20, span[0]); + Assert.True(Unsafe.AreSame(ref value2, ref span[0])); + } + [Fact] public static unsafe void WriteBytesIntoInt32() { @@ -197,6 +224,7 @@ public static unsafe void SizeOf() Assert.Equal(4, Unsafe.SizeOf()); Assert.Equal(8, Unsafe.SizeOf()); Assert.Equal(512, Unsafe.SizeOf()); + Assert.Equal(IntPtr.Size * 2, Unsafe.SizeOf>()); } [Theory] @@ -496,6 +524,19 @@ public static unsafe void AsRef() } } + [Fact] + public static unsafe void AsRef_RefStruct() + { + int i = 42; + Span span = new Span(ref i); + + Span* spanPtr = &span; + fixed (Span* spanPtrActual = &Unsafe.AsRef>(in span)) + { + Assert.Equal((IntPtr)spanPtr, (IntPtr)spanPtrActual); + } + } + [Fact] public static void InAsRef() { @@ -577,6 +618,33 @@ public static void RefAddIntPtr() Assert.Equal(0x123, r3); } + [Fact] + public static void RefAddIntPtr_RefStruct() + { + int i0 = 42, i1 = 43, i2 = 44, i3 = 45; + FourSpans span = new() + { + Span0 = new Span(ref i0), + Span1 = new Span(ref i1), + Span2 = new Span(ref i2), + Span3 = new Span(ref i3) + }; + + ref Span spanRef = ref Unsafe.AsRef(in span.Span0); + Assert.Equal(42, spanRef[0]); + + spanRef = ref Unsafe.Add(ref spanRef, 1); + Assert.Equal(43, spanRef[0]); + + spanRef = ref Unsafe.Add(ref spanRef, 2); + Assert.Equal(45, spanRef[0]); + } + + private ref struct FourSpans + { + public Span Span0, Span1, Span2, Span3; + } + [Fact] public static void RefAddNuint() { @@ -1123,6 +1191,11 @@ public static unsafe void IsNullRef_Null() Assert.True(Unsafe.IsNullRef(ref Unsafe.AsRef(null))); Assert.True(Unsafe.IsNullRef(ref Unsafe.AsRef(null))); + // Validate that calling on ref structs works. + + Assert.True(Unsafe.IsNullRef>(ref Unsafe.NullRef>())); + Assert.True(Unsafe.IsNullRef>(ref Unsafe.NullRef>())); + // Validate on ref created from a pointer int* p = (int*)0; @@ -1188,6 +1261,12 @@ public static unsafe void BitCast() Assert.Equal(int.MinValue, Unsafe.BitCast(0x8000_0000u)); Assert.Equal(0x8000_0000u, Unsafe.BitCast(int.MinValue)); + // Conversion between same sized ref structs should succeed + + int i = 42; + Span span = Unsafe.BitCast, Span>(new ReadOnlySpan(&i, 1)); + Assert.Equal(42, span[0]); + // Conversion from runtime SIMD type to a custom struct should succeed Vector4 vector4a = new Vector4(1.0f, 2.0f, 3.0f, 4.0f); diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj index 1e6b01ecf75b30..1c9fa97e35c6da 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System.Runtime.Tests.csproj @@ -183,6 +183,7 @@ + diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Collections/Generic/IEnumerableTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Collections/Generic/IEnumerableTests.cs new file mode 100644 index 00000000000000..110679add75596 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Collections/Generic/IEnumerableTests.cs @@ -0,0 +1,40 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Text; +using Xunit; + +namespace System.Collections.Generic.Tests +{ + public class IEnumerableTests + { + [Fact] + public void SupportsRefStructT() + { + StringBuilder builder = new(); + foreach (ReadOnlySpan c in new MySpanReturningEnumerable("hello")) + { + builder.Append(c); + } + Assert.Equal("hello", builder.ToString()); + } + } + + internal sealed class MySpanReturningEnumerable(string value) : IEnumerable>, IEnumerator> + { + private int _index = -1; + + public IEnumerator> GetEnumerator() => this; + IEnumerator IEnumerable.GetEnumerator() => this; + + public ReadOnlySpan Current => value.AsSpan(_index, 1); + + public bool MoveNext() => ++_index < value.Length; + + public void Dispose() { } + + object IEnumerator.Current => throw new NotSupportedException(); + + void IEnumerator.Reset() => throw new NotSupportedException(); + } +} diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs index 9e2dc8059fa8bc..0c154d15f9e15a 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/RuntimeHelpersTests.cs @@ -365,6 +365,15 @@ public static void IsReferenceOrContainsReferences() Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences()); Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences()); Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences()); + + // TODO https://github.com/dotnet/runtime/issues/102847: + // Enable these tests once IsReferenceOrContainsReferences is fixed to recognize ref fields. + // Assert.False(RuntimeHelpers.IsReferenceOrContainsReferences()); + // Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences()); + // Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences>()); + // Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences>()); + // Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences()); + // Assert.True(RuntimeHelpers.IsReferenceOrContainsReferences()); } [Fact] @@ -409,6 +418,7 @@ public static unsafe void AllocateTypeAssociatedMemoryValidArguments() Assert.True(new Span((void*)memory, 32).SequenceEqual(new byte[32])); } +#pragma warning disable CS0649 [StructLayoutAttribute(LayoutKind.Sequential)] private struct StructWithoutReferences { @@ -422,6 +432,29 @@ private struct StructWithReferences public object d; } + private ref struct RefStructWithoutReferences + { + public int a; + public long b; + } + + private ref struct RefStructWithReferences + { + public int a; + public object b; + } + + private ref struct RefStructWithRef + { + public ref int a; + } + + private ref struct RefStructWithNestedRef + { + public Span a; + } +#pragma warning restore CS0649 + [Fact] public static void FixedAddressValueTypeTest() { diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs index 9f59853b136dad..f6885ffc650f74 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/StringTests.cs @@ -148,6 +148,30 @@ public static void Create_ReturnsExpectedString(string expected) Assert.Equal(expected, result); } + [Fact] + public static void Create_CanSquirrelAwayArg() + { + object arg = new object(); + object storedArg = null; + string result = string.Create(5, arg, (span, arg) => + { + "hello".AsSpan().CopyTo(span); + storedArg = arg; + }); + Assert.Equal("hello", result); + Assert.Same(arg, storedArg); + } + + [Fact] + public static void Create_CanPassSpanAsArg() + { + string result = string.Create(5, "hello".AsSpan(), (span, arg) => + { + arg.CopyTo(span); + }); + Assert.Equal("hello", result); + } + [Fact] public static void Create_InterpolatedString_ConstructsStringAndClearsBuilder() { diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs index d1463546dd021f..7baed36c87f804 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RandomNumberGenerator.cs @@ -233,14 +233,9 @@ public static unsafe string GetString(ReadOnlySpan choices, int length) ArgumentOutOfRangeException.ThrowIfNegative(length); -#pragma warning disable 8500 return string.Create(length, - (IntPtr)(&choices), - static (destination, state) => - { - GetItemsCore(*(ReadOnlySpan*)state, destination); - }); -#pragma warning restore 8500 + choices, + static (destination, choices) => GetItemsCore(choices, destination)); } /// diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs index 5cbd1008cdb002..ac4066a2f000a7 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/Regex.Replace.cs @@ -228,10 +228,8 @@ internal static unsafe string SegmentsToStringAndDispose(ref StructListBuilder> tmpSpan = span; // avoid address exposing the span and impacting the other code in the method that uses it - string result = string.Create(length, (IntPtr)(&tmpSpan), static (dest, spanPtr) => + string result = string.Create(length, span, static (dest, span) => { - Span> span = *(Span>*)spanPtr; for (int i = 0; i < span.Length; i++) { ReadOnlySpan segment = span[i].Span;