Skip to content

Commit

Permalink
Make return and out equivalent for ref safety
Browse files Browse the repository at this point in the history
dotnet/roslyn#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.
  • Loading branch information
jaredpar committed Sep 30, 2022
1 parent 4b8b2ff commit 446e31e
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,10 @@ private unsafe void CheckArguments(

Unsafe.Add(ref copyOfParameters, i) = arg!;

#pragma warning disable 8500
#pragma warning disable 8500, 9094
((ByReference*)byrefParameters)[i] = new ByReference(ref (argumentInfo.Transform & Transform.Reference) != 0 ?
ref Unsafe.As<object, byte>(ref Unsafe.Add(ref copyOfParameters, i)) : ref arg.GetRawData());
#pragma warning restore 8500
#pragma warning restore 8500, 9094
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ internal unsafe ref struct BigInteger
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;
Expand Down Expand Up @@ -369,7 +369,7 @@ public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger re
}
}

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);
Expand Down Expand Up @@ -427,7 +427,7 @@ public static uint CountSignificantBits(ref BigInteger value)
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
Expand Down Expand Up @@ -558,6 +558,11 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger

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);

Expand All @@ -571,6 +576,7 @@ public static void DivRem(ref BigInteger lhs, ref BigInteger rhs, out BigInteger

Debug.Assert(carry == 1);
}
#pragma warning restore CS9080
}

// We have the digit!
Expand Down Expand Up @@ -693,7 +699,7 @@ public static uint HeuristicDivide(ref BigInteger dividend, ref BigInteger divis
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)
{
Expand Down Expand Up @@ -739,7 +745,7 @@ public static void Multiply(ref BigInteger lhs, uint value, out BigInteger resul
}
}

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)
{
Expand Down Expand Up @@ -1032,7 +1038,7 @@ public void Multiply(uint value)
Multiply(ref this, value, out this);
}

public void Multiply(ref BigInteger value)
public void Multiply(scoped ref BigInteger value)
{
if (value._length <= 1)
{
Expand Down Expand Up @@ -1115,7 +1121,7 @@ public static void SetUInt64(out BigInteger result, ulong value)
}
}

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int m
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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ internal static partial class RegexCaseEquivalences
/// <param name="equivalences">If <paramref name="c"/> is involved in case conversion, then equivalences will contain the
/// span of character which should be considered equal to <paramref name="c"/> in a case-insensitive comparison.</param>
/// <returns><see langword="true"/> if <paramref name="c"/> is involved in case conversion; otherwise, <see langword="false"/></returns>
public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan<char> equivalences)
public static bool TryFindCaseEquivalencesForCharWithIBehavior(char c, CultureInfo culture, scoped ref RegexCaseBehavior mappingBehavior, out ReadOnlySpan<char> equivalences)
{
if ((c | 0x20) == 'i' || (c | 0x01) == '\u0131')
{
Expand Down

0 comments on commit 446e31e

Please sign in to comment.