File: CodeGen\CodeGenRefConditionalOperatorTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit\Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit.UnitTests)
// 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 comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
 
            comp.VerifyEmitDiagnostics(
                // (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)
                );
        }
 
        [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 comp = CreateCompilationWithMscorlib461(source, options: TestOptions.ReleaseExe);
 
            comp.VerifyEmitDiagnostics(
                // (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)
               );
        }
 
        [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.Passes, @"
{
  // Code size       22 (0x16)
  .maxstack  1
  IL_0000:  ldc.i4.1
  IL_0001:  brtrue.s   IL_0008
  IL_0003:  ldc.i4.1
  IL_0004:  conv.i
  IL_0005:  pop
  IL_0006:  br.s       IL_000b
  IL_0008:  ldc.i4.0
  IL_0009:  conv.i
  IL_000a:  pop
  IL_000b:  ldstr      ""run""
  IL_0010:  call       ""void System.Console.WriteLine(string)""
  IL_0015:  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       28 (0x1c)
  .maxstack  1
  .locals init (int V_0, //i1
                int* V_1) //p1
  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:  brfalse.s  IL_0011
  IL_0009:  ldloc.1
  IL_000a:  ldind.i4
  IL_000b:  call       ""int* Program.<<Main>$>g__M|0_0(int)""
  IL_0010:  pop
  IL_0011:  ldstr      ""run""
  IL_0016:  call       ""void System.Console.WriteLine(string)""
  IL_001b:  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 comp = CreateCompilation(source);
 
            comp.VerifyEmitDiagnostics(
                // (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)
                );
        }
 
        [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);
        }
    }
}