未验证 提交 64b378ea 编写于 作者: V Vladimir Sadov 提交者: GitHub

Merge pull request #24273 from VSadov/fixSpill

Fix a case where the stack spiller spills more than needed. (possibly resulting in false errors)
......@@ -453,15 +453,21 @@ private BoundStatement UpdateStatement(BoundSpillSequenceBuilder builder, BoundS
bool forceSpill = false,
bool sideEffectsOnly = false)
{
Debug.Assert(!sideEffectsOnly || refKinds.IsDefault);
Debug.Assert(refKinds.IsDefault || refKinds.Length == args.Length);
if (args.Length == 0)
{
return args;
}
var newList = VisitList(args);
Debug.Assert(newList.Length == args.Length);
int lastSpill;
if (forceSpill)
{
lastSpill = newList.Length - 1;
lastSpill = newList.Length;
}
else
{
......@@ -486,22 +492,33 @@ private BoundStatement UpdateStatement(BoundSpillSequenceBuilder builder, BoundS
builder = new BoundSpillSequenceBuilder();
}
var result = ArrayBuilder<BoundExpression>.GetInstance();
for (int i = 0; i <= lastSpill; i++)
var result = ArrayBuilder<BoundExpression>.GetInstance(newList.Length);
// everything up until the last spill must be spilled entirely
for (int i = 0; i < lastSpill; i++)
{
var refKind = refKinds.IsDefault ? RefKind.None : refKinds[i];
var replacement = Spill(builder, newList[i], refKind, sideEffectsOnly);
Debug.Assert(sideEffectsOnly || replacement != null);
if (!sideEffectsOnly)
{
result.Add(replacement);
}
}
for (int i = lastSpill + 1; i < newList.Length; i++)
// the value of the last spill and everything that follows is not spilled
if (lastSpill < newList.Length)
{
result.Add(newList[i]);
var lastSpillNode = (BoundSpillSequenceBuilder)newList[lastSpill];
builder.Include(lastSpillNode);
result.Add(lastSpillNode.Value);
for (int i = lastSpill + 1; i < newList.Length; i++)
{
result.Add(newList[i]);
}
}
return result.ToImmutableAndFree();
......
......@@ -599,7 +599,7 @@ public static async Task<int> F(int[] array)
v.VerifyIL("Test.<F>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
{
// Code size 285 (0x11d)
// Code size 273 (0x111)
.maxstack 5
.locals init (int V_0,
int V_1,
......@@ -634,15 +634,15 @@ .maxstack 5
IL_0029: ldarg.0
IL_002a: ldarg.0
IL_002b: ldfld ""int[] Test.<F>d__2.array""
IL_0030: stfld ""int[] Test.<F>d__2.<>s__5""
IL_0030: stfld ""int[] Test.<F>d__2.<>s__4""
IL_0035: ldarg.0
IL_0036: ldfld ""int[] Test.<F>d__2.<>s__5""
IL_0036: ldfld ""int[] Test.<F>d__2.<>s__4""
IL_003b: ldc.i4.3
IL_003c: ldelem.i4
IL_003d: pop
IL_003e: ldarg.0
IL_003f: ldarg.0
IL_0040: ldfld ""int[] Test.<F>d__2.<>s__5""
IL_0040: ldfld ""int[] Test.<F>d__2.<>s__4""
IL_0045: ldc.i4.3
IL_0046: ldelem.i4
IL_0047: stfld ""int Test.<F>d__2.<>s__2""
......@@ -668,7 +668,7 @@ .maxstack 5
IL_007b: ldloca.s V_4
IL_007d: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<F>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<F>d__2)""
IL_0082: nop
IL_0083: leave IL_011c
IL_0083: leave IL_0110
>IL_0088: ldarg.0
IL_0089: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_008e: stloc.3
......@@ -685,55 +685,51 @@ .maxstack 5
IL_00a7: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00ac: stfld ""int Test.<F>d__2.<>s__3""
IL_00b1: ldarg.0
IL_00b2: ldarg.0
IL_00b3: ldfld ""int[] Test.<F>d__2.<>s__5""
IL_00b8: ldc.i4.3
IL_00b9: ldarg.0
IL_00ba: ldfld ""int Test.<F>d__2.<>s__2""
IL_00bf: ldarg.0
IL_00c0: ldfld ""int Test.<F>d__2.<>s__3""
IL_00c5: add
IL_00c6: dup
IL_00c7: stloc.2
IL_00c8: stelem.i4
IL_00c9: ldloc.2
IL_00ca: stfld ""int Test.<F>d__2.<>s__4""
IL_00cf: ldarg.0
IL_00d0: ldfld ""int Test.<F>d__2.<>s__1""
IL_00d5: ldarg.0
IL_00d6: ldfld ""int Test.<F>d__2.<>s__4""
IL_00db: ldc.i4.4
IL_00dc: call ""int Test.H(int, int, int)""
IL_00e1: pop
IL_00e2: ldarg.0
IL_00e3: ldnull
IL_00e4: stfld ""int[] Test.<F>d__2.<>s__5""
-IL_00e9: ldc.i4.1
IL_00ea: stloc.1
IL_00eb: leave.s IL_0107
IL_00b2: ldfld ""int Test.<F>d__2.<>s__1""
IL_00b7: ldarg.0
IL_00b8: ldfld ""int[] Test.<F>d__2.<>s__4""
IL_00bd: ldc.i4.3
IL_00be: ldarg.0
IL_00bf: ldfld ""int Test.<F>d__2.<>s__2""
IL_00c4: ldarg.0
IL_00c5: ldfld ""int Test.<F>d__2.<>s__3""
IL_00ca: add
IL_00cb: dup
IL_00cc: stloc.2
IL_00cd: stelem.i4
IL_00ce: ldloc.2
IL_00cf: ldc.i4.4
IL_00d0: call ""int Test.H(int, int, int)""
IL_00d5: pop
IL_00d6: ldarg.0
IL_00d7: ldnull
IL_00d8: stfld ""int[] Test.<F>d__2.<>s__4""
-IL_00dd: ldc.i4.1
IL_00de: stloc.1
IL_00df: leave.s IL_00fb
}
catch System.Exception
{
~IL_00ed: stloc.s V_5
IL_00ef: ldarg.0
IL_00f0: ldc.i4.s -2
IL_00f2: stfld ""int Test.<F>d__2.<>1__state""
IL_00f7: ldarg.0
IL_00f8: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00fd: ldloc.s V_5
IL_00ff: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
IL_0104: nop
IL_0105: leave.s IL_011c
~IL_00e1: stloc.s V_5
IL_00e3: ldarg.0
IL_00e4: ldc.i4.s -2
IL_00e6: stfld ""int Test.<F>d__2.<>1__state""
IL_00eb: ldarg.0
IL_00ec: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00f1: ldloc.s V_5
IL_00f3: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
IL_00f8: nop
IL_00f9: leave.s IL_0110
}
-IL_0107: ldarg.0
IL_0108: ldc.i4.s -2
IL_010a: stfld ""int Test.<F>d__2.<>1__state""
~IL_010f: ldarg.0
IL_0110: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_0115: ldloc.1
IL_0116: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
IL_011b: nop
IL_011c: ret
-IL_00fb: ldarg.0
IL_00fc: ldc.i4.s -2
IL_00fe: stfld ""int Test.<F>d__2.<>1__state""
~IL_0103: ldarg.0
IL_0104: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_0109: ldloc.1
IL_010a: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
IL_010f: nop
IL_0110: ret
}", sequencePoints: "Test+<F>d__2.MoveNext");
}
......@@ -766,22 +762,21 @@ public static async Task<int> F(int[] array)
v.VerifyIL("Test.<F>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @"
{
// Code size 260 (0x104)
.maxstack 4
// Code size 251 (0xfb)
.maxstack 5
.locals init (int V_0,
int V_1,
int V_2,
int V_3,
int V_4,
System.Runtime.CompilerServices.TaskAwaiter<int> V_5,
System.Exception V_6)
System.Runtime.CompilerServices.TaskAwaiter<int> V_4,
System.Exception V_5)
~IL_0000: ldarg.0
IL_0001: ldfld ""int Test.<F>d__2.<>1__state""
IL_0006: stloc.0
.try
{
~IL_0007: ldloc.0
IL_0008: brfalse.s IL_0082
IL_0008: brfalse.s IL_007d
-IL_000a: ldarg.0
IL_000b: ldarg.0
IL_000c: ldfld ""int[] Test.<F>d__2.array""
......@@ -792,108 +787,105 @@ .maxstack 4
IL_0019: ldc.i4.2
IL_001a: add
IL_001b: dup
IL_001c: stloc.s V_4
IL_001e: stind.i4
IL_001f: ldloc.s V_4
IL_0021: stfld ""int Test.<F>d__2.<>7__wrap1""
IL_0026: ldarg.0
IL_0027: ldarg.0
IL_0028: ldfld ""int[] Test.<F>d__2.array""
IL_002d: stfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0032: ldarg.0
IL_0033: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0038: ldc.i4.3
IL_0039: ldelem.i4
IL_003a: pop
IL_003b: ldarg.0
IL_003c: ldarg.0
IL_003d: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0042: ldc.i4.3
IL_0043: ldelem.i4
IL_0044: stfld ""int Test.<F>d__2.<>7__wrap2""
IL_0049: call ""System.Threading.Tasks.Task<int> Test.G()""
IL_004e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0053: stloc.s V_5
~IL_0055: ldloca.s V_5
IL_0057: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_005c: brtrue.s IL_009f
IL_005e: ldarg.0
IL_005f: ldc.i4.0
IL_0060: dup
IL_0061: stloc.0
IL_0062: stfld ""int Test.<F>d__2.<>1__state""
<IL_0067: ldarg.0
IL_0068: ldloc.s V_5
IL_006a: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_006f: ldarg.0
IL_0070: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_0075: ldloca.s V_5
IL_0077: ldarg.0
IL_0078: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<F>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<F>d__2)""
IL_007d: leave IL_0103
>IL_0082: ldarg.0
IL_0083: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_0088: stloc.s V_5
IL_008a: ldarg.0
IL_008b: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_0090: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_0096: ldarg.0
IL_0097: ldc.i4.m1
IL_0098: dup
IL_0099: stloc.0
IL_009a: stfld ""int Test.<F>d__2.<>1__state""
IL_009f: ldloca.s V_5
IL_00a1: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00a6: stloc.2
IL_00a7: ldarg.0
IL_00a8: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_00ad: ldc.i4.3
IL_00ae: ldarg.0
IL_00af: ldfld ""int Test.<F>d__2.<>7__wrap2""
IL_00b4: ldloc.2
IL_00b5: add
IL_00b6: dup
IL_00b7: stloc.s V_4
IL_001c: stloc.3
IL_001d: stind.i4
IL_001e: ldloc.3
IL_001f: stfld ""int Test.<F>d__2.<>7__wrap1""
IL_0024: ldarg.0
IL_0025: ldarg.0
IL_0026: ldfld ""int[] Test.<F>d__2.array""
IL_002b: stfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0030: ldarg.0
IL_0031: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0036: ldc.i4.3
IL_0037: ldelem.i4
IL_0038: pop
IL_0039: ldarg.0
IL_003a: ldarg.0
IL_003b: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_0040: ldc.i4.3
IL_0041: ldelem.i4
IL_0042: stfld ""int Test.<F>d__2.<>7__wrap2""
IL_0047: call ""System.Threading.Tasks.Task<int> Test.G()""
IL_004c: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<int> System.Threading.Tasks.Task<int>.GetAwaiter()""
IL_0051: stloc.s V_4
~IL_0053: ldloca.s V_4
IL_0055: call ""bool System.Runtime.CompilerServices.TaskAwaiter<int>.IsCompleted.get""
IL_005a: brtrue.s IL_009a
IL_005c: ldarg.0
IL_005d: ldc.i4.0
IL_005e: dup
IL_005f: stloc.0
IL_0060: stfld ""int Test.<F>d__2.<>1__state""
<IL_0065: ldarg.0
IL_0066: ldloc.s V_4
IL_0068: stfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_006d: ldarg.0
IL_006e: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_0073: ldloca.s V_4
IL_0075: ldarg.0
IL_0076: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<int>, Test.<F>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<int>, ref Test.<F>d__2)""
IL_007b: leave.s IL_00fa
>IL_007d: ldarg.0
IL_007e: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_0083: stloc.s V_4
IL_0085: ldarg.0
IL_0086: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<int> Test.<F>d__2.<>u__1""
IL_008b: initobj ""System.Runtime.CompilerServices.TaskAwaiter<int>""
IL_0091: ldarg.0
IL_0092: ldc.i4.m1
IL_0093: dup
IL_0094: stloc.0
IL_0095: stfld ""int Test.<F>d__2.<>1__state""
IL_009a: ldloca.s V_4
IL_009c: call ""int System.Runtime.CompilerServices.TaskAwaiter<int>.GetResult()""
IL_00a1: stloc.2
IL_00a2: ldarg.0
IL_00a3: ldfld ""int Test.<F>d__2.<>7__wrap1""
IL_00a8: ldarg.0
IL_00a9: ldfld ""int[] Test.<F>d__2.<>7__wrap3""
IL_00ae: ldc.i4.3
IL_00af: ldarg.0
IL_00b0: ldfld ""int Test.<F>d__2.<>7__wrap2""
IL_00b5: ldloc.2
IL_00b6: add
IL_00b7: dup
IL_00b8: stloc.3
IL_00b9: stelem.i4
IL_00ba: ldloc.s V_4
IL_00bc: stloc.3
IL_00bd: ldarg.0
IL_00be: ldfld ""int Test.<F>d__2.<>7__wrap1""
IL_00c3: ldloc.3
IL_00c4: ldc.i4.4
IL_00c5: call ""int Test.H(int, int, int)""
IL_00ca: pop
IL_00cb: ldarg.0
IL_00cc: ldnull
IL_00cd: stfld ""int[] Test.<F>d__2.<>7__wrap3""
-IL_00d2: ldc.i4.1
IL_00d3: stloc.1
IL_00d4: leave.s IL_00ef
IL_00ba: ldloc.3
IL_00bb: ldc.i4.4
IL_00bc: call ""int Test.H(int, int, int)""
IL_00c1: pop
IL_00c2: ldarg.0
IL_00c3: ldnull
IL_00c4: stfld ""int[] Test.<F>d__2.<>7__wrap3""
-IL_00c9: ldc.i4.1
IL_00ca: stloc.1
IL_00cb: leave.s IL_00e6
}
catch System.Exception
{
~IL_00d6: stloc.s V_6
IL_00d8: ldarg.0
IL_00d9: ldc.i4.s -2
IL_00db: stfld ""int Test.<F>d__2.<>1__state""
IL_00e0: ldarg.0
IL_00e1: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00e6: ldloc.s V_6
IL_00e8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
IL_00ed: leave.s IL_0103
~IL_00cd: stloc.s V_5
IL_00cf: ldarg.0
IL_00d0: ldc.i4.s -2
IL_00d2: stfld ""int Test.<F>d__2.<>1__state""
IL_00d7: ldarg.0
IL_00d8: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00dd: ldloc.s V_5
IL_00df: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
IL_00e4: leave.s IL_00fa
}
-IL_00ef: ldarg.0
IL_00f0: ldc.i4.s -2
IL_00f2: stfld ""int Test.<F>d__2.<>1__state""
~IL_00f7: ldarg.0
IL_00f8: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00fd: ldloc.1
IL_00fe: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
IL_0103: ret
-IL_00e6: ldarg.0
IL_00e7: ldc.i4.s -2
IL_00e9: stfld ""int Test.<F>d__2.<>1__state""
~IL_00ee: ldarg.0
IL_00ef: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> Test.<F>d__2.<>t__builder""
IL_00f4: ldloc.1
IL_00f5: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
IL_00fa: ret
}", sequencePoints: "Test+<F>d__2.MoveNext");
}
[Fact]
public void SpillSequencesInConditionalExpression1()
{
......@@ -981,9 +973,8 @@ public static async Task<int> F(int[] array)
"<>s__5",
"<>s__6",
"<>s__7",
"<>s__8",
"<>u__1",
"<>s__9"
"<>s__8"
}, module.GetFieldNames("C.<F>d__3"));
});
}
......@@ -3225,5 +3216,82 @@ static void Main(string[] args)
var expected = new bool[] { false, true, false, true, false }.Aggregate("", (str, next) => str += $"{next}{Environment.NewLine}");
var v = CompileAndVerify(source, expected);
}
[Fact]
[WorkItem(17706, "https://github.com/dotnet/roslyn/issues/17706")]
public void SpillAwaitBeforeRefReordered()
{
string source = @"
using System.Threading.Tasks;
public class C
{
private static int i;
static ref int P => ref i;
static void Assign(ref int first, int second)
{
first = second;
}
public static async Task M(Task<int> t)
{
// OK: await goes before the ref
Assign(second: await t, first: ref P);
}
public static void Main()
{
M(Task.FromResult(42)).Wait();
System.Console.WriteLine(i);
}
}
";
var v = CompileAndVerify(source, "42");
}
[Fact]
[WorkItem(17706, "https://github.com/dotnet/roslyn/issues/17706")]
public void SpillRefBeforeAwaitReordered()
{
string source = @"
using System.Threading.Tasks;
public class C
{
private static int i;
static ref int P => ref i;
static void Assign(int first, ref int second)
{
second = first;
}
public static async Task M(Task<int> t)
{
// ERROR: await goes after the ref
Assign(second: ref P, first: await t);
}
public static void Main()
{
M(Task.FromResult(42)).Wait();
System.Console.WriteLine(i);
}
}
";
var comp = CreateCompilationWithMscorlib46(source, options: TestOptions.ReleaseExe);
comp.VerifyEmitDiagnostics(
// (18,28): error CS8178: 'await' cannot be used in an expression containing a call to 'C.P.get' because it returns by reference
// Assign(second: ref P, first: await t);
Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, "P").WithArguments("C.P.get").WithLocation(18, 28)
);
}
}
}
......@@ -1737,15 +1737,24 @@ void Write(ref int y)
{
Console.WriteLine(y);
}
void Write(ref int y, int z)
{
Console.WriteLine(z);
}
async Task TestMethod()
{
// this is OK. `ref` is not spilled.
Write(ref Save(await Task.FromResult(0)));
// ERROR. `ref` is spilled because it must survive until after the second `await.
Write(ref Save(await Task.FromResult(0)), await Task.FromResult(1));
}
}";
CreateCompilationWithMscorlib45(code).VerifyEmitDiagnostics(
// (18,24): error CS8178: 'await' cannot be used in an expression containing a call to 'TestClass.Save(int)' because it returns by reference
// Write(ref Save(await Task.FromResult(0)));
Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, "await Task.FromResult(0)").WithArguments("TestClass.Save(int)").WithLocation(18, 24));
// (26,51): error CS8178: 'await' cannot be used in an expression containing a call to 'TestClass.Save(int)' because it returns by reference
// Write(ref Save(await Task.FromResult(0)), await Task.FromResult(1));
Diagnostic(ErrorCode.ERR_RefReturningCallAndAwait, "await Task.FromResult(1)").WithArguments("TestClass.Save(int)").WithLocation(26, 51)
);
}
[Fact]
......
......@@ -2325,6 +2325,136 @@ BC31143: Method 'Public Overloads ByRef Function F() As Integer' does not have a
</expected>)
End Sub
<Fact>
<WorkItem(17706, "https://github.com/dotnet/roslyn/issues/17706")>
Public Sub SpillingByRefCall_NoSpilling()
Dim comp1 = CreateCSharpCompilation(
"
using System;
public class TestClass
{
int x = 0;
public ref int Save(int y)
{
x = y;
return ref x;
}
public void Write(ref int y)
{
Console.WriteLine(y);
}
public void Write(ref int y, int z)
{
Console.WriteLine(y);
}
}")
comp1.VerifyDiagnostics()
Dim comp2 = CreateVisualBasicCompilation(
Nothing,
"
Imports System.Threading.Tasks
Module Module1
Sub Main()
TestMethod().Wait()
End Sub
Async Function TestMethod() As Task
Dim inst = New TestClass
' this is OK. `ref` call is not spilled.
' prints: 10 (last value)
inst.Write(inst.Save(Await Task.FromResult(10)))
' this is OK. `ref` call is not spilled.
' prints: 22 (last value)
inst.Write(inst.Save(Await Task.FromResult(20)), inst.Save(22))
End Function
End Module
",
referencedCompilations:={comp1},
referencedAssemblies:=LatestVbReferences,
compilationOptions:=TestOptions.DebugExe)
comp2.AssertTheseDiagnostics()
Dim verifier = CompileAndVerify(comp2, expectedOutput:=
"
10
22
")
verifier.VerifyDiagnostics()
End Sub
<Fact(Skip:="https://github.com/dotnet/roslyn/issues/24275")>
<WorkItem(24275, "https://github.com/dotnet/roslyn/issues/24275")>
Public Sub SpillingByRefCall_Spilling()
Dim comp1 = CreateCSharpCompilation(
"
using System;
public class TestClass
{
int x = 0;
public ref int Save(int y)
{
x = y;
return ref x;
}
public void Write(ref int y)
{
Console.WriteLine(y);
}
public void Write(ref int y, int z)
{
Console.WriteLine(y);
}
}")
comp1.VerifyDiagnostics()
Dim comp2 = CreateVisualBasicCompilation(
Nothing,
"
Imports System.Threading.Tasks
Module Module1
Sub Main()
TestMethod().Wait()
End Sub
Async Function TestMethod() As Task
Dim inst = New TestClass
' ERROR?
' currently `ref` is spilled 'by-value' and assert fires.
inst.Write(inst.Save(Await Task.FromResult(30)), inst.Save(Await Task.FromResult(33)))
End Function
End Module
",
referencedCompilations:={comp1},
referencedAssemblies:=LatestVbReferences,
compilationOptions:=TestOptions.DebugExe)
comp2.AssertTheseDiagnostics()
Dim verifier = CompileAndVerify(comp2, expectedOutput:=
"
??
")
verifier.VerifyDiagnostics()
End Sub
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册