diff --git a/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator_RefSafety.cs b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator_RefSafety.cs
new file mode 100644
index 0000000000000..07ea26d9bc8f0
--- /dev/null
+++ b/src/Compilers/CSharp/Portable/CodeGen/CodeGenerator_RefSafety.cs
@@ -0,0 +1,114 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Immutable;
+using Microsoft.CodeAnalysis.CSharp.Symbols;
+
+namespace Microsoft.CodeAnalysis.CSharp.CodeGen;
+
+internal partial class CodeGenerator
+{
+ ///
+ private static bool MightEscapeTemporaryRefs(BoundCall node, bool used)
+ {
+ return MightEscapeTemporaryRefs(
+ used: used,
+ returnType: node.Type,
+ returnRefKind: node.Method.RefKind,
+ thisParameterSymbol: node.Method.TryGetThisParameter(out var thisParameter) ? thisParameter : null,
+ parameters: node.Method.Parameters);
+ }
+
+ ///
+ private static bool MightEscapeTemporaryRefs(BoundObjectCreationExpression node, bool used)
+ {
+ return MightEscapeTemporaryRefs(
+ used: used,
+ returnType: node.Type,
+ returnRefKind: RefKind.None,
+ thisParameterSymbol: null,
+ parameters: node.Constructor.Parameters);
+ }
+
+ ///
+ private static bool MightEscapeTemporaryRefs(BoundFunctionPointerInvocation node, bool used)
+ {
+ FunctionPointerMethodSymbol method = node.FunctionPointer.Signature;
+ return MightEscapeTemporaryRefs(
+ used: used,
+ returnType: node.Type,
+ returnRefKind: method.RefKind,
+ thisParameterSymbol: null,
+ parameters: method.Parameters);
+ }
+
+ ///
+ /// Determines whether a 'ref' can be captured by the call (considering only its signature).
+ ///
+ ///
+ ///
+ /// The emit layer consults this to avoid reusing temporaries that are passed by ref to such methods.
+ ///
+ ///
+ /// This is a heuristic which might have false positives, i.e.,
+ /// it might not recognize that a call cannot capture a 'ref'
+ /// even if the binding-time ref safety analysis would recognize that.
+ /// That is fine, the IL will be correct, albeit less optimal (it might use more temps).
+ /// But we still want some heuristic to avoid regressing IL of common safe cases.
+ ///
+ ///
+ private static bool MightEscapeTemporaryRefs(
+ bool used,
+ TypeSymbol returnType,
+ RefKind returnRefKind,
+ ParameterSymbol? thisParameterSymbol,
+ ImmutableArray parameters)
+ {
+ // whether we have any outputs that can capture `ref`s
+ bool anyRefTargets = false;
+ // whether we have any inputs that can contain `ref`s
+ bool anyRefSources = false;
+
+ if (used && (returnRefKind != RefKind.None || returnType.IsRefLikeOrAllowsRefLikeType()))
+ {
+ // If returning by ref or returning a ref struct, the result might capture `ref`s.
+ anyRefTargets = true;
+ }
+
+ if (thisParameterSymbol is not null && processParameter(thisParameterSymbol, anyRefSources: ref anyRefSources, anyRefTargets: ref anyRefTargets))
+ {
+ return true;
+ }
+
+ foreach (var parameter in parameters)
+ {
+ if (processParameter(parameter, anyRefSources: ref anyRefSources, anyRefTargets: ref anyRefTargets))
+ {
+ return true;
+ }
+ }
+
+ return false;
+
+ // Returns true if we can return 'true' early.
+ static bool processParameter(ParameterSymbol parameter, ref bool anyRefSources, ref bool anyRefTargets)
+ {
+ if (parameter.Type.IsRefLikeOrAllowsRefLikeType() && parameter.EffectiveScope != ScopedKind.ScopedValue)
+ {
+ anyRefSources = true;
+ if (parameter.RefKind.IsWritableReference())
+ {
+ anyRefTargets = true;
+ }
+ }
+ else if (parameter.RefKind != RefKind.None && parameter.EffectiveScope == ScopedKind.None)
+ {
+ anyRefSources = true;
+ }
+
+ // If there is at least one output and at least one input, a `ref` can be captured.
+ return anyRefTargets && anyRefSources;
+ }
+ }
+}
diff --git a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
index 86b3e463535e1..b984244ad4d74 100644
--- a/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
+++ b/src/Compilers/CSharp/Portable/CodeGen/EmitExpression.cs
@@ -1660,7 +1660,13 @@ private void EmitStaticCallExpression(BoundCall call, UseKind useKind)
Debug.Assert(method.IsStatic);
+ var countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
EmitArguments(arguments, method.Parameters, call.ArgumentRefKindsOpt);
+
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore,
+ MightEscapeTemporaryRefs(call, used: useKind != UseKind.Unused));
+
int stackBehavior = GetCallStackBehavior(method, arguments);
if (method.IsAbstract || method.IsVirtual)
@@ -1690,6 +1696,8 @@ private void EmitInstanceCallExpression(BoundCall call, UseKind useKind)
bool box;
LocalDefinition tempOpt;
+ var countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
if (receiverIsInstanceCall(call, out BoundCall nested))
{
var calls = ArrayBuilder.GetInstance();
@@ -1755,6 +1763,11 @@ private void EmitInstanceCallExpression(BoundCall call, UseKind useKind)
}
emitArgumentsAndCallEpilogue(call, callKind, receiverUseKind);
+
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore, MightEscapeTemporaryRefs(call, used: true));
+
+ countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
FreeOptTemp(tempOpt);
tempOpt = null;
@@ -1815,6 +1828,9 @@ private void EmitInstanceCallExpression(BoundCall call, UseKind useKind)
}
emitArgumentsAndCallEpilogue(call, callKind, useKind);
+
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore, MightEscapeTemporaryRefs(call, used: useKind != UseKind.Unused));
+
FreeOptTemp(tempOpt);
return;
@@ -2446,8 +2462,14 @@ private void EmitObjectCreationExpression(BoundObjectCreationExpression expressi
}
// none of the above cases, so just create an instance
+
+ var countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
EmitArguments(expression.Arguments, constructor.Parameters, expression.ArgumentRefKindsOpt);
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore,
+ MightEscapeTemporaryRefs(expression, used));
+
var stackAdjustment = GetObjCreationStackBehavior(expression);
_builder.EmitOpCode(ILOpCode.Newobj, stackAdjustment);
@@ -2704,7 +2726,14 @@ private bool TryInPlaceCtorCall(BoundExpression target, BoundObjectCreationExpre
Debug.Assert(temp == null, "in-place ctor target should not create temps");
var constructor = objCreation.Constructor;
+
+ var countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
EmitArguments(objCreation.Arguments, constructor.Parameters, objCreation.ArgumentRefKindsOpt);
+
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore,
+ MightEscapeTemporaryRefs(objCreation, used));
+
// -2 to adjust for consumed target address and not produced value.
var stackAdjustment = GetObjCreationStackBehavior(objCreation) - 2;
_builder.EmitOpCode(ILOpCode.Call, stackAdjustment);
@@ -4026,7 +4055,14 @@ private void EmitCalli(BoundFunctionPointerInvocation ptrInvocation, UseKind use
}
FunctionPointerMethodSymbol method = ptrInvocation.FunctionPointer.Signature;
+
+ var countBefore = _builder.LocalSlotManager.StartScopeOfTrackingAddressedLocals();
+
EmitArguments(ptrInvocation.Arguments, method.Parameters, ptrInvocation.ArgumentRefKindsOpt);
+
+ _builder.LocalSlotManager.EndScopeOfTrackingAddressedLocals(countBefore,
+ MightEscapeTemporaryRefs(ptrInvocation, used: useKind != UseKind.Unused));
+
var stackBehavior = GetCallStackBehavior(ptrInvocation.FunctionPointer.Signature, ptrInvocation.Arguments);
if (temp is object)
diff --git a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs
index b3359712b498d..87cd14d63032f 100644
--- a/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs
@@ -368,6 +368,20 @@ public override ImmutableArray Parameters
}
}
+ internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
+ {
+ if (UnderlyingMethod.TryGetThisParameter(out ParameterSymbol? underlyingThisParameter))
+ {
+ thisParameter = underlyingThisParameter != null
+ ? new ThisParameterSymbol(this, _container)
+ : null;
+ return true;
+ }
+
+ thisParameter = null;
+ return false;
+ }
+
public override ImmutableArray ExplicitInterfaceImplementations => ImmutableArray.Empty;
public override ImmutableArray RefCustomModifiers => UnderlyingMethod.RefCustomModifiers;
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenInParametersTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenInParametersTests.cs
index 1f87e26e45231..b34b097c130ad 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenInParametersTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenInParametersTests.cs
@@ -861,7 +861,8 @@ static ref readonly int M(in int x)
// Code size 72 (0x48)
.maxstack 3
.locals init (int V_0,
- int V_1)
+ int V_1,
+ int V_2)
IL_0000: ldc.i4.s 42
IL_0002: stloc.0
IL_0003: ldloca.s V_0
@@ -870,22 +871,22 @@ .locals init (int V_0,
IL_000b: call ""void System.Console.WriteLine(int)""
IL_0010: newobj ""Program..ctor()""
IL_0015: ldc.i4.5
- IL_0016: stloc.0
- IL_0017: ldloca.s V_0
+ IL_0016: stloc.1
+ IL_0017: ldloca.s V_1
IL_0019: ldc.i4.6
- IL_001a: stloc.1
- IL_001b: ldloca.s V_1
+ IL_001a: stloc.2
+ IL_001b: ldloca.s V_2
IL_001d: call ""int Program.this[in int, in int].get""
IL_0022: call ""void System.Console.WriteLine(int)""
IL_0027: ldc.i4.s 42
- IL_0029: stloc.0
- IL_002a: ldloca.s V_0
+ IL_0029: stloc.1
+ IL_002a: ldloca.s V_1
IL_002c: call ""ref readonly int Program.M(in int)""
IL_0031: ldind.i4
IL_0032: call ""void System.Console.WriteLine(int)""
IL_0037: ldc.i4.s 42
- IL_0039: stloc.0
- IL_003a: ldloca.s V_0
+ IL_0039: stloc.2
+ IL_003a: ldloca.s V_2
IL_003c: call ""ref readonly int Program.M(in int)""
IL_0041: ldind.i4
IL_0042: call ""void System.Console.WriteLine(int)""
diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
index 292b8336a9ee2..41b3ab5677a5b 100644
--- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
+++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests.cs
@@ -9525,7 +9525,8 @@ .locals init (System.ReadOnlySpan V_0, //y
System.ReadOnlySpan V_3,
int V_4,
int[] V_5,
- System.Span V_6)
+ System.Span V_6,
+ System.Span V_7)
IL_0000: ldtoken ".__StaticArrayInitTypeSize=8_Align=4 .34FB5C825DE7CA4AEA6E712F19D439C1DA0C92C37B423936C5F618545CA4FA1F4"
IL_0005: call "System.ReadOnlySpan System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan(System.RuntimeFieldHandle)"
IL_000a: stloc.0
@@ -9561,8 +9562,8 @@ .locals init (System.ReadOnlySpan V_0, //y
IL_0056: ldloca.s V_3
IL_0058: ldloc.s V_5
IL_005a: newobj "System.Span..ctor(int[])"
- IL_005f: stloc.s V_6
- IL_0061: ldloca.s V_6
+ IL_005f: stloc.s V_7
+ IL_0061: ldloca.s V_7
IL_0063: ldloc.s V_4
IL_0065: ldloca.s V_3
IL_0067: call "int System.ReadOnlySpan.Length.get"
@@ -11541,7 +11542,8 @@ .locals init (System.Collections.Generic.List V_0,
T[] V_2,
System.Span V_3,
System.Span V_4,
- System.Span V_5)
+ System.Span V_5,
+ System.Span V_6)
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: stloc.0
@@ -11577,8 +11579,8 @@ .locals init (System.Collections.Generic.List V_0,
IL_004e: ldloca.s V_4
IL_0050: ldloc.2
IL_0051: newobj "System.Span..ctor(T[])"
- IL_0056: stloc.s V_5
- IL_0058: ldloca.s V_5
+ IL_0056: stloc.s V_6
+ IL_0058: ldloca.s V_6
IL_005a: ldloc.1
IL_005b: ldloca.s V_4
IL_005d: call "int System.Span.Length.get"
@@ -11645,7 +11647,8 @@ .locals init (int[] V_0,
int V_10,
int V_11,
int V_12,
- int V_13)
+ int V_13,
+ System.Span V_14)
IL_0000: ldstr "A"
IL_0005: ldc.i4.2
IL_0006: newarr "int"
@@ -11762,8 +11765,8 @@ .locals init (int[] V_0,
IL_0105: ldloca.s V_6
IL_0107: ldloc.s V_4
IL_0109: newobj "System.Span..ctor(int[])"
- IL_010e: stloc.s V_7
- IL_0110: ldloca.s V_7
+ IL_010e: stloc.s V_14
+ IL_0110: ldloca.s V_14
IL_0112: ldloc.3
IL_0113: ldloca.s V_6
IL_0115: call "int System.Span.Length.get"
@@ -33712,7 +33715,8 @@ .locals init (System.ReadOnlySpan V_0, //li1
System.ReadOnlySpan V_3,
int V_4,
int[] V_5,
- System.Span V_6)
+ System.Span V_6,
+ System.Span V_7)
IL_0000: ldtoken ".__StaticArrayInitTypeSize=12_Align=4 .4636993D3E1DA4E9D6B8F87B79E8F7C6D018580D52661950EABC3845C5897A4D4"
IL_0005: call "System.ReadOnlySpan System.Runtime.CompilerServices.RuntimeHelpers.CreateSpan(System.RuntimeFieldHandle)"
IL_000a: stloc.0
@@ -33754,8 +33758,8 @@ .locals init (System.ReadOnlySpan V_0, //li1
IL_006d: ldloca.s V_3
IL_006f: ldloc.s V_5
IL_0071: newobj "System.Span..ctor(int[])"
- IL_0076: stloc.s V_6
- IL_0078: ldloca.s V_6
+ IL_0076: stloc.s V_7
+ IL_0078: ldloca.s V_7
IL_007a: ldloc.s V_4
IL_007c: ldloca.s V_3
IL_007e: call "int System.ReadOnlySpan.Length.get"
@@ -33811,7 +33815,8 @@ .locals init (System.ReadOnlySpan V_0, //li1
C[] V_6,
System.ReadOnlySpan.Enumerator V_7,
D V_8,
- System.ReadOnlySpan V_9)
+ System.ReadOnlySpan.Enumerator V_9,
+ System.ReadOnlySpan V_10)
IL_0000: newobj "D..ctor()"
IL_0005: stloc.1
IL_0006: ldloca.s V_1
@@ -33854,9 +33859,9 @@ .locals init (System.ReadOnlySpan V_0, //li1
IL_0061: brtrue.s IL_0043
IL_0063: ldloca.s V_4
IL_0065: call "System.ReadOnlySpan.Enumerator System.ReadOnlySpan.GetEnumerator()"
- IL_006a: stloc.s V_7
+ IL_006a: stloc.s V_9
IL_006c: br.s IL_0085
- IL_006e: ldloca.s V_7
+ IL_006e: ldloca.s V_9
IL_0070: call "ref readonly D System.ReadOnlySpan.Enumerator.Current.get"
IL_0075: ldind.ref
IL_0076: stloc.s V_8
@@ -33868,13 +33873,13 @@ .locals init (System.ReadOnlySpan V_0, //li1
IL_0081: ldc.i4.1
IL_0082: add
IL_0083: stloc.s V_5
- IL_0085: ldloca.s V_7
+ IL_0085: ldloca.s V_9
IL_0087: call "bool System.ReadOnlySpan.Enumerator.MoveNext()"
IL_008c: brtrue.s IL_006e
IL_008e: ldloc.s V_6
IL_0090: call "System.ReadOnlySpan System.ReadOnlySpan.op_Implicit(C[])"
- IL_0095: stloc.s V_9
- IL_0097: ldloca.s V_9
+ IL_0095: stloc.s V_10
+ IL_0097: ldloca.s V_10
IL_0099: call "void CollectionExtensions.Report(in System.ReadOnlySpan)"
IL_009e: ret
}
@@ -34231,7 +34236,8 @@ .locals init (Base[] V_0,
int V_3,
Base[] V_4,
System.ReadOnlySpan V_5,
- System.Span V_6)
+ System.Span V_6,
+ System.Span V_7)
IL_0000: ldc.i4.1
IL_0001: newarr "Derived"
IL_0006: dup
@@ -34283,8 +34289,8 @@ .locals init (Base[] V_0,
IL_006a: ldloca.s V_5
IL_006c: ldloc.s V_4
IL_006e: newobj "System.Span..ctor(Base[])"
- IL_0073: stloc.s V_6
- IL_0075: ldloca.s V_6
+ IL_0073: stloc.s V_7
+ IL_0075: ldloca.s V_7
IL_0077: ldloc.3
IL_0078: ldloca.s V_5
IL_007a: call "int System.ReadOnlySpan.Length.get"
@@ -35283,7 +35289,8 @@ .locals init (int[] V_0,
int[] V_3,
System.ReadOnlySpan V_4,
System.ReadOnlySpan V_5,
- System.Span V_6)
+ System.Span V_6,
+ System.Span V_7)
IL_0000: ldc.i4.2
IL_0001: newarr "int"
IL_0006: dup
@@ -35335,8 +35342,8 @@ .locals init (int[] V_0,
IL_005f: ldloca.s V_5
IL_0061: ldloc.3
IL_0062: newobj "System.Span..ctor(int[])"
- IL_0067: stloc.s V_6
- IL_0069: ldloca.s V_6
+ IL_0067: stloc.s V_7
+ IL_0069: ldloca.s V_7
IL_006b: ldloc.2
IL_006c: ldloca.s V_5
IL_006e: call "int System.ReadOnlySpan.Length.get"
@@ -35564,7 +35571,8 @@ .locals init (int V_0,
System.ReadOnlySpan V_6,
System.Runtime.CompilerServices.TaskAwaiter V_7,
System.Span V_8,
- System.Exception V_9)
+ System.Span V_9,
+ System.Exception V_10)
IL_0000: ldarg.0
IL_0001: ldfld "int C.d__0.<>1__state"
IL_0006: stloc.0
@@ -35659,8 +35667,8 @@ .locals init (int V_0,
IL_00ea: ldarg.0
IL_00eb: ldfld "int[] C.d__0.<>7__wrap4"
IL_00f0: newobj "System.Span..ctor(int[])"
- IL_00f5: stloc.s V_8
- IL_00f7: ldloca.s V_8
+ IL_00f5: stloc.s V_9
+ IL_00f7: ldloca.s V_9
IL_00f9: ldloc.s V_4
IL_00fb: ldloca.s V_6
IL_00fd: call "int System.ReadOnlySpan.Length.get"
@@ -35739,13 +35747,13 @@ .locals init (int V_0,
}
catch System.Exception
{
- IL_01c5: stloc.s V_9
+ IL_01c5: stloc.s V_10
IL_01c7: ldarg.0
IL_01c8: ldc.i4.s -2
IL_01ca: stfld "int C.d__0.<>1__state"
IL_01cf: ldarg.0
IL_01d0: ldflda "System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"
- IL_01d5: ldloc.s V_9
+ IL_01d5: ldloc.s V_10
IL_01d7: call "void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"
IL_01dc: leave.s IL_01f1
}
@@ -35872,13 +35880,14 @@ static void Main()
verifier.VerifyDiagnostics();
verifier.VerifyIL("C.Main", """
{
- // Code size 146 (0x92)
+ // Code size 147 (0x93)
.maxstack 4
.locals init (int V_0,
System.Span V_1,
int V_2,
System.Collections.Generic.List V_3,
- System.Span V_4)
+ System.Span V_4,
+ System.Span V_5)
IL_0000: ldc.i4.3
IL_0001: stloc.0
IL_0002: ldloc.0
@@ -35928,27 +35937,27 @@ .locals init (int V_0,
IL_0055: call "void System.Runtime.InteropServices.CollectionsMarshal.SetCount(System.Collections.Generic.List, int)"
IL_005a: ldloc.3
IL_005b: call "System.Span System.Runtime.InteropServices.CollectionsMarshal.AsSpan(System.Collections.Generic.List)"
- IL_0060: stloc.1
- IL_0061: ldc.i4.0
- IL_0062: stloc.0
- IL_0063: call "System.Span System.Runtime.InteropServices.CollectionsMarshal.AsSpan(System.Collections.Generic.List)"
- IL_0068: stloc.s V_4
- IL_006a: ldloca.s V_4
- IL_006c: ldloca.s V_1
- IL_006e: ldloc.0
- IL_006f: ldloca.s V_4
- IL_0071: call "int System.Span.Length.get"
- IL_0076: call "System.Span System.Span.Slice(int, int)"
- IL_007b: call "void System.Span.CopyTo(System.Span)"
- IL_0080: ldloc.0
- IL_0081: ldloca.s V_4
- IL_0083: call "int System.Span.Length.get"
- IL_0088: add
- IL_0089: stloc.0
- IL_008a: ldloc.3
- IL_008b: ldc.i4.0
- IL_008c: call "void CollectionExtensions.Report(object, bool)"
- IL_0091: ret
+ IL_0060: stloc.s V_4
+ IL_0062: ldc.i4.0
+ IL_0063: stloc.0
+ IL_0064: call "System.Span System.Runtime.InteropServices.CollectionsMarshal.AsSpan(System.Collections.Generic.List)"
+ IL_0069: stloc.s V_5
+ IL_006b: ldloca.s V_5
+ IL_006d: ldloca.s V_4
+ IL_006f: ldloc.0
+ IL_0070: ldloca.s V_5
+ IL_0072: call "int System.Span.Length.get"
+ IL_0077: call "System.Span System.Span.Slice(int, int)"
+ IL_007c: call "void System.Span.CopyTo(System.Span)"
+ IL_0081: ldloc.0
+ IL_0082: ldloca.s V_5
+ IL_0084: call "int System.Span.Length.get"
+ IL_0089: add
+ IL_008a: stloc.0
+ IL_008b: ldloc.3
+ IL_008c: ldc.i4.0
+ IL_008d: call "void CollectionExtensions.Report(object, bool)"
+ IL_0092: ret
}
""");
}
@@ -37859,15 +37868,16 @@ static void Main()
// Ideally we'd like to be able to use *both* something like AddRange, *and* AsSpan/CopyTo/etc. while building the same target collection
verifier.VerifyIL("C.Main", """
{
- // Code size 181 (0xb5)
+ // Code size 182 (0xb6)
.maxstack 3
.locals init (int V_0,
System.Span V_1,
int V_2,
System.Collections.Generic.ICollection V_3,
System.Collections.Generic.List V_4,
- System.Collections.Generic.IEnumerator V_5,
- int V_6)
+ System.Span V_5,
+ System.Collections.Generic.IEnumerator V_6,
+ int V_7)
IL_0000: ldc.i4.3
IL_0001: stloc.0
IL_0002: ldloc.0
@@ -37920,49 +37930,49 @@ .locals init (int V_0,
IL_005a: call "void System.Runtime.InteropServices.CollectionsMarshal.SetCount(System.Collections.Generic.List, int)"
IL_005f: ldloc.s V_4
IL_0061: call "System.Span System.Runtime.InteropServices.CollectionsMarshal.AsSpan(System.Collections.Generic.List)"
- IL_0066: stloc.1
- IL_0067: ldc.i4.0
- IL_0068: stloc.0
- IL_0069: ldloc.3
- IL_006a: callvirt "System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator()"
- IL_006f: stloc.s V_5
+ IL_0066: stloc.s V_5
+ IL_0068: ldc.i4.0
+ IL_0069: stloc.0
+ IL_006a: ldloc.3
+ IL_006b: callvirt "System.Collections.Generic.IEnumerator System.Collections.Generic.IEnumerable.GetEnumerator()"
+ IL_0070: stloc.s V_6
.try
{
- IL_0071: br.s IL_008b
- IL_0073: ldloc.s V_5
- IL_0075: callvirt "int System.Collections.Generic.IEnumerator.Current.get"
- IL_007a: stloc.s V_6
- IL_007c: ldloca.s V_1
- IL_007e: ldloc.0
- IL_007f: call "ref int System.Span.this[int].get"
- IL_0084: ldloc.s V_6
- IL_0086: stind.i4
- IL_0087: ldloc.0
- IL_0088: ldc.i4.1
- IL_0089: add
- IL_008a: stloc.0
- IL_008b: ldloc.s V_5
- IL_008d: callvirt "bool System.Collections.IEnumerator.MoveNext()"
- IL_0092: brtrue.s IL_0073
- IL_0094: leave.s IL_00a2
+ IL_0072: br.s IL_008c
+ IL_0074: ldloc.s V_6
+ IL_0076: callvirt "int System.Collections.Generic.IEnumerator.Current.get"
+ IL_007b: stloc.s V_7
+ IL_007d: ldloca.s V_5
+ IL_007f: ldloc.0
+ IL_0080: call "ref int System.Span.this[int].get"
+ IL_0085: ldloc.s V_7
+ IL_0087: stind.i4
+ IL_0088: ldloc.0
+ IL_0089: ldc.i4.1
+ IL_008a: add
+ IL_008b: stloc.0
+ IL_008c: ldloc.s V_6
+ IL_008e: callvirt "bool System.Collections.IEnumerator.MoveNext()"
+ IL_0093: brtrue.s IL_0074
+ IL_0095: leave.s IL_00a3
}
finally
{
- IL_0096: ldloc.s V_5
- IL_0098: brfalse.s IL_00a1
- IL_009a: ldloc.s V_5
- IL_009c: callvirt "void System.IDisposable.Dispose()"
- IL_00a1: endfinally
+ IL_0097: ldloc.s V_6
+ IL_0099: brfalse.s IL_00a2
+ IL_009b: ldloc.s V_6
+ IL_009d: callvirt "void System.IDisposable.Dispose()"
+ IL_00a2: endfinally
}
- IL_00a2: ldloca.s V_1
- IL_00a4: ldloc.0
- IL_00a5: call "ref int System.Span.this[int].get"
- IL_00aa: ldc.i4.4
- IL_00ab: stind.i4
- IL_00ac: ldloc.s V_4
- IL_00ae: ldc.i4.0
- IL_00af: call "void CollectionExtensions.Report(object, bool)"
- IL_00b4: ret
+ IL_00a3: ldloca.s V_5
+ IL_00a5: ldloc.0
+ IL_00a6: call "ref int System.Span.this[int].get"
+ IL_00ab: ldc.i4.4
+ IL_00ac: stind.i4
+ IL_00ad: ldloc.s V_4
+ IL_00af: ldc.i4.0
+ IL_00b0: call "void CollectionExtensions.Report(object, bool)"
+ IL_00b5: ret
}
""");
}
diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs
index 027e23174b049..a9621b5999619 100644
--- a/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs
+++ b/src/Compilers/CSharp/Test/Emit3/Semantics/InlineArrayTests.cs
@@ -7339,13 +7339,14 @@ static async Task FromResult(T r)
verifier.VerifyIL("Program.d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext",
@"
{
- // Code size 208 (0xd0)
+ // Code size 209 (0xd1)
.maxstack 3
.locals init (int V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter V_2,
System.Span V_3,
- System.Exception V_4)
+ System.Span V_4,
+ System.Exception V_5)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.d__2.<>1__state""
IL_0006: stloc.0
@@ -7377,7 +7378,7 @@ .locals init (int V_0,
IL_0041: ldloca.s V_2
IL_0043: ldarg.0
IL_0044: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, Program.d__2>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.d__2)""
- IL_0049: leave IL_00cf
+ IL_0049: leave IL_00d0
IL_004e: ldarg.0
IL_004f: ldfld ""System.Runtime.CompilerServices.TaskAwaiter Program.d__2.<>u__1""
IL_0054: stloc.2
@@ -7402,36 +7403,36 @@ .locals init (int V_0,
IL_0087: ldc.i4.0
IL_0088: ldloc.1
IL_0089: call ""System.Span System.Span.Slice(int, int)""
- IL_008e: stloc.3
- IL_008f: ldloca.s V_3
- IL_0091: ldc.i4.0
- IL_0092: call ""ref int System.Span.this[int].get""
- IL_0097: ldc.i4.s 111
- IL_0099: stind.i4
- IL_009a: ldarg.0
- IL_009b: ldnull
- IL_009c: stfld ""C Program.d__2.<>7__wrap1""
- IL_00a1: leave.s IL_00bc
+ IL_008e: stloc.s V_4
+ IL_0090: ldloca.s V_4
+ IL_0092: ldc.i4.0
+ IL_0093: call ""ref int System.Span.this[int].get""
+ IL_0098: ldc.i4.s 111
+ IL_009a: stind.i4
+ IL_009b: ldarg.0
+ IL_009c: ldnull
+ IL_009d: stfld ""C Program.d__2.<>7__wrap1""
+ IL_00a2: leave.s IL_00bd
}
catch System.Exception
{
- IL_00a3: stloc.s V_4
- IL_00a5: ldarg.0
- IL_00a6: ldc.i4.s -2
- IL_00a8: stfld ""int Program.d__2.<>1__state""
- IL_00ad: ldarg.0
- IL_00ae: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
- IL_00b3: ldloc.s V_4
- IL_00b5: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
- IL_00ba: leave.s IL_00cf
+ IL_00a4: stloc.s V_5
+ IL_00a6: ldarg.0
+ IL_00a7: ldc.i4.s -2
+ IL_00a9: stfld ""int Program.d__2.<>1__state""
+ IL_00ae: ldarg.0
+ IL_00af: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
+ IL_00b4: ldloc.s V_5
+ IL_00b6: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_00bb: leave.s IL_00d0
}
- IL_00bc: ldarg.0
- IL_00bd: ldc.i4.s -2
- IL_00bf: stfld ""int Program.d__2.<>1__state""
- IL_00c4: ldarg.0
- IL_00c5: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
- IL_00ca: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
- IL_00cf: ret
+ IL_00bd: ldarg.0
+ IL_00be: ldc.i4.s -2
+ IL_00c0: stfld ""int Program.d__2.<>1__state""
+ IL_00c5: ldarg.0
+ IL_00c6: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
+ IL_00cb: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_00d0: ret
}
");
}
@@ -7482,7 +7483,8 @@ .locals init (int V_0,
int V_2,
System.Runtime.CompilerServices.TaskAwaiter V_3,
System.Span V_4,
- System.Exception V_5)
+ System.Span V_5,
+ System.Exception V_6)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.d__2.<>1__state""
IL_0006: stloc.0
@@ -7547,8 +7549,8 @@ .locals init (int V_0,
IL_0098: ldloc.2
IL_0099: sub
IL_009a: call ""System.Span System.Span.Slice(int, int)""
- IL_009f: stloc.s V_4
- IL_00a1: ldloca.s V_4
+ IL_009f: stloc.s V_5
+ IL_00a1: ldloca.s V_5
IL_00a3: ldc.i4.0
IL_00a4: call ""ref int System.Span.this[int].get""
IL_00a9: ldc.i4.s 111
@@ -7560,13 +7562,13 @@ .locals init (int V_0,
}
catch System.Exception
{
- IL_00b5: stloc.s V_5
+ IL_00b5: stloc.s V_6
IL_00b7: ldarg.0
IL_00b8: ldc.i4.s -2
IL_00ba: stfld ""int Program.d__2.<>1__state""
IL_00bf: ldarg.0
IL_00c0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
- IL_00c5: ldloc.s V_5
+ IL_00c5: ldloc.s V_6
IL_00c7: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_00cc: leave.s IL_00e1
}
@@ -7630,7 +7632,8 @@ .locals init (int V_0,
System.Runtime.CompilerServices.TaskAwaiter V_5,
System.Index V_6,
System.Span V_7,
- System.Exception V_8)
+ System.Span V_8,
+ System.Exception V_9)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.d__2.<>1__state""
IL_0006: stloc.0
@@ -7711,8 +7714,8 @@ .locals init (int V_0,
IL_00cc: ldloc.3
IL_00cd: ldloc.s V_4
IL_00cf: call ""System.Span System.Span.Slice(int, int)""
- IL_00d4: stloc.s V_7
- IL_00d6: ldloca.s V_7
+ IL_00d4: stloc.s V_8
+ IL_00d6: ldloca.s V_8
IL_00d8: ldc.i4.0
IL_00d9: call ""ref int System.Span.this[int].get""
IL_00de: ldc.i4.s 111
@@ -7724,13 +7727,13 @@ .locals init (int V_0,
}
catch System.Exception
{
- IL_00ea: stloc.s V_8
+ IL_00ea: stloc.s V_9
IL_00ec: ldarg.0
IL_00ed: ldc.i4.s -2
IL_00ef: stfld ""int Program.d__2.<>1__state""
IL_00f4: ldarg.0
IL_00f5: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
- IL_00fa: ldloc.s V_8
+ IL_00fa: ldloc.s V_9
IL_00fc: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_0101: leave.s IL_0116
}
@@ -7795,7 +7798,8 @@ .locals init (int V_0,
int V_2,
System.Runtime.CompilerServices.TaskAwaiter V_3,
System.Span V_4,
- System.Exception V_5)
+ System.Span V_5,
+ System.Exception V_6)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.d__2.<>1__state""
IL_0006: stloc.0
@@ -7872,8 +7876,8 @@ .locals init (int V_0,
IL_00c5: ldarg.0
IL_00c6: ldfld ""int Program.d__2.<>7__wrap2""
IL_00cb: call ""System.Span System.Span.Slice(int, int)""
- IL_00d0: stloc.s V_4
- IL_00d2: ldloca.s V_4
+ IL_00d0: stloc.s V_5
+ IL_00d2: ldloca.s V_5
IL_00d4: ldarg.0
IL_00d5: ldfld ""int Program.d__2.<>7__wrap3""
IL_00da: call ""ref int System.Span.this[int].get""
@@ -7886,13 +7890,13 @@ .locals init (int V_0,
}
catch System.Exception
{
- IL_00ea: stloc.s V_5
+ IL_00ea: stloc.s V_6
IL_00ec: ldarg.0
IL_00ed: ldc.i4.s -2
IL_00ef: stfld ""int Program.d__2.<>1__state""
IL_00f4: ldarg.0
IL_00f5: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__2.<>t__builder""
- IL_00fa: ldloc.s V_5
+ IL_00fa: ldloc.s V_6
IL_00fc: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_0101: leave.s IL_0116
}
@@ -7961,7 +7965,8 @@ .locals init (int V_0,
System.Index V_6,
System.Runtime.CompilerServices.TaskAwaiter V_7,
System.ReadOnlySpan V_8,
- System.Exception V_9)
+ System.ReadOnlySpan V_9,
+ System.Exception V_10)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.d__1.<>1__state""
IL_0006: stloc.0
@@ -8051,8 +8056,8 @@ .locals init (int V_0,
IL_00ee: ldarg.0
IL_00ef: ldfld ""int Program.d__1.<>7__wrap2""
IL_00f4: call ""System.ReadOnlySpan System.ReadOnlySpan.Slice(int, int)""
- IL_00f9: stloc.s V_8
- IL_00fb: ldloca.s V_8
+ IL_00f9: stloc.s V_9
+ IL_00fb: ldloca.s V_9
IL_00fd: ldloc.s V_5
IL_00ff: call ""ref readonly int System.ReadOnlySpan.this[int].get""
IL_0104: ldind.i4
@@ -8061,13 +8066,13 @@ .locals init (int V_0,
}
catch System.Exception
{
- IL_0108: stloc.s V_9
+ IL_0108: stloc.s V_10
IL_010a: ldarg.0
IL_010b: ldc.i4.s -2
IL_010d: stfld ""int Program.d__1.<>1__state""
IL_0112: ldarg.0
IL_0113: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.d__1.<>t__builder""
- IL_0118: ldloc.s V_9
+ IL_0118: ldloc.s V_10
IL_011a: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
IL_011f: leave.s IL_0135
}
@@ -8813,7 +8818,8 @@ static int M4(in int x, Buffer10 y)
// Code size 32 (0x20)
.maxstack 2
.locals init (Buffer10 V_0,
- int V_1)
+ int V_1,
+ Buffer10 V_2)
IL_0000: call ""Buffer10 Program.M3()""
IL_0005: stloc.0
IL_0006: ldloca.s V_0
@@ -8821,9 +8827,9 @@ .locals init (Buffer10 V_0,
IL_000d: ldind.i4
IL_000e: stloc.1
IL_000f: ldloca.s V_1
- IL_0011: ldloca.s V_0
+ IL_0011: ldloca.s V_2
IL_0013: initobj ""Buffer10""
- IL_0019: ldloc.0
+ IL_0019: ldloc.2
IL_001a: call ""int Program.M4(in int, Buffer10)""
IL_001f: ret
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs
index 1c2864d66eac5..7ae0f73ffafb3 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InterpolationTests.cs
@@ -3822,7 +3822,8 @@ public void NestedInterpolatedStrings_02(string expression)
.maxstack 4
.locals init (int V_0, //i1
int V_1, //i2
- System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_2)
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_2,
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_3)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldc.i4.2
@@ -3836,14 +3837,14 @@ .locals init (int V_0, //i1
IL_0010: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
IL_0015: ldloca.s V_2
IL_0017: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
- IL_001c: ldloca.s V_2
+ IL_001c: ldloca.s V_3
IL_001e: ldc.i4.0
IL_001f: ldc.i4.1
IL_0020: call ""System.Runtime.CompilerServices.DefaultInterpolatedStringHandler..ctor(int, int)""
- IL_0025: ldloca.s V_2
+ IL_0025: ldloca.s V_3
IL_0027: ldloc.1
IL_0028: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
- IL_002d: ldloca.s V_2
+ IL_002d: ldloca.s V_3
IL_002f: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
IL_0034: call ""string string.Concat(string, string)""
IL_0039: call ""void System.Console.WriteLine(string)""
@@ -10151,14 +10152,15 @@ Creating DummyHandler from StructLogger#2
verifier.VerifyIL("", @"
{
- // Code size 175 (0xaf)
+ // Code size 177 (0xb1)
.maxstack 4
.locals init (int V_0, //i
StructLogger V_1, //s
StructLogger V_2,
DummyHandler V_3,
bool V_4,
- StructLogger& V_5)
+ StructLogger& V_5,
+ DummyHandler V_6)
IL_0000: ldc.i4.0
IL_0001: stloc.0
IL_0002: ldloca.s V_2
@@ -10207,32 +10209,32 @@ .locals init (int V_0, //i
IL_0064: ldobj ""StructLogger""
IL_0069: ldloca.s V_4
IL_006b: newobj ""DummyHandler..ctor(int, int, StructLogger, out bool)""
- IL_0070: stloc.3
- IL_0071: ldloc.s V_4
- IL_0073: brfalse.s IL_008f
- IL_0075: ldloca.s V_3
- IL_0077: ldstr ""log:""
- IL_007c: call ""void DummyHandler.AppendLiteral(string)""
- IL_0081: nop
- IL_0082: ldloca.s V_3
- IL_0084: ldloc.0
- IL_0085: dup
- IL_0086: ldc.i4.1
- IL_0087: add
- IL_0088: stloc.0
- IL_0089: call ""void DummyHandler.AppendFormatted(int)""
- IL_008e: nop
- IL_008f: ldloc.s V_5
- IL_0091: ldloc.3
- IL_0092: call ""void StructLogger.Log(DummyHandler)""
- IL_0097: nop
- IL_0098: ldstr ""(2) i={0}""
- IL_009d: ldloc.0
- IL_009e: box ""int""
- IL_00a3: call ""string string.Format(string, object)""
- IL_00a8: call ""void System.Console.WriteLine(string)""
- IL_00ad: nop
- IL_00ae: ret
+ IL_0070: stloc.s V_6
+ IL_0072: ldloc.s V_4
+ IL_0074: brfalse.s IL_0090
+ IL_0076: ldloca.s V_6
+ IL_0078: ldstr ""log:""
+ IL_007d: call ""void DummyHandler.AppendLiteral(string)""
+ IL_0082: nop
+ IL_0083: ldloca.s V_6
+ IL_0085: ldloc.0
+ IL_0086: dup
+ IL_0087: ldc.i4.1
+ IL_0088: add
+ IL_0089: stloc.0
+ IL_008a: call ""void DummyHandler.AppendFormatted(int)""
+ IL_008f: nop
+ IL_0090: ldloc.s V_5
+ IL_0092: ldloc.s V_6
+ IL_0094: call ""void StructLogger.Log(DummyHandler)""
+ IL_0099: nop
+ IL_009a: ldstr ""(2) i={0}""
+ IL_009f: ldloc.0
+ IL_00a0: box ""int""
+ IL_00a5: call ""string string.Format(string, object)""
+ IL_00aa: call ""void System.Console.WriteLine(string)""
+ IL_00af: nop
+ IL_00b0: ret
}
");
}
@@ -16800,13 +16802,14 @@ public void ParenthesizedAdditiveExpression_04()
verifier.VerifyIL("Program.<$>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
- // Code size 244 (0xf4)
+ // Code size 245 (0xf5)
.maxstack 4
.locals init (int V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter V_2,
System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_3,
- System.Exception V_4)
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_4,
+ System.Exception V_5)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.<$>d__0.<>1__state""
IL_0006: stloc.0
@@ -16839,7 +16842,7 @@ .locals init (int V_0,
IL_0042: ldloca.s V_2
IL_0044: ldarg.0
IL_0045: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, Program.<$>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.<$>d__0)""
- IL_004a: leave IL_00f3
+ IL_004a: leave IL_00f4
IL_004f: ldarg.0
IL_0050: ldfld ""System.Runtime.CompilerServices.TaskAwaiter Program.<$>d__0.<>u__1""
IL_0055: stloc.2
@@ -16871,36 +16874,36 @@ .locals init (int V_0,
IL_009f: ldc.i4.0
IL_00a0: ldc.i4.1
IL_00a1: newobj ""System.Runtime.CompilerServices.DefaultInterpolatedStringHandler..ctor(int, int)""
- IL_00a6: stloc.3
- IL_00a7: ldloca.s V_3
- IL_00a9: ldarg.0
- IL_00aa: ldfld ""int Program.<$>d__0.5__3""
- IL_00af: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
- IL_00b4: ldloca.s V_3
- IL_00b6: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
- IL_00bb: call ""string string.Concat(string, string, string)""
- IL_00c0: call ""void System.Console.WriteLine(string)""
- IL_00c5: leave.s IL_00e0
+ IL_00a6: stloc.s V_4
+ IL_00a8: ldloca.s V_4
+ IL_00aa: ldarg.0
+ IL_00ab: ldfld ""int Program.<$>d__0.5__3""
+ IL_00b0: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
+ IL_00b5: ldloca.s V_4
+ IL_00b7: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
+ IL_00bc: call ""string string.Concat(string, string, string)""
+ IL_00c1: call ""void System.Console.WriteLine(string)""
+ IL_00c6: leave.s IL_00e1
}
catch System.Exception
{
- IL_00c7: stloc.s V_4
- IL_00c9: ldarg.0
- IL_00ca: ldc.i4.s -2
- IL_00cc: stfld ""int Program.<$>d__0.<>1__state""
- IL_00d1: ldarg.0
- IL_00d2: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
- IL_00d7: ldloc.s V_4
- IL_00d9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
- IL_00de: leave.s IL_00f3
+ IL_00c8: stloc.s V_5
+ IL_00ca: ldarg.0
+ IL_00cb: ldc.i4.s -2
+ IL_00cd: stfld ""int Program.<$>d__0.<>1__state""
+ IL_00d2: ldarg.0
+ IL_00d3: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
+ IL_00d8: ldloc.s V_5
+ IL_00da: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_00df: leave.s IL_00f4
}
- IL_00e0: ldarg.0
- IL_00e1: ldc.i4.s -2
- IL_00e3: stfld ""int Program.<$>d__0.<>1__state""
- IL_00e8: ldarg.0
- IL_00e9: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
- IL_00ee: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
- IL_00f3: ret
+ IL_00e1: ldarg.0
+ IL_00e2: ldc.i4.s -2
+ IL_00e4: stfld ""int Program.<$>d__0.<>1__state""
+ IL_00e9: ldarg.0
+ IL_00ea: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
+ IL_00ef: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_00f4: ret
}");
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs
index 9770e5eb3930b..81c060e72a02b 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RawInterpolationTests_Handler.cs
@@ -2223,7 +2223,8 @@ public void NestedInterpolatedStrings_02(string expression)
.maxstack 4
.locals init (int V_0, //i1
int V_1, //i2
- System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_2)
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_2,
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_3)
IL_0000: ldc.i4.1
IL_0001: stloc.0
IL_0002: ldc.i4.2
@@ -2237,14 +2238,14 @@ .locals init (int V_0, //i1
IL_0010: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
IL_0015: ldloca.s V_2
IL_0017: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
- IL_001c: ldloca.s V_2
+ IL_001c: ldloca.s V_3
IL_001e: ldc.i4.0
IL_001f: ldc.i4.1
IL_0020: call ""System.Runtime.CompilerServices.DefaultInterpolatedStringHandler..ctor(int, int)""
- IL_0025: ldloca.s V_2
+ IL_0025: ldloca.s V_3
IL_0027: ldloc.1
IL_0028: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
- IL_002d: ldloca.s V_2
+ IL_002d: ldloca.s V_3
IL_002f: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
IL_0034: call ""string string.Concat(string, string)""
IL_0039: call ""void System.Console.WriteLine(string)""
@@ -12228,13 +12229,14 @@ public void ParenthesizedAdditiveExpression_04()
verifier.VerifyIL("Program.<$>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
- // Code size 244 (0xf4)
+ // Code size 245 (0xf5)
.maxstack 4
.locals init (int V_0,
int V_1,
System.Runtime.CompilerServices.TaskAwaiter V_2,
System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_3,
- System.Exception V_4)
+ System.Runtime.CompilerServices.DefaultInterpolatedStringHandler V_4,
+ System.Exception V_5)
IL_0000: ldarg.0
IL_0001: ldfld ""int Program.<$>d__0.<>1__state""
IL_0006: stloc.0
@@ -12267,7 +12269,7 @@ .locals init (int V_0,
IL_0042: ldloca.s V_2
IL_0044: ldarg.0
IL_0045: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted, Program.<$>d__0>(ref System.Runtime.CompilerServices.TaskAwaiter, ref Program.<$>d__0)""
- IL_004a: leave IL_00f3
+ IL_004a: leave IL_00f4
IL_004f: ldarg.0
IL_0050: ldfld ""System.Runtime.CompilerServices.TaskAwaiter Program.<$>d__0.<>u__1""
IL_0055: stloc.2
@@ -12299,36 +12301,36 @@ .locals init (int V_0,
IL_009f: ldc.i4.0
IL_00a0: ldc.i4.1
IL_00a1: newobj ""System.Runtime.CompilerServices.DefaultInterpolatedStringHandler..ctor(int, int)""
- IL_00a6: stloc.3
- IL_00a7: ldloca.s V_3
- IL_00a9: ldarg.0
- IL_00aa: ldfld ""int Program.<$>d__0.5__3""
- IL_00af: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
- IL_00b4: ldloca.s V_3
- IL_00b6: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
- IL_00bb: call ""string string.Concat(string, string, string)""
- IL_00c0: call ""void System.Console.WriteLine(string)""
- IL_00c5: leave.s IL_00e0
+ IL_00a6: stloc.s V_4
+ IL_00a8: ldloca.s V_4
+ IL_00aa: ldarg.0
+ IL_00ab: ldfld ""int Program.<$>d__0.5__3""
+ IL_00b0: call ""void System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.AppendFormatted(int)""
+ IL_00b5: ldloca.s V_4
+ IL_00b7: call ""string System.Runtime.CompilerServices.DefaultInterpolatedStringHandler.ToStringAndClear()""
+ IL_00bc: call ""string string.Concat(string, string, string)""
+ IL_00c1: call ""void System.Console.WriteLine(string)""
+ IL_00c6: leave.s IL_00e1
}
catch System.Exception
{
- IL_00c7: stloc.s V_4
- IL_00c9: ldarg.0
- IL_00ca: ldc.i4.s -2
- IL_00cc: stfld ""int Program.<$>d__0.<>1__state""
- IL_00d1: ldarg.0
- IL_00d2: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
- IL_00d7: ldloc.s V_4
- IL_00d9: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
- IL_00de: leave.s IL_00f3
+ IL_00c8: stloc.s V_5
+ IL_00ca: ldarg.0
+ IL_00cb: ldc.i4.s -2
+ IL_00cd: stfld ""int Program.<$>d__0.<>1__state""
+ IL_00d2: ldarg.0
+ IL_00d3: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
+ IL_00d8: ldloc.s V_5
+ IL_00da: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
+ IL_00df: leave.s IL_00f4
}
- IL_00e0: ldarg.0
- IL_00e1: ldc.i4.s -2
- IL_00e3: stfld ""int Program.<$>d__0.<>1__state""
- IL_00e8: ldarg.0
- IL_00e9: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
- IL_00ee: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
- IL_00f3: ret
+ IL_00e1: ldarg.0
+ IL_00e2: ldc.i4.s -2
+ IL_00e4: stfld ""int Program.<$>d__0.<>1__state""
+ IL_00e9: ldarg.0
+ IL_00ea: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program.<$>d__0.<>t__builder""
+ IL_00ef: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
+ IL_00f4: ret
}");
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
index 0b3a373b843a2..4ab1f964b7031 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RefEscapingTests.cs
@@ -11009,6 +11009,1099 @@ static R F2()
Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "1").WithLocation(18, 22));
}
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67435")]
+ public void RefTemp_Escapes()
+ {
+ var source = """
+ var r1 = new R(111);
+ var r2 = new R(222);
+ Report(r1.F, r2.F);
+
+ static void Report(int x, int y) => System.Console.WriteLine($"{x} {y}");
+
+ ref struct R(in int x)
+ {
+ public ref readonly int F = ref x;
+ }
+ """;
+ CompileAndVerify(source,
+ expectedOutput: RefFieldTests.IncludeExpectedOutput("111 222"),
+ targetFramework: TargetFramework.Net70,
+ verify: Verification.FailsPEVerify)
+ .VerifyDiagnostics()
+ // Needs two int temps.
+ .VerifyIL("", """
+ {
+ // Code size 43 (0x2b)
+ .maxstack 2
+ .locals init (R V_0, //r2
+ int V_1,
+ int V_2)
+ IL_0000: ldc.i4.s 111
+ IL_0002: stloc.1
+ IL_0003: ldloca.s V_1
+ IL_0005: newobj "R..ctor(in int)"
+ IL_000a: ldc.i4 0xde
+ IL_000f: stloc.2
+ IL_0010: ldloca.s V_2
+ IL_0012: newobj "R..ctor(in int)"
+ IL_0017: stloc.0
+ IL_0018: ldfld "ref readonly int R.F"
+ IL_001d: ldind.i4
+ IL_001e: ldloc.0
+ IL_001f: ldfld "ref readonly int R.F"
+ IL_0024: ldind.i4
+ IL_0025: call "void Program.<$>g__Report|0_0(int, int)"
+ IL_002a: ret
+ }
+ """);
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67435")]
+ public void RefTemp_CannotEscape_NonRefStruct()
+ {
+ var source = """
+ var r1 = new R(111);
+ var r2 = new R(222);
+
+ struct R(in int x)
+ {
+ public readonly int F = x;
+ }
+ """;
+ CompileAndVerify(source)
+ .VerifyDiagnostics()
+ // One int temp is enough.
+ .VerifyIL("", """
+ {
+ // Code size 26 (0x1a)
+ .maxstack 1
+ .locals init (int V_0)
+ IL_0000: ldc.i4.s 111
+ IL_0002: stloc.0
+ IL_0003: ldloca.s V_0
+ IL_0005: newobj "R..ctor(in int)"
+ IL_000a: pop
+ IL_000b: ldc.i4 0xde
+ IL_0010: stloc.0
+ IL_0011: ldloca.s V_0
+ IL_0013: newobj "R..ctor(in int)"
+ IL_0018: pop
+ IL_0019: ret
+ }
+ """);
+ }
+
+ [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/67435")]
+ public void RefTemp_CannotEscape_UnusedResult()
+ {
+ var source = """
+ new R(111);
+ new R(222);
+
+ ref struct R
+ {
+ public R(in int x) { }
+ }
+ """;
+ CompileAndVerify(source)
+ .VerifyDiagnostics()
+ // One int temp is enough.
+ .VerifyIL("