From c286a8efb3c0d534557dde476d5b54b15c0aeaed Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 3 Jun 2024 17:23:46 -0400 Subject: [PATCH] Revert uses of Unsafe.BitCast with spans to unblock mono (#102998) * Revert uses of Unsafe.BitCast with spans to unblock mono * Comment out a test --- .../System.Linq/src/System/Linq/Sum.cs | 4 +- .../Tensors/TensorPrimitives.Helpers.cs | 8 --- .../System/Globalization/DateTimeFormat.cs | 8 +-- .../Globalization/DateTimeFormatInfo.cs | 20 +++---- .../System/Globalization/NumberFormatInfo.cs | 56 +++++++++---------- .../src/System/Number.Formatting.cs | 4 +- .../src/System/Number.Parsing.cs | 22 ++++---- .../src/System/Version.cs | 4 +- .../src/System/Numerics/Complex.cs | 8 +-- .../UnsafeTests.cs | 7 ++- 10 files changed, 67 insertions(+), 74 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/Sum.cs b/src/libraries/System.Linq/src/System/Linq/Sum.cs index 481997b8f8263..7eb2dc855dc67 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(Unsafe.BitCast, ReadOnlySpan>(span)); + return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast(span)); } if (typeof(T) == typeof(int)) { - return (TResult)(object)SumSignedIntegersVectorized(Unsafe.BitCast, ReadOnlySpan>(span)); + return (TResult)(object)SumSignedIntegersVectorized(MemoryMarshal.Cast(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 5e4e89b61742d..1ddabb93dd0ea 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,11 +36,7 @@ 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. @@ -52,11 +48,7 @@ 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/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index 5192820e1a4d5..db12f89bf2dd1 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(Unsafe.BitCast, ReadOnlySpan>(s)); + result.Append(MemoryMarshal.Cast(s)); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - Encoding.UTF8.GetBytes(s, Unsafe.BitCast, Span>(result.AppendSpan(Encoding.UTF8.GetByteCount(s)))); + Encoding.UTF8.GetBytes(s, MemoryMarshal.Cast(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(Unsafe.BitCast, Span>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) : - fraction.TryFormat(Unsafe.BitCast, Span>(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture); + fraction.TryFormat(MemoryMarshal.Cast(chars), out charCount, fractionFormat, CultureInfo.InvariantCulture) : + fraction.TryFormat(MemoryMarshal.Cast(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 f2b99e5a81b3b..e87960b61792d 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) ? - Unsafe.BitCast, ReadOnlySpan>(AMDesignator) : - Unsafe.BitCast, ReadOnlySpan>(amDesignatorUtf8 ??= Encoding.UTF8.GetBytes(AMDesignator)); + MemoryMarshal.Cast(AMDesignator) : + MemoryMarshal.Cast(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) ? - Unsafe.BitCast, ReadOnlySpan>(DateSeparator) : - Unsafe.BitCast, ReadOnlySpan>(dateSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DateSeparator)); + MemoryMarshal.Cast(DateSeparator) : + MemoryMarshal.Cast(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) ? - Unsafe.BitCast, ReadOnlySpan>(PMDesignator) : - Unsafe.BitCast, ReadOnlySpan>(pmDesignatorUtf8 ??= Encoding.UTF8.GetBytes(PMDesignator)); + MemoryMarshal.Cast(PMDesignator) : + MemoryMarshal.Cast(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) ? - Unsafe.BitCast, ReadOnlySpan>(TimeSeparator) : - Unsafe.BitCast, ReadOnlySpan>(timeSeparatorUtf8 ??= Encoding.UTF8.GetBytes(TimeSeparator)); + MemoryMarshal.Cast(TimeSeparator) : + MemoryMarshal.Cast(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) ? - Unsafe.BitCast, ReadOnlySpan>(DecimalSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_decimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(DecimalSeparator)); + MemoryMarshal.Cast(DecimalSeparator) : + MemoryMarshal.Cast(_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 60882f7aaaa0e..0424b678e4b18 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) ? - Unsafe.BitCast, ReadOnlySpan>(_currencyDecimalSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_currencyDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyDecimalSeparator)); + MemoryMarshal.Cast(_currencyDecimalSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_currencyGroupSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_currencyGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_currencyGroupSeparator)); + MemoryMarshal.Cast(_currencyGroupSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_currencySymbol) : - Unsafe.BitCast, ReadOnlySpan>(_currencySymbolUtf8 ??= Encoding.UTF8.GetBytes(_currencySymbol)); + MemoryMarshal.Cast(_currencySymbol) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_nanSymbol) : - Unsafe.BitCast, ReadOnlySpan>(_nanSymbolUtf8 ??= Encoding.UTF8.GetBytes(_nanSymbol)); + MemoryMarshal.Cast(_nanSymbol) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_negativeInfinitySymbol) : - Unsafe.BitCast, ReadOnlySpan>(_negativeInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_negativeInfinitySymbol)); + MemoryMarshal.Cast(_negativeInfinitySymbol) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_negativeSign) : - Unsafe.BitCast, ReadOnlySpan>(_negativeSignUtf8 ??= Encoding.UTF8.GetBytes(_negativeSign)); + MemoryMarshal.Cast(_negativeSign) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_numberDecimalSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_numberDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberDecimalSeparator)); + MemoryMarshal.Cast(_numberDecimalSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_numberGroupSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_numberGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_numberGroupSeparator)); + MemoryMarshal.Cast(_numberGroupSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_positiveInfinitySymbol) : - Unsafe.BitCast, ReadOnlySpan>(_positiveInfinitySymbolUtf8 ??= Encoding.UTF8.GetBytes(_positiveInfinitySymbol)); + MemoryMarshal.Cast(_positiveInfinitySymbol) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_positiveSign) : - Unsafe.BitCast, ReadOnlySpan>(_positiveSignUtf8 ??= Encoding.UTF8.GetBytes(_positiveSign)); + MemoryMarshal.Cast(_positiveSign) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_percentDecimalSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_percentDecimalSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentDecimalSeparator)); + MemoryMarshal.Cast(_percentDecimalSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_percentGroupSeparator) : - Unsafe.BitCast, ReadOnlySpan>(_percentGroupSeparatorUtf8 ??= Encoding.UTF8.GetBytes(_percentGroupSeparator)); + MemoryMarshal.Cast(_percentGroupSeparator) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_percentSymbol) : - Unsafe.BitCast, ReadOnlySpan>(_percentSymbolUtf8 ??= Encoding.UTF8.GetBytes(_percentSymbol)); + MemoryMarshal.Cast(_percentSymbol) : + MemoryMarshal.Cast(_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) ? - Unsafe.BitCast, ReadOnlySpan>(_perMilleSymbol) : - Unsafe.BitCast, ReadOnlySpan>(_perMilleSymbolUtf8 ??= Encoding.UTF8.GetBytes(_perMilleSymbol)); + MemoryMarshal.Cast(_perMilleSymbol) : + MemoryMarshal.Cast(_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 38a752c6810ff..928eaea0d9540 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs @@ -621,7 +621,7 @@ private static bool TryCopyTo(string source, Span destination, out if (typeof(TChar) == typeof(char)) { - if (source.TryCopyTo(Unsafe.BitCast, Span>(destination))) + if (source.TryCopyTo(MemoryMarshal.Cast(destination))) { charsWritten = source.Length; return true; @@ -632,7 +632,7 @@ private static bool TryCopyTo(string source, Span destination, out } else { - return Encoding.UTF8.TryGetBytes(source, Unsafe.BitCast, Span>(destination), out charsWritten); + return Encoding.UTF8.TryGetBytes(source, MemoryMarshal.Cast(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 f15712bf5fe92..263f60ad0ba10 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs @@ -895,16 +895,16 @@ internal static bool SpanStartsWith(ReadOnlySpan span, ReadOnlySpa { if (typeof(TChar) == typeof(char)) { - ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); - ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); + ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); + ReadOnlySpan typedValue = MemoryMarshal.Cast(value); return typedSpan.StartsWith(typedValue, comparisonType); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); - ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); + ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); + ReadOnlySpan typedValue = MemoryMarshal.Cast(value); return typedSpan.StartsWithUtf8(typedValue, comparisonType); } } @@ -915,13 +915,13 @@ internal static ReadOnlySpan SpanTrim(ReadOnlySpan span) { if (typeof(TChar) == typeof(char)) { - return Unsafe.BitCast, ReadOnlySpan>(Unsafe.BitCast, ReadOnlySpan>(span).Trim()); + return MemoryMarshal.Cast(MemoryMarshal.Cast(span).Trim()); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - return Unsafe.BitCast, ReadOnlySpan>(Unsafe.BitCast, ReadOnlySpan>(span).TrimUtf8()); + return MemoryMarshal.Cast(MemoryMarshal.Cast(span).TrimUtf8()); } } @@ -931,16 +931,16 @@ internal static bool SpanEqualsOrdinalIgnoreCase(ReadOnlySpan span { if (typeof(TChar) == typeof(char)) { - ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); - ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); + ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); + ReadOnlySpan typedValue = MemoryMarshal.Cast(value); return typedSpan.EqualsOrdinalIgnoreCase(typedValue); } else { Debug.Assert(typeof(TChar) == typeof(byte)); - ReadOnlySpan typedSpan = Unsafe.BitCast, ReadOnlySpan>(span); - ReadOnlySpan typedValue = Unsafe.BitCast, ReadOnlySpan>(value); + ReadOnlySpan typedSpan = MemoryMarshal.Cast(span); + ReadOnlySpan typedValue = MemoryMarshal.Cast(value); return typedSpan.EqualsOrdinalIgnoreCaseUtf8(typedValue); } } @@ -1053,7 +1053,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 = Unsafe.BitCast, ReadOnlySpan>(value); + ReadOnlySpan bytes = MemoryMarshal.Cast(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/Version.cs b/src/libraries/System.Private.CoreLib/src/System/Version.cs index 607a72d03fb9a..99c26d59a9143 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(Unsafe.BitCast, Span>(destination), out valueCharsWritten) : - ((uint)value).TryFormat(Unsafe.BitCast, Span>(destination), out valueCharsWritten, default, CultureInfo.InvariantCulture); + ((uint)value).TryFormat(MemoryMarshal.Cast(destination), out valueCharsWritten) : + ((uint)value).TryFormat(MemoryMarshal.Cast(destination), out valueCharsWritten, default, CultureInfo.InvariantCulture); if (!formatted) { 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 a62190ee40d93..8d6b7abbfdbd9 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(Unsafe.BitCast, Span>(destination.Slice(1)), out realChars, format, provider) : - m_real.TryFormat(Unsafe.BitCast, Span>(destination.Slice(1)), out realChars, format, provider)) + m_real.TryFormat(MemoryMarshal.Cast(destination.Slice(1)), out realChars, format, provider) : + m_real.TryFormat(MemoryMarshal.Cast(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(Unsafe.BitCast, Span>(destination.Slice(2)), out imaginaryChars, format, provider) : - m_imaginary.TryFormat(Unsafe.BitCast, Span>(destination.Slice(2)), out imaginaryChars, format, provider)) + m_imaginary.TryFormat(MemoryMarshal.Cast(destination.Slice(2)), out imaginaryChars, format, provider) : + m_imaginary.TryFormat(MemoryMarshal.Cast(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/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.CompilerServices.Unsafe.Tests/UnsafeTests.cs index 8cc4f236af4de..3df92cd860935 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 @@ -1263,9 +1263,10 @@ public static unsafe void BitCast() // 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]); + // TODO https://github.com/dotnet/runtime/issues/102988: Uncomment once this works on mono + //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