/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenRefConditionalOperatorTests.cs
2 491 строка
72 KB
Jan Jones
Avoid eliding nested pointer-to-ref conversions (#82263)
01 мар 2026, 11:49
Не верифицирован
01 мар 2026, 11:49
9a3bdad
Код
Авторство
О чём код?
// 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. #nullable disable using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Basic.Reference.Assemblies; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen { [CompilerTrait(CompilerFeature.RefConditionalOperator)] public class CodeGenRefConditionalOperatorTests : CSharpTestBase { [Fact] public void TestRefConditionalOperatorInRefReturn() { var source = @" class C { static void Main() { System.Console.Write(Test1(true)); System.Console.Write(Test2(false)); } static int val1 = 33; static int val2 = 44; static ref int Test1(bool b) { return ref b ? ref val1 : ref val2; } static ref int Test2(bool b) => ref b ? ref val1 : ref val2; }"; var comp = CompileAndVerify(source, expectedOutput: "3344"); comp.VerifyDiagnostics(); comp.VerifyIL("C.Test1", @" { // Code size 15 (0xf) .maxstack 1 IL_0000: ldarg.0 IL_0001: brtrue.s IL_0009 IL_0003: ldsflda ""int C.val2"" IL_0008: ret IL_0009: ldsflda ""int C.val1"" IL_000e: ret } "); comp.VerifyIL("C.Test2", @" { // Code size 15 (0xf) .maxstack 1 IL_0000: ldarg.0 IL_0001: brtrue.s IL_0009 IL_0003: ldsflda ""int C.val2"" IL_0008: ret IL_0009: ldsflda ""int C.val1"" IL_000e: ret } "); } [Fact] public void TestRefConditionalOperatorInRefArgument() { var source = @" class C { static void Main() { bool b = false; System.Console.Write( M1(ref b? ref val1: ref val2)); } static int val1 = 33; static int val2 = 44; static ref int M1(ref int arg) => ref arg; }"; var comp = CompileAndVerify(source, expectedOutput: "44", verify: Verification.Fails); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 27 (0x1b) .maxstack 1 IL_0000: ldc.i4.0 IL_0001: brtrue.s IL_000a IL_0003: ldsflda ""int C.val2"" IL_0008: br.s IL_000f IL_000a: ldsflda ""int C.val1"" IL_000f: call ""ref int C.M1(ref int)"" IL_0014: ldind.i4 IL_0015: call ""void System.Console.Write(int)"" IL_001a: ret } "); } [Fact] public void TestRefConditionalOperatorAsValue() { var source = @" class C { static void Main() { bool b = false; System.Console.Write(b? ref val1: ref val2); } static int val1 = 33; static int val2 = 44; }"; var comp = CompileAndVerify(source, expectedOutput: "44", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 21 (0x15) .maxstack 1 IL_0000: ldc.i4.0 IL_0001: brtrue.s IL_000a IL_0003: ldsfld ""int C.val2"" IL_0008: br.s IL_000f IL_000a: ldsfld ""int C.val1"" IL_000f: call ""void System.Console.Write(int)"" IL_0014: ret } "); } [Fact] public void TestRefConditionalOperatorAssignmentTarget() { var source = @" class C { static void Main() { bool b = false; (b? ref val1: ref val2) = 55; System.Console.Write(val2); } static int val1 = 33; static int val2 = 44; }"; var comp = CompileAndVerify(source, expectedOutput: "55", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 29 (0x1d) .maxstack 2 IL_0000: ldc.i4.0 IL_0001: brtrue.s IL_000a IL_0003: ldsflda ""int C.val2"" IL_0008: br.s IL_000f IL_000a: ldsflda ""int C.val1"" IL_000f: ldc.i4.s 55 IL_0011: stind.i4 IL_0012: ldsfld ""int C.val2"" IL_0017: call ""void System.Console.Write(int)"" IL_001c: ret } "); } [Fact] public void TestRefConditionalOperatorAssignmentTargetUsed() { var source = @" class C { static void Main() { bool b = false; System.Console.Write((b? ref val1: ref val2) = 55); System.Console.Write(val2); } static int val1 = 33; static int val2 = 44; }"; var comp = CompileAndVerify(source, expectedOutput: "5555", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 37 (0x25) .maxstack 3 .locals init (int V_0) IL_0000: ldc.i4.0 IL_0001: brtrue.s IL_000a IL_0003: ldsflda ""int C.val2"" IL_0008: br.s IL_000f IL_000a: ldsflda ""int C.val1"" IL_000f: ldc.i4.s 55 IL_0011: dup IL_0012: stloc.0 IL_0013: stind.i4 IL_0014: ldloc.0 IL_0015: call ""void System.Console.Write(int)"" IL_001a: ldsfld ""int C.val2"" IL_001f: call ""void System.Console.Write(int)"" IL_0024: ret } "); } [Fact] public void TestRefConditionalOperatorIncrement() { var source = @" class C { static void Main() { bool b = false; (b? ref val1: ref M1(ref val2)) ++; (b? ref val1: ref M1(ref val2)) += 22; System.Console.Write(val2); } static int val1 = 33; static int val2 = 44; static ref int M1(ref int arg) => ref arg; }"; var comp = CompileAndVerify(source, expectedOutput: "67", verify: Verification.Fails); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 62 (0x3e) .maxstack 4 IL_0000: ldc.i4.0 IL_0001: dup IL_0002: brtrue.s IL_0010 IL_0004: ldsflda ""int C.val2"" IL_0009: call ""ref int C.M1(ref int)"" IL_000e: br.s IL_0015 IL_0010: ldsflda ""int C.val1"" IL_0015: dup IL_0016: ldind.i4 IL_0017: ldc.i4.1 IL_0018: add IL_0019: stind.i4 IL_001a: brtrue.s IL_0028 IL_001c: ldsflda ""int C.val2"" IL_0021: call ""ref int C.M1(ref int)"" IL_0026: br.s IL_002d IL_0028: ldsflda ""int C.val1"" IL_002d: dup IL_002e: ldind.i4 IL_002f: ldc.i4.s 22 IL_0031: add IL_0032: stind.i4 IL_0033: ldsfld ""int C.val2"" IL_0038: call ""void System.Console.Write(int)"" IL_003d: ret } "); } [Fact] public void TestRefConditionalOperatorIncrementUsed() { var source = @" class C { static void Main() { bool b = false; System.Console.Write((b? ref val1: ref val2) ++); System.Console.Write((b? ref val1: ref val2) += 22); System.Console.Write(val2); } static int val1 = 33; static int val2 = 44; }"; var comp = CompileAndVerify(source, expectedOutput: "446767", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 68 (0x44) .maxstack 4 .locals init (int V_0) IL_0000: ldc.i4.0 IL_0001: dup IL_0002: brtrue.s IL_000b IL_0004: ldsflda ""int C.val2"" IL_0009: br.s IL_0010 IL_000b: ldsflda ""int C.val1"" IL_0010: dup IL_0011: ldind.i4 IL_0012: stloc.0 IL_0013: ldloc.0 IL_0014: ldc.i4.1 IL_0015: add IL_0016: stind.i4 IL_0017: ldloc.0 IL_0018: call ""void System.Console.Write(int)"" IL_001d: brtrue.s IL_0026 IL_001f: ldsflda ""int C.val2"" IL_0024: br.s IL_002b IL_0026: ldsflda ""int C.val1"" IL_002b: dup IL_002c: ldind.i4 IL_002d: ldc.i4.s 22 IL_002f: add IL_0030: dup IL_0031: stloc.0 IL_0032: stind.i4 IL_0033: ldloc.0 IL_0034: call ""void System.Console.Write(int)"" IL_0039: ldsfld ""int C.val2"" IL_003e: call ""void System.Console.Write(int)"" IL_0043: ret } "); } [Fact] public void TestRefConditionalOperatorInRefAssignment() { var source = @" class C { static void Main() { bool b = true; int x = 1; int y = 2; ref var local = ref b ? ref x : ref y; System.Console.WriteLine(local); } }"; var comp = CompileAndVerify(source, expectedOutput: "1"); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 20 (0x14) .maxstack 2 .locals init (int V_0, //x int V_1) //y IL_0000: ldc.i4.1 IL_0001: ldc.i4.1 IL_0002: stloc.0 IL_0003: ldc.i4.2 IL_0004: stloc.1 IL_0005: brtrue.s IL_000b IL_0007: ldloca.s V_1 IL_0009: br.s IL_000d IL_000b: ldloca.s V_0 IL_000d: ldind.i4 IL_000e: call ""void System.Console.WriteLine(int)"" IL_0013: ret } "); } [Fact] public void TestRefConditionalOperatorElvis() { var source = @" class Program { interface IDisposable1 { void Dispose(); } class C1 : IDisposable1 { private bool disposed; public void Dispose() { System.Console.WriteLine(disposed); disposed = true; } } struct S1 : IDisposable1 { private bool disposed; public void Dispose() { System.Console.WriteLine(disposed); disposed = true; } } static void Main(string[] args) { C1 c = new C1(); Test(ref c, ref c); S1 s = new S1(); Test(ref s, ref s); } static void Test<T>(ref T x, ref T y) where T : IDisposable1 { bool b = true; (b? ref x: ref y)?.Dispose(); (!b? ref x: ref y)?.Dispose(); } }"; var comp = CompileAndVerify(source, expectedOutput: @"False True False True"); comp.VerifyDiagnostics(); comp.VerifyIL("Program.Test<T>(ref T, ref T)", @" { // Code size 106 (0x6a) .maxstack 3 .locals init (T V_0) IL_0000: ldc.i4.1 IL_0001: dup IL_0002: brtrue.s IL_0007 IL_0004: ldarg.1 IL_0005: br.s IL_0008 IL_0007: ldarg.0 IL_0008: ldloca.s V_0 IL_000a: initobj ""T"" IL_0010: ldloc.0 IL_0011: box ""T"" IL_0016: brtrue.s IL_002b IL_0018: ldobj ""T"" IL_001d: stloc.0 IL_001e: ldloca.s V_0 IL_0020: ldloc.0 IL_0021: box ""T"" IL_0026: brtrue.s IL_002b IL_0028: pop IL_0029: br.s IL_0036 IL_002b: constrained. ""T"" IL_0031: callvirt ""void Program.IDisposable1.Dispose()"" IL_0036: brfalse.s IL_003b IL_0038: ldarg.1 IL_0039: br.s IL_003c IL_003b: ldarg.0 IL_003c: ldloca.s V_0 IL_003e: initobj ""T"" IL_0044: ldloc.0 IL_0045: box ""T"" IL_004a: brtrue.s IL_005e IL_004c: ldobj ""T"" IL_0051: stloc.0 IL_0052: ldloca.s V_0 IL_0054: ldloc.0 IL_0055: box ""T"" IL_005a: brtrue.s IL_005e IL_005c: pop IL_005d: ret IL_005e: constrained. ""T"" IL_0064: callvirt ""void Program.IDisposable1.Dispose()"" IL_0069: ret } "); } [Fact] public void TestRefConditionalAsyncIncrement() { var source = @" using System.Threading.Tasks; class C { static void Main() { Test().Wait(); System.Console.Write(val1); } static async Task<int> Test() { bool b = true; (b? ref val1: ref val2) += await One(); return 1; } static int val1 = 33; static int val2 = 44; static ref int M1() => ref val1; static async Task<int> One() { await Task.Yield(); return 1; } }"; var expected = // (16,10): error CS8325: 'await' cannot be used in an expression containing a ref conditional operator // (b? ref val1: ref val2) += await One(); Diagnostic(ErrorCode.ERR_RefConditionalAndAwait, "b? ref val1: ref val2").WithLocation(16, 10); var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics(expected); comp = CreateRuntimeAsyncCompilation(source); comp.VerifyEmitDiagnostics(expected); } [Fact] public void TestRefConditionalAsyncAssign() { var source = @" using System.Threading.Tasks; class C { static void Main() { Test().Wait(); System.Console.Write(val1); } static async Task<int> Test() { bool b = true; (b? ref val1: ref val2) = await One(); return 1; } static int val1 = 33; static int val2 = 44; static ref int M1() => ref val1; static async Task<int> One() { await Task.Yield(); return 1; } }"; var expected = // (16,10): error CS8325: 'await' cannot be used in an expression containing a ref conditional operator // (b? ref val1: ref val2) = await One(); Diagnostic(ErrorCode.ERR_RefConditionalAndAwait, "b? ref val1: ref val2").WithLocation(16, 10); var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics(expected); comp = CreateRuntimeAsyncCompilation(source); comp.VerifyEmitDiagnostics(expected); } [Fact] public void TestRefConditionalOneRef() { var source = @" class C { static void Main() { bool b = false; System.Console.Write(b? val1: ref val2); System.Console.Write(b? ref val1: val2); } static int val1 = 33; static int val2 = 44; } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (8,43): error CS8326: Both conditional operator values must be ref values or neither may be a ref value // System.Console.Write(b? val1: ref val2); Diagnostic(ErrorCode.ERR_RefConditionalNeedsTwoRefs, "val2").WithLocation(8, 43), // (9,37): error CS8326: Both conditional operator values must be ref values or neither may be a ref value // System.Console.Write(b? ref val1: val2); Diagnostic(ErrorCode.ERR_RefConditionalNeedsTwoRefs, "val1").WithLocation(9, 37) ); } [Fact] public void TestRefConditionalRValue() { var source = @" class C { static void Main() { bool b = false; (b? ref val1: ref 42) = 1; ref var local = ref b? ref val1: ref 42; } static int val1 = 33; } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (8,27): error CS8156: An expression cannot be used in this context because it may not be returned by reference // (b? ref val1: ref 42) = 1; Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "42").WithLocation(8, 27), // (10,46): error CS8156: An expression cannot be used in this context because it may not be returned by reference // ref var local = ref b? ref val1: ref 42; Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "42").WithLocation(10, 46) ); } [Fact] [WorkItem(24306, "https://github.com/dotnet/roslyn/issues/24306")] public void TestRefConditional_71() { var source = @" class C { static void Main() { } void Test() { int local1 = 1; int local2 = 2; bool b = true; ref int r = ref b? ref local1: ref local2; } } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.Regular7_1); comp.VerifyEmitDiagnostics( // (15,25): error CS8302: Feature 'ref conditional expression' is not available in C# 7.1. Please use language version 7.2 or greater. // ref int r = ref b? ref local1: ref local2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_1, "b? ref local1: ref local2").WithArguments("ref conditional expression", "7.2").WithLocation(15, 25) ); } [Fact] public void TestRefConditionalUnsafeToReturn1() { var source = @" class C { static void Main() { } ref int Test() { int local1 = 1; int local2 = 2; bool b = true; return ref b? ref local1: ref local2; } } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (15,27): error CS8168: Cannot return local 'local1' by reference because it is not a ref local // return ref b? ref local1: ref local2; Diagnostic(ErrorCode.ERR_RefReturnLocal, "local1").WithArguments("local1").WithLocation(15, 27) ); } [Fact] public void TestRefConditionalUnsafeToReturn2() { var source = @" class C { static void Main() { } ref int Test() { int local2 = 1; bool b = true; return ref b? ref val1: ref local2; } static int val1 = 33; } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (14,37): error CS8168: Cannot return local 'local2' by reference because it is not a ref local // return ref b? ref val1: ref local2; Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 37) ); } [Fact] public void TestRefConditionalUnsafeToReturn3() { var source = @" class C { static void Main() { } ref int Test() { S1 local2 = default(S1); bool b = true; return ref (b? ref val1: ref local2).x; } static S1 val1; struct S1 { public int x; } } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (14,38): error CS8168: Cannot return local 'local2' by reference because it is not a ref local // return ref (b? ref val1: ref local2).x; Diagnostic(ErrorCode.ERR_RefReturnLocal, "local2").WithArguments("local2").WithLocation(14, 38) ); } [Fact] public void TestRefConditionalUnsafeToReturn4() { var source = @" class C { static void Main() { } ref int Test() { S1 local2 = default(S1); bool b = true; ref var temp = ref (b? ref val1: ref local2).x; return ref temp; } static S1 val1; struct S1 { public int x; } } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (15,20): error CS8157: Cannot return 'temp' by reference because it was initialized to a value that cannot be returned by reference // return ref temp; Diagnostic(ErrorCode.ERR_RefReturnNonreturnableLocal, "temp").WithArguments("temp").WithLocation(15, 20) ); } [Fact] public void TestRefConditionalSafeToReturn1() { var source = @" class C { static void Main() { Test() ++; System.Console.WriteLine(val1.x); } static ref int Test() { bool b = true; return ref (b? ref val1: ref val2).x; } static S1 val1; static S1 val2; struct S1 { public int x; } } "; var comp = CompileAndVerify(source, expectedOutput: "1", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Test", @" { // Code size 21 (0x15) .maxstack 1 IL_0000: ldc.i4.1 IL_0001: brtrue.s IL_000a IL_0003: ldsflda ""C.S1 C.val2"" IL_0008: br.s IL_000f IL_000a: ldsflda ""C.S1 C.val1"" IL_000f: ldflda ""int C.S1.x"" IL_0014: ret } "); } [Fact] public void TestRefConditionalSafeToReturn2() { var source = @" class C { static void Main() { Test() ++; System.Console.WriteLine(val1.x); } static ref int Test() { return ref (true? ref val1: ref val2).x; } static S1 val1; static S1 val2; struct S1 { public int x; } } "; var comp = CompileAndVerify(source, expectedOutput: "1", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Test", @" { // Code size 11 (0xb) .maxstack 1 IL_0000: ldsflda ""C.S1 C.val1"" IL_0005: ldflda ""int C.S1.x"" IL_000a: ret } "); } [Fact] public void TestRefConditionalSafeToReturn3() { var source = @" class C { static void Main() { (false? ref val1: ref val2) = (true? 1: val2); (true? ref val1: ref val2) = (false? ref val1: ref val2); System.Console.WriteLine(val1); } static int val1; static int val2; } "; var comp = CompileAndVerify(source, expectedOutput: "1", verify: Verification.Passes); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main()", @" { // Code size 27 (0x1b) .maxstack 1 IL_0000: ldc.i4.1 IL_0001: stsfld ""int C.val2"" IL_0006: ldsfld ""int C.val2"" IL_000b: stsfld ""int C.val1"" IL_0010: ldsfld ""int C.val1"" IL_0015: call ""void System.Console.WriteLine(int)"" IL_001a: ret } "); } [Fact] public void TestRefConditionalDifferentTypes1() { var source = @" class C { static void Main() { bool b = false; System.Console.Write(b? ref val1: ref val2); } static int val1 = 33; static short val2 = 44; } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (8,47): error CS8327: The expression must be of type 'int' to match the alternative ref value // System.Console.Write(b? ref val1: ref val2); Diagnostic(ErrorCode.ERR_RefConditionalDifferentTypes, "val2").WithArguments("int").WithLocation(8, 47) ); } [Fact] public void TestRefConditionalDifferentTypes2() { var source = @" class C { static void Main() { bool b = false; System.Console.Write(b? ref val1: ref ()=>1); } static System.Func<int> val1 = null; } "; var comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (8,47): error CS8156: An expression cannot be used in this context because it may not be returned by reference // System.Console.Write(b? ref val1: ref ()=>1); Diagnostic(ErrorCode.ERR_RefReturnLvalueExpected, "()=>1").WithLocation(8, 47) ); } [Fact] public void TestRefConditionalDifferentTypes3() { var source = @" class C { static void Main() { bool b = true; ref var x = ref b? ref val1: ref val2; System.Console.Write(x.Alice); } static (int Alice, int) val1 = (1,2); static (int Alice, int Bob) val2 = (3,4); } "; var comp = CompileAndVerify(source, expectedOutput: "1"); comp.VerifyDiagnostics(); comp.VerifyIL("C.Main", @" { // Code size 26 (0x1a) .maxstack 1 IL_0000: ldc.i4.1 IL_0001: brtrue.s IL_000a IL_0003: ldsflda ""System.ValueTuple<int, int> C.val2"" IL_0008: br.s IL_000f IL_000a: ldsflda ""System.ValueTuple<int, int> C.val1"" IL_000f: ldfld ""int System.ValueTuple<int, int>.Item1"" IL_0014: call ""void System.Console.Write(int)"" IL_0019: ret } "); } [Fact] public void TestRefConditionalHomelessBranches() { var source = @" class Program { static void Main(string[] args) { var o = new C1(); var o1 = new C1(); (args != null ? ref o.field : ref o1.field).ToString(); System.Console.Write(o.field.value); // no copying expected (args != null ? ref o.field : ref o1.field).RoExtension(); System.Console.Write(o.field.value); } } class C1 { public readonly S1 field; } public struct S1 { public int value; public override string ToString() { value = 42; return base.ToString(); } } public static class S1Ext { public static void RoExtension(in this S1 self) { // do nothing } } "; // PEVerify: Cannot change initonly field outside its .ctor. var comp = CompileAndVerifyWithMscorlib40(source, references: new[] { Net40.References.System, ValueTupleRef, Net40.References.SystemCore }, expectedOutput: "00", verify: Verification.FailsPEVerify); comp.VerifyDiagnostics(); comp.VerifyIL("Program.Main", @" { // Code size 99 (0x63) .maxstack 1 .locals init (C1 V_0, //o C1 V_1, //o1 S1 V_2) IL_0000: newobj ""C1..ctor()"" IL_0005: stloc.0 IL_0006: newobj ""C1..ctor()"" IL_000b: stloc.1 IL_000c: ldarg.0 IL_000d: brtrue.s IL_0017 IL_000f: ldloc.1 IL_0010: ldfld ""S1 C1.field"" IL_0015: br.s IL_001d IL_0017: ldloc.0 IL_0018: ldfld ""S1 C1.field"" IL_001d: stloc.2 IL_001e: ldloca.s V_2 IL_0020: constrained. ""S1"" IL_0026: callvirt ""string object.ToString()"" IL_002b: pop IL_002c: ldloc.0 IL_002d: ldflda ""S1 C1.field"" IL_0032: ldfld ""int S1.value"" IL_0037: call ""void System.Console.Write(int)"" IL_003c: ldarg.0 IL_003d: brtrue.s IL_0047 IL_003f: ldloc.1 IL_0040: ldflda ""S1 C1.field"" IL_0045: br.s IL_004d IL_0047: ldloc.0 IL_0048: ldflda ""S1 C1.field"" IL_004d: call ""void S1Ext.RoExtension(in S1)"" IL_0052: ldloc.0 IL_0053: ldflda ""S1 C1.field"" IL_0058: ldfld ""int S1.value"" IL_005d: call ""void System.Console.Write(int)"" IL_0062: ret } "); } [Fact] public void TestRefConditionalOneHomelessBranch() { var source = @" class Program { static void Main(string[] args) { var o = new C1(); Test(true, o); Test(false, o); System.Console.Write(o.field.value); System.Console.Write(o.field1.value); } private static void Test(bool flag, C1 o) { (flag ? ref o.field : ref o.field1).ToString(); } } class C1 { public readonly S1 field; public S1 field1; } struct S1 { public int value; public override string ToString() { value = 42; return base.ToString(); } } "; // PEVerify: Cannot change initonly field outside its .ctor. var comp = CompileAndVerify(source, expectedOutput: "00", verify: Verification.FailsPEVerify); comp.VerifyDiagnostics(); comp.VerifyIL("Program.Test", @" { // Code size 33 (0x21) .maxstack 1 .locals init (S1 V_0) IL_0000: ldarg.0 IL_0001: brtrue.s IL_000b IL_0003: ldarg.1 IL_0004: ldfld ""S1 C1.field1"" IL_0009: br.s IL_0011 IL_000b: ldarg.1 IL_000c: ldfld ""S1 C1.field"" IL_0011: stloc.0 IL_0012: ldloca.s V_0 IL_0014: constrained. ""S1"" IL_001a: callvirt ""string object.ToString()"" IL_001f: pop IL_0020: ret } "); } [Fact] public void TestRefConditionalDifferentTypes4() { var source = @" class C { static void Main() { bool b = true; ref var x = ref b? ref val1: ref val2; System.Console.Write(x.Bob); } static (int Alice, int) val1 = (1,2); static (int Alice, int Bob) val2 = (3,4); } "; var comp = CreateCompilationWithMscorlib461(source, references: new[] { SystemRuntimeFacadeRef, ValueTupleRef }, options: TestOptions.ReleaseExe); comp.VerifyEmitDiagnostics( // (9,32): error CS1061: '(int Alice, int)' does not contain a definition for 'Bob' and no extension method 'Bob' accepting a first argument of type '(int Alice, int)' could be found (are you missing a using directive or an assembly reference?) // System.Console.Write(x.Bob); Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Bob").WithArguments("(int Alice, int)", "Bob").WithLocation(9, 32) ); } [Fact, WorkItem(53113, "https://github.com/dotnet/roslyn/issues/53113")] public void TestRefOnPointerIndirection_ThroughTernary_01() { var code = @" using System; unsafe { bool b = true; ref int x = ref b ? ref *(int*)0 : ref *(int*)1; Console.WriteLine(""run""); } "; verify(TestOptions.UnsafeReleaseExe, Verification.Fails, @" { // Code size 21 (0x15) .maxstack 1 .locals init (int& V_0) //x IL_0000: ldc.i4.1 IL_0001: brtrue.s IL_0007 IL_0003: ldc.i4.1 IL_0004: conv.i IL_0005: br.s IL_0009 IL_0007: ldc.i4.0 IL_0008: conv.i IL_0009: stloc.0 IL_000a: ldstr ""run"" IL_000f: call ""void System.Console.WriteLine(string)"" IL_0014: ret } "); verify(TestOptions.UnsafeDebugExe, Verification.Fails, @" { // Code size 26 (0x1a) .maxstack 1 .locals init (bool V_0, //b int& V_1) //x IL_0000: nop IL_0001: ldc.i4.1 IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: brtrue.s IL_000a IL_0006: ldc.i4.1 IL_0007: conv.i IL_0008: br.s IL_000c IL_000a: ldc.i4.0 IL_000b: conv.i IL_000c: stloc.1 IL_000d: ldstr ""run"" IL_0012: call ""void System.Console.WriteLine(string)"" IL_0017: nop IL_0018: nop IL_0019: ret } "); void verify(CSharpCompilationOptions options, Verification verify, string expectedIL) { var comp = CreateCompilation(code, options: options); var verifier = CompileAndVerify(comp, expectedOutput: "run", verify: verify); verifier.VerifyDiagnostics(); verifier.VerifyIL("<top-level-statements-entry-point>", expectedIL); } } [Fact, WorkItem(53113, "https://github.com/dotnet/roslyn/issues/53113")] public void TestRefOnPointerIndirection_ThroughTernary_02() { var code = @" using System; unsafe { int i1 = 0; int* p1 = &i1; bool b = true; ref int x = ref b ? ref *M(*p1) : ref i1; Console.WriteLine(""run""); int* M(int i) { Console.Write(i); return (int*)0; } } "; verify(TestOptions.UnsafeReleaseExe, @" { // Code size 32 (0x20) .maxstack 1 .locals init (int V_0, //i1 int* V_1, //p1 int& V_2) //x IL_0000: ldc.i4.0 IL_0001: stloc.0 IL_0002: ldloca.s V_0 IL_0004: conv.u IL_0005: stloc.1 IL_0006: ldc.i4.1 IL_0007: brtrue.s IL_000d IL_0009: ldloca.s V_0 IL_000b: br.s IL_0014 IL_000d: ldloc.1 IL_000e: ldind.i4 IL_000f: call ""int* Program.<<Main>$>g__M|0_0(int)"" IL_0014: stloc.2 IL_0015: ldstr ""run"" IL_001a: call ""void System.Console.WriteLine(string)"" IL_001f: ret } "); verify(TestOptions.UnsafeDebugExe, @" { // Code size 38 (0x26) .maxstack 1 .locals init (int V_0, //i1 int* V_1, //p1 bool V_2, //b int& V_3) //x IL_0000: nop IL_0001: ldc.i4.0 IL_0002: stloc.0 IL_0003: ldloca.s V_0 IL_0005: conv.u IL_0006: stloc.1 IL_0007: ldc.i4.1 IL_0008: stloc.2 IL_0009: ldloc.2 IL_000a: brtrue.s IL_0010 IL_000c: ldloca.s V_0 IL_000e: br.s IL_0017 IL_0010: ldloc.1 IL_0011: ldind.i4 IL_0012: call ""int* Program.<<Main>$>g__M|0_0(int)"" IL_0017: stloc.3 IL_0018: ldstr ""run"" IL_001d: call ""void System.Console.WriteLine(string)"" IL_0022: nop IL_0023: nop IL_0024: nop IL_0025: ret } "); void verify(CSharpCompilationOptions options, string expectedIL) { var comp = CreateCompilation(code, options: options); var verifier = CompileAndVerify(comp, expectedOutput: "0run", verify: Verification.Fails); verifier.VerifyDiagnostics(); verifier.VerifyIL("<top-level-statements-entry-point>", expectedIL); } } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_01() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C(); var c2 = new C(); await Test(false, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); System.Console.Write('-'); c1 = new C(); c2 = new C(); await Test(true, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); } static async Task Test(bool b, C c1, C c2) { ((await GetBool(b)) ? ref GetC(c1).F: ref GetC(c2).F) = 123; } static async Task<bool> GetBool(bool b) { await Task.Yield(); return b; } static C GetC(C c) => c; } "; var comp = CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.ReleaseExe); CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.DebugExe); comp.VerifyIL("C.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { // Code size 187 (0xbb) .maxstack 3 .locals init (int V_0, System.Runtime.CompilerServices.TaskAwaiter<bool> V_1, System.Exception V_2) IL_0000: ldarg.0 IL_0001: ldfld ""int C.<Test>d__2.<>1__state"" IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: brfalse.s IL_0044 IL_000a: ldarg.0 IL_000b: ldfld ""bool C.<Test>d__2.b"" IL_0010: call ""System.Threading.Tasks.Task<bool> C.GetBool(bool)"" IL_0015: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<bool> System.Threading.Tasks.Task<bool>.GetAwaiter()"" IL_001a: stloc.1 IL_001b: ldloca.s V_1 IL_001d: call ""bool System.Runtime.CompilerServices.TaskAwaiter<bool>.IsCompleted.get"" IL_0022: brtrue.s IL_0060 IL_0024: ldarg.0 IL_0025: ldc.i4.0 IL_0026: dup IL_0027: stloc.0 IL_0028: stfld ""int C.<Test>d__2.<>1__state"" IL_002d: ldarg.0 IL_002e: ldloc.1 IL_002f: stfld ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_0034: ldarg.0 IL_0035: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_003a: ldloca.s V_1 IL_003c: ldarg.0 IL_003d: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<bool>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<bool>, ref C.<Test>d__2)"" IL_0042: leave.s IL_00ba IL_0044: ldarg.0 IL_0045: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_004a: stloc.1 IL_004b: ldarg.0 IL_004c: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_0051: initobj ""System.Runtime.CompilerServices.TaskAwaiter<bool>"" IL_0057: ldarg.0 IL_0058: ldc.i4.m1 IL_0059: dup IL_005a: stloc.0 IL_005b: stfld ""int C.<Test>d__2.<>1__state"" IL_0060: ldloca.s V_1 IL_0062: call ""bool System.Runtime.CompilerServices.TaskAwaiter<bool>.GetResult()"" IL_0067: brtrue.s IL_007b IL_0069: ldarg.0 IL_006a: ldfld ""C C.<Test>d__2.c2"" IL_006f: call ""C C.GetC(C)"" IL_0074: ldflda ""int C.F"" IL_0079: br.s IL_008b IL_007b: ldarg.0 IL_007c: ldfld ""C C.<Test>d__2.c1"" IL_0081: call ""C C.GetC(C)"" IL_0086: ldflda ""int C.F"" IL_008b: ldc.i4.s 123 IL_008d: stind.i4 IL_008e: leave.s IL_00a7 } catch System.Exception { IL_0090: stloc.2 IL_0091: ldarg.0 IL_0092: ldc.i4.s -2 IL_0094: stfld ""int C.<Test>d__2.<>1__state"" IL_0099: ldarg.0 IL_009a: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_009f: ldloc.2 IL_00a0: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" IL_00a5: leave.s IL_00ba } IL_00a7: ldarg.0 IL_00a8: ldc.i4.s -2 IL_00aa: stfld ""int C.<Test>d__2.<>1__state"" IL_00af: ldarg.0 IL_00b0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00b5: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()"" IL_00ba: ret } "); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_02() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C(); var c2 = new C(); await Test(false, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); System.Console.Write('-'); c1 = new C(); c2 = new C(); await Test(true, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); } static async Task Test(bool b, C c1, C c2) { (GetBool(b) ? ref (await GetC1(c1)).F: ref GetC2(c2).F) = 123; } static bool GetBool(bool b) => b; static async Task<C> GetC1(C c) { await Task.Yield(); return c; } static C GetC2(C c) => c; } "; var comp = CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.ReleaseExe); CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.DebugExe); comp.VerifyIL("C.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { // Code size 209 (0xd1) .maxstack 3 .locals init (int V_0, C V_1, System.Runtime.CompilerServices.TaskAwaiter<C> V_2, System.Exception V_3) IL_0000: ldarg.0 IL_0001: ldfld ""int C.<Test>d__2.<>1__state"" IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: brfalse.s IL_005d IL_000a: ldarg.0 IL_000b: ldarg.0 IL_000c: ldfld ""bool C.<Test>d__2.b"" IL_0011: call ""bool C.GetBool(bool)"" IL_0016: stfld ""bool C.<Test>d__2.<>7__wrap1"" IL_001b: ldarg.0 IL_001c: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0021: brfalse.s IL_0081 IL_0023: ldarg.0 IL_0024: ldfld ""C C.<Test>d__2.c1"" IL_0029: call ""System.Threading.Tasks.Task<C> C.GetC1(C)"" IL_002e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_0033: stloc.2 IL_0034: ldloca.s V_2 IL_0036: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_003b: brtrue.s IL_0079 IL_003d: ldarg.0 IL_003e: ldc.i4.0 IL_003f: dup IL_0040: stloc.0 IL_0041: stfld ""int C.<Test>d__2.<>1__state"" IL_0046: ldarg.0 IL_0047: ldloc.2 IL_0048: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_004d: ldarg.0 IL_004e: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_0053: ldloca.s V_2 IL_0055: ldarg.0 IL_0056: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_005b: leave.s IL_00d0 IL_005d: ldarg.0 IL_005e: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0063: stloc.2 IL_0064: ldarg.0 IL_0065: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_006a: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_0070: ldarg.0 IL_0071: ldc.i4.m1 IL_0072: dup IL_0073: stloc.0 IL_0074: stfld ""int C.<Test>d__2.<>1__state"" IL_0079: ldloca.s V_2 IL_007b: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_0080: stloc.1 IL_0081: ldarg.0 IL_0082: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0087: brtrue.s IL_009b IL_0089: ldarg.0 IL_008a: ldfld ""C C.<Test>d__2.c2"" IL_008f: call ""C C.GetC2(C)"" IL_0094: ldflda ""int C.F"" IL_0099: br.s IL_00a1 IL_009b: ldloc.1 IL_009c: ldflda ""int C.F"" IL_00a1: ldc.i4.s 123 IL_00a3: stind.i4 IL_00a4: leave.s IL_00bd } catch System.Exception { IL_00a6: stloc.3 IL_00a7: ldarg.0 IL_00a8: ldc.i4.s -2 IL_00aa: stfld ""int C.<Test>d__2.<>1__state"" IL_00af: ldarg.0 IL_00b0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00b5: ldloc.3 IL_00b6: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" IL_00bb: leave.s IL_00d0 } IL_00bd: ldarg.0 IL_00be: ldc.i4.s -2 IL_00c0: stfld ""int C.<Test>d__2.<>1__state"" IL_00c5: ldarg.0 IL_00c6: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00cb: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()"" IL_00d0: ret } "); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_03() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C(); var c2 = new C(); await Test(false, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); System.Console.Write('-'); c1 = new C(); c2 = new C(); await Test(true, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); } static async Task Test(bool b, C c1, C c2) { (GetBool(b) ? ref GetC1(c1).F: ref (await GetC2(c2)).F) = 123; } static bool GetBool(bool b) => b; static C GetC1(C c) => c; static async Task<C> GetC2(C c) { await Task.Yield(); return c; } } "; var comp = CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.ReleaseExe); CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.DebugExe); comp.VerifyIL("C.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { // Code size 209 (0xd1) .maxstack 3 .locals init (int V_0, C V_1, System.Runtime.CompilerServices.TaskAwaiter<C> V_2, System.Exception V_3) IL_0000: ldarg.0 IL_0001: ldfld ""int C.<Test>d__2.<>1__state"" IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: brfalse.s IL_005d IL_000a: ldarg.0 IL_000b: ldarg.0 IL_000c: ldfld ""bool C.<Test>d__2.b"" IL_0011: call ""bool C.GetBool(bool)"" IL_0016: stfld ""bool C.<Test>d__2.<>7__wrap1"" IL_001b: ldarg.0 IL_001c: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0021: brtrue.s IL_0081 IL_0023: ldarg.0 IL_0024: ldfld ""C C.<Test>d__2.c2"" IL_0029: call ""System.Threading.Tasks.Task<C> C.GetC2(C)"" IL_002e: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_0033: stloc.2 IL_0034: ldloca.s V_2 IL_0036: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_003b: brtrue.s IL_0079 IL_003d: ldarg.0 IL_003e: ldc.i4.0 IL_003f: dup IL_0040: stloc.0 IL_0041: stfld ""int C.<Test>d__2.<>1__state"" IL_0046: ldarg.0 IL_0047: ldloc.2 IL_0048: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_004d: ldarg.0 IL_004e: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_0053: ldloca.s V_2 IL_0055: ldarg.0 IL_0056: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_005b: leave.s IL_00d0 IL_005d: ldarg.0 IL_005e: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0063: stloc.2 IL_0064: ldarg.0 IL_0065: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_006a: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_0070: ldarg.0 IL_0071: ldc.i4.m1 IL_0072: dup IL_0073: stloc.0 IL_0074: stfld ""int C.<Test>d__2.<>1__state"" IL_0079: ldloca.s V_2 IL_007b: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_0080: stloc.1 IL_0081: ldarg.0 IL_0082: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0087: brtrue.s IL_0091 IL_0089: ldloc.1 IL_008a: ldflda ""int C.F"" IL_008f: br.s IL_00a1 IL_0091: ldarg.0 IL_0092: ldfld ""C C.<Test>d__2.c1"" IL_0097: call ""C C.GetC1(C)"" IL_009c: ldflda ""int C.F"" IL_00a1: ldc.i4.s 123 IL_00a3: stind.i4 IL_00a4: leave.s IL_00bd } catch System.Exception { IL_00a6: stloc.3 IL_00a7: ldarg.0 IL_00a8: ldc.i4.s -2 IL_00aa: stfld ""int C.<Test>d__2.<>1__state"" IL_00af: ldarg.0 IL_00b0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00b5: ldloc.3 IL_00b6: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" IL_00bb: leave.s IL_00d0 } IL_00bd: ldarg.0 IL_00be: ldc.i4.s -2 IL_00c0: stfld ""int C.<Test>d__2.<>1__state"" IL_00c5: ldarg.0 IL_00c6: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00cb: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()"" IL_00d0: ret } "); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_04() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C(); var c2 = new C(); await Test(false, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); System.Console.Write('-'); c1 = new C(); c2 = new C(); await Test(true, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); } static async Task Test(bool b, C c1, C c2) { ((await GetBool(b)) ? ref (await GetC1(c1)).F: ref (await GetC2(c2)).F) = 123; } static async Task<bool> GetBool(bool b) { await Task.Yield(); return b; } static async Task<C> GetC1(C c) { await Task.Yield(); return c; } static async Task<C> GetC2(C c) { await Task.Yield(); return c; } } "; var comp = CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.ReleaseExe); CompileAndVerify(source, expectedOutput: "0123-1230", options: TestOptions.DebugExe); comp.VerifyIL("C.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { // Code size 439 (0x1b7) .maxstack 3 .locals init (int V_0, bool V_1, System.Runtime.CompilerServices.TaskAwaiter<bool> V_2, System.Runtime.CompilerServices.TaskAwaiter<C> V_3, System.Exception V_4) IL_0000: ldarg.0 IL_0001: ldfld ""int C.<Test>d__2.<>1__state"" IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: switch ( IL_0056, IL_00c6, IL_012e) IL_0019: ldarg.0 IL_001a: ldfld ""bool C.<Test>d__2.b"" IL_001f: call ""System.Threading.Tasks.Task<bool> C.GetBool(bool)"" IL_0024: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<bool> System.Threading.Tasks.Task<bool>.GetAwaiter()"" IL_0029: stloc.2 IL_002a: ldloca.s V_2 IL_002c: call ""bool System.Runtime.CompilerServices.TaskAwaiter<bool>.IsCompleted.get"" IL_0031: brtrue.s IL_0072 IL_0033: ldarg.0 IL_0034: ldc.i4.0 IL_0035: dup IL_0036: stloc.0 IL_0037: stfld ""int C.<Test>d__2.<>1__state"" IL_003c: ldarg.0 IL_003d: ldloc.2 IL_003e: stfld ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_0043: ldarg.0 IL_0044: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_0049: ldloca.s V_2 IL_004b: ldarg.0 IL_004c: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<bool>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<bool>, ref C.<Test>d__2)"" IL_0051: leave IL_01b6 IL_0056: ldarg.0 IL_0057: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_005c: stloc.2 IL_005d: ldarg.0 IL_005e: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<bool> C.<Test>d__2.<>u__1"" IL_0063: initobj ""System.Runtime.CompilerServices.TaskAwaiter<bool>"" IL_0069: ldarg.0 IL_006a: ldc.i4.m1 IL_006b: dup IL_006c: stloc.0 IL_006d: stfld ""int C.<Test>d__2.<>1__state"" IL_0072: ldloca.s V_2 IL_0074: call ""bool System.Runtime.CompilerServices.TaskAwaiter<bool>.GetResult()"" IL_0079: stloc.1 IL_007a: ldarg.0 IL_007b: ldloc.1 IL_007c: stfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0081: ldarg.0 IL_0082: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0087: brfalse.s IL_00f1 IL_0089: ldarg.0 IL_008a: ldfld ""C C.<Test>d__2.c1"" IL_008f: call ""System.Threading.Tasks.Task<C> C.GetC1(C)"" IL_0094: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_0099: stloc.3 IL_009a: ldloca.s V_3 IL_009c: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_00a1: brtrue.s IL_00e2 IL_00a3: ldarg.0 IL_00a4: ldc.i4.1 IL_00a5: dup IL_00a6: stloc.0 IL_00a7: stfld ""int C.<Test>d__2.<>1__state"" IL_00ac: ldarg.0 IL_00ad: ldloc.3 IL_00ae: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_00b3: ldarg.0 IL_00b4: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00b9: ldloca.s V_3 IL_00bb: ldarg.0 IL_00bc: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_00c1: leave IL_01b6 IL_00c6: ldarg.0 IL_00c7: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_00cc: stloc.3 IL_00cd: ldarg.0 IL_00ce: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_00d3: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_00d9: ldarg.0 IL_00da: ldc.i4.m1 IL_00db: dup IL_00dc: stloc.0 IL_00dd: stfld ""int C.<Test>d__2.<>1__state"" IL_00e2: ldarg.0 IL_00e3: ldloca.s V_3 IL_00e5: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_00ea: stfld ""C C.<Test>d__2.<>7__wrap2"" IL_00ef: br.s IL_0157 IL_00f1: ldarg.0 IL_00f2: ldfld ""C C.<Test>d__2.c2"" IL_00f7: call ""System.Threading.Tasks.Task<C> C.GetC2(C)"" IL_00fc: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_0101: stloc.3 IL_0102: ldloca.s V_3 IL_0104: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_0109: brtrue.s IL_014a IL_010b: ldarg.0 IL_010c: ldc.i4.2 IL_010d: dup IL_010e: stloc.0 IL_010f: stfld ""int C.<Test>d__2.<>1__state"" IL_0114: ldarg.0 IL_0115: ldloc.3 IL_0116: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_011b: ldarg.0 IL_011c: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_0121: ldloca.s V_3 IL_0123: ldarg.0 IL_0124: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_0129: leave IL_01b6 IL_012e: ldarg.0 IL_012f: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_0134: stloc.3 IL_0135: ldarg.0 IL_0136: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__2"" IL_013b: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_0141: ldarg.0 IL_0142: ldc.i4.m1 IL_0143: dup IL_0144: stloc.0 IL_0145: stfld ""int C.<Test>d__2.<>1__state"" IL_014a: ldarg.0 IL_014b: ldloca.s V_3 IL_014d: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_0152: stfld ""C C.<Test>d__2.<>7__wrap3"" IL_0157: ldarg.0 IL_0158: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_015d: brtrue.s IL_016c IL_015f: ldarg.0 IL_0160: ldfld ""C C.<Test>d__2.<>7__wrap3"" IL_0165: ldflda ""int C.F"" IL_016a: br.s IL_0177 IL_016c: ldarg.0 IL_016d: ldfld ""C C.<Test>d__2.<>7__wrap2"" IL_0172: ldflda ""int C.F"" IL_0177: ldc.i4.s 123 IL_0179: stind.i4 IL_017a: ldarg.0 IL_017b: ldnull IL_017c: stfld ""C C.<Test>d__2.<>7__wrap2"" IL_0181: ldarg.0 IL_0182: ldnull IL_0183: stfld ""C C.<Test>d__2.<>7__wrap3"" IL_0188: leave.s IL_01a3 } catch System.Exception { IL_018a: stloc.s V_4 IL_018c: ldarg.0 IL_018d: ldc.i4.s -2 IL_018f: stfld ""int C.<Test>d__2.<>1__state"" IL_0194: ldarg.0 IL_0195: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_019a: ldloc.s V_4 IL_019c: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" IL_01a1: leave.s IL_01b6 } IL_01a3: ldarg.0 IL_01a4: ldc.i4.s -2 IL_01a6: stfld ""int C.<Test>d__2.<>1__state"" IL_01ab: ldarg.0 IL_01ac: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_01b1: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()"" IL_01b6: ret } "); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_05() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C() { F = 123}; var c2 = new C() { F = 124}; await Test(false, c1, c2); System.Console.Write('-'); await Test(true, c1, c2); } static async Task Test(bool b, C c1, C c2) { Test(b ? ref (await GetC(c1)).F : ref (await GetC(c2)).F, await GetC(new C())); } static void Test(int x, C y) { System.Console.Write(x); } static async Task<C> GetC(C c) { await Task.Yield(); return c; } } "; var comp = CompileAndVerify(source, expectedOutput: "124-123", options: TestOptions.ReleaseExe); CompileAndVerify(source, expectedOutput: "124-123", options: TestOptions.DebugExe); comp.VerifyIL("C.<Test>d__2.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext", @" { // Code size 453 (0x1c5) .maxstack 3 .locals init (int V_0, C V_1, System.Runtime.CompilerServices.TaskAwaiter<C> V_2, System.Exception V_3) IL_0000: ldarg.0 IL_0001: ldfld ""int C.<Test>d__2.<>1__state"" IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: switch ( IL_006a, IL_00d2, IL_015a) IL_0019: ldarg.0 IL_001a: ldarg.0 IL_001b: ldfld ""bool C.<Test>d__2.b"" IL_0020: stfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0025: ldarg.0 IL_0026: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_002b: brfalse.s IL_0095 IL_002d: ldarg.0 IL_002e: ldfld ""C C.<Test>d__2.c1"" IL_0033: call ""System.Threading.Tasks.Task<C> C.GetC(C)"" IL_0038: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_003d: stloc.2 IL_003e: ldloca.s V_2 IL_0040: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_0045: brtrue.s IL_0086 IL_0047: ldarg.0 IL_0048: ldc.i4.0 IL_0049: dup IL_004a: stloc.0 IL_004b: stfld ""int C.<Test>d__2.<>1__state"" IL_0050: ldarg.0 IL_0051: ldloc.2 IL_0052: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0057: ldarg.0 IL_0058: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_005d: ldloca.s V_2 IL_005f: ldarg.0 IL_0060: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_0065: leave IL_01c4 IL_006a: ldarg.0 IL_006b: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0070: stloc.2 IL_0071: ldarg.0 IL_0072: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0077: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_007d: ldarg.0 IL_007e: ldc.i4.m1 IL_007f: dup IL_0080: stloc.0 IL_0081: stfld ""int C.<Test>d__2.<>1__state"" IL_0086: ldarg.0 IL_0087: ldloca.s V_2 IL_0089: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_008e: stfld ""C C.<Test>d__2.<>7__wrap2"" IL_0093: br.s IL_00fb IL_0095: ldarg.0 IL_0096: ldfld ""C C.<Test>d__2.c2"" IL_009b: call ""System.Threading.Tasks.Task<C> C.GetC(C)"" IL_00a0: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_00a5: stloc.2 IL_00a6: ldloca.s V_2 IL_00a8: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_00ad: brtrue.s IL_00ee IL_00af: ldarg.0 IL_00b0: ldc.i4.1 IL_00b1: dup IL_00b2: stloc.0 IL_00b3: stfld ""int C.<Test>d__2.<>1__state"" IL_00b8: ldarg.0 IL_00b9: ldloc.2 IL_00ba: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_00bf: ldarg.0 IL_00c0: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_00c5: ldloca.s V_2 IL_00c7: ldarg.0 IL_00c8: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_00cd: leave IL_01c4 IL_00d2: ldarg.0 IL_00d3: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_00d8: stloc.2 IL_00d9: ldarg.0 IL_00da: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_00df: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_00e5: ldarg.0 IL_00e6: ldc.i4.m1 IL_00e7: dup IL_00e8: stloc.0 IL_00e9: stfld ""int C.<Test>d__2.<>1__state"" IL_00ee: ldarg.0 IL_00ef: ldloca.s V_2 IL_00f1: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_00f6: stfld ""C C.<Test>d__2.<>7__wrap3"" IL_00fb: ldarg.0 IL_00fc: ldarg.0 IL_00fd: ldfld ""bool C.<Test>d__2.<>7__wrap1"" IL_0102: brtrue.s IL_0111 IL_0104: ldarg.0 IL_0105: ldfld ""C C.<Test>d__2.<>7__wrap3"" IL_010a: ldfld ""int C.F"" IL_010f: br.s IL_011c IL_0111: ldarg.0 IL_0112: ldfld ""C C.<Test>d__2.<>7__wrap2"" IL_0117: ldfld ""int C.F"" IL_011c: stfld ""int C.<Test>d__2.<>7__wrap4"" IL_0121: newobj ""C..ctor()"" IL_0126: call ""System.Threading.Tasks.Task<C> C.GetC(C)"" IL_012b: callvirt ""System.Runtime.CompilerServices.TaskAwaiter<C> System.Threading.Tasks.Task<C>.GetAwaiter()"" IL_0130: stloc.2 IL_0131: ldloca.s V_2 IL_0133: call ""bool System.Runtime.CompilerServices.TaskAwaiter<C>.IsCompleted.get"" IL_0138: brtrue.s IL_0176 IL_013a: ldarg.0 IL_013b: ldc.i4.2 IL_013c: dup IL_013d: stloc.0 IL_013e: stfld ""int C.<Test>d__2.<>1__state"" IL_0143: ldarg.0 IL_0144: ldloc.2 IL_0145: stfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_014a: ldarg.0 IL_014b: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_0150: ldloca.s V_2 IL_0152: ldarg.0 IL_0153: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.TaskAwaiter<C>, C.<Test>d__2>(ref System.Runtime.CompilerServices.TaskAwaiter<C>, ref C.<Test>d__2)"" IL_0158: leave.s IL_01c4 IL_015a: ldarg.0 IL_015b: ldfld ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0160: stloc.2 IL_0161: ldarg.0 IL_0162: ldflda ""System.Runtime.CompilerServices.TaskAwaiter<C> C.<Test>d__2.<>u__1"" IL_0167: initobj ""System.Runtime.CompilerServices.TaskAwaiter<C>"" IL_016d: ldarg.0 IL_016e: ldc.i4.m1 IL_016f: dup IL_0170: stloc.0 IL_0171: stfld ""int C.<Test>d__2.<>1__state"" IL_0176: ldloca.s V_2 IL_0178: call ""C System.Runtime.CompilerServices.TaskAwaiter<C>.GetResult()"" IL_017d: stloc.1 IL_017e: ldarg.0 IL_017f: ldfld ""int C.<Test>d__2.<>7__wrap4"" IL_0184: ldloc.1 IL_0185: call ""void C.Test(int, C)"" IL_018a: ldarg.0 IL_018b: ldnull IL_018c: stfld ""C C.<Test>d__2.<>7__wrap2"" IL_0191: ldarg.0 IL_0192: ldnull IL_0193: stfld ""C C.<Test>d__2.<>7__wrap3"" IL_0198: leave.s IL_01b1 } catch System.Exception { IL_019a: stloc.3 IL_019b: ldarg.0 IL_019c: ldc.i4.s -2 IL_019e: stfld ""int C.<Test>d__2.<>1__state"" IL_01a3: ldarg.0 IL_01a4: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_01a9: ldloc.3 IL_01aa: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)"" IL_01af: leave.s IL_01c4 } IL_01b1: ldarg.0 IL_01b2: ldc.i4.s -2 IL_01b4: stfld ""int C.<Test>d__2.<>1__state"" IL_01b9: ldarg.0 IL_01ba: ldflda ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Test>d__2.<>t__builder"" IL_01bf: call ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()"" IL_01c4: ret } "); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_06() { var source = @" using System.Threading.Tasks; class C { int F; static async Task Main() { var c1 = new C(); var c2 = new C(); await Test(false, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); System.Console.Write('-'); c1 = new C(); c2 = new C(); await Test(true, c1, c2); System.Console.Write(c1.F); System.Console.Write(c2.F); } static async Task Test(bool b, C c1, C c2) { Test(ref b ? ref (await GetC(c1)).F : ref (await GetC(c2)).F, await GetC(new C())); Test(ref b ? ref c1.F : ref c2.F, await GetC(new C())); } static void Test(ref int x, C y) { x = 123; } static async Task<C> GetC(C c) { await Task.Yield(); return c; } } "; var expected = new[] { // (27,18): error CS8325: 'await' cannot be used in an expression containing a ref conditional operator // Test(ref b ? ref (await GetC(c1)).F : ref (await GetC(c2)).F, await GetC(new C())); Diagnostic(ErrorCode.ERR_RefConditionalAndAwait, "b ? ref (await GetC(c1)).F : ref (await GetC(c2)).F").WithLocation(27, 18), // (28,18): error CS8325: 'await' cannot be used in an expression containing a ref conditional operator // Test(ref b ? ref c1.F : ref c2.F, await GetC(new C())); Diagnostic(ErrorCode.ERR_RefConditionalAndAwait, "b ? ref c1.F : ref c2.F").WithLocation(28, 18) }; var comp = CreateCompilation(source); comp.VerifyEmitDiagnostics(expected); comp = CreateRuntimeAsyncCompilation(source); comp.VerifyEmitDiagnostics(expected); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void AwaitInRefConditional_07() { var source = @" using System.Threading.Tasks; using System; class C { static void Main() { _ = NumberBuggy().Result; Console.WriteLine(""--------""); _ = NumberNotBuggy(); } public static async Task<int> NumberBuggy() { string str = ""a2""; int x = 1; int y = 2; ref int r = ref await EvalAsync(str, 1) is ""a1"" ? ref x : ref await EvalAsync(str, 2) is ""a2"" ? ref y : ref System.Runtime.CompilerServices.Unsafe.NullRef<int>(); r++; r++; r++; int xxx = r; System.Console.WriteLine(xxx); System.Console.WriteLine(x); System.Console.WriteLine(y); //should be 5 now! return xxx; } public static ValueTask<int> NumberNotBuggy() { string str = ""a2""; int x = 1; int y = 2; ref int r = ref EvalAsync(str, 1).Result is ""a1"" ? ref x : ref EvalAsync(str, 2).Result is ""a2"" ? ref y : ref System.Runtime.CompilerServices.Unsafe.NullRef<int>(); r++; r++; r++; int xxx = r; System.Console.WriteLine(xxx); System.Console.WriteLine(x); System.Console.WriteLine(y); return new(xxx); } static ValueTask<string> EvalAsync(string s, int i) { System.Console.WriteLine($""{s} {i}""); return ValueTask.FromResult(s); } } "; var expectedOutput = @" a2 1 a2 2 5 1 5 -------- a2 1 a2 2 5 1 5 "; CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.ReleaseExe, verify: Verification.FailsPEVerify); CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.DebugExe, verify: Verification.FailsPEVerify); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void SpillingInRefConditional_01() { var source = @" using System; class C { static void Main() { string str = ""a2""; int x = 1; int y = 2; ref int r = ref str is ""Hallo"" ? ref x : ref str is { Length: >= 2 and <= 10 or 22 } ? ref y : ref System.Runtime.CompilerServices.Unsafe.NullRef<int>(); r++; r++; r++; int xxx = r; System.Console.WriteLine(xxx); System.Console.WriteLine(x); System.Console.WriteLine(y); } } "; var expectedOutput = @" 5 1 5 "; CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.ReleaseExe, verify: Verification.FailsPEVerify); CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.DebugExe, verify: Verification.FailsPEVerify); } [Fact] [WorkItem("https://github.com/dotnet/roslyn/issues/74115")] public void SpillingInRefConditional_02() { var source = @" using System; class C { static void Main() { string str = ""a2""; int x = 1; int y = 2; ref readonly var xx = ref x; ref readonly int r = ref Eval(str, 1) is ""Hallo"" ? ref xx : ref Eval(str, 2) is { Length: >= 2 and <= 10 or 22 } ? ref y : ref System.Runtime.CompilerServices.Unsafe.NullRef<int>(); ref var rx = ref System.Runtime.CompilerServices.Unsafe.AsRef(in r); rx++; rx++; rx++; int xxx = r; System.Console.WriteLine(xxx); System.Console.WriteLine(x); System.Console.WriteLine(y); } static T Eval<T>(T s, int i) { System.Console.WriteLine($""{s} {i}""); return s; } } "; var expectedOutput = @" a2 1 a2 2 5 1 5 "; CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.ReleaseExe, verify: Verification.FailsPEVerify); CompileAndVerify(source, targetFramework: TargetFramework.NetCoreApp, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? expectedOutput : null, options: TestOptions.DebugExe, verify: Verification.FailsPEVerify); } } }