From b1fbe695196c90223a3d8b67a9961392b067d13d Mon Sep 17 00:00:00 2001 From: Jared Parsons Date: Mon, 3 Oct 2022 13:28:32 -0700 Subject: [PATCH] Update to latest .NET 7 Roslyn compiler (#76459) * Patches for scoped locals https://github.com/dotnet/roslyn/pull/64093 This change enforced that `scoped` on a local set the escape scope to the current block where previously it was incorrectly setting to the containing method. * Make return and out equivalent for ref safety https://github.com/dotnet/roslyn/pull/64318 This change allows anything returnable from a method to be assigned to an `out` parameter. In several places had to add `scoped` to `ref` to inform compiler they could not be captured in an `out` parameter. * Warnings on managed pointer types https://github.com/dotnet/roslyn/pull/64294 Compiler now issues warnings for pointer operations involving managed types * Update compiler version * PR feedback * Ref safety rules attribute Co-authored-by: Charles Stoner <10732005+cston@users.noreply.github.com> --- eng/Versions.props | 2 +- .../Reflection/Emit/DynamicMethod.CoreCLR.cs | 2 ++ .../System/Reflection/RuntimeMethodInfo.CoreCLR.cs | 2 ++ .../src/System/Reflection/DynamicInvokeInfo.cs | 14 ++++++++++--- .../ILCompiler.Compiler.Tests.Assets.csproj | 1 + .../ILCompiler.Compiler.Tests.csproj | 1 + .../src/System/Number.BigInteger.cs | 20 +++++++++++------- .../src/System/Number.NumberToFloatingPointBits.cs | 2 +- .../src/System/Reflection/MethodBase.cs | 2 ++ .../System/Reflection/RuntimeConstructorInfo.cs | 4 ++++ .../src/System/Reflection/RuntimeMethodInfo.cs | 2 ++ .../src/System/Text/Json/JsonHelpers.cs | 2 +- .../Utf8JsonWriter.WriteProperties.String.cs | 24 +++++++++++++--------- .../RegularExpressions/RegexCaseEquivalences.cs | 2 +- 14 files changed, 56 insertions(+), 24 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index e15a3bbf..392cc63 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -52,7 +52,7 @@ - 4.4.0-3.22452.8 + 4.4.0-3.22479.16 0.2.0 8.0.100-alpha.1.22462.3 diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs index 194108b..34b53bb 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs @@ -172,7 +172,9 @@ namespace System.Reflection.Emit Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable CS8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore CS8500 CheckArguments( copyOfParameters, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index c55ee60..4e1246b 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -316,7 +316,9 @@ namespace System.Reflection Span shouldCopyBackParameters = new(ref argStorage._copyBack0, 1); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs index 234f8a1..4f01069 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/DynamicInvokeInfo.cs @@ -235,11 +235,15 @@ namespace System.Reflection StackAllocedArguments argStorage = default; StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 CheckArguments(ref argStorage._arg0!, (ByReference*)&byrefStorage, parameters, binderBundle); +#pragma warning restore 8500 try { +#pragma warning disable 8500 ret = ref RawCalliHelper.Call(InvokeThunk, (void*)methodToCall, ref thisArg, ref ret, &byrefStorage); +#pragma warning restore 8500 DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } catch (Exception e) when (wrapInTargetInvocationException) @@ -268,7 +272,9 @@ namespace System.Reflection IntPtr* pStorage = stackalloc IntPtr[2 * argCount]; NativeMemory.Clear(pStorage, (nuint)(2 * argCount) * (nuint)sizeof(IntPtr)); - ByReference* pByRefStorage = (ByReference*)(pStorage + argCount); +#pragma warning disable 8500 + void* pByRefStorage = (ByReference*)(pStorage + argCount); +#pragma warning restore 8500 RuntimeImports.GCFrameRegistration regArgStorage = new(pStorage, (uint)argCount, areByRefs: false); RuntimeImports.GCFrameRegistration regByRefStorage = new(pByRefStorage, (uint)argCount, areByRefs: true); @@ -326,7 +332,7 @@ namespace System.Reflection private unsafe void CheckArguments( ref object copyOfParameters, - ByReference* byrefParameters, + void* byrefParameters, object?[] parameters, BinderBundle binderBundle) { @@ -398,8 +404,10 @@ namespace System.Reflection Unsafe.Add(ref copyOfParameters, i) = arg!; - byrefParameters[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? +#pragma warning disable 8500, 9094 + ((ByReference*)byrefParameters)[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ? ref Unsafe.As(ref Unsafe.Add(ref copyOfParameters, i)) : ref arg.GetRawData()); +#pragma warning restore 8500, 9094 } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj index ea167e0..605d407 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.Assets/ILCompiler.Compiler.Tests.Assets.csproj @@ -8,6 +8,7 @@ netstandard2.0 true + noRefSafetyRulesAttribute=true diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj index 5967b09..b09ef31 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj @@ -14,6 +14,7 @@ x86;x64 AnyCPU true + noRefSafetyRulesAttribute=true diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs index c19e7d0..f7e613f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs @@ -317,7 +317,7 @@ namespace System private int _length; private fixed uint _blocks[MaxBlockCount]; - public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) + public static void Add(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger result) { // determine which operand has the smaller length ref BigInteger large = ref (lhs._length < rhs._length) ? ref rhs : ref lhs; @@ -369,7 +369,7 @@ namespace System } } - public static int Compare(ref BigInteger lhs, ref BigInteger rhs) + public static int Compare(scoped ref BigInteger lhs, scoped ref BigInteger rhs) { Debug.Assert(unchecked((uint)(lhs._length)) <= MaxBlockCount); Debug.Assert(unchecked((uint)(rhs._length)) <= MaxBlockCount); @@ -427,7 +427,7 @@ namespace System return (lastIndex * BitsPerBlock) + CountSignificantBits(value._blocks[lastIndex]); } - public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger quo, out BigInteger rem) + public static void DivRem(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger quo, out BigInteger rem) { // This is modified from the libraries BigIntegerCalculator.DivRem.cs implementation: // https://github.com/dotnet/runtime/blob/main/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigIntegerCalculator.DivRem.cs @@ -558,6 +558,11 @@ namespace System if (digit > 0) { + // rem and rhs have different lifetimes here and compiler is warning + // about potential for one to copy into the other. This is a place + // ref scoped parameters would alleviate. + // https://github.com/dotnet/roslyn/issues/64393 +#pragma warning disable CS9080 // Now it's time to subtract our current quotient uint carry = SubtractDivisor(ref rem, n, ref rhs, digit); @@ -571,6 +576,7 @@ namespace System Debug.Assert(carry == 1); } +#pragma warning restore CS9080 } // We have the digit! @@ -693,7 +699,7 @@ namespace System return quotient; } - public static void Multiply(ref BigInteger lhs, uint value, out BigInteger result) + public static void Multiply(scoped ref BigInteger lhs, uint value, out BigInteger result) { if (lhs._length <= 1) { @@ -739,7 +745,7 @@ namespace System } } - public static void Multiply(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result) + public static void Multiply(scoped ref BigInteger lhs, scoped ref BigInteger rhs, out BigInteger result) { if (lhs._length <= 1) { @@ -1032,7 +1038,7 @@ namespace System Multiply(ref this, value, out this); } - public void Multiply(ref BigInteger value) + public void Multiply(scoped ref BigInteger value) { if (value._length <= 1) { @@ -1115,7 +1121,7 @@ namespace System } } - public static void SetValue(out BigInteger result, ref BigInteger value) + public static void SetValue(out BigInteger result, scoped ref BigInteger value) { int rhsLength = value._length; result._length = rhsLength; diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs index e88014c..bec85ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs @@ -794,7 +794,7 @@ namespace System 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648 }; - private static void AccumulateDecimalDigitsIntoBigInteger(ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result) + private static void AccumulateDecimalDigitsIntoBigInteger(scoped ref NumberBuffer number, uint firstIndex, uint lastIndex, out BigInteger result) { BigInteger.SetZero(out result); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs index 13ff9e3..98069a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs @@ -236,6 +236,7 @@ namespace System.Reflection shouldCopyBack[i] = copyBackArg; copyOfParameters[i] = arg; +#pragma warning disable 8500 if (isValueType) { #if !MONO // Temporary until Mono is updated. @@ -254,6 +255,7 @@ namespace System.Reflection ByReference objRef = ByReference.Create(ref copyOfParameters[i]); *(ByReference*)(byrefParameters + i) = objRef; } +#pragma warning restore 8500 } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs index b1f3222..1fd9c17 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs @@ -146,7 +146,9 @@ namespace System.Reflection Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, @@ -299,7 +301,9 @@ namespace System.Reflection Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs index 770a59d..bf534c5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.cs @@ -143,7 +143,9 @@ namespace System.Reflection Span shouldCopyBackParameters = new(ref argStorage._copyBack0, argCount); StackAllocatedByRefs byrefStorage = default; +#pragma warning disable 8500 IntPtr* pByRefStorage = (IntPtr*)&byrefStorage; +#pragma warning restore 8500 CheckArguments( copyOfParameters, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 9e9adcd..4706b64 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -15,7 +15,7 @@ namespace System.Text.Json /// Returns the span for the given reader. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ReadOnlySpan GetSpan(this ref Utf8JsonReader reader) + public static ReadOnlySpan GetSpan(this scoped ref Utf8JsonReader reader) { return reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs index 65c6fd3..7cd0e3b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteProperties.String.cs @@ -112,12 +112,12 @@ namespace System.Text.Json Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= propertyName.Length); char[]? propertyArray = null; + scoped Span escapedPropertyName; if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -269,12 +269,12 @@ namespace System.Text.Json Debug.Assert(int.MaxValue / JsonConstants.MaxExpansionFactorWhileEscaping >= utf8PropertyName.Length); byte[]? propertyArray = null; + scoped Span escapedPropertyName; if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1076,12 +1076,12 @@ namespace System.Text.Json char[]? valueArray = null; char[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocCharThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1096,11 +1096,12 @@ namespace System.Text.Json value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1135,12 +1136,12 @@ namespace System.Text.Json byte[]? valueArray = null; byte[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocByteThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1155,11 +1156,12 @@ namespace System.Text.Json utf8Value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1194,12 +1196,12 @@ namespace System.Text.Json byte[]? valueArray = null; char[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8Value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocByteThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1214,11 +1216,12 @@ namespace System.Text.Json utf8Value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(propertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocCharThreshold) { propertyArray = ArrayPool.Shared.Rent(length); @@ -1253,12 +1256,12 @@ namespace System.Text.Json char[]? valueArray = null; byte[]? propertyArray = null; + scoped Span escapedValue; if (firstEscapeIndexVal != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(value.Length, firstEscapeIndexVal); - scoped Span escapedValue; if (length > JsonConstants.StackallocCharThreshold) { valueArray = ArrayPool.Shared.Rent(length); @@ -1273,11 +1276,12 @@ namespace System.Text.Json value = escapedValue.Slice(0, written); } + scoped Span escapedPropertyName; + if (firstEscapeIndexProp != -1) { int length = JsonWriterHelper.GetMaxEscapedLength(utf8PropertyName.Length, firstEscapeIndexProp); - scoped Span escapedPropertyName; if (length > JsonConstants.StackallocByteThreshold) { propertyArray = ArrayPool.Shared.Rent(length); diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs index 7c65c63..72a6199 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCaseEquivalences.cs @@ -33,7 +33,7 @@ namespace System.Text.RegularExpressions /// If is involved in case conversion, then equivalences will contain the /// span of character which should be considered equal to in a case-insensitive comparison. /// if is involved in case conversion; otherwise, - public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan equivalences) + public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, scoped ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan equivalences) { if ((c | 0x20) == 'i' || (c | 0x01) == '\u0131') { -- 2.7.4