File: CodeGen\PatternTests.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 System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
    public class PatternTests : EmitMetadataTestBase
    {
        #region Miscellaneous
 
        [Fact, WorkItem(48493, "https://github.com/dotnet/roslyn/issues/48493")]
        public void Repro_48493()
        {
            var source = @"
using System;
using System.Linq;
 
namespace Sample
{
    internal class Row
    {
        public string Message { get; set; } = """";
    }
 
    internal class Program
    {
        private static void Main()
        {
            Console.WriteLine(ProcessRow(new Row()));
        }
 
        private static string ProcessRow(Row row)
        {
            if (row == null) throw new ArgumentNullException(nameof(row));
            return row switch
            {
                { Message: ""stringA"" } => ""stringB"",
                var r when new[] { ""stringC"", ""stringD"" }.Any(x => r.Message.Contains(x)) => ""stringE"",
                { Message: ""stringF"" } => ""stringG"",
                _ => ""stringH"",
            };
        }
    }
}";
            CompileAndVerify(source, expectedOutput: "stringH");
        }
 
        [Fact, WorkItem(48493, "https://github.com/dotnet/roslyn/issues/48493")]
        public void Repro_48493_Simple()
        {
            var source = @"
using System;
 
internal class Widget
{
    public bool IsGood { get; set; }
}
 
internal class Program
{
    private static bool M0(Func<bool> fn) => fn();
 
    private static void Main()
    {
        Console.Write(new Widget() switch
        {
            { IsGood: true } => 1,
            _ when M0(() => true) => 2,
            { } => 3,
        });
    }
}";
            CompileAndVerify(source, expectedOutput: @"2");
        }
 
        [Fact, WorkItem(18811, "https://github.com/dotnet/roslyn/issues/18811")]
        public void MissingNullable_01()
        {
            var source = @"namespace System {
    public class Object { }
    public abstract class ValueType { }
    public struct Void { }
    public struct Boolean { }
    public struct Int32 { }
}
static class C {
    public static bool M() => ((object)123) is int i;
}
";
            var compilation = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), options: TestOptions.ReleaseDll);
            compilation.GetDiagnostics().Verify();
            compilation.GetEmitDiagnostics().Verify(
                // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
                Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1)
                );
        }
 
        [Fact, WorkItem(18811, "https://github.com/dotnet/roslyn/issues/18811")]
        public void MissingNullable_02()
        {
            var source = @"namespace System {
    public class Object { }
    public abstract class ValueType { }
    public struct Void { }
    public struct Boolean { }
    public struct Int32 { }
    public struct Nullable<T> where T : struct { }
}
static class C {
    public static bool M() => ((object)123) is int i;
}
";
            var compilation = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), options: TestOptions.UnsafeReleaseDll);
            compilation.GetDiagnostics().Verify();
            compilation.GetEmitDiagnostics().Verify(
                // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
                Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion)
                );
        }
 
        [Fact]
        public void MissingNullable_03()
        {
            var source = @"namespace System {
    public class Object { }
    public abstract class ValueType { }
    public struct Void { }
    public struct Boolean { }
    public struct Int32 { }
    public struct Nullable<T> where T : struct { }
}
static class C {
    static void M1(int? x)
    {
        switch (x)
        {
            case int i: break;
        }
    }
    static bool M2(int? x) => x is int i;
}
";
            var compilation = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), options: TestOptions.UnsafeReleaseDll);
            compilation.GetDiagnostics().Verify();
            compilation.GetEmitDiagnostics().Verify(
                // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
                Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1),
                // (14,18): error CS0656: Missing compiler required member 'System.Nullable`1.get_HasValue'
                //             case int i: break;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_HasValue").WithLocation(14, 18),
                // (14,18): error CS0656: Missing compiler required member 'System.Nullable`1.GetValueOrDefault'
                //             case int i: break;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "GetValueOrDefault").WithLocation(14, 18),
                // (14,18): error CS0656: Missing compiler required member 'System.Nullable`1.get_Value'
                //             case int i: break;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_Value").WithLocation(14, 18),
                // (17,36): error CS0656: Missing compiler required member 'System.Nullable`1.get_HasValue'
                //     static bool M2(int? x) => x is int i;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_HasValue").WithLocation(17, 36),
                // (17,36): error CS0656: Missing compiler required member 'System.Nullable`1.GetValueOrDefault'
                //     static bool M2(int? x) => x is int i;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "GetValueOrDefault").WithLocation(17, 36),
                // (17,36): error CS0656: Missing compiler required member 'System.Nullable`1.get_Value'
                //     static bool M2(int? x) => x is int i;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_Value").WithLocation(17, 36)
                );
        }
 
        [Fact]
        public void MissingNullable_04()
        {
            var source = @"namespace System {
    public class Object { }
    public abstract class ValueType { }
    public struct Void { }
    public struct Boolean { }
    public struct Int32 { }
    public struct Nullable<T> where T : struct { public T GetValueOrDefault() => default(T); }
}
static class C {
    static void M1(int? x)
    {
        switch (x)
        {
            case int i: break;
        }
    }
    static bool M2(int? x) => x is int i;
}
";
            var compilation = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), options: TestOptions.UnsafeReleaseDll);
            compilation.GetDiagnostics().Verify();
            compilation.GetEmitDiagnostics().Verify(
                // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
                Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1),
                // (14,18): error CS0656: Missing compiler required member 'System.Nullable`1.get_HasValue'
                //             case int i: break;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_HasValue").WithLocation(14, 18),
                // (17,36): error CS0656: Missing compiler required member 'System.Nullable`1.get_HasValue'
                //     static bool M2(int? x) => x is int i;
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "int i").WithArguments("System.Nullable`1", "get_HasValue").WithLocation(17, 36)
                );
        }
 
        [Fact, WorkItem(17266, "https://github.com/dotnet/roslyn/issues/17266")]
        public void DoubleEvaluation01()
        {
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        if (TryGet() is int index)
        {
            Console.WriteLine(index);
        }
    }
 
    public static int? TryGet()
    {
        Console.WriteLine(""eval"");
        return null;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"eval";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.Main",
@"{
  // Code size       42 (0x2a)
  .maxstack  1
  .locals init (int V_0, //index
                bool V_1,
                int? V_2)
  IL_0000:  nop
  IL_0001:  call       ""int? C.TryGet()""
  IL_0006:  stloc.2
  IL_0007:  ldloca.s   V_2
  IL_0009:  call       ""bool int?.HasValue.get""
  IL_000e:  brfalse.s  IL_001b
  IL_0010:  ldloca.s   V_2
  IL_0012:  call       ""int int?.GetValueOrDefault()""
  IL_0017:  stloc.0
  IL_0018:  ldc.i4.1
  IL_0019:  br.s       IL_001c
  IL_001b:  ldc.i4.0
  IL_001c:  stloc.1
  IL_001d:  ldloc.1
  IL_001e:  brfalse.s  IL_0029
  IL_0020:  nop
  IL_0021:  ldloc.0
  IL_0022:  call       ""void System.Console.WriteLine(int)""
  IL_0027:  nop
  IL_0028:  nop
  IL_0029:  ret
}");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.Main",
@"{
  // Code size       30 (0x1e)
  .maxstack  1
  .locals init (int V_0, //index
                int? V_1)
  IL_0000:  call       ""int? C.TryGet()""
  IL_0005:  stloc.1
  IL_0006:  ldloca.s   V_1
  IL_0008:  call       ""bool int?.HasValue.get""
  IL_000d:  brfalse.s  IL_001d
  IL_000f:  ldloca.s   V_1
  IL_0011:  call       ""int int?.GetValueOrDefault()""
  IL_0016:  stloc.0
  IL_0017:  ldloc.0
  IL_0018:  call       ""void System.Console.WriteLine(int)""
  IL_001d:  ret
}");
        }
 
        [Fact, WorkItem(19122, "https://github.com/dotnet/roslyn/issues/19122")]
        public void PatternCrash_01()
        {
            var source = @"using System;
using System.Collections.Generic;
using System.Linq;
 
public class Class2 : IDisposable
{
    public Class2(bool parameter = false)
    {
    }
 
    public void Dispose()
    {
    }
}
 
class X<T>
{
    IdentityAccessor<T> idAccessor = new IdentityAccessor<T>();
    void Y<U>() where U : T
    {
        // BUG: The following line is the problem
        if (GetT().FirstOrDefault(p => idAccessor.GetId(p) == Guid.Empty) is U u)
        {
        }
    }
 
    IEnumerable<T> GetT()
    {
        yield return default(T);
    }
}
class IdentityAccessor<T>
{
    public Guid GetId(T t)
    {
        return Guid.Empty;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("X<T>.Y<U>",
@"{
  // Code size       61 (0x3d)
  .maxstack  3
  .locals init (U V_0, //u
                bool V_1,
                T V_2)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       ""System.Collections.Generic.IEnumerable<T> X<T>.GetT()""
  IL_0007:  ldarg.0
  IL_0008:  ldftn      ""bool X<T>.<Y>b__1_0<U>(T)""
  IL_000e:  newobj     ""System.Func<T, bool>..ctor(object, System.IntPtr)""
  IL_0013:  call       ""T System.Linq.Enumerable.FirstOrDefault<T>(System.Collections.Generic.IEnumerable<T>, System.Func<T, bool>)""
  IL_0018:  stloc.2
  IL_0019:  ldloc.2
  IL_001a:  box        ""T""
  IL_001f:  isinst     ""U""
  IL_0024:  brfalse.s  IL_0035
  IL_0026:  ldloc.2
  IL_0027:  box        ""T""
  IL_002c:  unbox.any  ""U""
  IL_0031:  stloc.0
  IL_0032:  ldc.i4.1
  IL_0033:  br.s       IL_0036
  IL_0035:  ldc.i4.0
  IL_0036:  stloc.1
  IL_0037:  ldloc.1
  IL_0038:  brfalse.s  IL_003c
  IL_003a:  nop
  IL_003b:  nop
  IL_003c:  ret
}");
        }
 
        [Fact, WorkItem(24522, "https://github.com/dotnet/roslyn/issues/24522")]
        public void IgnoreDeclaredConversion_01()
        {
            var source =
@"class Base<T>
{
    public static implicit operator Derived(Base<T> obj)
    {
        return new Derived();
    }
}
 
class Derived : Base<object>
{
}
 
class Program
{
    static void Main(string[] args)
    {
        Base<object> x = new Derived();
        System.Console.WriteLine(x is Derived);
        System.Console.WriteLine(x is Derived y);
        switch (x)
        {
            case Derived z: System.Console.WriteLine(true); break;
        }
        System.Console.WriteLine(null != (x as Derived));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"True
True
True
True";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Program.Main",
@"{
  // Code size       84 (0x54)
  .maxstack  2
  .locals init (Base<object> V_0, //x
                Derived V_1, //y
                Derived V_2, //z
                Base<object> V_3,
                Base<object> V_4)
  IL_0000:  nop
  IL_0001:  newobj     ""Derived..ctor()""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  isinst     ""Derived""
  IL_000d:  ldnull
  IL_000e:  cgt.un
  IL_0010:  call       ""void System.Console.WriteLine(bool)""
  IL_0015:  nop
  IL_0016:  ldloc.0
  IL_0017:  isinst     ""Derived""
  IL_001c:  stloc.1
  IL_001d:  ldloc.1
  IL_001e:  ldnull
  IL_001f:  cgt.un
  IL_0021:  call       ""void System.Console.WriteLine(bool)""
  IL_0026:  nop
  IL_0027:  ldloc.0
  IL_0028:  stloc.s    V_4
  IL_002a:  ldloc.s    V_4
  IL_002c:  stloc.3
  IL_002d:  ldloc.3
  IL_002e:  isinst     ""Derived""
  IL_0033:  stloc.2
  IL_0034:  ldloc.2
  IL_0035:  brtrue.s   IL_0039
  IL_0037:  br.s       IL_0044
  IL_0039:  br.s       IL_003b
  IL_003b:  ldc.i4.1
  IL_003c:  call       ""void System.Console.WriteLine(bool)""
  IL_0041:  nop
  IL_0042:  br.s       IL_0044
  IL_0044:  ldloc.0
  IL_0045:  isinst     ""Derived""
  IL_004a:  ldnull
  IL_004b:  cgt.un
  IL_004d:  call       ""void System.Console.WriteLine(bool)""
  IL_0052:  nop
  IL_0053:  ret
}");
        }
 
        [Fact]
        public void DoublePattern01()
        {
            var source =
@"using System;
class Program
{
    static bool P1(double d) => d is double.NaN;
    static bool P2(float f) => f is float.NaN;
    static bool P3(double d) => d is 3.14d;
    static bool P4(float f) => f is 3.14f;
    static bool P5(object o)
    {
        switch (o)
        {
            case double.NaN: return true;
            case float.NaN: return true;
            case 3.14d: return true;
            case 3.14f: return true;
            default: return false;
        }
    }
    public static void Main(string[] args)
    {
        Console.Write(P1(double.NaN));
        Console.Write(P1(1.0));
        Console.Write(P2(float.NaN));
        Console.Write(P2(1.0f));
        Console.Write(P3(3.14));
        Console.Write(P3(double.NaN));
        Console.Write(P4(3.14f));
        Console.Write(P4(float.NaN));
        Console.Write(P5(double.NaN));
        Console.Write(P5(0.0d));
        Console.Write(P5(float.NaN));
        Console.Write(P5(0.0f));
        Console.Write(P5(3.14d));
        Console.Write(P5(125));
        Console.Write(P5(3.14f));
        Console.Write(P5(1.0f));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"TrueFalseTrueFalseTrueFalseTrueFalseTrueFalseTrueFalseTrueFalseTrueFalse";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Program.P1",
@"{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  call       ""bool double.IsNaN(double)""
  IL_0006:  ret
}");
            compVerifier.VerifyIL("Program.P2",
@"{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  call       ""bool float.IsNaN(float)""
  IL_0006:  ret
}");
            compVerifier.VerifyIL("Program.P3",
@"{
  // Code size       13 (0xd)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldc.r8     3.14
  IL_000a:  ceq
  IL_000c:  ret
}");
            compVerifier.VerifyIL("Program.P4",
@"{
  // Code size        9 (0x9)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldc.r4     3.14
  IL_0006:  ceq
  IL_0008:  ret
}");
            compVerifier.VerifyIL("Program.P5",
@"{
  // Code size      103 (0x67)
  .maxstack  2
  .locals init (object V_0,
                double V_1,
                float V_2,
                object V_3,
                bool V_4)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  stloc.3
  IL_0003:  ldloc.3
  IL_0004:  stloc.0
  IL_0005:  ldloc.0
  IL_0006:  isinst     ""double""
  IL_000b:  brfalse.s  IL_002a
  IL_000d:  ldloc.0
  IL_000e:  unbox.any  ""double""
  IL_0013:  stloc.1
  IL_0014:  ldloc.1
  IL_0015:  call       ""bool double.IsNaN(double)""
  IL_001a:  brtrue.s   IL_004b
  IL_001c:  ldloc.1
  IL_001d:  ldc.r8     3.14
  IL_0026:  beq.s      IL_0055
  IL_0028:  br.s       IL_005f
  IL_002a:  ldloc.0
  IL_002b:  isinst     ""float""
  IL_0030:  brfalse.s  IL_005f
  IL_0032:  ldloc.0
  IL_0033:  unbox.any  ""float""
  IL_0038:  stloc.2
  IL_0039:  ldloc.2
  IL_003a:  call       ""bool float.IsNaN(float)""
  IL_003f:  brtrue.s   IL_0050
  IL_0041:  ldloc.2
  IL_0042:  ldc.r4     3.14
  IL_0047:  beq.s      IL_005a
  IL_0049:  br.s       IL_005f
  IL_004b:  ldc.i4.1
  IL_004c:  stloc.s    V_4
  IL_004e:  br.s       IL_0064
  IL_0050:  ldc.i4.1
  IL_0051:  stloc.s    V_4
  IL_0053:  br.s       IL_0064
  IL_0055:  ldc.i4.1
  IL_0056:  stloc.s    V_4
  IL_0058:  br.s       IL_0064
  IL_005a:  ldc.i4.1
  IL_005b:  stloc.s    V_4
  IL_005d:  br.s       IL_0064
  IL_005f:  ldc.i4.0
  IL_0060:  stloc.s    V_4
  IL_0062:  br.s       IL_0064
  IL_0064:  ldloc.s    V_4
  IL_0066:  ret
}");
        }
 
        [Fact]
        public void DecimalEquality()
        {
            // demonstrate that pattern-matching against a decimal constant is
            // at least as efficient as simply using ==
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        Console.Write(M1(1.0m));
        Console.Write(M2(1.0m));
        Console.Write(M1(2.0m));
        Console.Write(M2(2.0m));
    }
 
    static int M1(decimal d)
    {
        if (M(d) is 1.0m) return 1;
        return 0;
    }
 
    static int M2(decimal d)
    {
        if (M(d) == 1.0m) return 1;
        return 0;
    }
 
    public static decimal M(decimal d)
    {
        return d;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"1100";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       37 (0x25)
  .maxstack  6
  .locals init (bool V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       ""decimal C.M(decimal)""
  IL_0007:  ldc.i4.s   10
  IL_0009:  ldc.i4.0
  IL_000a:  ldc.i4.0
  IL_000b:  ldc.i4.0
  IL_000c:  ldc.i4.1
  IL_000d:  newobj     ""decimal..ctor(int, int, int, bool, byte)""
  IL_0012:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0017:  stloc.0
  IL_0018:  ldloc.0
  IL_0019:  brfalse.s  IL_001f
  IL_001b:  ldc.i4.1
  IL_001c:  stloc.1
  IL_001d:  br.s       IL_0023
  IL_001f:  ldc.i4.0
  IL_0020:  stloc.1
  IL_0021:  br.s       IL_0023
  IL_0023:  ldloc.1
  IL_0024:  ret
}");
            compVerifier.VerifyIL("C.M2",
@"{
  // Code size       37 (0x25)
  .maxstack  6
  .locals init (bool V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  call       ""decimal C.M(decimal)""
  IL_0007:  ldc.i4.s   10
  IL_0009:  ldc.i4.0
  IL_000a:  ldc.i4.0
  IL_000b:  ldc.i4.0
  IL_000c:  ldc.i4.1
  IL_000d:  newobj     ""decimal..ctor(int, int, int, bool, byte)""
  IL_0012:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0017:  stloc.0
  IL_0018:  ldloc.0
  IL_0019:  brfalse.s  IL_001f
  IL_001b:  ldc.i4.1
  IL_001c:  stloc.1
  IL_001d:  br.s       IL_0023
  IL_001f:  ldc.i4.0
  IL_0020:  stloc.1
  IL_0021:  br.s       IL_0023
  IL_0023:  ldloc.1
  IL_0024:  ret
}");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       28 (0x1c)
  .maxstack  6
  IL_0000:  ldarg.0
  IL_0001:  call       ""decimal C.M(decimal)""
  IL_0006:  ldc.i4.s   10
  IL_0008:  ldc.i4.0
  IL_0009:  ldc.i4.0
  IL_000a:  ldc.i4.0
  IL_000b:  ldc.i4.1
  IL_000c:  newobj     ""decimal..ctor(int, int, int, bool, byte)""
  IL_0011:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0016:  brfalse.s  IL_001a
  IL_0018:  ldc.i4.1
  IL_0019:  ret
  IL_001a:  ldc.i4.0
  IL_001b:  ret
}");
            compVerifier.VerifyIL("C.M2",
@"{
  // Code size       28 (0x1c)
  .maxstack  6
  IL_0000:  ldarg.0
  IL_0001:  call       ""decimal C.M(decimal)""
  IL_0006:  ldc.i4.s   10
  IL_0008:  ldc.i4.0
  IL_0009:  ldc.i4.0
  IL_000a:  ldc.i4.0
  IL_000b:  ldc.i4.1
  IL_000c:  newobj     ""decimal..ctor(int, int, int, bool, byte)""
  IL_0011:  call       ""bool decimal.op_Equality(decimal, decimal)""
  IL_0016:  brfalse.s  IL_001a
  IL_0018:  ldc.i4.1
  IL_0019:  ret
  IL_001a:  ldc.i4.0
  IL_001b:  ret
}");
        }
 
        [Fact, WorkItem(16878, "https://github.com/dotnet/roslyn/issues/16878")]
        public void RedundantNullCheck()
        {
            var source =
@"public class C
{
    static int M1(bool? b1, bool b2)
    {
        switch (b1)
        {
            case null:
                return 1;
            case var _ when b2:
                return 2;
            case true:
                return 3;
            case false:
                return 4;
        }
    }
 
    static int M2(object o, bool b)
    {
        switch (o)
        {
            case string a when b:
                return 1;
            case string a:
                return 2;
        }
        return 3;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       35 (0x23)
  .maxstack  1
  .locals init (bool? V_0)
  IL_0000:  ldarg.0
  IL_0001:  stloc.0
  IL_0002:  ldloca.s   V_0
  IL_0004:  call       ""bool bool?.HasValue.get""
  IL_0009:  brfalse.s  IL_0018
  IL_000b:  br.s       IL_001a
  IL_000d:  ldloca.s   V_0
  IL_000f:  call       ""bool bool?.GetValueOrDefault()""
  IL_0014:  brtrue.s   IL_001f
  IL_0016:  br.s       IL_0021
  IL_0018:  ldc.i4.1
  IL_0019:  ret
  IL_001a:  ldarg.1
  IL_001b:  brfalse.s  IL_000d
  IL_001d:  ldc.i4.2
  IL_001e:  ret
  IL_001f:  ldc.i4.3
  IL_0020:  ret
  IL_0021:  ldc.i4.4
  IL_0022:  ret
}");
            compVerifier.VerifyIL("C.M2",
@"{
  // Code size       19 (0x13)
  .maxstack  1
  .locals init (string V_0) //a
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""string""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brfalse.s  IL_0011
  IL_000a:  ldarg.1
  IL_000b:  brfalse.s  IL_000f
  IL_000d:  ldc.i4.1
  IL_000e:  ret
  IL_000f:  ldc.i4.2
  IL_0010:  ret
  IL_0011:  ldc.i4.3
  IL_0012:  ret
}");
        }
 
        [Fact, WorkItem(12813, "https://github.com/dotnet/roslyn/issues/12813")]
        public void NoBoxingOnIntegerConstantPattern()
        {
            var source =
@"public class C
{
    static bool M1(int x)
    {
        return x is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size        6 (0x6)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.s   42
  IL_0003:  ceq
  IL_0005:  ret
}");
        }
 
        [Fact, WorkItem(40403, "https://github.com/dotnet/roslyn/issues/40403")]
        public void RefParameter_StoreToTemp()
        {
            var source =
@"public class C
{
    static bool M1(ref object x)
    {
        return x is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       24 (0x18)
  .maxstack  2
  .locals init (object V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldind.ref
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  isinst     ""int""
  IL_0009:  brfalse.s  IL_0016
  IL_000b:  ldloc.0
  IL_000c:  unbox.any  ""int""
  IL_0011:  ldc.i4.s   42
  IL_0013:  ceq
  IL_0015:  ret
  IL_0016:  ldc.i4.0
  IL_0017:  ret
}");
        }
 
        [Fact, WorkItem(40403, "https://github.com/dotnet/roslyn/issues/40403")]
        public void RefLocal_StoreToTemp()
        {
            var source =
@"public class C
{
    static bool M1(bool b, ref object x, ref object y)
    {
        ref object z = ref b ? ref x : ref y;
        return z is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       30 (0x1e)
  .maxstack  2
  .locals init (object V_0)
  IL_0000:  ldarg.0
  IL_0001:  brtrue.s   IL_0006
  IL_0003:  ldarg.2
  IL_0004:  br.s       IL_0007
  IL_0006:  ldarg.1
  IL_0007:  ldind.ref
  IL_0008:  stloc.0
  IL_0009:  ldloc.0
  IL_000a:  isinst     ""int""
  IL_000f:  brfalse.s  IL_001c
  IL_0011:  ldloc.0
  IL_0012:  unbox.any  ""int""
  IL_0017:  ldc.i4.s   42
  IL_0019:  ceq
  IL_001b:  ret
  IL_001c:  ldc.i4.0
  IL_001d:  ret
}");
        }
 
        [Fact, WorkItem(40403, "https://github.com/dotnet/roslyn/issues/40403")]
        public void InParameter_StoreToTemp()
        {
            var source =
@"public class C
{
    static bool M1(in object x)
    {
        return x is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       24 (0x18)
  .maxstack  2
  .locals init (object V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldind.ref
  IL_0002:  stloc.0
  IL_0003:  ldloc.0
  IL_0004:  isinst     ""int""
  IL_0009:  brfalse.s  IL_0016
  IL_000b:  ldloc.0
  IL_000c:  unbox.any  ""int""
  IL_0011:  ldc.i4.s   42
  IL_0013:  ceq
  IL_0015:  ret
  IL_0016:  ldc.i4.0
  IL_0017:  ret
}");
        }
 
        [Fact, WorkItem(40403, "https://github.com/dotnet/roslyn/issues/40403")]
        public void RefReadonlyLocal_StoreToTemp()
        {
            var source =
@"public class C
{
    static bool M1(bool b, in object x, in object y)
    {
        ref readonly object z = ref b ? ref x : ref y;
        return z is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       30 (0x1e)
  .maxstack  2
  .locals init (object V_0)
  IL_0000:  ldarg.0
  IL_0001:  brtrue.s   IL_0006
  IL_0003:  ldarg.2
  IL_0004:  br.s       IL_0007
  IL_0006:  ldarg.1
  IL_0007:  ldind.ref
  IL_0008:  stloc.0
  IL_0009:  ldloc.0
  IL_000a:  isinst     ""int""
  IL_000f:  brfalse.s  IL_001c
  IL_0011:  ldloc.0
  IL_0012:  unbox.any  ""int""
  IL_0017:  ldc.i4.s   42
  IL_0019:  ceq
  IL_001b:  ret
  IL_001c:  ldc.i4.0
  IL_001d:  ret
}");
        }
 
        [Fact, WorkItem(40403, "https://github.com/dotnet/roslyn/issues/40403")]
        public void OutParameter_StoreToTemp()
        {
            var source =
@"public class C
{
    static bool M1(out object x)
    {
        x = null;
        return x is 42;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1",
@"{
  // Code size       27 (0x1b)
  .maxstack  2
  .locals init (object V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldnull
  IL_0002:  stind.ref
  IL_0003:  ldarg.0
  IL_0004:  ldind.ref
  IL_0005:  stloc.0
  IL_0006:  ldloc.0
  IL_0007:  isinst     ""int""
  IL_000c:  brfalse.s  IL_0019
  IL_000e:  ldloc.0
  IL_000f:  unbox.any  ""int""
  IL_0014:  ldc.i4.s   42
  IL_0016:  ceq
  IL_0018:  ret
  IL_0019:  ldc.i4.0
  IL_001a:  ret
}");
        }
 
        [Fact, WorkItem(22654, "https://github.com/dotnet/roslyn/issues/22654")]
        public void NoRedundantTypeCheck()
        {
            var source =
@"using System;
public class C
{
    public void SwitchBasedPatternMatching(object o)
    {
        switch (o)
        {
            case int n when n == 1:
                Console.WriteLine(""1""); break;
            case string s:
                Console.WriteLine(""s""); break;
            case int n when n == 2:
                Console.WriteLine(""2""); break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.SwitchBasedPatternMatching",
@"{
  // Code size       69 (0x45)
  .maxstack  2
  .locals init (int V_0, //n
                object V_1)
  IL_0000:  ldarg.1
  IL_0001:  stloc.1
  IL_0002:  ldloc.1
  IL_0003:  isinst     ""int""
  IL_0008:  brfalse.s  IL_0013
  IL_000a:  ldloc.1
  IL_000b:  unbox.any  ""int""
  IL_0010:  stloc.0
  IL_0011:  br.s       IL_001c
  IL_0013:  ldloc.1
  IL_0014:  isinst     ""string""
  IL_0019:  brtrue.s   IL_002b
  IL_001b:  ret
  IL_001c:  ldloc.0
  IL_001d:  ldc.i4.1
  IL_001e:  bne.un.s   IL_0036
  IL_0020:  ldstr      ""1""
  IL_0025:  call       ""void System.Console.WriteLine(string)""
  IL_002a:  ret
  IL_002b:  ldstr      ""s""
  IL_0030:  call       ""void System.Console.WriteLine(string)""
  IL_0035:  ret
  IL_0036:  ldloc.0
  IL_0037:  ldc.i4.2
  IL_0038:  bne.un.s   IL_0044
  IL_003a:  ldstr      ""2""
  IL_003f:  call       ""void System.Console.WriteLine(string)""
  IL_0044:  ret
}");
        }
 
        [Fact, WorkItem(15437, "https://github.com/dotnet/roslyn/issues/15437")]
        public void IsTypeDiscard()
        {
            var source =
@"public class C
{
    public bool IsString(object o)
    {
        return o is string _;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.IsString",
@"{
  // Code size       10 (0xa)
  .maxstack  2
  IL_0000:  ldarg.1
  IL_0001:  isinst     ""string""
  IL_0006:  ldnull
  IL_0007:  cgt.un
  IL_0009:  ret
}");
        }
 
        [Fact, WorkItem(19150, "https://github.com/dotnet/roslyn/issues/19150")]
        public void RedundantHasValue()
        {
            var source =
@"using System;
public class C
{
    public static void M(int? x)
    {
        switch (x)
        {
            case int i:
                Console.Write(i);
                break;
            case null:
                Console.Write(""null"");
                break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       33 (0x21)
  .maxstack  1
  IL_0000:  ldarga.s   V_0
  IL_0002:  call       ""bool int?.HasValue.get""
  IL_0007:  brfalse.s  IL_0016
  IL_0009:  ldarga.s   V_0
  IL_000b:  call       ""int int?.GetValueOrDefault()""
  IL_0010:  call       ""void System.Console.Write(int)""
  IL_0015:  ret
  IL_0016:  ldstr      ""null""
  IL_001b:  call       ""void System.Console.Write(string)""
  IL_0020:  ret
}");
        }
 
        [Fact, WorkItem(19153, "https://github.com/dotnet/roslyn/issues/19153")]
        public void RedundantBox()
        {
            var source = @"using System;
public class C
{
    public static void M<T, U>(U x) where T : U
    {
        // when T is not known to be a reference type, there is an unboxing conversion from
        // a type parameter U to T, provided T depends on U.
        switch (x)
        {
            case T i:
                Console.Write(i);
                break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M<T, U>(U)",
@"{
  // Code size       35 (0x23)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  box        ""U""
  IL_0006:  isinst     ""T""
  IL_000b:  brfalse.s  IL_0022
  IL_000d:  ldarg.0
  IL_000e:  box        ""U""
  IL_0013:  unbox.any  ""T""
  IL_0018:  box        ""T""
  IL_001d:  call       ""void System.Console.Write(object)""
  IL_0022:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead01()
        {
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill"" }:
                Console.WriteLine(""Hey Bill!"");
            break;
            case { Name: ""Bob"" }:
                Console.WriteLine(""Hey Bob!"");
            break;
            case { Name: var name }:
                Console.WriteLine($""Hello {name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       82 (0x52)
  .maxstack  3
  .locals init (string V_0) //name
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0051
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  ldstr      ""Bill""
  IL_0010:  call       ""bool string.op_Equality(string, string)""
  IL_0015:  brtrue.s   IL_0026
  IL_0017:  ldloc.0
  IL_0018:  ldstr      ""Bob""
  IL_001d:  call       ""bool string.op_Equality(string, string)""
  IL_0022:  brtrue.s   IL_0031
  IL_0024:  br.s       IL_003c
  IL_0026:  ldstr      ""Hey Bill!""
  IL_002b:  call       ""void System.Console.WriteLine(string)""
  IL_0030:  ret
  IL_0031:  ldstr      ""Hey Bob!""
  IL_0036:  call       ""void System.Console.WriteLine(string)""
  IL_003b:  ret
  IL_003c:  ldstr      ""Hello ""
  IL_0041:  ldloc.0
  IL_0042:  ldstr      ""!""
  IL_0047:  call       ""string string.Concat(string, string, string)""
  IL_004c:  call       ""void System.Console.WriteLine(string)""
  IL_0051:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead02()
        {
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
    public int Age;
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case Person { Name: var name, Age: 0}:
                Console.WriteLine($""Hello baby { name }!"");
            break;
            case Person { Name: var name }:
                Console.WriteLine($""Hello { name }!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       64 (0x40)
  .maxstack  3
  .locals init (string V_0, //name
                string V_1) //name
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_003f
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldarg.1
  IL_000b:  ldfld      ""int Person.Age""
  IL_0010:  brtrue.s   IL_0028
  IL_0012:  ldstr      ""Hello baby ""
  IL_0017:  ldloc.0
  IL_0018:  ldstr      ""!""
  IL_001d:  call       ""string string.Concat(string, string, string)""
  IL_0022:  call       ""void System.Console.WriteLine(string)""
  IL_0027:  ret
  IL_0028:  ldloc.0
  IL_0029:  stloc.1
  IL_002a:  ldstr      ""Hello ""
  IL_002f:  ldloc.1
  IL_0030:  ldstr      ""!""
  IL_0035:  call       ""string string.Concat(string, string, string)""
  IL_003a:  call       ""void System.Console.WriteLine(string)""
  IL_003f:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead03()
        {
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class Student : Person { }
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill"" }:
                Console.WriteLine(""Hey Bill!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Hello student { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       65 (0x41)
  .maxstack  3
  .locals init (string V_0) //name
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0040
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  ldstr      ""Bill""
  IL_0010:  call       ""bool string.op_Equality(string, string)""
  IL_0015:  brtrue.s   IL_0020
  IL_0017:  ldarg.1
  IL_0018:  isinst     ""Student""
  IL_001d:  brtrue.s   IL_002b
  IL_001f:  ret
  IL_0020:  ldstr      ""Hey Bill!""
  IL_0025:  call       ""void System.Console.WriteLine(string)""
  IL_002a:  ret
  IL_002b:  ldstr      ""Hello student ""
  IL_0030:  ldloc.0
  IL_0031:  ldstr      ""!""
  IL_0036:  call       ""string string.Concat(string, string, string)""
  IL_003b:  call       ""void System.Console.WriteLine(string)""
  IL_0040:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead04()
        {
            // Cannot combine the evaluations of name here, since we first check if p is Teacher,
            // and only if that fails check if p is null. 
            // Combining the evaluations would mean first checking if p is null, then evaluating name, then checking if p is Teacher.
            // This would not necessarily be more performant.
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class Teacher : Person { }
 
public class C {
    public void M(Person p) {
        switch (p) {
            case Teacher { Name: var name }:
                Console.WriteLine($""Hello teacher { name}!"");
            break;
            case Person { Name: var name }:
                Console.WriteLine($""Hello { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       75 (0x4b)
  .maxstack  3
  .locals init (string V_0, //name
                string V_1) //name
  IL_0000:  ldarg.1
  IL_0001:  isinst     ""Teacher""
  IL_0006:  brfalse.s  IL_0011
  IL_0008:  ldarg.1
  IL_0009:  callvirt   ""string Person.Name.get""
  IL_000e:  stloc.0
  IL_000f:  br.s       IL_001d
  IL_0011:  ldarg.1
  IL_0012:  brfalse.s  IL_004a
  IL_0014:  ldarg.1
  IL_0015:  callvirt   ""string Person.Name.get""
  IL_001a:  stloc.0
  IL_001b:  br.s       IL_0033
  IL_001d:  ldstr      ""Hello teacher ""
  IL_0022:  ldloc.0
  IL_0023:  ldstr      ""!""
  IL_0028:  call       ""string string.Concat(string, string, string)""
  IL_002d:  call       ""void System.Console.WriteLine(string)""
  IL_0032:  ret
  IL_0033:  ldloc.0
  IL_0034:  stloc.1
  IL_0035:  ldstr      ""Hello ""
  IL_003a:  ldloc.1
  IL_003b:  ldstr      ""!""
  IL_0040:  call       ""string string.Concat(string, string, string)""
  IL_0045:  call       ""void System.Console.WriteLine(string)""
  IL_004a:  ret
}
");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead05()
        {
            // Cannot combine the evaluations of name here, since we first check if p is Teacher,
            // and only if that fails check if p is Student. 
            // Combining the evaluations would mean first checking if p is null, 
            // then evaluating name, 
            // then checking if p is Teacher, 
            // then checking if p is Student.
            // This would not necessarily be more performant.
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class Student : Person { }
 
public class Teacher : Person { }
 
public class C {
    public void M(Person p) {
        switch (p) {
            case Teacher { Name: var name }:
                Console.WriteLine($""Hello teacher { name}!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Hello student { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       80 (0x50)
  .maxstack  3
  .locals init (string V_0, //name
                string V_1) //name
  IL_0000:  ldarg.1
  IL_0001:  isinst     ""Teacher""
  IL_0006:  brfalse.s  IL_0011
  IL_0008:  ldarg.1
  IL_0009:  callvirt   ""string Person.Name.get""
  IL_000e:  stloc.0
  IL_000f:  br.s       IL_0022
  IL_0011:  ldarg.1
  IL_0012:  isinst     ""Student""
  IL_0017:  brfalse.s  IL_004f
  IL_0019:  ldarg.1
  IL_001a:  callvirt   ""string Person.Name.get""
  IL_001f:  stloc.0
  IL_0020:  br.s       IL_0038
  IL_0022:  ldstr      ""Hello teacher ""
  IL_0027:  ldloc.0
  IL_0028:  ldstr      ""!""
  IL_002d:  call       ""string string.Concat(string, string, string)""
  IL_0032:  call       ""void System.Console.WriteLine(string)""
  IL_0037:  ret
  IL_0038:  ldloc.0
  IL_0039:  stloc.1
  IL_003a:  ldstr      ""Hello student ""
  IL_003f:  ldloc.1
  IL_0040:  ldstr      ""!""
  IL_0045:  call       ""string string.Concat(string, string, string)""
  IL_004a:  call       ""void System.Console.WriteLine(string)""
  IL_004f:  ret
}
");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead06()
        {
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class Student : Person { }
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: { Length: 0 } }:
                Console.WriteLine(""Hello!"");
            break;
            case Student { Name: { Length : 1 } }:
                Console.WriteLine($""Hello student!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       58 (0x3a)
  .maxstack  2
  .locals init (string V_0,
                int V_1)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0039
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  brfalse.s  IL_0039
  IL_000d:  ldloc.0
  IL_000e:  callvirt   ""int string.Length.get""
  IL_0013:  stloc.1
  IL_0014:  ldloc.1
  IL_0015:  brfalse.s  IL_0024
  IL_0017:  ldarg.1
  IL_0018:  isinst     ""Student""
  IL_001d:  brfalse.s  IL_0039
  IL_001f:  ldloc.1
  IL_0020:  ldc.i4.1
  IL_0021:  beq.s      IL_002f
  IL_0023:  ret
  IL_0024:  ldstr      ""Hello!""
  IL_0029:  call       ""void System.Console.WriteLine(string)""
  IL_002e:  ret
  IL_002f:  ldstr      ""Hello student!""
  IL_0034:  call       ""void System.Console.WriteLine(string)""
  IL_0039:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead07()
        {
            // Cannot combine the evaluations of name here, since we first check if name is MemoryStream,
            // and only if that fails check if name is null. 
            // Combining the evaluations would mean first checking if name is null, then evaluating name, then checking if p is Teacher.
            // This would not necessarily be more performant.
            var source = @"using System;
using System.IO;
 
public class Person {
    public Stream Name { get; set; }
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case Person { Name: MemoryStream { Length: 1 } }:
                Console.WriteLine(""Your Names A MemoryStream!"");
            break;
            case Person { Name: { Length : var x } }:
                Console.WriteLine(""Your Names A Stream!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       66 (0x42)
  .maxstack  2
  .locals init (System.IO.Stream V_0,
                System.IO.MemoryStream V_1)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0041
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""System.IO.Stream Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  isinst     ""System.IO.MemoryStream""
  IL_0010:  stloc.1
  IL_0011:  ldloc.1
  IL_0012:  brfalse.s  IL_0020
  IL_0014:  ldloc.1
  IL_0015:  callvirt   ""long System.IO.Stream.Length.get""
  IL_001a:  ldc.i4.1
  IL_001b:  conv.i8
  IL_001c:  beq.s      IL_002c
  IL_001e:  br.s       IL_0023
  IL_0020:  ldloc.0
  IL_0021:  brfalse.s  IL_0041
  IL_0023:  ldloc.0
  IL_0024:  callvirt   ""long System.IO.Stream.Length.get""
  IL_0029:  pop
  IL_002a:  br.s       IL_0037
  IL_002c:  ldstr      ""Your Names A MemoryStream!""
  IL_0031:  call       ""void System.Console.WriteLine(string)""
  IL_0036:  ret
  IL_0037:  ldstr      ""Your Names A Stream!""
  IL_003c:  call       ""void System.Console.WriteLine(string)""
  IL_0041:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead08()
        {
            var source = @"
public class Person {
    public string Name { get; set; }
}
 
public class Student : Person { }
 
public class C {
    public string M(Person p) {
        return p switch  {
            { Name: ""Bill"" } => ""Hey Bill!"",
            Student { Name: var name } => ""Hello student { name}!"",
            _ => null,
        };
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       51 (0x33)
  .maxstack  2
  .locals init (string V_0)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_002f
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  ldstr      ""Bill""
  IL_000e:  call       ""bool string.op_Equality(string, string)""
  IL_0013:  brtrue.s   IL_001f
  IL_0015:  ldarg.1
  IL_0016:  isinst     ""Student""
  IL_001b:  brtrue.s   IL_0027
  IL_001d:  br.s       IL_002f
  IL_001f:  ldstr      ""Hey Bill!""
  IL_0024:  stloc.0
  IL_0025:  br.s       IL_0031
  IL_0027:  ldstr      ""Hello student { name}!""
  IL_002c:  stloc.0
  IL_002d:  br.s       IL_0031
  IL_002f:  ldnull
  IL_0030:  stloc.0
  IL_0031:  ldloc.0
  IL_0032:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead09()
        {
            var source = @"using System;
 
public class Person {
    public virtual string Name { get; set; }
}
 
public class Student : Person { }
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill"" }:
                Console.WriteLine(""Hey Bill!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Hello student { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       65 (0x41)
  .maxstack  3
  .locals init (string V_0) //name
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0040
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  ldstr      ""Bill""
  IL_0010:  call       ""bool string.op_Equality(string, string)""
  IL_0015:  brtrue.s   IL_0020
  IL_0017:  ldarg.1
  IL_0018:  isinst     ""Student""
  IL_001d:  brtrue.s   IL_002b
  IL_001f:  ret
  IL_0020:  ldstr      ""Hey Bill!""
  IL_0025:  call       ""void System.Console.WriteLine(string)""
  IL_002a:  ret
  IL_002b:  ldstr      ""Hello student ""
  IL_0030:  ldloc.0
  IL_0031:  ldstr      ""!""
  IL_0036:  call       ""string string.Concat(string, string, string)""
  IL_003b:  call       ""void System.Console.WriteLine(string)""
  IL_0040:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void NoRedundantPropertyRead10()
        {
            // Currently we don't combine these redundant property reads.
            // However we could do so in the future.
 
            var source = @"using System;
 
public abstract class Person {
    public abstract string Name { get; set; }
}
 
public class Student : Person { 
    public override string Name { get; set; }
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill"" }:
                Console.WriteLine(""Hey Bill!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Hello student { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       73 (0x49)
  .maxstack  3
  .locals init (string V_0, //name
                Student V_1)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0048
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  ldstr      ""Bill""
  IL_000e:  call       ""bool string.op_Equality(string, string)""
  IL_0013:  brtrue.s   IL_0028
  IL_0015:  ldarg.1
  IL_0016:  isinst     ""Student""
  IL_001b:  stloc.1
  IL_001c:  ldloc.1
  IL_001d:  brfalse.s  IL_0048
  IL_001f:  ldloc.1
  IL_0020:  callvirt   ""string Person.Name.get""
  IL_0025:  stloc.0
  IL_0026:  br.s       IL_0033
  IL_0028:  ldstr      ""Hey Bill!""
  IL_002d:  call       ""void System.Console.WriteLine(string)""
  IL_0032:  ret
  IL_0033:  ldstr      ""Hello student ""
  IL_0038:  ldloc.0
  IL_0039:  ldstr      ""!""
  IL_003e:  call       ""string string.Concat(string, string, string)""
  IL_0043:  call       ""void System.Console.WriteLine(string)""
  IL_0048:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void CombiningRedundantPropertyReadsDoesNotChangeNullabilityAnalysis01()
        {
            // Currently we don't combine the redundant property reads at all.
            // However this could be improved in the future so this test is important
 
            var source = @"using System;
 
#nullable enable
 
public class Person {
    public virtual string? Name { get; }
}
 
public class Student : Person {
    public override string Name { get => base.Name ?? """"; }
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill""}:
                Console.WriteLine(""Hey Bill!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Student has name of length { name.Length }!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       78 (0x4e)
  .maxstack  2
  .locals init (string V_0, //name
                Student V_1)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_004d
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  ldstr      ""Bill""
  IL_000e:  call       ""bool string.op_Equality(string, string)""
  IL_0013:  brtrue.s   IL_0028
  IL_0015:  ldarg.1
  IL_0016:  isinst     ""Student""
  IL_001b:  stloc.1
  IL_001c:  ldloc.1
  IL_001d:  brfalse.s  IL_004d
  IL_001f:  ldloc.1
  IL_0020:  callvirt   ""string Person.Name.get""
  IL_0025:  stloc.0
  IL_0026:  br.s       IL_0033
  IL_0028:  ldstr      ""Hey Bill!""
  IL_002d:  call       ""void System.Console.WriteLine(string)""
  IL_0032:  ret
  IL_0033:  ldstr      ""Student has name of length {0}!""
  IL_0038:  ldloc.0
  IL_0039:  callvirt   ""int string.Length.get""
  IL_003e:  box        ""int""
  IL_0043:  call       ""string string.Format(string, object)""
  IL_0048:  call       ""void System.Console.WriteLine(string)""
  IL_004d:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void CombiningRedundantPropertyReadsDoesNotChangeNullabilityAnalysis02()
        {
            var source = @"using System;
 
#nullable enable
 
public class Person {
    public string? Name { get;}
}
 
public class Student : Person {
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: var name } when name is null:
                Console.WriteLine($""Hey { name }"");
            break;
            case Student { Name: var name } when name != null:
                Console.WriteLine($""Student has name of length { name.Length }!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       75 (0x4b)
  .maxstack  2
  .locals init (string V_0, //name
                string V_1, //name
                Person V_2)
  IL_0000:  ldarg.1
  IL_0001:  stloc.2
  IL_0002:  ldloc.2
  IL_0003:  brfalse.s  IL_004a
  IL_0005:  ldloc.2
  IL_0006:  callvirt   ""string Person.Name.get""
  IL_000b:  stloc.0
  IL_000c:  br.s       IL_0017
  IL_000e:  ldloc.2
  IL_000f:  isinst     ""Student""
  IL_0014:  brtrue.s   IL_002b
  IL_0016:  ret
  IL_0017:  ldloc.0
  IL_0018:  brtrue.s   IL_000e
  IL_001a:  ldstr      ""Hey ""
  IL_001f:  ldloc.0
  IL_0020:  call       ""string string.Concat(string, string)""
  IL_0025:  call       ""void System.Console.WriteLine(string)""
  IL_002a:  ret
  IL_002b:  ldloc.0
  IL_002c:  stloc.1
  IL_002d:  ldloc.1
  IL_002e:  brfalse.s  IL_004a
  IL_0030:  ldstr      ""Student has name of length {0}!""
  IL_0035:  ldloc.1
  IL_0036:  callvirt   ""int string.Length.get""
  IL_003b:  box        ""int""
  IL_0040:  call       ""string string.Format(string, object)""
  IL_0045:  call       ""void System.Console.WriteLine(string)""
  IL_004a:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void CombiningRedundantPropertyReadsDoesNotChangeNullabilityAnalysis03()
        {
            var source = @"using System;
 
#nullable enable
 
public class Person {
    public string? Name { get; }
}
 
public class Student : Person {
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: string name }:
                Console.WriteLine($""Hey {name}"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Student has name of length { name.Length }!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics(
                // (19,66): warning CS8602: Dereference of a possibly null reference.
                //                 Console.WriteLine($"Student has name of length { name.Length }!");
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "name").WithLocation(19, 66));
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       68 (0x44)
  .maxstack  2
  .locals init (string V_0, //name
                string V_1) //name
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0043
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  brtrue.s   IL_0016
  IL_000d:  ldarg.1
  IL_000e:  isinst     ""Student""
  IL_0013:  brtrue.s   IL_0027
  IL_0015:  ret
  IL_0016:  ldstr      ""Hey ""
  IL_001b:  ldloc.0
  IL_001c:  call       ""string string.Concat(string, string)""
  IL_0021:  call       ""void System.Console.WriteLine(string)""
  IL_0026:  ret
  IL_0027:  ldloc.0
  IL_0028:  stloc.1
  IL_0029:  ldstr      ""Student has name of length {0}!""
  IL_002e:  ldloc.1
  IL_002f:  callvirt   ""int string.Length.get""
  IL_0034:  box        ""int""
  IL_0039:  call       ""string string.Format(string, object)""
  IL_003e:  call       ""void System.Console.WriteLine(string)""
  IL_0043:  ret
}");
        }
 
        [Fact, WorkItem(34933, "https://github.com/dotnet/roslyn/issues/34933")]
        public void DoNotCombineDifferentPropertyReadsWithSameName()
        {
            var source = @"using System;
 
public class Person {
    public string Name { get; set; }
}
 
public class Student : Person {
    public new string Name { get; set; }
}
 
public class C {
    public void M(Person p) {
        switch (p) {
            case { Name: ""Bill"" }:
                Console.WriteLine(""Hey Bill!"");
            break;
            case Student { Name: var name }:
                Console.WriteLine($""Hello student { name}!"");
            break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M",
@"{
  // Code size       73 (0x49)
  .maxstack  3
  .locals init (string V_0, //name
                Student V_1)
  IL_0000:  ldarg.1
  IL_0001:  brfalse.s  IL_0048
  IL_0003:  ldarg.1
  IL_0004:  callvirt   ""string Person.Name.get""
  IL_0009:  ldstr      ""Bill""
  IL_000e:  call       ""bool string.op_Equality(string, string)""
  IL_0013:  brtrue.s   IL_0028
  IL_0015:  ldarg.1
  IL_0016:  isinst     ""Student""
  IL_001b:  stloc.1
  IL_001c:  ldloc.1
  IL_001d:  brfalse.s  IL_0048
  IL_001f:  ldloc.1
  IL_0020:  callvirt   ""string Student.Name.get""
  IL_0025:  stloc.0
  IL_0026:  br.s       IL_0033
  IL_0028:  ldstr      ""Hey Bill!""
  IL_002d:  call       ""void System.Console.WriteLine(string)""
  IL_0032:  ret
  IL_0033:  ldstr      ""Hello student ""
  IL_0038:  ldloc.0
  IL_0039:  ldstr      ""!""
  IL_003e:  call       ""string string.Concat(string, string, string)""
  IL_0043:  call       ""void System.Console.WriteLine(string)""
  IL_0048:  ret
}");
        }
 
        [Fact, WorkItem(51801, "https://github.com/dotnet/roslyn/issues/51801")]
        public void PropertyOverrideLacksAccessor()
        {
            var source = @"
#nullable enable
 
class Base
{
  public virtual bool IsOk { get { return true; } set { } }
}
 
class C : Base
{
  public override bool IsOk { set { } }
  public string? Value { get; }
 
  public string M()
  {
    switch (this)
    {
      case { IsOk: true }:
        return Value;
      default:
        return Value;
    }
  }
}
";
            var verifier = CompileAndVerify(source);
            verifier.VerifyIL("C.M", @"
{
  // Code size       26 (0x1a)
  .maxstack  1
  .locals init (C V_0)
  IL_0000:  ldarg.0
  IL_0001:  stloc.0
  IL_0002:  ldloc.0
  IL_0003:  brfalse.s  IL_0013
  IL_0005:  ldloc.0
  IL_0006:  callvirt   ""bool Base.IsOk.get""
  IL_000b:  pop
  IL_000c:  ldarg.0
  IL_000d:  call       ""string C.Value.get""
  IL_0012:  ret
  IL_0013:  ldarg.0
  IL_0014:  call       ""string C.Value.get""
  IL_0019:  ret
}");
        }
 
        [Fact, WorkItem(20641, "https://github.com/dotnet/roslyn/issues/20641")]
        public void PatternsVsAs01()
        {
            var source = @"using System.Collections;
using System.Collections.Generic;
 
class Program
{
    static void Main() { }
 
    internal static bool TryGetCount1<T>(IEnumerable<T> source, out int count)
    {
        ICollection nonGeneric = source as ICollection;
        if (nonGeneric != null)
        {
            count = nonGeneric.Count;
            return true;
        }
 
        ICollection<T> generic = source as ICollection<T>;
        if (generic != null)
        {
            count = generic.Count;
            return true;
        }
 
        count = -1;
        return false;
    }
 
    internal static bool TryGetCount2<T>(IEnumerable<T> source, out int count)
    {
        switch (source)
        {
            case ICollection nonGeneric:
                count = nonGeneric.Count;
                return true;
 
            case ICollection<T> generic:
                count = generic.Count;
                return true;
 
            default:
                count = -1;
                return false;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("Program.TryGetCount1<T>",
@"{
  // Code size       45 (0x2d)
  .maxstack  2
  .locals init (System.Collections.ICollection V_0, //nonGeneric
                System.Collections.Generic.ICollection<T> V_1) //generic
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""System.Collections.ICollection""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brfalse.s  IL_0014
  IL_000a:  ldarg.1
  IL_000b:  ldloc.0
  IL_000c:  callvirt   ""int System.Collections.ICollection.Count.get""
  IL_0011:  stind.i4
  IL_0012:  ldc.i4.1
  IL_0013:  ret
  IL_0014:  ldarg.0
  IL_0015:  isinst     ""System.Collections.Generic.ICollection<T>""
  IL_001a:  stloc.1
  IL_001b:  ldloc.1
  IL_001c:  brfalse.s  IL_0028
  IL_001e:  ldarg.1
  IL_001f:  ldloc.1
  IL_0020:  callvirt   ""int System.Collections.Generic.ICollection<T>.Count.get""
  IL_0025:  stind.i4
  IL_0026:  ldc.i4.1
  IL_0027:  ret
  IL_0028:  ldarg.1
  IL_0029:  ldc.i4.m1
  IL_002a:  stind.i4
  IL_002b:  ldc.i4.0
  IL_002c:  ret
}");
            compVerifier.VerifyIL("Program.TryGetCount2<T>",
@"{
  // Code size       47 (0x2f)
  .maxstack  2
  .locals init (System.Collections.ICollection V_0, //nonGeneric
                System.Collections.Generic.ICollection<T> V_1) //generic
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""System.Collections.ICollection""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brtrue.s   IL_0016
  IL_000a:  ldarg.0
  IL_000b:  isinst     ""System.Collections.Generic.ICollection<T>""
  IL_0010:  stloc.1
  IL_0011:  ldloc.1
  IL_0012:  brtrue.s   IL_0020
  IL_0014:  br.s       IL_002a
  IL_0016:  ldarg.1
  IL_0017:  ldloc.0
  IL_0018:  callvirt   ""int System.Collections.ICollection.Count.get""
  IL_001d:  stind.i4
  IL_001e:  ldc.i4.1
  IL_001f:  ret
  IL_0020:  ldarg.1
  IL_0021:  ldloc.1
  IL_0022:  callvirt   ""int System.Collections.Generic.ICollection<T>.Count.get""
  IL_0027:  stind.i4
  IL_0028:  ldc.i4.1
  IL_0029:  ret
  IL_002a:  ldarg.1
  IL_002b:  ldc.i4.m1
  IL_002c:  stind.i4
  IL_002d:  ldc.i4.0
  IL_002e:  ret
}");
        }
 
        [Fact, WorkItem(20641, "https://github.com/dotnet/roslyn/issues/20641")]
        public void PatternsVsAs02()
        {
            var source = @"using System.Collections;
class Program
{
    static void Main() { }
 
    internal static bool IsEmpty1(IEnumerable source)
    {
        var c = source as ICollection;
        return c != null && c.Count > 0;
    }
 
    internal static bool IsEmpty2(IEnumerable source)
    {
        return source is ICollection c && c.Count > 0;
    }
 
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("Program.IsEmpty1",
@"{
  // Code size       22 (0x16)
  .maxstack  2
  .locals init (System.Collections.ICollection V_0) //c
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""System.Collections.ICollection""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brfalse.s  IL_0014
  IL_000a:  ldloc.0
  IL_000b:  callvirt   ""int System.Collections.ICollection.Count.get""
  IL_0010:  ldc.i4.0
  IL_0011:  cgt
  IL_0013:  ret
  IL_0014:  ldc.i4.0
  IL_0015:  ret
}");
            compVerifier.VerifyIL("Program.IsEmpty2",
@"{
  // Code size       22 (0x16)
  .maxstack  2
  .locals init (System.Collections.ICollection V_0) //c
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""System.Collections.ICollection""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brfalse.s  IL_0014
  IL_000a:  ldloc.0
  IL_000b:  callvirt   ""int System.Collections.ICollection.Count.get""
  IL_0010:  ldc.i4.0
  IL_0011:  cgt
  IL_0013:  ret
  IL_0014:  ldc.i4.0
  IL_0015:  ret
}");
        }
 
        [Fact]
        [WorkItem(20641, "https://github.com/dotnet/roslyn/issues/20641")]
        [WorkItem(1395, "https://github.com/dotnet/csharplang/issues/1395")]
        public void TupleSwitch01()
        {
            var source = @"using System;
 
public class Door
{
    public DoorState State;
 
    public enum DoorState { Opened, Closed, Locked }
 
    public enum Action { Open, Close, Lock, Unlock }
 
    public void Act0(Action action, bool haveKey = false)
    {
        Console.Write($""{State} {action}{(haveKey ? "" withKey"" : null)}"");
        State = ChangeState0(State, action, haveKey);
        Console.WriteLine($"" -> {State}"");
    }
 
    public void Act1(Action action, bool haveKey = false)
    {
        Console.Write($""{State} {action}{(haveKey ? "" withKey"" : null)}"");
        State = ChangeState1(State, action, haveKey);
        Console.WriteLine($"" -> {State}"");
    }
 
    public static DoorState ChangeState0(DoorState state, Action action, bool haveKey = false)
    {
        switch (state, action)
        {
            case (DoorState.Opened, Action.Close):
                return DoorState.Closed;
            case (DoorState.Closed, Action.Open):
                return DoorState.Opened;
            case (DoorState.Closed, Action.Lock) when haveKey:
                return DoorState.Locked;
            case (DoorState.Locked, Action.Unlock) when haveKey:
                return DoorState.Closed;
            case var (oldState, _):
                return oldState;
        }
    }
 
    public static DoorState ChangeState1(DoorState state, Action action, bool haveKey = false) =>
        (state, action) switch {
            (DoorState.Opened, Action.Close) => DoorState.Closed,
            (DoorState.Closed, Action.Open) => DoorState.Opened,
            (DoorState.Closed, Action.Lock) when haveKey => DoorState.Locked,
            (DoorState.Locked, Action.Unlock) when haveKey => DoorState.Closed,
            _ => state };
}
 
class Program
{
    static void Main(string[] args)
    {
        var door = new Door();
        door.Act0(Door.Action.Close);
        door.Act0(Door.Action.Lock);
        door.Act0(Door.Action.Lock, true);
        door.Act0(Door.Action.Open);
        door.Act0(Door.Action.Unlock);
        door.Act0(Door.Action.Unlock, true);
        door.Act0(Door.Action.Open);
        Console.WriteLine();
 
        door = new Door();
        door.Act1(Door.Action.Close);
        door.Act1(Door.Action.Lock);
        door.Act1(Door.Action.Lock, true);
        door.Act1(Door.Action.Open);
        door.Act1(Door.Action.Unlock);
        door.Act1(Door.Action.Unlock, true);
        door.Act1(Door.Action.Open);
    }
}";
            var expectedOutput =
@"Opened Close -> Closed
Closed Lock -> Closed
Closed Lock withKey -> Locked
Locked Open -> Locked
Locked Unlock -> Locked
Locked Unlock withKey -> Closed
Closed Open -> Opened
 
Opened Close -> Closed
Closed Lock -> Closed
Closed Lock withKey -> Locked
Locked Open -> Locked
Locked Unlock -> Locked
Locked Unlock withKey -> Closed
Closed Open -> Opened
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithRecursivePatterns);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Door.ChangeState0",
@"{
  // Code size       61 (0x3d)
  .maxstack  2
  .locals init (Door.DoorState V_0, //oldState
                Door.Action V_1)
  IL_0000:  ldarg.0
  IL_0001:  stloc.0
  IL_0002:  ldarg.1
  IL_0003:  stloc.1
  IL_0004:  ldloc.0
  IL_0005:  switch    (
        IL_0018,
        IL_001e,
        IL_0027)
  IL_0016:  br.s       IL_003b
  IL_0018:  ldloc.1
  IL_0019:  ldc.i4.1
  IL_001a:  beq.s      IL_002d
  IL_001c:  br.s       IL_003b
  IL_001e:  ldloc.1
  IL_001f:  brfalse.s  IL_002f
  IL_0021:  ldloc.1
  IL_0022:  ldc.i4.2
  IL_0023:  beq.s      IL_0031
  IL_0025:  br.s       IL_003b
  IL_0027:  ldloc.1
  IL_0028:  ldc.i4.3
  IL_0029:  beq.s      IL_0036
  IL_002b:  br.s       IL_003b
  IL_002d:  ldc.i4.1
  IL_002e:  ret
  IL_002f:  ldc.i4.0
  IL_0030:  ret
  IL_0031:  ldarg.2
  IL_0032:  brfalse.s  IL_003b
  IL_0034:  ldc.i4.2
  IL_0035:  ret
  IL_0036:  ldarg.2
  IL_0037:  brfalse.s  IL_003b
  IL_0039:  ldc.i4.1
  IL_003a:  ret
  IL_003b:  ldloc.0
  IL_003c:  ret
}");
            compVerifier.VerifyIL("Door.ChangeState1",
@"{
  // Code size       71 (0x47)
  .maxstack  2
  .locals init (Door.DoorState V_0,
                Door.DoorState V_1,
                Door.Action V_2)
  IL_0000:  ldarg.0
  IL_0001:  stloc.1
  IL_0002:  ldarg.1
  IL_0003:  stloc.2
  IL_0004:  ldloc.1
  IL_0005:  switch    (
        IL_0018,
        IL_001e,
        IL_0027)
  IL_0016:  br.s       IL_0043
  IL_0018:  ldloc.2
  IL_0019:  ldc.i4.1
  IL_001a:  beq.s      IL_002d
  IL_001c:  br.s       IL_0043
  IL_001e:  ldloc.2
  IL_001f:  brfalse.s  IL_0031
  IL_0021:  ldloc.2
  IL_0022:  ldc.i4.2
  IL_0023:  beq.s      IL_0035
  IL_0025:  br.s       IL_0043
  IL_0027:  ldloc.2
  IL_0028:  ldc.i4.3
  IL_0029:  beq.s      IL_003c
  IL_002b:  br.s       IL_0043
  IL_002d:  ldc.i4.1
  IL_002e:  stloc.0
  IL_002f:  br.s       IL_0045
  IL_0031:  ldc.i4.0
  IL_0032:  stloc.0
  IL_0033:  br.s       IL_0045
  IL_0035:  ldarg.2
  IL_0036:  brfalse.s  IL_0043
  IL_0038:  ldc.i4.2
  IL_0039:  stloc.0
  IL_003a:  br.s       IL_0045
  IL_003c:  ldarg.2
  IL_003d:  brfalse.s  IL_0043
  IL_003f:  ldc.i4.1
  IL_0040:  stloc.0
  IL_0041:  br.s       IL_0045
  IL_0043:  ldarg.0
  IL_0044:  stloc.0
  IL_0045:  ldloc.0
  IL_0046:  ret
}");
        }
 
        [Fact]
        [WorkItem(20641, "https://github.com/dotnet/roslyn/issues/20641")]
        [WorkItem(1395, "https://github.com/dotnet/csharplang/issues/1395")]
        public void SharingTemps01()
        {
            var source =
@"class Program
{
    static void Main(string[] args) { }
    void M1(string x)
    {
        switch (x)
        {
            case ""a"":
            case ""b"" when Mutate(ref x): // prevents sharing temps
            case ""c"":
                break;
        }
    }
    void M2(string x)
    {
        switch (x)
        {
            case ""a"":
            case ""b"" when Pure(x):
            case ""c"":
                break;
        }
    }
    static bool Mutate(ref string x) { x = null; return false; }
    static bool Pure(string x) { return false; }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithoutRecursivePatterns);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("Program.M1",
@"{
  // Code size       50 (0x32)
  .maxstack  2
  .locals init (string V_0)
  IL_0000:  ldarg.1
  IL_0001:  stloc.0
  IL_0002:  ldloc.0
  IL_0003:  ldstr      ""a""
  IL_0008:  call       ""bool string.op_Equality(string, string)""
  IL_000d:  brtrue.s   IL_0031
  IL_000f:  ldloc.0
  IL_0010:  ldstr      ""b""
  IL_0015:  call       ""bool string.op_Equality(string, string)""
  IL_001a:  brtrue.s   IL_0029
  IL_001c:  ldloc.0
  IL_001d:  ldstr      ""c""
  IL_0022:  call       ""bool string.op_Equality(string, string)""
  IL_0027:  pop
  IL_0028:  ret
  IL_0029:  ldarga.s   V_1
  IL_002b:  call       ""bool Program.Mutate(ref string)""
  IL_0030:  pop
  IL_0031:  ret
}");
            compVerifier.VerifyIL("Program.M2",
@"{
  // Code size       49 (0x31)
  .maxstack  2
  .locals init (string V_0)
  IL_0000:  ldarg.1
  IL_0001:  stloc.0
  IL_0002:  ldloc.0
  IL_0003:  ldstr      ""a""
  IL_0008:  call       ""bool string.op_Equality(string, string)""
  IL_000d:  brtrue.s   IL_0030
  IL_000f:  ldloc.0
  IL_0010:  ldstr      ""b""
  IL_0015:  call       ""bool string.op_Equality(string, string)""
  IL_001a:  brtrue.s   IL_0029
  IL_001c:  ldloc.0
  IL_001d:  ldstr      ""c""
  IL_0022:  call       ""bool string.op_Equality(string, string)""
  IL_0027:  pop
  IL_0028:  ret
  IL_0029:  ldarg.1
  IL_002a:  call       ""bool Program.Pure(string)""
  IL_002f:  pop
  IL_0030:  ret
}");
        }
 
        [Fact, WorkItem(17266, "https://github.com/dotnet/roslyn/issues/17266")]
        public void IrrefutablePatternInIs01()
        {
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        if (Get() is int index) { }
        Console.WriteLine(index);
    }
 
    public static int Get()
    {
        Console.WriteLine(""eval"");
        return 1;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"eval
1";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact, WorkItem(17266, "https://github.com/dotnet/roslyn/issues/17266")]
        public void IrrefutablePatternInIs02()
        {
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        if (Get() is Assignment(int left, var right)) { }
        Console.WriteLine(left);
        Console.WriteLine(right);
    }
 
    public static Assignment Get()
    {
        Console.WriteLine(""eval"");
        return new Assignment(1, 2);
    }
}
public struct Assignment
{
    public int Left, Right;
    public Assignment(int left, int right) => (Left, Right) = (left, right);
    public void Deconstruct(out int left, out int right) => (left, right) = (Left, Right);
}
";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"eval
1
2";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void MissingNullCheck01()
        {
            var source =
@"class Program
{
    public static void Main()
    {
        string s = null;
        System.Console.WriteLine(s is string { Length: 3 });
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithRecursivePatterns);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"False";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        [WorkItem(24550, "https://github.com/dotnet/roslyn/issues/24550")]
        [WorkItem(1284, "https://github.com/dotnet/csharplang/issues/1284")]
        public void ConstantPatternVsUnconstrainedTypeParameter01()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        Console.WriteLine(Test1<object>(null));
        Console.WriteLine(Test1<int>(1));
        Console.WriteLine(Test1<int?>(null));
        Console.WriteLine(Test1<int?>(1));
 
        Console.WriteLine(Test2<object>(0));
        Console.WriteLine(Test2<int>(1));
        Console.WriteLine(Test2<int?>(0));
        Console.WriteLine(Test2<string>(""frog""));
 
        Console.WriteLine(Test3<object>(""frog""));
        Console.WriteLine(Test3<int>(1));
        Console.WriteLine(Test3<string>(""frog""));
        Console.WriteLine(Test3<int?>(1));
    }
 
    public static bool Test1<T>(T t)
    {
        return t is null;
    }
    public static bool Test2<T>(T t)
    {
        return t is 0;
    }
    public static bool Test3<T>(T t)
    {
        return t is ""frog"";
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"True
False
True
False
True
False
True
False
True
False
True
False
";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Program.Test1<T>(T)",
@"{
  // Code size       10 (0xa)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  ldnull
  IL_0007:  ceq
  IL_0009:  ret
}");
            compVerifier.VerifyIL("Program.Test2<T>(T)",
@"{
  // Code size       35 (0x23)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  isinst     ""int""
  IL_000b:  brfalse.s  IL_0021
  IL_000d:  ldarg.0
  IL_000e:  box        ""T""
  IL_0013:  isinst     ""int""
  IL_0018:  unbox.any  ""int""
  IL_001d:  ldc.i4.0
  IL_001e:  ceq
  IL_0020:  ret
  IL_0021:  ldc.i4.0
  IL_0022:  ret
}
");
            compVerifier.VerifyIL("Program.Test3<T>(T)",
@"{
  // Code size       29 (0x1d)
  .maxstack  2
  .locals init (string V_0)
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  isinst     ""string""
  IL_000b:  stloc.0
  IL_000c:  ldloc.0
  IL_000d:  brfalse.s  IL_001b
  IL_000f:  ldloc.0
  IL_0010:  ldstr      ""frog""
  IL_0015:  call       ""bool string.op_Equality(string, string)""
  IL_001a:  ret
  IL_001b:  ldc.i4.0
  IL_001c:  ret
}");
        }
 
        [Fact]
        [WorkItem(24550, "https://github.com/dotnet/roslyn/issues/24550")]
        [WorkItem(1284, "https://github.com/dotnet/csharplang/issues/1284")]
        public void ConstantPatternVsUnconstrainedTypeParameter02()
        {
            var source =
@"class C<T>
{
    internal struct S { }
    static bool Test(S s)
    {
        return s is 1;
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C<T>.Test(C<T>.S)",
@"{
  // Code size       35 (0x23)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  box        ""C<T>.S""
  IL_0006:  isinst     ""int""
  IL_000b:  brfalse.s  IL_0021
  IL_000d:  ldarg.0
  IL_000e:  box        ""C<T>.S""
  IL_0013:  isinst     ""int""
  IL_0018:  unbox.any  ""int""
  IL_001d:  ldc.i4.1
  IL_001e:  ceq
  IL_0020:  ret
  IL_0021:  ldc.i4.0
  IL_0022:  ret
}
");
        }
 
        [Fact]
        [WorkItem(26274, "https://github.com/dotnet/roslyn/issues/26274")]
        public void VariablesInSwitchExpressionArms()
        {
            var source =
@"class C
{
    public override bool Equals(object obj) =>
        obj switch
        {
            C x1 when x1 is var x2 => x2 is var x3 && x3 is {},
            _ => false
        };
    public override int GetHashCode() => 1;
    public static void Main()
    {
        C c = new C();
        System.Console.Write(c.Equals(new C()));
        System.Console.Write(c.Equals(new object()));
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation, expectedOutput: "TrueFalse");
            compVerifier.VerifyIL("C.Equals(object)",
@"{
  // Code size       25 (0x19)
  .maxstack  2
  .locals init (C V_0, //x1
                C V_1, //x2
                C V_2, //x3
                bool V_3)
  IL_0000:  ldarg.1
  IL_0001:  isinst     ""C""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brfalse.s  IL_0015
  IL_000a:  ldloc.0
  IL_000b:  stloc.1
  IL_000c:  ldloc.1
  IL_000d:  stloc.2
  IL_000e:  ldloc.2
  IL_000f:  ldnull
  IL_0010:  cgt.un
  IL_0012:  stloc.3
  IL_0013:  br.s       IL_0017
  IL_0015:  ldc.i4.0
  IL_0016:  stloc.3
  IL_0017:  ldloc.3
  IL_0018:  ret
}");
        }
 
        [Fact, WorkItem(26387, "https://github.com/dotnet/roslyn/issues/26387")]
        public void ValueTypeArgument01()
        {
            var source =
@"using System;
 
class TestHelper
{
    static void Main()
    {
        Console.WriteLine(IsValueTypeT0(new S()));
        Console.WriteLine(IsValueTypeT1(new S()));
        Console.WriteLine(IsValueTypeT2(new S()));
    }
 
    static bool IsValueTypeT0<T>(T result)
    {
        return result is T;
    }
    static bool IsValueTypeT1<T>(T result)
    {
        return result is T v;
    }
    static bool IsValueTypeT2<T>(T result)
    {
        return result is T _;
    }
}
 
struct S { }
";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"True
True
True";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("TestHelper.IsValueTypeT0<T>(T)",
@"{
  // Code size       15 (0xf)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  box        ""T""
  IL_0007:  ldnull
  IL_0008:  cgt.un
  IL_000a:  stloc.0
  IL_000b:  br.s       IL_000d
  IL_000d:  ldloc.0
  IL_000e:  ret
}");
            compVerifier.VerifyIL("TestHelper.IsValueTypeT1<T>(T)",
@"{
  // Code size       20 (0x14)
  .maxstack  1
  .locals init (T V_0, //v
                bool V_1)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  box        ""T""
  IL_0007:  brfalse.s  IL_000e
  IL_0009:  ldarg.0
  IL_000a:  stloc.0
  IL_000b:  ldc.i4.1
  IL_000c:  br.s       IL_000f
  IL_000e:  ldc.i4.0
  IL_000f:  stloc.1
  IL_0010:  br.s       IL_0012
  IL_0012:  ldloc.1
  IL_0013:  ret
}");
            compVerifier.VerifyIL("TestHelper.IsValueTypeT2<T>(T)",
@"{
  // Code size       15 (0xf)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  box        ""T""
  IL_0007:  ldnull
  IL_0008:  cgt.un
  IL_000a:  stloc.0
  IL_000b:  br.s       IL_000d
  IL_000d:  ldloc.0
  IL_000e:  ret
}");
        }
 
        [Fact, WorkItem(26387, "https://github.com/dotnet/roslyn/issues/26387")]
        public void ValueTypeArgument02()
        {
            var source =
@"namespace ConsoleApp1
{
    public class TestHelper
    {
        public static void Main()
        {
            IsValueTypeT(new Result<(Cls, IInt)>((new Cls(), new Int())));
            System.Console.WriteLine(""done"");
        }
 
        public static void IsValueTypeT<T>(Result<T> result)
        {
            if (!(result.Value is T v))
                throw new NotPossibleException();
        }
    }
 
    public class Result<T>
    {
        public T Value { get; }
 
        public Result(T value)
        {
            Value = value;
        }
    }
 
    public class Cls { }
    public interface IInt { }
 
    public class Int : IInt { }
 
    public class NotPossibleException : System.Exception { }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"done";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("ConsoleApp1.TestHelper.IsValueTypeT<T>(ConsoleApp1.Result<T>)",
@"{
  // Code size       31 (0x1f)
  .maxstack  2
  .locals init (T V_0, //v
                bool V_1)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  callvirt   ""T ConsoleApp1.Result<T>.Value.get""
  IL_0007:  stloc.0
  IL_0008:  ldloc.0
  IL_0009:  box        ""T""
  IL_000e:  ldnull
  IL_000f:  cgt.un
  IL_0011:  ldc.i4.0
  IL_0012:  ceq
  IL_0014:  stloc.1
  IL_0015:  ldloc.1
  IL_0016:  brfalse.s  IL_001e
  IL_0018:  newobj     ""ConsoleApp1.NotPossibleException..ctor()""
  IL_001d:  throw
  IL_001e:  ret
}");
        }
 
        [Fact]
        public void DeconstructNullableTuple_01()
        {
            var source =
@"
class C {
    static int i = 3;
    static (int,int)? GetNullableTuple() => (i++, i++);
 
    static void Main() {
        if (GetNullableTuple() is (int x1, int y1) tupl1)
        {
            System.Console.WriteLine($""x = {x1}, y = {y1}"");
        }
        if (GetNullableTuple() is (int x2, int y2) _)
        {
            System.Console.WriteLine($""x = {x2}, y = {y2}"");
        }
        switch (GetNullableTuple())
        {
            case (int x3, int y3) s:
                System.Console.WriteLine($""x = {x3}, y = {y3}"");
                break;
        }
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"x = 3, y = 4
x = 5, y = 6
x = 7, y = 8";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void DeconstructNullable_01()
        {
            var source =
@"
class C {
    static int i = 3;
    static S? GetNullableTuple() => new S(i++, i++);
 
    static void Main() {
        if (GetNullableTuple() is (int x1, int y1) tupl1)
        {
            System.Console.WriteLine($""x = {x1}, y = {y1}"");
        }
        if (GetNullableTuple() is (int x2, int y2) _)
        {
            System.Console.WriteLine($""x = {x2}, y = {y2}"");
        }
        switch (GetNullableTuple())
        {
            case (int x3, int y3) s:
                System.Console.WriteLine($""x = {x3}, y = {y3}"");
                break;
        }
    }
}
struct S
{
    int x, y;
    public S(int X, int Y) => (this.x, this.y) = (X, Y);
    public void Deconstruct(out int X, out int Y) => (X, Y) = (x, y);
}
";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"x = 3, y = 4
x = 5, y = 6
x = 7, y = 8";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact, WorkItem(28632, "https://github.com/dotnet/roslyn/issues/28632")]
        public void UnboxNullableInRecursivePattern01()
        {
            var source =
@"
static class Program
{
    public static int M1(int? x)
    {
        return x is int y ? y : 1;
    }
    public static int M2(int? x)
    {
        return x is { } y ? y : 2;
    }
    public static void Main()
    {
        System.Console.WriteLine(M1(null));
        System.Console.WriteLine(M2(null));
        System.Console.WriteLine(M1(3));
        System.Console.WriteLine(M2(4));
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"1
2
3
4";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Program.M1",
@"{
  // Code size       23 (0x17)
  .maxstack  1
  .locals init (int V_0) //y
  IL_0000:  ldarga.s   V_0
  IL_0002:  call       ""bool int?.HasValue.get""
  IL_0007:  brfalse.s  IL_0013
  IL_0009:  ldarga.s   V_0
  IL_000b:  call       ""int int?.GetValueOrDefault()""
  IL_0010:  stloc.0
  IL_0011:  br.s       IL_0015
  IL_0013:  ldc.i4.1
  IL_0014:  ret
  IL_0015:  ldloc.0
  IL_0016:  ret
}");
            compVerifier.VerifyIL("Program.M2",
@"{
  // Code size       23 (0x17)
  .maxstack  1
  .locals init (int V_0) //y
  IL_0000:  ldarga.s   V_0
  IL_0002:  call       ""bool int?.HasValue.get""
  IL_0007:  brfalse.s  IL_0013
  IL_0009:  ldarga.s   V_0
  IL_000b:  call       ""int int?.GetValueOrDefault()""
  IL_0010:  stloc.0
  IL_0011:  br.s       IL_0015
  IL_0013:  ldc.i4.2
  IL_0014:  ret
  IL_0015:  ldloc.0
  IL_0016:  ret
}");
        }
 
        [Fact]
        public void DoNotShareInputForMutatingWhenClause()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        Console.Write(M1(1));
        Console.Write(M2(1));
        Console.Write(M3(1));
        Console.Write(M4(1));
        Console.Write(M5(1));
        Console.Write(M6(1));
        Console.Write(M7(1));
        Console.Write(M8(1));
        Console.Write(M9(1));
    }
    public static int M1(int x)
    {
        return x switch { _ when (++x) == 5 => 1, 1 => 2, _ => 3 };
    }
    public static int M2(int x)
    {
        return x switch { _ when (x+=1) == 5 => 1, 1 => 2, _ => 3 };
    }
    public static int M3(int x)
    {
        return x switch { _ when ((x, _) = (5, 6)) == (0, 0) => 1, 1 => 2, _ => 3 };
    }
    public static int M4(int x)
    {
        dynamic d = new Program();
        return x switch { _ when d.M(ref x) => 1, 1 => 2, _ => 3 };
    }
    bool M(ref int x) { x = 100; return false; }
    public static int M5(int x)
    {
        return x switch { _ when new Program(ref x).P => 1, 1 => 2, _ => 3 };
    }
    public static int M6(int x)
    {
        dynamic d = x;
        return x switch { _ when new Program(d, ref x).P => 1, 1 => 2, _ => 3 };
    }
    public static int M7(int x)
    {
        return x switch { _ when new Program(ref x).P && new Program().P => 1, 1 => 2, _ => 3 };
    }
    public static int M8(int x)
    {
        dynamic d = x;
        return x switch { _ when new Program(d, ref x).P && new Program().P => 1, 1 => 2, _ => 3 };
    }
    public static int M9(int x)
    {
        return x switch { _ when (x=100) == 1 => 1, 1 => 2, _ => 3 };
    }
    Program() { }
    Program(ref int x) { x = 100; }
    Program(int a, ref int x) { x = 100; }
    bool P => false;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, references: new[] { CSharpRef });
            compilation.VerifyDiagnostics();
            var expectedOutput = @"222222222";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void GenerateStringHashOnlyOnce()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        Console.Write(M1(string.Empty));
        Console.Write(M2(string.Empty));
    }
    public static int M1(string s)
    {
        return s switch { ""a""=>1, ""b""=>2, ""c""=>3, ""d""=>4, ""e""=>5, ""f""=>6, ""g""=>7, ""h""=>8, _ => 9 };
    }
    public static int M2(string s)
    {
        return s switch { ""a""=>1, ""b""=>2, ""c""=>3, ""d""=>4, ""e""=>5, ""f""=>6, ""g""=>7, ""h""=>8, _ => 9 };
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"99";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void BindVariablesInWhenClause()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        var t = (1, 2);
        switch (t)
        {
            case var (x, y) when x+1 == y:
                Console.Write(1);
                break;
        }
        Console.Write(t switch
        {
            var (x, y) when x+1 == y => 1,
            _ => 2
        });
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"11";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void MissingExceptions_01()
        {
            var source = @"namespace System {
    public class Object { }
    public abstract class ValueType { }
    public struct Void { }
    public struct Boolean { }
    public struct Int32 { }
}
static class C {
    public static bool M(int i) => i switch { 1 => true };
}
";
            var compilation = CreateEmptyCompilation(source, parseOptions: TestOptions.Regular.WithNoRefSafetyRulesAttribute(), options: TestOptions.ReleaseDll);
            compilation.GetDiagnostics().Verify(
                // (9,38): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '0' is not covered.
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("0").WithLocation(9, 38)
                );
            compilation.GetEmitDiagnostics().Verify(
                // warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
                Diagnostic(ErrorCode.WRN_NoRuntimeMetadataVersion).WithLocation(1, 1),
                // (9,5): error CS0518: Predefined type 'System.Byte' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Byte").WithLocation(9, 5),
                // (9,5): error CS0518: Predefined type 'System.Byte' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Byte").WithLocation(9, 5),
                // (9,5): error CS0518: Predefined type 'System.Int16' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Int16").WithLocation(9, 5),
                // (9,5): error CS0518: Predefined type 'System.Int16' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Int16").WithLocation(9, 5),
                // (9,5): error CS0518: Predefined type 'System.Int64' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Int64").WithLocation(9, 5),
                // (9,5): error CS0518: Predefined type 'System.Int64' is not defined or imported
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "public static bool M(int i) => i switch { 1 => true };").WithArguments("System.Int64").WithLocation(9, 5),
                // (9,36): error CS0656: Missing compiler required member 'System.InvalidOperationException..ctor'
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "i switch { 1 => true }").WithArguments("System.InvalidOperationException", ".ctor").WithLocation(9, 36),
                // (9,38): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '0' is not covered.
                //     public static bool M(int i) => i switch { 1 => true };
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("0").WithLocation(9, 38)
                );
        }
 
        [Fact, WorkItem(32774, "https://github.com/dotnet/roslyn/issues/32774")]
        public void BadCode_32774()
        {
            var source = @"
public class Class1
{
    static void Main()
    {
        System.Console.WriteLine(SwitchCaseThatFails(12.123));
    }
 
    public static bool SwitchCaseThatFails(object someObject)
    {
        switch (someObject)
        {
            case IObject x when x.SubObject != null:
                return false;
            case IOtherObject x:
                return false;
            case double x:
                return true;
            default:
                return false;
        }
    }
 
    public interface IObject
    {
        IObject SubObject { get; }
    }
 
    public interface IOtherObject { }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"True";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("Class1.SwitchCaseThatFails",
@"{
  // Code size       97 (0x61)
  .maxstack  1
  .locals init (Class1.IObject V_0, //x
                Class1.IOtherObject V_1, //x
                double V_2, //x
                object V_3,
                object V_4,
                bool V_5)
  IL_0000:  nop
  IL_0001:  ldarg.0
  IL_0002:  stloc.s    V_4
  IL_0004:  ldloc.s    V_4
  IL_0006:  stloc.3
  IL_0007:  ldloc.3
  IL_0008:  isinst     ""Class1.IObject""
  IL_000d:  stloc.0
  IL_000e:  ldloc.0
  IL_000f:  brtrue.s   IL_003c
  IL_0011:  br.s       IL_001f
  IL_0013:  ldloc.3
  IL_0014:  isinst     ""Class1.IOtherObject""
  IL_0019:  stloc.1
  IL_001a:  ldloc.1
  IL_001b:  brtrue.s   IL_004b
  IL_001d:  br.s       IL_0059
  IL_001f:  ldloc.3
  IL_0020:  isinst     ""Class1.IOtherObject""
  IL_0025:  stloc.1
  IL_0026:  ldloc.1
  IL_0027:  brtrue.s   IL_004b
  IL_0029:  br.s       IL_002b
  IL_002b:  ldloc.3
  IL_002c:  isinst     ""double""
  IL_0031:  brfalse.s  IL_0059
  IL_0033:  ldloc.3
  IL_0034:  unbox.any  ""double""
  IL_0039:  stloc.2
  IL_003a:  br.s       IL_0052
  IL_003c:  ldloc.0
  IL_003d:  callvirt   ""Class1.IObject Class1.IObject.SubObject.get""
  IL_0042:  brtrue.s   IL_0046
  IL_0044:  br.s       IL_0013
  IL_0046:  ldc.i4.0
  IL_0047:  stloc.s    V_5
  IL_0049:  br.s       IL_005e
  IL_004b:  br.s       IL_004d
  IL_004d:  ldc.i4.0
  IL_004e:  stloc.s    V_5
  IL_0050:  br.s       IL_005e
  IL_0052:  br.s       IL_0054
  IL_0054:  ldc.i4.1
  IL_0055:  stloc.s    V_5
  IL_0057:  br.s       IL_005e
  IL_0059:  ldc.i4.0
  IL_005a:  stloc.s    V_5
  IL_005c:  br.s       IL_005e
  IL_005e:  ldloc.s    V_5
  IL_0060:  ret
}");
        }
 
        // Possible test helper bug on Linux; see https://github.com/dotnet/roslyn/issues/33356
        [ConditionalFact(typeof(WindowsOnly))]
        public void SwitchExpressionSequencePoints()
        {
            string source = @"
public class Program
{
    public static void Main()
    {
        int i = 0;
        var y = (i switch
        {
            0 => new Program(),
            1 => new Program(),
            _ => new Program(),
        }).Chain();
        y.Chain2();
    }
    public Program Chain() => this;
    public Program Chain2() => this;
}
";
            var v = CompileAndVerify(source, options: TestOptions.DebugExe);
            v.VerifyIL(qualifiedMethodName: "Program.Main", @"
    {
      // Code size       61 (0x3d)
      .maxstack  2
      .locals init (int V_0, //i
                    Program V_1, //y
                    Program V_2)
      // sequence point: {
      IL_0000:  nop
      // sequence point: int i = 0;
      IL_0001:  ldc.i4.0
      IL_0002:  stloc.0
      // sequence point: var y = (i s ...   }).Chain()
      IL_0003:  ldc.i4.1
      IL_0004:  brtrue.s   IL_0007
      // sequence point: switch ...         }
      IL_0006:  nop
      // sequence point: <hidden>
      IL_0007:  ldloc.0
      IL_0008:  brfalse.s  IL_0012
      IL_000a:  br.s       IL_000c
      IL_000c:  ldloc.0
      IL_000d:  ldc.i4.1
      IL_000e:  beq.s      IL_001a
      IL_0010:  br.s       IL_0022
      // sequence point: new Program()
      IL_0012:  newobj     ""Program..ctor()""
      IL_0017:  stloc.2
      IL_0018:  br.s       IL_002a
      // sequence point: new Program()
      IL_001a:  newobj     ""Program..ctor()""
      IL_001f:  stloc.2
      IL_0020:  br.s       IL_002a
      // sequence point: new Program()
      IL_0022:  newobj     ""Program..ctor()""
      IL_0027:  stloc.2
      IL_0028:  br.s       IL_002a
      // sequence point: <hidden>
      IL_002a:  ldc.i4.1
      IL_002b:  brtrue.s   IL_002e
      // sequence point: var y = (i s ...   }).Chain()
      IL_002d:  nop
      // sequence point: <hidden>
      IL_002e:  ldloc.2
      IL_002f:  callvirt   ""Program Program.Chain()""
      IL_0034:  stloc.1
      // sequence point: y.Chain2();
      IL_0035:  ldloc.1
      IL_0036:  callvirt   ""Program Program.Chain2()""
      IL_003b:  pop
      // sequence point: }
      IL_003c:  ret
    }
", sequencePoints: "Program.Main", source: source);
        }
 
        [Fact, WorkItem(33675, "https://github.com/dotnet/roslyn/issues/33675")]
        public void ParsingParenthesizedExpressionAsPatternOfExpressionSwitch()
        {
            var source = @"
public class Class1
{
    static void Main()
    {
        System.Console.Write(M(42));
        System.Console.Write(M(41));
    }
 
    static bool M(object o)
    {
        const int X = 42;
        return o switch { (X) => true, _ => false };
    }
}";
            foreach (var options in new[] { TestOptions.DebugExe, TestOptions.ReleaseExe })
            {
                var compilation = CreateCompilation(source, options: options);
                compilation.VerifyDiagnostics();
                var expectedOutput = @"TrueFalse";
                var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
                if (options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    compVerifier.VerifyIL("Class1.M", @"
    {
      // Code size       45 (0x2d)
      .maxstack  2
      .locals init (bool V_0,
                    int V_1,
                    bool V_2)
      IL_0000:  nop
      IL_0001:  ldc.i4.1
      IL_0002:  brtrue.s   IL_0005
      IL_0004:  nop
      IL_0005:  ldarg.0
      IL_0006:  isinst     ""int""
      IL_000b:  brfalse.s  IL_001f
      IL_000d:  ldarg.0
      IL_000e:  unbox.any  ""int""
      IL_0013:  stloc.1
      IL_0014:  ldloc.1
      IL_0015:  ldc.i4.s   42
      IL_0017:  beq.s      IL_001b
      IL_0019:  br.s       IL_001f
      IL_001b:  ldc.i4.1
      IL_001c:  stloc.0
      IL_001d:  br.s       IL_0023
      IL_001f:  ldc.i4.0
      IL_0020:  stloc.0
      IL_0021:  br.s       IL_0023
      IL_0023:  ldc.i4.1
      IL_0024:  brtrue.s   IL_0027
      IL_0026:  nop
      IL_0027:  ldloc.0
      IL_0028:  stloc.2
      IL_0029:  br.s       IL_002b
      IL_002b:  ldloc.2
      IL_002c:  ret
    }
");
                }
                else
                {
                    compVerifier.VerifyIL("Class1.M",
@"{
  // Code size       26 (0x1a)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""int""
  IL_0006:  brfalse.s  IL_0016
  IL_0008:  ldarg.0
  IL_0009:  unbox.any  ""int""
  IL_000e:  ldc.i4.s   42
  IL_0010:  bne.un.s   IL_0016
  IL_0012:  ldc.i4.1
  IL_0013:  stloc.0
  IL_0014:  br.s       IL_0018
  IL_0016:  ldc.i4.0
  IL_0017:  stloc.0
  IL_0018:  ldloc.0
  IL_0019:  ret
}");
                }
            }
        }
 
        [Fact, WorkItem(35584, "https://github.com/dotnet/roslyn/issues/35584")]
        public void MatchToTypeParameterUnbox_01()
        {
            var source = @"
class Program
{
    public static void Main() => System.Console.WriteLine(P<int>(0));
    public static string P<T>(T t) => (t is object o) ? o.ToString() : string.Empty;
}
";
            var expectedOutput = @"0";
            foreach (var options in new[] { TestOptions.DebugExe, TestOptions.ReleaseExe })
            {
                var compilation = CreateCompilation(source, options: options);
                compilation.VerifyDiagnostics();
                var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
                if (options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    compVerifier.VerifyIL("Program.P<T>",
@"{
  // Code size       24 (0x18)
  .maxstack  1
  .locals init (object V_0) //o
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brtrue.s   IL_0011
  IL_000a:  ldsfld     ""string string.Empty""
  IL_000f:  br.s       IL_0017
  IL_0011:  ldloc.0
  IL_0012:  callvirt   ""string object.ToString()""
  IL_0017:  ret
}
");
                }
                else
                {
                    compVerifier.VerifyIL("Program.P<T>",
@"{
  // Code size       23 (0x17)
  .maxstack  1
  .locals init (object V_0) //o
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brtrue.s   IL_0010
  IL_000a:  ldsfld     ""string string.Empty""
  IL_000f:  ret
  IL_0010:  ldloc.0
  IL_0011:  callvirt   ""string object.ToString()""
  IL_0016:  ret
}
");
                }
            }
        }
 
        [Fact, WorkItem(35584, "https://github.com/dotnet/roslyn/issues/35584")]
        public void MatchToTypeParameterUnbox_02()
        {
            var source =
@"using System;
 class Program
{
    public static void Main()
    {
        var generic = new Generic<int>(0);
    }
}
public class Generic<T>
{
    public Generic(T value)
    {
        if (value is object obj && obj == null)
        {
            throw new Exception(""Kaboom!"");
        }
    }
}
";
            var expectedOutput = @"";
            foreach (var options in new[] { TestOptions.DebugExe, TestOptions.ReleaseExe })
            {
                var compilation = CreateCompilation(source, options: options);
                compilation.VerifyDiagnostics();
                var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
                if (options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    compVerifier.VerifyIL("Generic<T>..ctor(T)",
@"{
  // Code size       42 (0x2a)
  .maxstack  2
  .locals init (object V_0, //obj
                bool V_1)
  IL_0000:  ldarg.0
  IL_0001:  call       ""object..ctor()""
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  ldarg.1
  IL_0009:  box        ""T""
  IL_000e:  stloc.0
  IL_000f:  ldloc.0
  IL_0010:  brfalse.s  IL_0018
  IL_0012:  ldloc.0
  IL_0013:  ldnull
  IL_0014:  ceq
  IL_0016:  br.s       IL_0019
  IL_0018:  ldc.i4.0
  IL_0019:  stloc.1
  IL_001a:  ldloc.1
  IL_001b:  brfalse.s  IL_0029
  IL_001d:  nop
  IL_001e:  ldstr      ""Kaboom!""
  IL_0023:  newobj     ""System.Exception..ctor(string)""
  IL_0028:  throw
  IL_0029:  ret
}
");
                }
                else
                {
                    compVerifier.VerifyIL("Generic<T>..ctor(T)",
@"{
  // Code size       31 (0x1f)
  .maxstack  1
  .locals init (object V_0) //obj
  IL_0000:  ldarg.0
  IL_0001:  call       ""object..ctor()""
  IL_0006:  ldarg.1
  IL_0007:  box        ""T""
  IL_000c:  stloc.0
  IL_000d:  ldloc.0
  IL_000e:  brfalse.s  IL_001e
  IL_0010:  ldloc.0
  IL_0011:  brtrue.s   IL_001e
  IL_0013:  ldstr      ""Kaboom!""
  IL_0018:  newobj     ""System.Exception..ctor(string)""
  IL_001d:  throw
  IL_001e:  ret
}
");
                }
            }
        }
 
        [Fact, WorkItem(35584, "https://github.com/dotnet/roslyn/issues/35584")]
        public void MatchToTypeParameterUnbox_03()
        {
            var source =
@"using System;
class Program
{
    public static void Main() => System.Console.WriteLine(P<Enum>(null));
    public static string P<T>(T t) where T: Enum => (t is ValueType o) ? o.ToString() : ""1"";
}
";
            var expectedOutput = @"1";
            foreach (var options in new[] { TestOptions.DebugExe, TestOptions.ReleaseExe })
            {
                var compilation = CreateCompilation(source, options: options);
                compilation.VerifyDiagnostics();
                var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
                if (options.OptimizationLevel == OptimizationLevel.Debug)
                {
                    compVerifier.VerifyIL("Program.P<T>",
@"{
  // Code size       24 (0x18)
  .maxstack  1
  .locals init (System.ValueType V_0) //o
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brtrue.s   IL_0011
  IL_000a:  ldstr      ""1""
  IL_000f:  br.s       IL_0017
  IL_0011:  ldloc.0
  IL_0012:  callvirt   ""string object.ToString()""
  IL_0017:  ret
}
");
                }
                else
                {
                    compVerifier.VerifyIL("Program.P<T>",
@"{
  // Code size       23 (0x17)
  .maxstack  1
  .locals init (System.ValueType V_0) //o
  IL_0000:  ldarg.0
  IL_0001:  box        ""T""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  brtrue.s   IL_0010
  IL_000a:  ldstr      ""1""
  IL_000f:  ret
  IL_0010:  ldloc.0
  IL_0011:  callvirt   ""string object.ToString()""
  IL_0016:  ret
}
");
                }
            }
        }
 
        [Fact]
        public void CompileTimeRuntimeInstanceofMismatch_01()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        M(new byte[1]);
        M(new sbyte[1]);
        M(new Ebyte[1]);
        M(new Esbyte[1]);
 
        M(new short[1]);
        M(new ushort[1]);
        M(new Eshort[1]);
        M(new Eushort[1]);
 
        M(new int[1]);
        M(new uint[1]);
        M(new Eint[1]);
        M(new Euint[1]);
 
        M(new int[1][]);
        M(new uint[1][]);
        M(new Eint[1][]);
        M(new Euint[1][]);
 
        M(new long[1]);
        M(new ulong[1]);
        M(new Elong[1]);
        M(new Eulong[1]);
 
        M(new IntPtr[1]);
        M(new UIntPtr[1]);
 
        M(new IntPtr[1][]);
        M(new UIntPtr[1][]);
    }
 
    static void M(object o)
    {
        switch (o)
        {
            case byte[] _ when o.GetType() == typeof(byte[]):
                Console.WriteLine(""byte[]"");
                break;
            case sbyte[] _ when o.GetType() == typeof(sbyte[]):
                Console.WriteLine(""sbyte[]"");
                break;
            case Ebyte[] _ when o.GetType() == typeof(Ebyte[]):
                Console.WriteLine(""Ebyte[]"");
                break;
            case Esbyte[] _ when o.GetType() == typeof(Esbyte[]):
                Console.WriteLine(""Esbyte[]"");
                break;
 
            case short[] _ when o.GetType() == typeof(short[]):
                Console.WriteLine(""short[]"");
                break;
            case ushort[] _ when o.GetType() == typeof(ushort[]):
                Console.WriteLine(""ushort[]"");
                break;
            case Eshort[] _ when o.GetType() == typeof(Eshort[]):
                Console.WriteLine(""Eshort[]"");
                break;
            case Eushort[] _ when o.GetType() == typeof(Eushort[]):
                Console.WriteLine(""Eushort[]"");
                break;
 
            case int[] _ when o.GetType() == typeof(int[]):
                Console.WriteLine(""int[]"");
                break;
            case uint[] _ when o.GetType() == typeof(uint[]):
                Console.WriteLine(""uint[]"");
                break;
            case Eint[] _ when o.GetType() == typeof(Eint[]):
                Console.WriteLine(""Eint[]"");
                break;
            case Euint[] _ when o.GetType() == typeof(Euint[]):
                Console.WriteLine(""Euint[]"");
                break;
 
            case int[][] _ when o.GetType() == typeof(int[][]):
                Console.WriteLine(""int[][]"");
                break;
            case uint[][] _ when o.GetType() == typeof(uint[][]):
                Console.WriteLine(""uint[][]"");
                break;
            case Eint[][] _ when o.GetType() == typeof(Eint[][]):
                Console.WriteLine(""Eint[][]"");
                break;
            case Euint[][] _ when o.GetType() == typeof(Euint[][]):
                Console.WriteLine(""Euint[][]"");
                break;
 
            case long[] _ when o.GetType() == typeof(long[]):
                Console.WriteLine(""long[]"");
                break;
            case ulong[] _ when o.GetType() == typeof(ulong[]):
                Console.WriteLine(""ulong[]"");
                break;
            case Elong[] _ when o.GetType() == typeof(Elong[]):
                Console.WriteLine(""Elong[]"");
                break;
            case Eulong[] _ when o.GetType() == typeof(Eulong[]):
                Console.WriteLine(""Eulong[]"");
                break;
 
            case IntPtr[] _ when o.GetType() == typeof(IntPtr[]):
                Console.WriteLine(""IntPtr[]"");
                break;
            case UIntPtr[] _ when o.GetType() == typeof(UIntPtr[]):
                Console.WriteLine(""UIntPtr[]"");
                break;
 
            case IntPtr[][] _ when o.GetType() == typeof(IntPtr[][]):
                Console.WriteLine(""IntPtr[][]"");
                break;
            case UIntPtr[][] _ when o.GetType() == typeof(UIntPtr[][]):
                Console.WriteLine(""UIntPtr[][]"");
                break;
 
            default:
                Console.WriteLine(""oops: "" + o.GetType());
                break;
        }
    }
}
enum Ebyte : byte {}
enum Esbyte : sbyte {}
enum Eshort : short {}
enum Eushort : ushort {}
enum Eint : int {}
enum Euint : uint {}
enum Elong : long {}
enum Eulong : ulong {}
";
            var expectedOutput =
@"byte[]
sbyte[]
Ebyte[]
Esbyte[]
short[]
ushort[]
Eshort[]
Eushort[]
int[]
uint[]
Eint[]
Euint[]
int[][]
uint[][]
Eint[][]
Euint[][]
long[]
ulong[]
Elong[]
Eulong[]
IntPtr[]
UIntPtr[]
IntPtr[][]
UIntPtr[][]
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void CompileTimeRuntimeInstanceofMismatch_02()
        {
            var source =
@"using System;
class Program
{
    static void Main()
    {
        M(new byte[1]);
        M(new sbyte[1]);
    }
    static void M(object o)
    {
        switch (o)
        {
            case byte[] _:
                Console.WriteLine(""byte[]"");
                break;
            case sbyte[] _: // not subsumed, even though it will never occur due to CLR behavior
                Console.WriteLine(""sbyte[]"");
                break;
        }
    }
}
";
            var expectedOutput =
@"byte[]
byte[]
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        [WorkItem(36496, "https://github.com/dotnet/roslyn/issues/36496")]
        public void EmptyVarPatternVsDeconstruct()
        {
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        Console.Write(M(new C()));
        Console.Write(M(null));
    }
    public static bool M(C c)
    {
        return c is var ();
    }
    public void Deconstruct() { }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation, expectedOutput: "TrueFalse");
            compVerifier.VerifyIL("C.M(C)",
@"
{
    // Code size        5 (0x5)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  ldnull
    IL_0002:  cgt.un
    IL_0004:  ret
}
");
        }
 
        [Fact]
        [WorkItem(36496, "https://github.com/dotnet/roslyn/issues/36496")]
        public void EmptyPositionalPatternVsDeconstruct()
        {
            var source =
@"using System;
public class C
{
    public static void Main()
    {
        Console.Write(M(new C()));
        Console.Write(M(null));
    }
    public static bool M(C c)
    {
        return c is ();
    }
    public void Deconstruct() { }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation, expectedOutput: "TrueFalse");
            compVerifier.VerifyIL("C.M(C)",
@"
{
    // Code size        5 (0x5)
    .maxstack  2
    IL_0000:  ldarg.0
    IL_0001:  ldnull
    IL_0002:  cgt.un
    IL_0004:  ret
}
");
        }
 
        [Fact, WorkItem(31494, "https://github.com/dotnet/roslyn/issues/31494")]
        public void NoRedundantNullCheckForStringConstantPattern_01()
        {
            var source =
@"public class C
{
    public static bool M1(string s) => s is ""Frog"";
    public static bool M2(string s) => s == ""Frog"";
    public static bool M3(string s) => s switch { ""Frog"" => true, _ => false };
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1(string)", @"
{
  // Code size       12 (0xc)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldstr      ""Frog""
  IL_0006:  call       ""bool string.op_Equality(string, string)""
  IL_000b:  ret
}
");
            compVerifier.VerifyIL("C.M2(string)", @"
{
  // Code size       12 (0xc)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldstr      ""Frog""
  IL_0006:  call       ""bool string.op_Equality(string, string)""
  IL_000b:  ret
}
");
            compVerifier.VerifyIL("C.M3(string)", @"
{
  // Code size       21 (0x15)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldstr      ""Frog""
  IL_0006:  call       ""bool string.op_Equality(string, string)""
  IL_000b:  brfalse.s  IL_0011
  IL_000d:  ldc.i4.1
  IL_000e:  stloc.0
  IL_000f:  br.s       IL_0013
  IL_0011:  ldc.i4.0
  IL_0012:  stloc.0
  IL_0013:  ldloc.0
  IL_0014:  ret
}
");
        }
 
        [Fact, WorkItem(31494, "https://github.com/dotnet/roslyn/issues/31494")]
        public void NoRedundantNullCheckForStringConstantPattern_02()
        {
            var source =
@"public class C
{
    public static bool M1(string s) => s switch { ""Frog"" => true, ""Newt"" => true, _ => false };
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1(string)", @"
{
  // Code size       40 (0x28)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldstr      ""Frog""
  IL_0006:  call       ""bool string.op_Equality(string, string)""
  IL_000b:  brtrue.s   IL_001c
  IL_000d:  ldarg.0
  IL_000e:  ldstr      ""Newt""
  IL_0013:  call       ""bool string.op_Equality(string, string)""
  IL_0018:  brtrue.s   IL_0020
  IL_001a:  br.s       IL_0024
  IL_001c:  ldc.i4.1
  IL_001d:  stloc.0
  IL_001e:  br.s       IL_0026
  IL_0020:  ldc.i4.1
  IL_0021:  stloc.0
  IL_0022:  br.s       IL_0026
  IL_0024:  ldc.i4.0
  IL_0025:  stloc.0
  IL_0026:  ldloc.0
  IL_0027:  ret
}
");
        }
 
        [Fact, WorkItem(31494, "https://github.com/dotnet/roslyn/issues/31494")]
        public void NoRedundantNullCheckForStringConstantPattern_03()
        {
            var source =
@"public class C
{
    public static bool M1(System.Type x) => x is { Name: ""Program"" };
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1(System.Type)", @"
{
  // Code size       22 (0x16)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  brfalse.s  IL_0014
  IL_0003:  ldarg.0
  IL_0004:  callvirt   ""string System.Reflection.MemberInfo.Name.get""
  IL_0009:  ldstr      ""Program""
  IL_000e:  call       ""bool string.op_Equality(string, string)""
  IL_0013:  ret
  IL_0014:  ldc.i4.0
  IL_0015:  ret
}
");
        }
 
        [Fact]
        [WorkItem(42912, "https://github.com/dotnet/roslyn/issues/42912")]
        [WorkItem(31494, "https://github.com/dotnet/roslyn/issues/31494")]
        public void NoRedundantNullCheckForNullableConstantPattern_04()
        {
            // Note that we do not produce the same code for `x is 1` and `x == 1`.
            // The latter has been optimized to avoid branches.
 
            var source =
@"public class C
{
    public static bool M1(int? x) => x is 1;
    public static bool M2(int? x) => x == 1;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseDll);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation);
            compVerifier.VerifyIL("C.M1(int?)", @"
{
  // Code size       22 (0x16)
  .maxstack  2
  IL_0000:  ldarga.s   V_0
  IL_0002:  call       ""bool int?.HasValue.get""
  IL_0007:  brfalse.s  IL_0014
  IL_0009:  ldarga.s   V_0
  IL_000b:  call       ""int int?.GetValueOrDefault()""
  IL_0010:  ldc.i4.1
  IL_0011:  ceq
  IL_0013:  ret
  IL_0014:  ldc.i4.0
  IL_0015:  ret
}
");
            compVerifier.VerifyIL("C.M2(int?)", @"
{
  // Code size       11 (0xb)
  .maxstack  2
  IL_0000:  ldarga.s   V_0
  IL_0002:  call       ""int int?.GetValueOrDefault()""
  IL_0007:  ldc.i4.1
  IL_0008:  ceq
  IL_000a:  ret
}
");
        }
 
        [Fact]
        public void SwitchExpressionAsExceptionFilter_01()
        {
            var source = @"
using System;
class C
{
    const string K1 = ""frog"";
    const string K2 = ""toad"";
    public static void M(string msg)
    {
        try
        {
            T(msg);
        }
        catch (Exception e) when (e.Message switch
            {
                K1 => true,
                K2 => true,
                _ => false,
            })
        {
            throw new Exception(e.Message);
        }
        catch
        {
        }
    }
    static void T(string msg)
    {
        throw new Exception(msg);
    }
    static void Main()
    {
        Try(K1);
        Try(K2);
        Try(""fox"");
    }
    static void Try(string s)
    {
        try { M(s); } catch (Exception ex) { Console.WriteLine(ex.Message); }
    }
}
";
            var expectedOutput =
@"frog
toad";
            foreach (var compilationOptions in new[] { TestOptions.ReleaseExe, TestOptions.DebugExe })
            {
                var compilation = CreateCompilation(source, options: compilationOptions);
                compilation.VerifyDiagnostics();
                var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
                if (compilationOptions.OptimizationLevel == OptimizationLevel.Debug)
                {
                    compVerifier.VerifyIL("C.M(string)", @"
{
  // Code size      108 (0x6c)
  .maxstack  2
  .locals init (System.Exception V_0, //e
                bool V_1,
                string V_2,
                bool V_3)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  ldarg.0
    IL_0003:  call       ""void C.T(string)""
    IL_0008:  nop
    IL_0009:  nop
    IL_000a:  leave.s    IL_006b
  }
  filter
  {
    IL_000c:  isinst     ""System.Exception""
    IL_0011:  dup
    IL_0012:  brtrue.s   IL_0018
    IL_0014:  pop
    IL_0015:  ldc.i4.0
    IL_0016:  br.s       IL_0056
    IL_0018:  stloc.0
    IL_0019:  ldloc.0
    IL_001a:  callvirt   ""string System.Exception.Message.get""
    IL_001f:  stloc.2
    IL_0020:  ldc.i4.1
    IL_0021:  brtrue.s   IL_0024
    IL_0023:  nop
    IL_0024:  ldloc.2
    IL_0025:  ldstr      ""frog""
    IL_002a:  call       ""bool string.op_Equality(string, string)""
    IL_002f:  brtrue.s   IL_0040
    IL_0031:  ldloc.2
    IL_0032:  ldstr      ""toad""
    IL_0037:  call       ""bool string.op_Equality(string, string)""
    IL_003c:  brtrue.s   IL_0044
    IL_003e:  br.s       IL_0048
    IL_0040:  ldc.i4.1
    IL_0041:  stloc.1
    IL_0042:  br.s       IL_004c
    IL_0044:  ldc.i4.1
    IL_0045:  stloc.1
    IL_0046:  br.s       IL_004c
    IL_0048:  ldc.i4.0
    IL_0049:  stloc.1
    IL_004a:  br.s       IL_004c
    IL_004c:  ldc.i4.1
    IL_004d:  brtrue.s   IL_0050
    IL_004f:  nop
    IL_0050:  ldloc.1
    IL_0051:  stloc.3
    IL_0052:  ldloc.3
    IL_0053:  ldc.i4.0
    IL_0054:  cgt.un
    IL_0056:  endfilter
  }  // end filter
  {  // handler
    IL_0058:  pop
    IL_0059:  nop
    IL_005a:  ldloc.0
    IL_005b:  callvirt   ""string System.Exception.Message.get""
    IL_0060:  newobj     ""System.Exception..ctor(string)""
    IL_0065:  throw
  }
  catch object
  {
    IL_0066:  pop
    IL_0067:  nop
    IL_0068:  nop
    IL_0069:  leave.s    IL_006b
  }
  IL_006b:  ret
}
");
                }
                else
                {
                    compVerifier.VerifyIL("C.M(string)", @"
{
  // Code size       89 (0x59)
  .maxstack  2
  .locals init (System.Exception V_0, //e
                bool V_1,
                string V_2)
  .try
  {
    IL_0000:  ldarg.0
    IL_0001:  call       ""void C.T(string)""
    IL_0006:  leave.s    IL_0058
  }
  filter
  {
    IL_0008:  isinst     ""System.Exception""
    IL_000d:  dup
    IL_000e:  brtrue.s   IL_0014
    IL_0010:  pop
    IL_0011:  ldc.i4.0
    IL_0012:  br.s       IL_0046
    IL_0014:  stloc.0
    IL_0015:  ldloc.0
    IL_0016:  callvirt   ""string System.Exception.Message.get""
    IL_001b:  stloc.2
    IL_001c:  ldloc.2
    IL_001d:  ldstr      ""frog""
    IL_0022:  call       ""bool string.op_Equality(string, string)""
    IL_0027:  brtrue.s   IL_0038
    IL_0029:  ldloc.2
    IL_002a:  ldstr      ""toad""
    IL_002f:  call       ""bool string.op_Equality(string, string)""
    IL_0034:  brtrue.s   IL_003c
    IL_0036:  br.s       IL_0040
    IL_0038:  ldc.i4.1
    IL_0039:  stloc.1
    IL_003a:  br.s       IL_0042
    IL_003c:  ldc.i4.1
    IL_003d:  stloc.1
    IL_003e:  br.s       IL_0042
    IL_0040:  ldc.i4.0
    IL_0041:  stloc.1
    IL_0042:  ldloc.1
    IL_0043:  ldc.i4.0
    IL_0044:  cgt.un
    IL_0046:  endfilter
  }  // end filter
  {  // handler
    IL_0048:  pop
    IL_0049:  ldloc.0
    IL_004a:  callvirt   ""string System.Exception.Message.get""
    IL_004f:  newobj     ""System.Exception..ctor(string)""
    IL_0054:  throw
  }
  catch object
  {
    IL_0055:  pop
    IL_0056:  leave.s    IL_0058
  }
  IL_0058:  ret
}
");
                }
            }
        }
 
        [Fact]
        public void SwitchExpressionAsExceptionFilter_02()
        {
            var source = @"
using System;
class C
{
    public static void Main()
    {
        try
        {
            throw new Exception();
        }
        catch when ((3 is int i) switch { true when M(() => i) => true, _ => false })
        {
            Console.WriteLine(""correct"");
        }
    }
    static bool M(Func<int> func)
    {
        func();
        return true;
    }
}
";
            var expectedOutput = @"correct";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        [WorkItem(48259, "https://github.com/dotnet/roslyn/issues/48259")]
        public void SwitchExpressionAsExceptionFilter_03()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
public static class Program
{
    static async Task Main()
    {
        Exception ex = new ArgumentException();
        try
        {
            throw ex;
        }
        catch (Exception e) when (e switch { InvalidOperationException => true, _ => false })
        {
            return;
        }
        catch (Exception)
        {
            Console.WriteLine(""correct"");
        }
    }
}
";
            var expectedOutput = "correct";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics(
                // (7,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task Main()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Main").WithLocation(7, 23));
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        [WorkItem(48259, "https://github.com/dotnet/roslyn/issues/48259")]
        public void SwitchExpressionAsExceptionFilter_04()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
public static class Program
{
    static async Task Main()
    {
        Exception ex = new ArgumentException();
        try
        {
            throw ex;
        }
        catch (Exception e) when (e switch { ArgumentException => true, _ => false })
        {
            Console.WriteLine(""correct"");
            return;
        }
    }
}
";
            var expectedOutput = "correct";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics(
                // (7,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     static async Task Main()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Main").WithLocation(7, 23));
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [WorkItem(48563, "https://github.com/dotnet/roslyn/issues/48563")]
        [Theory]
        [InlineData("void*")]
        [InlineData("char*")]
        [InlineData("delegate*<void>")]
        public void IsNull_01(string pointerType)
        {
            var source =
$@"using static System.Console;
unsafe class Program
{{
    static void Main()
    {{
        Check(0);
        Check(-1);
    }}
    static void Check(nint i)
    {{
        {pointerType} p = ({pointerType})i;
        WriteLine(EqualNull(p));
        WriteLine(IsNull(p));
        WriteLine(NotEqualNull(p));
        WriteLine(IsNotNull(p));
    }}
    static bool EqualNull({pointerType} p) => p == null;
    static bool NotEqualNull({pointerType} p) => p != null;
    static bool IsNull({pointerType} p) => p is null;
    static bool IsNotNull({pointerType} p) => p is not null;
}}";
            var verifier = CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Skipped, expectedOutput:
@"True
True
False
False
False
False
True
True");
            string expectedEqualNull =
@"{
  // Code size        6 (0x6)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.0
  IL_0002:  conv.u
  IL_0003:  ceq
  IL_0005:  ret
}";
            string expectedNotEqualNull =
@"{
  // Code size        9 (0x9)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.0
  IL_0002:  conv.u
  IL_0003:  ceq
  IL_0005:  ldc.i4.0
  IL_0006:  ceq
  IL_0008:  ret
}";
            verifier.VerifyIL("Program.EqualNull", expectedEqualNull);
            verifier.VerifyIL("Program.NotEqualNull", expectedNotEqualNull);
            verifier.VerifyIL("Program.IsNull", expectedEqualNull);
            verifier.VerifyIL("Program.IsNotNull", expectedNotEqualNull);
        }
 
        [WorkItem(48563, "https://github.com/dotnet/roslyn/issues/48563")]
        [Fact]
        public void IsNull_02()
        {
            var source =
@"using static System.Console;
unsafe class Program
{
    static void Main()
    {
        Check(0);
        Check(-1);
    }
    static void Check(nint i)
    {
        char* p = (char*)i;
        WriteLine(EqualNull(p));
    }
    static bool EqualNull(char* p) => p switch { null => true, _ => false };
}";
            var verifier = CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Skipped, expectedOutput:
@"True
False");
            verifier.VerifyIL("Program.EqualNull",
@"{
  // Code size       13 (0xd)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.0
  IL_0002:  conv.u
  IL_0003:  bne.un.s   IL_0009
  IL_0005:  ldc.i4.1
  IL_0006:  stloc.0
  IL_0007:  br.s       IL_000b
  IL_0009:  ldc.i4.0
  IL_000a:  stloc.0
  IL_000b:  ldloc.0
  IL_000c:  ret
}");
        }
 
        [WorkItem(48563, "https://github.com/dotnet/roslyn/issues/48563")]
        [Fact]
        public void IsNull_03()
        {
            var source =
@"using static System.Console;
unsafe class C
{
    public char* P;
}
unsafe class Program
{
    static void Main()
    {
        Check(0);
        Check(-1);
    }
    static void Check(nint i)
    {
        char* p = (char*)i;
        WriteLine(EqualNull(new C() { P = p }));
    }
    static bool EqualNull(C c) => c switch { { P: null } => true, _ => false };
}";
            var verifier = CompileAndVerify(source, options: TestOptions.UnsafeReleaseExe, verify: Verification.Skipped, expectedOutput:
@"True
False");
            verifier.VerifyIL("Program.EqualNull",
@"{
  // Code size       21 (0x15)
  .maxstack  2
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  brfalse.s  IL_0011
  IL_0003:  ldarg.0
  IL_0004:  ldfld      ""char* C.P""
  IL_0009:  ldc.i4.0
  IL_000a:  conv.u
  IL_000b:  bne.un.s   IL_0011
  IL_000d:  ldc.i4.1
  IL_000e:  stloc.0
  IL_000f:  br.s       IL_0013
  IL_0011:  ldc.i4.0
  IL_0012:  stloc.0
  IL_0013:  ldloc.0
  IL_0014:  ret
}");
        }
 
        #endregion Miscellaneous
 
        #region Target Typed Switch
 
        [Fact]
        public void TargetTypedSwitch_Assignment()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.Write(M(false));
        Console.Write(M(true));
    }
    static object M(bool b)
    {
        int result = b switch { false => new A(), true => new B() };
        return result;
    }
}
class A
{
    public static implicit operator int(A a) => throw null;
    public static implicit operator B(A a) => new B();
}
class B
{
    public static implicit operator int(B b) => (b == null) ? throw null : 2;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"22";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void TargetTypedSwitch_Return()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.Write(M(false));
        Console.Write(M(true));
    }
    static long M(bool b)
    {
        return b switch { false => new A(), true => new B() };
    }
}
class A
{
    public static implicit operator int(A a) => throw null;
    public static implicit operator B(A a) => new B();
}
class B
{
    public static implicit operator int(B b) => (b == null) ? throw null : 2;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"22";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void TargetTypedSwitch_Argument_01()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.Write(M1(false));
        Console.Write(M1(true));
    }
    static object M1(bool b)
    {
        return M2(b switch { false => new A(), true => new B() });
    }
    static Exception M2(Exception ex) => ex;
    static int M2(int i) => i;
    static int M2(string s) => s.Length;
}
class A : Exception
{
    public static implicit operator int(A a) => throw null;
    public static implicit operator B(A a) => throw null;
}
class B : Exception
{
    public static implicit operator int(B b) => throw null;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics(
                    // (12,16): error CS0121: The call is ambiguous between the following methods or properties: 'Program.M2(Exception)' and 'Program.M2(int)'
                    //         return M2(b switch { false => new A(), true => new B() });
                    Diagnostic(ErrorCode.ERR_AmbigCall, "M2").WithArguments("Program.M2(System.Exception)", "Program.M2(int)").WithLocation(12, 16)
                );
        }
 
        [Fact]
        public void TargetTypedSwitch_Argument_02()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.Write(M1(false));
        Console.Write(M1(true));
    }
    static object M1(bool b)
    {
        return M2(b switch { false => new A(), true => new B() });
    }
    // static Exception M2(Exception ex) => ex;
    static int M2(int i) => i;
    static int M2(string s) => s.Length;
}
class A : Exception
{
    public static implicit operator int(A a) => throw null;
    public static implicit operator B(A a) => new B();
}
class B : Exception
{
    public static implicit operator int(B b) => (b == null) ? throw null : 2;
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"22";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [ConditionalFact(typeof(WindowsDesktopOnly), Reason = ConditionalSkipReason.RestrictedTypesNeedDesktop)]
        public void TargetTypedSwitch_Arglist()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.WriteLine(M1(false));
        Console.WriteLine(M1(true));
    }
    static object M1(bool b)
    {
        return M2(__arglist(b switch { false => new A(), true => new B() }));
    }
    static int M2(__arglist) => 1;
}
class A
{
    public A() { Console.Write(""new A; ""); }
    public static implicit operator B(A a) { Console.Write(""A->""); return new B(); }
}
class B
{
    public B() { Console.Write(""new B; ""); }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"new A; A->new B; 1
new B; 1";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void TargetTypedSwitch_StackallocSize()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        M1(false);
        M1(true);
    }
    static void M1(bool b)
    {
        Span<int> s = stackalloc int[b switch { false => new A(), true => new B() }];
        Console.WriteLine(s.Length);
    }
}
class A
{
    public A() { Console.Write(""new A; ""); }
    public static implicit operator int(A a) { Console.Write(""A->int; ""); return 4; }
}
class B
{
    public B() { Console.Write(""new B; ""); }
    public static implicit operator int(B b) { Console.Write(""B->int; ""); return 2; }
}
";
            var compilation = CreateCompilationWithMscorlibAndSpan(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"new A; A->int; 4
new B; B->int; 2";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput, verify: Verification.Skipped);
        }
 
        [Fact]
        public void TargetTypedSwitch_Attribute()
        {
            var source = @"
using System;
class Program
{
    [My(1 switch { 1 => 1, _ => 2 })]
    public static void M1() { }
 
    [My(1 switch { 1 => new A(), _ => new B() })]
    public static void M2() { }
 
    [My(1 switch { 1 => 1, _ => string.Empty })]
    public static void M3() { }
}
public class MyAttribute : Attribute
{
    public MyAttribute(int Value) { }
}
public class A
{
    public static implicit operator int(A a) => 4;
}
public class B
{
    public static implicit operator int(B b) => 2;
}
";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                    // (5,9): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
                    //     [My(1 switch { 1 => 1, _ => 2 })]
                    Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => 1, _ => 2 }").WithLocation(5, 9),
                    // (8,9): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
                    //     [My(1 switch { 1 => new A(), _ => new B() })]
                    Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => new A(), _ => new B() }").WithLocation(8, 9),
                    // (11,9): error CS1503: Argument 1: cannot convert from '<switch expression>' to 'int'
                    //     [My(1 switch { 1 => 1, _ => string.Empty })]
                    Diagnostic(ErrorCode.ERR_BadArgType, "1 switch { 1 => 1, _ => string.Empty }").WithArguments("1", "<switch expression>", "int").WithLocation(11, 9)
                );
 
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
 
            var switchExpressions = tree.GetRoot().DescendantNodes().OfType<SwitchExpressionSyntax>().ToArray();
 
            VerifyOperationTreeForNode(compilation, model, switchExpressions[0], @"
ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch {  ... 1, _ => 2 }')
  Value: 
    ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
  Arms(2):
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
        Pattern: 
          IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
            Value: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
        Value: 
          ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => 2')
        Pattern: 
          IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
        Value: 
          ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
");
 
            VerifyOperationTreeForNode(compilation, model, switchExpressions[1], @"
ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch {  ... > new B() }')
  Value: 
    ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
  Arms(2):
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => new A()')
        Pattern: 
          IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
            Value: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
        Value: 
          IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 A.op_Implicit(A a)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new A()')
            Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 A.op_Implicit(A a))
            Operand: 
              IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A, IsInvalid) (Syntax: 'new A()')
                Arguments(0)
                Initializer: 
                  null
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => new B()')
        Pattern: 
          IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
        Value: 
          IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 B.op_Implicit(B b)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new B()')
            Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 B.op_Implicit(B b))
            Operand: 
              IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B, IsInvalid) (Syntax: 'new B()')
                Arguments(0)
                Initializer: 
                  null
");
 
            VerifyOperationTreeForNode(compilation, model, switchExpressions[2], @"
ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: ?, IsInvalid) (Syntax: '1 switch {  ... ing.Empty }')
  Value: 
    ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
  Arms(2):
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
        Pattern: 
          IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
            Value: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
        Value: 
          IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: '1')
            Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
            Operand: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
      ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => string.Empty')
        Pattern: 
          IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
        Value: 
          IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: 'string.Empty')
            Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
            Operand: 
              IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String, IsInvalid) (Syntax: 'string.Empty')
                Instance Receiver: 
                  null
");
        }
 
        [Fact]
        public void TargetTypedSwitch_Attribute_NamedArgument()
        {
            var source = @"
using System;
class Program
{
    [My(Value = 1 switch { 1 => 1, _ => 2 })]
    public static void M1() { }
 
    [My(Value = 1 switch { 1 => new A(), _ => new B() })]
    public static void M2() { }
 
    [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
    public static void M3() { }
}
public class MyAttribute : Attribute
{
    public MyAttribute() { }
    public int Value { get; set; }
}
public class A
{
    public static implicit operator int(A a) => 4;
}
public class B
{
    public static implicit operator int(B b) => 2;
}
";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                // (5,17): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
                //     [My(Value = 1 switch { 1 => 1, _ => 2 })]
                Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => 1, _ => 2 }").WithLocation(5, 17),
                // (8,17): error CS0182: An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
                //     [My(Value = 1 switch { 1 => new A(), _ => new B() })]
                Diagnostic(ErrorCode.ERR_BadAttributeArgument, "1 switch { 1 => new A(), _ => new B() }").WithLocation(8, 17),
                // (11,41): error CS0029: Cannot implicitly convert type 'string' to 'int'
                //     [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "string.Empty").WithArguments("string", "int").WithLocation(11, 41)
                );
 
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
 
            var attributeArguments = tree.GetRoot().DescendantNodes().OfType<AttributeArgumentSyntax>().ToArray();
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[0], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... 1, _ => 2 }')
  Left: 
    IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
      Instance Receiver: 
        null
  Right: 
    ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch {  ... 1, _ => 2 }')
      Value: 
        ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
      Arms(2):
          ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => 1')
            Pattern: 
              IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
            Value: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
          ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => 2')
            Pattern: 
              IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
            Value: 
              ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2, IsInvalid) (Syntax: '2')
");
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[1], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... > new B() }')
  Left: 
    IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
      Instance Receiver: 
        null
  Right: 
    IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: '1 switch {  ... > new B() }')
      Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
      Operand: 
        ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: System.Int32, IsInvalid) (Syntax: '1 switch {  ... > new B() }')
          Value: 
            ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
          Arms(2):
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '1 => new A()')
                Pattern: 
                  IConstantPatternOperation (OperationKind.ConstantPattern, Type: null, IsInvalid) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                    Value: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1, IsInvalid) (Syntax: '1')
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 A.op_Implicit(A a)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new A()')
                    Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 A.op_Implicit(A a))
                    Operand: 
                      IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A, IsInvalid) (Syntax: 'new A()')
                        Arguments(0)
                        Initializer: 
                          null
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => new B()')
                Pattern: 
                  IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null, IsInvalid) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperatorMethod: System.Int32 B.op_Implicit(B b)) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: 'new B()')
                    Conversion: CommonConversion (Exists: True, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: True) (MethodSymbol: System.Int32 B.op_Implicit(B b))
                    Operand: 
                      IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B, IsInvalid) (Syntax: 'new B()')
                        Arguments(0)
                        Initializer: 
                          null
");
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[2], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Value = 1 s ... ing.Empty }')
  Left: 
    IPropertyReferenceOperation: System.Int32 MyAttribute.Value { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'Value')
      Instance Receiver: 
        null
  Right: 
    IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: System.Int32, IsInvalid, IsImplicit) (Syntax: '1 switch {  ... ing.Empty }')
      Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
      Operand: 
        ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: ?, IsInvalid) (Syntax: '1 switch {  ... ing.Empty }')
          Value: 
            ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
          Arms(2):
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
                Pattern: 
                  IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                    Value: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null, IsInvalid) (Syntax: '_ => string.Empty')
                Pattern: 
                  IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsInvalid, IsImplicit) (Syntax: 'string.Empty')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String, IsInvalid) (Syntax: 'string.Empty')
                        Instance Receiver: 
                          null
");
        }
 
        [Fact]
        public void TargetTypedSwitch_Attribute_MissingNamedArgument()
        {
            var source = @"
using System;
class Program
{
    [My(Value = 1 switch { 1 => 1, _ => 2 })]
    public static void M1() { }
 
    [My(Value = 1 switch { 1 => new A(), _ => new B() })]
    public static void M2() { }
 
    [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
    public static void M3() { }
}
public class MyAttribute : Attribute
{
    public MyAttribute() { }
}
public class A
{
    public static implicit operator int(A a) => 4;
}
public class B
{
    public static implicit operator int(B b) => 2;
}
";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                // (5,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
                //     [My(Value = 1 switch { 1 => 1, _ => 2 })]
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(5, 9),
                // (8,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
                //     [My(Value = 1 switch { 1 => new A(), _ => new B() })]
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(8, 9),
                // (11,9): error CS0246: The type or namespace name 'Value' could not be found (are you missing a using directive or an assembly reference?)
                //     [My(Value = 1 switch { 1 => 1, _ => string.Empty })]
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Value").WithArguments("Value").WithLocation(11, 9)
                );
 
            var tree = compilation.SyntaxTrees[0];
            var model = compilation.GetSemanticModel(tree);
 
            var attributeArguments = tree.GetRoot().DescendantNodes().OfType<AttributeArgumentSyntax>().ToArray();
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[0], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... 1, _ => 2 }')
  Left: 
    IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
      Children(0)
  Right: 
    IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch {  ... 1, _ => 2 }')
      Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
      Operand: 
        ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: System.Int32) (Syntax: '1 switch {  ... 1, _ => 2 }')
          Value: 
            ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
          Arms(2):
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
                Pattern: 
                  IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                    Value: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
                Value: 
                  ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => 2')
                Pattern: 
                  IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 2) (Syntax: '2')
");
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[1], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... > new B() }')
  Left: 
    IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
      Children(0)
  Right: 
    IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch {  ... > new B() }')
      Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
      Operand: 
        ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: ?) (Syntax: '1 switch {  ... > new B() }')
          Value: 
            ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
          Arms(2):
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => new A()')
                Pattern: 
                  IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                    Value: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'new A()')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      IObjectCreationOperation (Constructor: A..ctor()) (OperationKind.ObjectCreation, Type: A) (Syntax: 'new A()')
                        Arguments(0)
                        Initializer: 
                          null
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => new B()')
                Pattern: 
                  IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'new B()')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      IObjectCreationOperation (Constructor: B..ctor()) (OperationKind.ObjectCreation, Type: B) (Syntax: 'new B()')
                        Arguments(0)
                        Initializer: 
                          null
");
 
            VerifyOperationTreeForNode(compilation, model, attributeArguments[2], @"
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: ?, IsInvalid) (Syntax: 'Value = 1 s ... ing.Empty }')
  Left: 
    IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'Value')
      Children(0)
  Right: 
    IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1 switch {  ... ing.Empty }')
      Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
      Operand: 
        ISwitchExpressionOperation (2 arms, IsExhaustive: True) (OperationKind.SwitchExpression, Type: ?) (Syntax: '1 switch {  ... ing.Empty }')
          Value: 
            ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
          Arms(2):
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '1 => 1')
                Pattern: 
                  IConstantPatternOperation (OperationKind.ConstantPattern, Type: null) (Syntax: '1') (InputType: System.Int32, NarrowedType: System.Int32)
                    Value: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: '1')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
              ISwitchExpressionArmOperation (0 locals) (OperationKind.SwitchExpressionArm, Type: null) (Syntax: '_ => string.Empty')
                Pattern: 
                  IDiscardPatternOperation (OperationKind.DiscardPattern, Type: null) (Syntax: '_') (InputType: System.Int32, NarrowedType: System.Int32)
                Value: 
                  IConversionOperation (TryCast: False, Unchecked) (OperationKind.Conversion, Type: ?, IsImplicit) (Syntax: 'string.Empty')
                    Conversion: CommonConversion (Exists: False, IsIdentity: False, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
                    Operand: 
                      IFieldReferenceOperation: System.String System.String.Empty (Static) (OperationKind.FieldReference, Type: System.String) (Syntax: 'string.Empty')
                        Instance Receiver: 
                          null
");
        }
 
        [Fact]
        public void TargetTypedSwitch_As()
        {
            var source = @"
class Program
{
    public static void M(int i, string s)
    {
        // we do not target-type the left-hand-side of an as expression
        _ = i switch { 1 => i, _ => s } as object;
    }
}
";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                // (7,15): error CS8506: No best type was found for the switch expression.
                //         _ = i switch { 1 => i, _ => s } as object;
                Diagnostic(ErrorCode.ERR_SwitchExpressionNoBestType, "switch").WithLocation(7, 15)
                );
        }
 
        [Fact]
        public void TargetTypedSwitch_DoubleConversion()
        {
            var source = @"using System;
class Program
{
    public static void Main(string[] args)
    {
        M(false);
        M(true);
    }
    public static void M(bool b)
    {
        C c = b switch { false => new A(), true => new B() };
        Console.WriteLine(""."");
    }
}
class A
{
    public A()
    {
        Console.Write(""new A; "");
    }
    public static implicit operator B(A a)
    {
        Console.Write(""A->"");
        return new B();
    }
}
class B
{
    public B()
    {
        Console.Write(""new B; "");
    }
    public static implicit operator C(B a)
    {
        Console.Write(""B->"");
        return new C();
    }
}
class C
{
    public C()
    {
        Console.Write(""new C; "");
    }
}
";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe);
            compilation.VerifyDiagnostics();
            var expectedOutput =
@"new A; A->new B; B->new C; .
new B; B->new C; .";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void TargetTypedSwitch_StringInsert()
        {
            var source = @"
using System;
class Program
{
    public static void Main()
    {
        Console.Write($""{false switch { false => new A(), true => new B() }}"");
        Console.Write($""{true switch { false => new A(), true => new B() }}"");
    }
}
class A
{
}
class B
{
}
";
            var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe);
            compilation.VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: "AB");
        }
 
        #endregion Target Typed Switch
 
        #region Pattern Combinators
 
        [Fact]
        public void IsPatternDisjunct_01()
        {
            var source = @"
using System;
class C
{
    static bool M1(object o) => o is int or long;
    static bool M2(object o) => o is int || o is long;
    public static void Main()
    {
        Console.Write(M1(1));
        Console.Write(M1(string.Empty));
        Console.Write(M1(1L));
        Console.Write(M1(1UL));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"TrueFalseTrueFalse";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", """
{
  // Code size       26 (0x1a)
  .maxstack  1
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0012
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  brtrue.s   IL_0012
  IL_0010:  br.s       IL_0016
  IL_0012:  ldc.i4.1
  IL_0013:  stloc.0
  IL_0014:  br.s       IL_0018
  IL_0016:  ldc.i4.0
  IL_0017:  stloc.0
  IL_0018:  ldloc.0
  IL_0019:  ret
}
""");
            compVerifier.VerifyIL("C.M2", """
{
  // Code size       21 (0x15)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0013
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  ldnull
  IL_000f:  cgt.un
  IL_0011:  br.s       IL_0014
  IL_0013:  ldc.i4.1
  IL_0014:  ret
}
""");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", """
{
  // Code size       24 (0x18)
  .maxstack  1
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0010
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  brfalse.s  IL_0014
  IL_0010:  ldc.i4.1
  IL_0011:  stloc.0
  IL_0012:  br.s       IL_0016
  IL_0014:  ldc.i4.0
  IL_0015:  stloc.0
  IL_0016:  ldloc.0
  IL_0017:  ret
}
""");
            compVerifier.VerifyIL("C.M2", @"
{
  // Code size       20 (0x14)
  .maxstack  2
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""int""
  IL_0006:  brtrue.s   IL_0012
  IL_0008:  ldarg.0
  IL_0009:  isinst     ""long""
  IL_000e:  ldnull
  IL_000f:  cgt.un
  IL_0011:  ret
  IL_0012:  ldc.i4.1
  IL_0013:  ret
}
");
        }
 
        [Fact]
        public void IsPatternDisjunct_02()
        {
            var source = @"
using System;
class C
{
    static string M1(object o) => (o is int or long) ? ""True"" : ""False"";
    static string M2(object o) => (o is int || o is long) ? ""True"" : ""False"";
    public static void Main()
    {
        Console.Write(M1(1));
        Console.Write(M1(string.Empty));
        Console.Write(M1(1L));
        Console.Write(M1(1UL));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"TrueFalseTrueFalse";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", """
{
  // Code size       40 (0x28)
  .maxstack  1
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0012
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  brtrue.s   IL_0012
  IL_0010:  br.s       IL_0016
  IL_0012:  ldc.i4.1
  IL_0013:  stloc.0
  IL_0014:  br.s       IL_0018
  IL_0016:  ldc.i4.0
  IL_0017:  stloc.0
  IL_0018:  ldloc.0
  IL_0019:  brtrue.s   IL_0022
  IL_001b:  ldstr      "False"
  IL_0020:  br.s       IL_0027
  IL_0022:  ldstr      "True"
  IL_0027:  ret
}
""");
            compVerifier.VerifyIL("C.M2", """
{
  // Code size       29 (0x1d)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0017
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  brtrue.s   IL_0017
  IL_0010:  ldstr      "False"
  IL_0015:  br.s       IL_001c
  IL_0017:  ldstr      "True"
  IL_001c:  ret
}
""");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", """
{
  // Code size       37 (0x25)
  .maxstack  1
  .locals init (bool V_0)
  IL_0000:  ldarg.0
  IL_0001:  isinst     "int"
  IL_0006:  brtrue.s   IL_0010
  IL_0008:  ldarg.0
  IL_0009:  isinst     "long"
  IL_000e:  brfalse.s  IL_0014
  IL_0010:  ldc.i4.1
  IL_0011:  stloc.0
  IL_0012:  br.s       IL_0016
  IL_0014:  ldc.i4.0
  IL_0015:  stloc.0
  IL_0016:  ldloc.0
  IL_0017:  brtrue.s   IL_001f
  IL_0019:  ldstr      "False"
  IL_001e:  ret
  IL_001f:  ldstr      "True"
  IL_0024:  ret
}
""");
            compVerifier.VerifyIL("C.M2", @"
{
  // Code size       28 (0x1c)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  isinst     ""int""
  IL_0006:  brtrue.s   IL_0016
  IL_0008:  ldarg.0
  IL_0009:  isinst     ""long""
  IL_000e:  brtrue.s   IL_0016
  IL_0010:  ldstr      ""False""
  IL_0015:  ret
  IL_0016:  ldstr      ""True""
  IL_001b:  ret
}
");
        }
 
        [Fact]
        public void IsPatternDisjunct_03()
        {
            var source = @"
using System;
class C
{
    static bool M1(object o) => o is >= 'A' and <= 'Z' or >= 'a' and <= 'z';
    static bool M2(object o) => o is char c && (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z');
    public static void Main()
    {
        Console.Write(M1('A'));
        Console.Write(M1('0'));
        Console.Write(M1('q'));
        Console.Write(M1(2));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"TrueFalseTrueFalse";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       47 (0x2f)
      .maxstack  2
      .locals init (char V_0,
                    bool V_1)
      IL_0000:  ldarg.0
      IL_0001:  isinst     ""char""
      IL_0006:  brfalse.s  IL_002b
      IL_0008:  ldarg.0
      IL_0009:  unbox.any  ""char""
      IL_000e:  stloc.0
      IL_000f:  ldloc.0
      IL_0010:  ldc.i4.s   97
      IL_0012:  blt.s      IL_001b
      IL_0014:  ldloc.0
      IL_0015:  ldc.i4.s   122
      IL_0017:  ble.s      IL_0027
      IL_0019:  br.s       IL_002b
      IL_001b:  ldloc.0
      IL_001c:  ldc.i4.s   65
      IL_001e:  blt.s      IL_002b
      IL_0020:  ldloc.0
      IL_0021:  ldc.i4.s   90
      IL_0023:  ble.s      IL_0027
      IL_0025:  br.s       IL_002b
      IL_0027:  ldc.i4.1
      IL_0028:  stloc.1
      IL_0029:  br.s       IL_002d
      IL_002b:  ldc.i4.0
      IL_002c:  stloc.1
      IL_002d:  ldloc.1
      IL_002e:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       48 (0x30)
      .maxstack  2
      .locals init (char V_0) //c
      IL_0000:  ldarg.0
      IL_0001:  isinst     ""char""
      IL_0006:  brfalse.s  IL_002e
      IL_0008:  ldarg.0
      IL_0009:  unbox.any  ""char""
      IL_000e:  stloc.0
      IL_000f:  ldloc.0
      IL_0010:  ldc.i4.s   65
      IL_0012:  blt.s      IL_0019
      IL_0014:  ldloc.0
      IL_0015:  ldc.i4.s   90
      IL_0017:  ble.s      IL_002b
      IL_0019:  ldloc.0
      IL_001a:  ldc.i4.s   97
      IL_001c:  blt.s      IL_0028
      IL_001e:  ldloc.0
      IL_001f:  ldc.i4.s   122
      IL_0021:  cgt
      IL_0023:  ldc.i4.0
      IL_0024:  ceq
      IL_0026:  br.s       IL_0029
      IL_0028:  ldc.i4.0
      IL_0029:  br.s       IL_002c
      IL_002b:  ldc.i4.1
      IL_002c:  br.s       IL_002f
      IL_002e:  ldc.i4.0
      IL_002f:  ret
    }
");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       45 (0x2d)
      .maxstack  2
      .locals init (char V_0,
                    bool V_1)
      IL_0000:  ldarg.0
      IL_0001:  isinst     ""char""
      IL_0006:  brfalse.s  IL_0029
      IL_0008:  ldarg.0
      IL_0009:  unbox.any  ""char""
      IL_000e:  stloc.0
      IL_000f:  ldloc.0
      IL_0010:  ldc.i4.s   97
      IL_0012:  blt.s      IL_001b
      IL_0014:  ldloc.0
      IL_0015:  ldc.i4.s   122
      IL_0017:  ble.s      IL_0025
      IL_0019:  br.s       IL_0029
      IL_001b:  ldloc.0
      IL_001c:  ldc.i4.s   65
      IL_001e:  blt.s      IL_0029
      IL_0020:  ldloc.0
      IL_0021:  ldc.i4.s   90
      IL_0023:  bgt.s      IL_0029
      IL_0025:  ldc.i4.1
      IL_0026:  stloc.1
      IL_0027:  br.s       IL_002b
      IL_0029:  ldc.i4.0
      IL_002a:  stloc.1
      IL_002b:  ldloc.1
      IL_002c:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       45 (0x2d)
      .maxstack  2
      .locals init (char V_0) //c
      IL_0000:  ldarg.0
      IL_0001:  isinst     ""char""
      IL_0006:  brfalse.s  IL_002b
      IL_0008:  ldarg.0
      IL_0009:  unbox.any  ""char""
      IL_000e:  stloc.0
      IL_000f:  ldloc.0
      IL_0010:  ldc.i4.s   65
      IL_0012:  blt.s      IL_0019
      IL_0014:  ldloc.0
      IL_0015:  ldc.i4.s   90
      IL_0017:  ble.s      IL_0029
      IL_0019:  ldloc.0
      IL_001a:  ldc.i4.s   97
      IL_001c:  blt.s      IL_0027
      IL_001e:  ldloc.0
      IL_001f:  ldc.i4.s   122
      IL_0021:  cgt
      IL_0023:  ldc.i4.0
      IL_0024:  ceq
      IL_0026:  ret
      IL_0027:  ldc.i4.0
      IL_0028:  ret
      IL_0029:  ldc.i4.1
      IL_002a:  ret
      IL_002b:  ldc.i4.0
      IL_002c:  ret
    }
");
        }
 
        [Fact]
        public void IsPatternDisjunct_04()
        {
            var source = @"
using System;
class C
{
    static int M1(char c) => (c is >= 'A' and <= 'Z' or >= 'a' and <= 'z') ? 1 : 0;
    static int M2(char c) => (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') ? 1 : 0;
    public static void Main()
    {
        Console.Write(M1('A'));
        Console.Write(M1('0'));
        Console.Write(M1('q'));
        Console.Write(M1(' '));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"1010";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       38 (0x26)
      .maxstack  2
      .locals init (bool V_0)
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   97
      IL_0003:  blt.s      IL_000c
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   122
      IL_0008:  ble.s      IL_0018
      IL_000a:  br.s       IL_001c
      IL_000c:  ldarg.0
      IL_000d:  ldc.i4.s   65
      IL_000f:  blt.s      IL_001c
      IL_0011:  ldarg.0
      IL_0012:  ldc.i4.s   90
      IL_0014:  ble.s      IL_0018
      IL_0016:  br.s       IL_001c
      IL_0018:  ldc.i4.1
      IL_0019:  stloc.0
      IL_001a:  br.s       IL_001e
      IL_001c:  ldc.i4.0
      IL_001d:  stloc.0
      IL_001e:  ldloc.0
      IL_001f:  brtrue.s   IL_0024
      IL_0021:  ldc.i4.0
      IL_0022:  br.s       IL_0025
      IL_0024:  ldc.i4.1
      IL_0025:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       25 (0x19)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   65
      IL_0003:  blt.s      IL_000a
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   90
      IL_0008:  ble.s      IL_0017
      IL_000a:  ldarg.0
      IL_000b:  ldc.i4.s   97
      IL_000d:  blt.s      IL_0014
      IL_000f:  ldarg.0
      IL_0010:  ldc.i4.s   122
      IL_0012:  ble.s      IL_0017
      IL_0014:  ldc.i4.0
      IL_0015:  br.s       IL_0018
      IL_0017:  ldc.i4.1
      IL_0018:  ret
    }
");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       33 (0x21)
      .maxstack  2
      .locals init (bool V_0)
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   97
      IL_0003:  blt.s      IL_000c
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   122
      IL_0008:  ble.s      IL_0016
      IL_000a:  br.s       IL_001a
      IL_000c:  ldarg.0
      IL_000d:  ldc.i4.s   65
      IL_000f:  blt.s      IL_001a
      IL_0011:  ldarg.0
      IL_0012:  ldc.i4.s   90
      IL_0014:  bgt.s      IL_001a
      IL_0016:  ldc.i4.1
      IL_0017:  stloc.0
      IL_0018:  br.s       IL_001c
      IL_001a:  ldc.i4.0
      IL_001b:  stloc.0
      IL_001c:  ldloc.0
      IL_001d:  ldc.i4.0
      IL_001e:  cgt.un
      IL_0020:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       24 (0x18)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   65
      IL_0003:  blt.s      IL_000a
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   90
      IL_0008:  ble.s      IL_0016
      IL_000a:  ldarg.0
      IL_000b:  ldc.i4.s   97
      IL_000d:  blt.s      IL_0014
      IL_000f:  ldarg.0
      IL_0010:  ldc.i4.s   122
      IL_0012:  ble.s      IL_0016
      IL_0014:  ldc.i4.0
      IL_0015:  ret
      IL_0016:  ldc.i4.1
      IL_0017:  ret
    }
");
        }
 
        [Fact]
        public void IsPatternDisjunct_05()
        {
            var source = @"
using System;
class C
{
    static int M1(char c)
    {
        if (c is >= 'A' and <= 'Z' or >= 'a' and <= 'z')
            return 1;
        else
            return 0;
    }
    static int M2(char c)
    {
        if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')
            return 1;
        else
            return 0;
    }
    public static void Main()
    {
        Console.Write(M1('A'));
        Console.Write(M1('0'));
        Console.Write(M1('q'));
        Console.Write(M1(' '));
    }
}";
            var compilation = CreateCompilation(source, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            var expectedOutput = @"1010";
            var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       46 (0x2e)
      .maxstack  2
      .locals init (bool V_0,
                    bool V_1,
                    int V_2)
      IL_0000:  nop
      IL_0001:  ldarg.0
      IL_0002:  ldc.i4.s   97
      IL_0004:  blt.s      IL_000d
      IL_0006:  ldarg.0
      IL_0007:  ldc.i4.s   122
      IL_0009:  ble.s      IL_0019
      IL_000b:  br.s       IL_001d
      IL_000d:  ldarg.0
      IL_000e:  ldc.i4.s   65
      IL_0010:  blt.s      IL_001d
      IL_0012:  ldarg.0
      IL_0013:  ldc.i4.s   90
      IL_0015:  ble.s      IL_0019
      IL_0017:  br.s       IL_001d
      IL_0019:  ldc.i4.1
      IL_001a:  stloc.0
      IL_001b:  br.s       IL_001f
      IL_001d:  ldc.i4.0
      IL_001e:  stloc.0
      IL_001f:  ldloc.0
      IL_0020:  stloc.1
      IL_0021:  ldloc.1
      IL_0022:  brfalse.s  IL_0028
      IL_0024:  ldc.i4.1
      IL_0025:  stloc.2
      IL_0026:  br.s       IL_002c
      IL_0028:  ldc.i4.0
      IL_0029:  stloc.2
      IL_002a:  br.s       IL_002c
      IL_002c:  ldloc.2
      IL_002d:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       44 (0x2c)
      .maxstack  2
      .locals init (bool V_0,
                    int V_1)
      IL_0000:  nop
      IL_0001:  ldarg.0
      IL_0002:  ldc.i4.s   65
      IL_0004:  blt.s      IL_000b
      IL_0006:  ldarg.0
      IL_0007:  ldc.i4.s   90
      IL_0009:  ble.s      IL_001d
      IL_000b:  ldarg.0
      IL_000c:  ldc.i4.s   97
      IL_000e:  blt.s      IL_001a
      IL_0010:  ldarg.0
      IL_0011:  ldc.i4.s   122
      IL_0013:  cgt
      IL_0015:  ldc.i4.0
      IL_0016:  ceq
      IL_0018:  br.s       IL_001b
      IL_001a:  ldc.i4.0
      IL_001b:  br.s       IL_001e
      IL_001d:  ldc.i4.1
      IL_001e:  stloc.0
      IL_001f:  ldloc.0
      IL_0020:  brfalse.s  IL_0026
      IL_0022:  ldc.i4.1
      IL_0023:  stloc.1
      IL_0024:  br.s       IL_002a
      IL_0026:  ldc.i4.0
      IL_0027:  stloc.1
      IL_0028:  br.s       IL_002a
      IL_002a:  ldloc.1
      IL_002b:  ret
    }
");
 
            compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
            compilation.VerifyDiagnostics();
            compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
            compVerifier.VerifyIL("C.M1", @"
    {
      // Code size       35 (0x23)
      .maxstack  2
      .locals init (bool V_0)
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   97
      IL_0003:  blt.s      IL_000c
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   122
      IL_0008:  ble.s      IL_0016
      IL_000a:  br.s       IL_001a
      IL_000c:  ldarg.0
      IL_000d:  ldc.i4.s   65
      IL_000f:  blt.s      IL_001a
      IL_0011:  ldarg.0
      IL_0012:  ldc.i4.s   90
      IL_0014:  bgt.s      IL_001a
      IL_0016:  ldc.i4.1
      IL_0017:  stloc.0
      IL_0018:  br.s       IL_001c
      IL_001a:  ldc.i4.0
      IL_001b:  stloc.0
      IL_001c:  ldloc.0
      IL_001d:  brfalse.s  IL_0021
      IL_001f:  ldc.i4.1
      IL_0020:  ret
      IL_0021:  ldc.i4.0
      IL_0022:  ret
    }
");
            compVerifier.VerifyIL("C.M2", @"
    {
      // Code size       24 (0x18)
      .maxstack  2
      IL_0000:  ldarg.0
      IL_0001:  ldc.i4.s   65
      IL_0003:  blt.s      IL_000a
      IL_0005:  ldarg.0
      IL_0006:  ldc.i4.s   90
      IL_0008:  ble.s      IL_0014
      IL_000a:  ldarg.0
      IL_000b:  ldc.i4.s   97
      IL_000d:  blt.s      IL_0016
      IL_000f:  ldarg.0
      IL_0010:  ldc.i4.s   122
      IL_0012:  bgt.s      IL_0016
      IL_0014:  ldc.i4.1
      IL_0015:  ret
      IL_0016:  ldc.i4.0
      IL_0017:  ret
    }
");
        }
 
        [Fact, WorkItem(46536, "https://github.com/dotnet/roslyn/issues/46536")]
        public void MultiplePathsToNode_SwitchDispatch_01()
        {
            var source = @"
using System;
 
class Program
{
    static void Main()
    {
        Console.Write(M("""", 0)); // 0
        Console.Write(M("""", 1)); // 1
        Console.Write(M("""", 2)); // 2
        Console.Write(M("""", 3)); // 3
        Console.Write(M(""a"", 2)); // 2
        Console.Write(M(""a"", 10)); // 3
    }
 
    static int M(string x, int y)
    {
        return (x, y) switch
        {
            ("""", 0) => 0,
            ("""", 1) => 1,
            (_, 2) => 2,
            _ => 3
        };
    }
}
";
            var verifier = CompileAndVerify(source, expectedOutput: "012323", options: TestOptions.DebugExe);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Program.M", @"{
  // Code size       70 (0x46)
  .maxstack  2
  .locals init (int V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  brtrue.s   IL_0005
  IL_0004:  nop
  IL_0005:  ldarg.0
  IL_0006:  ldstr      """"
  IL_000b:  call       ""bool string.op_Equality(string, string)""
  IL_0010:  brfalse.s  IL_0026
  IL_0012:  ldarg.1
  IL_0013:  switch    (
        IL_002c,
        IL_0030,
        IL_0034)
  IL_0024:  br.s       IL_0038
  IL_0026:  ldarg.1
  IL_0027:  ldc.i4.2
  IL_0028:  beq.s      IL_0034
  IL_002a:  br.s       IL_0038
  IL_002c:  ldc.i4.0
  IL_002d:  stloc.0
  IL_002e:  br.s       IL_003c
  IL_0030:  ldc.i4.1
  IL_0031:  stloc.0
  IL_0032:  br.s       IL_003c
  IL_0034:  ldc.i4.2
  IL_0035:  stloc.0
  IL_0036:  br.s       IL_003c
  IL_0038:  ldc.i4.3
  IL_0039:  stloc.0
  IL_003a:  br.s       IL_003c
  IL_003c:  ldc.i4.1
  IL_003d:  brtrue.s   IL_0040
  IL_003f:  nop
  IL_0040:  ldloc.0
  IL_0041:  stloc.1
  IL_0042:  br.s       IL_0044
  IL_0044:  ldloc.1
  IL_0045:  ret
}");
        }
 
        [Fact, WorkItem(46536, "https://github.com/dotnet/roslyn/issues/46536")]
        public void MultiplePathsToNode_SwitchDispatch_02()
        {
            var source = @"
using System;
 
class Program
{
    static void Main()
    {
        Console.Write(M0("""", 0)); // 0
        Console.Write(M0("""", 1)); // 1
        Console.Write(M0("""", 2)); // 2
        Console.Write(M0("""", 3)); // 3
        Console.Write(M0(""a"", 2)); // 2
        Console.Write(M0(""a"", 10)); // 3
    }
 
    static int M0(string x, int y)
    {
        return (x, y) switch
        {
            ("""", 0) => M1(0),
            ("""", 1) => M1(1),
            (_, 2) => M1(2),
            _ => M1(3)
        };
    }
 
    static int M1(int z)
    {
        Console.Write(' ');
        return z;
    }
}
";
            var verifier = CompileAndVerify(source, expectedOutput: " 0 1 2 3 2 3", options: TestOptions.DebugExe);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Program.M0", @"{
  // Code size       90 (0x5a)
  .maxstack  2
  .locals init (int V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  brtrue.s   IL_0005
  IL_0004:  nop
  IL_0005:  ldarg.0
  IL_0006:  ldstr      """"
  IL_000b:  call       ""bool string.op_Equality(string, string)""
  IL_0010:  brfalse.s  IL_0026
  IL_0012:  ldarg.1
  IL_0013:  switch    (
        IL_002c,
        IL_0035,
        IL_003e)
  IL_0024:  br.s       IL_0047
  IL_0026:  ldarg.1
  IL_0027:  ldc.i4.2
  IL_0028:  beq.s      IL_003e
  IL_002a:  br.s       IL_0047
  IL_002c:  ldc.i4.0
  IL_002d:  call       ""int Program.M1(int)""
  IL_0032:  stloc.0
  IL_0033:  br.s       IL_0050
  IL_0035:  ldc.i4.1
  IL_0036:  call       ""int Program.M1(int)""
  IL_003b:  stloc.0
  IL_003c:  br.s       IL_0050
  IL_003e:  ldc.i4.2
  IL_003f:  call       ""int Program.M1(int)""
  IL_0044:  stloc.0
  IL_0045:  br.s       IL_0050
  IL_0047:  ldc.i4.3
  IL_0048:  call       ""int Program.M1(int)""
  IL_004d:  stloc.0
  IL_004e:  br.s       IL_0050
  IL_0050:  ldc.i4.1
  IL_0051:  brtrue.s   IL_0054
  IL_0053:  nop
  IL_0054:  ldloc.0
  IL_0055:  stloc.1
  IL_0056:  br.s       IL_0058
  IL_0058:  ldloc.1
  IL_0059:  ret
}");
        }
 
        [Fact, WorkItem(46536, "https://github.com/dotnet/roslyn/issues/46536")]
        public void MultiplePathsToNode_SwitchDispatch_03()
        {
            var source = @"
using System;
 
class Program
{
    static void Main()
    {
        Console.Write(M("""", 0)); // 0
        Console.Write(M("""", 1)); // 1
        Console.Write(M("""", 2)); // 2
        Console.Write(M("""", 3)); // 3
        Console.Write(M("""", 4)); // 4
        Console.Write(M("""", 5)); // 5
        Console.Write(M(""a"", 2)); // 2
        Console.Write(M(""a"", 3)); // 3
        Console.Write(M(""a"", 4)); // 4
        Console.Write(M(""a"", 10)); // 5
    }
 
    static int M(string x, int y)
    {
        return (x, y) switch
        {
            ("""", 0) => 0,
            ("""", 1) => 1,
            (_, 2) => 2,
            (_, 3) => 3,
            (_, 4) => 4,
            _ => 5
        };
    }
}
";
            var verifier = CompileAndVerify(source, expectedOutput: "0123452345", options: TestOptions.DebugExe);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Program.M", @"{
  // Code size       98 (0x62)
  .maxstack  2
  .locals init (int V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  brtrue.s   IL_0005
  IL_0004:  nop
  IL_0005:  ldarg.0
  IL_0006:  ldstr      """"
  IL_000b:  call       ""bool string.op_Equality(string, string)""
  IL_0010:  brfalse.s  IL_002e
  IL_0012:  ldarg.1
  IL_0013:  switch    (
        IL_0040,
        IL_0044,
        IL_0048,
        IL_004c,
        IL_0050)
  IL_002c:  br.s       IL_0054
  IL_002e:  ldarg.1
  IL_002f:  ldc.i4.2
  IL_0030:  beq.s      IL_0048
  IL_0032:  br.s       IL_0034
  IL_0034:  ldarg.1
  IL_0035:  ldc.i4.3
  IL_0036:  beq.s      IL_004c
  IL_0038:  br.s       IL_003a
  IL_003a:  ldarg.1
  IL_003b:  ldc.i4.4
  IL_003c:  beq.s      IL_0050
  IL_003e:  br.s       IL_0054
  IL_0040:  ldc.i4.0
  IL_0041:  stloc.0
  IL_0042:  br.s       IL_0058
  IL_0044:  ldc.i4.1
  IL_0045:  stloc.0
  IL_0046:  br.s       IL_0058
  IL_0048:  ldc.i4.2
  IL_0049:  stloc.0
  IL_004a:  br.s       IL_0058
  IL_004c:  ldc.i4.3
  IL_004d:  stloc.0
  IL_004e:  br.s       IL_0058
  IL_0050:  ldc.i4.4
  IL_0051:  stloc.0
  IL_0052:  br.s       IL_0058
  IL_0054:  ldc.i4.5
  IL_0055:  stloc.0
  IL_0056:  br.s       IL_0058
  IL_0058:  ldc.i4.1
  IL_0059:  brtrue.s   IL_005c
  IL_005b:  nop
  IL_005c:  ldloc.0
  IL_005d:  stloc.1
  IL_005e:  br.s       IL_0060
  IL_0060:  ldloc.1
  IL_0061:  ret
}");
        }
 
        [Fact, WorkItem(46536, "https://github.com/dotnet/roslyn/issues/46536")]
        public void MultiplePathsToNode_SwitchDispatch_04()
        {
            var source = @"
using System;
 
class Program
{
    static void Main()
    {
        Console.Write(M(""a"", ""x"")); // 0
        Console.Write(M(""a"", ""y"")); // 1
        Console.Write(M(""a"", ""z"")); // 2
        Console.Write(M(""a"", ""w"")); // 3
        Console.Write(M(""b"", ""z"")); // 2
        Console.Write(M(""c"", ""z"")); // 3
        Console.Write(M(""c"", ""w"")); // 3
    }
 
    static int M(string x, string y)
    {
        return (x, y) switch
        {
            (""a"", ""x"") => 0,
            (""a"", ""y"") => 1,
            (""a"" or ""b"", ""z"") => 2,
            _ => 3
        };
    }
}
";
            var verifier = CompileAndVerify(source, expectedOutput: "0123233", options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Program.M", @"{
  // Code size      115 (0x73)
  .maxstack  2
  .locals init (int V_0,
                int V_1)
  IL_0000:  nop
  IL_0001:  ldc.i4.1
  IL_0002:  brtrue.s   IL_0005
  IL_0004:  nop
  IL_0005:  ldarg.0
  IL_0006:  ldstr      ""a""
  IL_000b:  call       ""bool string.op_Equality(string, string)""
  IL_0010:  brtrue.s   IL_0021
  IL_0012:  ldarg.0
  IL_0013:  ldstr      ""b""
  IL_0018:  call       ""bool string.op_Equality(string, string)""
  IL_001d:  brtrue.s   IL_004a
  IL_001f:  br.s       IL_0065
  IL_0021:  ldarg.1
  IL_0022:  ldstr      ""z""
  IL_0027:  call       ""bool string.op_Equality(string, string)""
  IL_002c:  brtrue.s   IL_0061
  IL_002e:  ldarg.1
  IL_002f:  ldstr      ""x""
  IL_0034:  call       ""bool string.op_Equality(string, string)""
  IL_0039:  brtrue.s   IL_0059
  IL_003b:  ldarg.1
  IL_003c:  ldstr      ""y""
  IL_0041:  call       ""bool string.op_Equality(string, string)""
  IL_0046:  brtrue.s   IL_005d
  IL_0048:  br.s       IL_0065
  IL_004a:  ldarg.1
  IL_004b:  ldstr      ""z""
  IL_0050:  call       ""bool string.op_Equality(string, string)""
  IL_0055:  brtrue.s   IL_0061
  IL_0057:  br.s       IL_0065
  IL_0059:  ldc.i4.0
  IL_005a:  stloc.0
  IL_005b:  br.s       IL_0069
  IL_005d:  ldc.i4.1
  IL_005e:  stloc.0
  IL_005f:  br.s       IL_0069
  IL_0061:  ldc.i4.2
  IL_0062:  stloc.0
  IL_0063:  br.s       IL_0069
  IL_0065:  ldc.i4.3
  IL_0066:  stloc.0
  IL_0067:  br.s       IL_0069
  IL_0069:  ldc.i4.1
  IL_006a:  brtrue.s   IL_006d
  IL_006c:  nop
  IL_006d:  ldloc.0
  IL_006e:  stloc.1
  IL_006f:  br.s       IL_0071
  IL_0071:  ldloc.1
  IL_0072:  ret
}");
        }
 
        [Fact, WorkItem(46536, "https://github.com/dotnet/roslyn/issues/46536")]
        public void MultiplePathsToNode_SwitchDispatch_05()
        {
            var source = @"
using System;
 
public enum EnumA { A, B, C }
 
public enum EnumB { X, Y, Z }
 
public class Class1
{
    public string Repro(EnumA a, EnumB b)
        => (a, b) switch
        {
            (EnumA.A, EnumB.X) => ""AX"",
            (_, EnumB.Y) => ""_Y"",
            (EnumA.B, EnumB.X) => ""BZ"",
            (_, EnumB.Z) => ""_Z"",
            (_, _) => throw new ArgumentException()
        };
}
";
            var verifier = CompileAndVerify(source, options: TestOptions.DebugDll);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Class1.Repro", @"{
  // Code size       90 (0x5a)
  .maxstack  2
  .locals init (string V_0)
  IL_0000:  ldc.i4.1
  IL_0001:  brtrue.s   IL_0004
  IL_0003:  nop
  IL_0004:  ldarg.1
  IL_0005:  brtrue.s   IL_001b
  IL_0007:  ldarg.2
  IL_0008:  switch    (
        IL_002e,
        IL_0036,
        IL_0046)
  IL_0019:  br.s       IL_004e
  IL_001b:  ldarg.2
  IL_001c:  ldc.i4.1
  IL_001d:  beq.s      IL_0036
  IL_001f:  ldarg.1
  IL_0020:  ldc.i4.1
  IL_0021:  bne.un.s   IL_0028
  IL_0023:  ldarg.2
  IL_0024:  brfalse.s  IL_003e
  IL_0026:  br.s       IL_0028
  IL_0028:  ldarg.2
  IL_0029:  ldc.i4.2
  IL_002a:  beq.s      IL_0046
  IL_002c:  br.s       IL_004e
  IL_002e:  ldstr      ""AX""
  IL_0033:  stloc.0
  IL_0034:  br.s       IL_0054
  IL_0036:  ldstr      ""_Y""
  IL_003b:  stloc.0
  IL_003c:  br.s       IL_0054
  IL_003e:  ldstr      ""BZ""
  IL_0043:  stloc.0
  IL_0044:  br.s       IL_0054
  IL_0046:  ldstr      ""_Z""
  IL_004b:  stloc.0
  IL_004c:  br.s       IL_0054
  IL_004e:  newobj     ""System.ArgumentException..ctor()""
  IL_0053:  throw
  IL_0054:  ldc.i4.1
  IL_0055:  brtrue.s   IL_0058
  IL_0057:  nop
  IL_0058:  ldloc.0
  IL_0059:  ret
}");
        }
 
        #endregion Pattern Combinators
 
        [Fact, WorkItem(62563, "https://github.com/dotnet/roslyn/issues/62563")]
        public void AssignToStructFieldOnClassTypeThroughCall_01()
        {
            var source = @"
using System;
 
struct Inner
{
    public int Value { get; set; }
}
 
class Outer
{
    public Inner Inner;
}
 
class Program
{
    static T Id<T>(T t) => t;
 
    static void Main()
    {
        var outer = new Outer();
        Console.Write(outer.Inner.Value);
 
        M1(outer);
        M2(outer);
    }
 
    static void M1(Outer outer)
    {
        Id(outer).Inner.Value = 1;
        Console.Write(outer.Inner.Value);
    }
 
    static void M2(Outer outer)
    {
        Id(outer).Inner.Value = outer switch
        {
            _ => 2
        };
        Console.Write(outer.Inner.Value);
    }
}
";
            var verifier = CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: "012");
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Program.M1", """
            {
              // Code size       37 (0x25)
              .maxstack  2
              IL_0000:  nop
              IL_0001:  ldarg.0
              IL_0002:  call       "Outer Program.Id<Outer>(Outer)"
              IL_0007:  ldflda     "Inner Outer.Inner"
              IL_000c:  ldc.i4.1
              IL_000d:  call       "void Inner.Value.set"
              IL_0012:  nop
              IL_0013:  ldarg.0
              IL_0014:  ldflda     "Inner Outer.Inner"
              IL_0019:  call       "readonly int Inner.Value.get"
              IL_001e:  call       "void System.Console.Write(int)"
              IL_0023:  nop
              IL_0024:  ret
            }
            """);
 
            verifier.VerifyIL("Program.M2", """
            {
              // Code size       53 (0x35)
              .maxstack  2
              .locals init (Outer V_0,
                            int V_1)
              IL_0000:  nop
              IL_0001:  ldarg.0
              IL_0002:  call       "Outer Program.Id<Outer>(Outer)"
              IL_0007:  stloc.0
              IL_0008:  ldc.i4.1
              IL_0009:  brtrue.s   IL_000c
              IL_000b:  nop
              IL_000c:  br.s       IL_000e
              IL_000e:  ldc.i4.2
              IL_000f:  stloc.1
              IL_0010:  br.s       IL_0012
              IL_0012:  ldc.i4.1
              IL_0013:  brtrue.s   IL_0016
              IL_0015:  nop
              IL_0016:  ldloc.0
              IL_0017:  ldflda     "Inner Outer.Inner"
              IL_001c:  ldloc.1
              IL_001d:  call       "void Inner.Value.set"
              IL_0022:  nop
              IL_0023:  ldarg.0
              IL_0024:  ldflda     "Inner Outer.Inner"
              IL_0029:  call       "readonly int Inner.Value.get"
              IL_002e:  call       "void System.Console.Write(int)"
              IL_0033:  nop
              IL_0034:  ret
            }
            """);
        }
 
        [Fact, WorkItem(62563, "https://github.com/dotnet/roslyn/issues/62563")]
        public void AssignToStructFieldOnClassTypeThroughCall_02()
        {
            var source = """
using System;
 
 
var val = 0.1;
var obj = new Obj();
ThrowWhenNull(obj).Color.Value = val switch
{
	0 => "green",
	_ => "red"
};
Console.WriteLine($"{obj.Color.Value ?? "null"} should not be null");
ThrowWhenNull(obj).Color.Value = "yikes";
Console.WriteLine(obj.Color.Value); // yikes
ThrowWhenNull(obj).Color.Value = val == 0 ? "green" : "red";
Console.WriteLine(obj.Color.Value); // red
 
static T ThrowWhenNull<T>(T obj) => obj ?? throw new System.InvalidOperationException();
 
struct Wrapper<T>
{
	private T _value;
	public T Value
	{
		get => _value;
		set => _value = value;
	}
}
 
class Obj
{
	public Wrapper<string> Color;
}
""";
            var verifier = CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput: """
                red should not be null
                yikes
                red
                """);
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("<top-level-statements-entry-point>", """
                {
                  // Code size      186 (0xba)
                  .maxstack  4
                  .locals init (double V_0, //val
                                string V_1)
                  IL_0000:  ldc.r8     0.1
                  IL_0009:  stloc.0
                  IL_000a:  newobj     "Obj..ctor()"
                  IL_000f:  dup
                  IL_0010:  call       "Obj Program.<<Main>$>g__ThrowWhenNull|0_0<Obj>(Obj)"
                  IL_0015:  ldloc.0
                  IL_0016:  ldc.r8     0
                  IL_001f:  bne.un.s   IL_0029
                  IL_0021:  ldstr      "green"
                  IL_0026:  stloc.1
                  IL_0027:  br.s       IL_002f
                  IL_0029:  ldstr      "red"
                  IL_002e:  stloc.1
                  IL_002f:  ldflda     "Wrapper<string> Obj.Color"
                  IL_0034:  ldloc.1
                  IL_0035:  call       "void Wrapper<string>.Value.set"
                  IL_003a:  dup
                  IL_003b:  ldflda     "Wrapper<string> Obj.Color"
                  IL_0040:  call       "string Wrapper<string>.Value.get"
                  IL_0045:  dup
                  IL_0046:  brtrue.s   IL_004e
                  IL_0048:  pop
                  IL_0049:  ldstr      "null"
                  IL_004e:  ldstr      " should not be null"
                  IL_0053:  call       "string string.Concat(string, string)"
                  IL_0058:  call       "void System.Console.WriteLine(string)"
                  IL_005d:  dup
                  IL_005e:  call       "Obj Program.<<Main>$>g__ThrowWhenNull|0_0<Obj>(Obj)"
                  IL_0063:  ldflda     "Wrapper<string> Obj.Color"
                  IL_0068:  ldstr      "yikes"
                  IL_006d:  call       "void Wrapper<string>.Value.set"
                  IL_0072:  dup
                  IL_0073:  ldflda     "Wrapper<string> Obj.Color"
                  IL_0078:  call       "string Wrapper<string>.Value.get"
                  IL_007d:  call       "void System.Console.WriteLine(string)"
                  IL_0082:  dup
                  IL_0083:  call       "Obj Program.<<Main>$>g__ThrowWhenNull|0_0<Obj>(Obj)"
                  IL_0088:  ldflda     "Wrapper<string> Obj.Color"
                  IL_008d:  ldloc.0
                  IL_008e:  ldc.r8     0
                  IL_0097:  beq.s      IL_00a0
                  IL_0099:  ldstr      "red"
                  IL_009e:  br.s       IL_00a5
                  IL_00a0:  ldstr      "green"
                  IL_00a5:  call       "void Wrapper<string>.Value.set"
                  IL_00aa:  ldflda     "Wrapper<string> Obj.Color"
                  IL_00af:  call       "string Wrapper<string>.Value.get"
                  IL_00b4:  call       "void System.Console.WriteLine(string)"
                  IL_00b9:  ret
                }
                """);
        }
 
        [Fact, WorkItem(62563, "https://github.com/dotnet/roslyn/issues/62563")]
        public void AssignToEventFieldOnClassTypeThroughCall()
        {
            var source = @"
using System;
 
class Outer
{
    static readonly Action A = () => { };
    static T Id<T>(T t) => t;
 
    public event Action Inner;
 
 
    static void Main()
    {
        var outer = new Outer();
        Console.Write(outer.Inner);
 
        M1(outer);
 
        outer.Inner = null;
        M2(outer);
    }
 
    static void M1(Outer outer)
    {
        Id(outer).Inner = A;
        Console.Write(outer.Inner);
    }
 
    static void M2(Outer outer)
    {
        Id(outer).Inner = outer switch
        {
            _ => A
        };
        Console.Write(outer.Inner);
    }
}
";
            var verifier = CompileAndVerify(source, options: TestOptions.DebugExe, expectedOutput: "System.ActionSystem.Action");
            verifier.VerifyDiagnostics();
 
            verifier.VerifyIL("Outer.M1", """
            {
              // Code size       30 (0x1e)
              .maxstack  2
              IL_0000:  nop
              IL_0001:  ldarg.0
              IL_0002:  call       "Outer Outer.Id<Outer>(Outer)"
              IL_0007:  ldsfld     "System.Action Outer.A"
              IL_000c:  stfld      "System.Action Outer.Inner"
              IL_0011:  ldarg.0
              IL_0012:  ldfld      "System.Action Outer.Inner"
              IL_0017:  call       "void System.Console.Write(object)"
              IL_001c:  nop
              IL_001d:  ret
            }
            """);
 
            verifier.VerifyIL("Outer.M2", """
            {
              // Code size       46 (0x2e)
              .maxstack  2
              .locals init (Outer V_0,
                            System.Action V_1)
              IL_0000:  nop
              IL_0001:  ldarg.0
              IL_0002:  call       "Outer Outer.Id<Outer>(Outer)"
              IL_0007:  stloc.0
              IL_0008:  ldc.i4.1
              IL_0009:  brtrue.s   IL_000c
              IL_000b:  nop
              IL_000c:  br.s       IL_000e
              IL_000e:  ldsfld     "System.Action Outer.A"
              IL_0013:  stloc.1
              IL_0014:  br.s       IL_0016
              IL_0016:  ldc.i4.1
              IL_0017:  brtrue.s   IL_001a
              IL_0019:  nop
              IL_001a:  ldloc.0
              IL_001b:  ldloc.1
              IL_001c:  stfld      "System.Action Outer.Inner"
              IL_0021:  ldarg.0
              IL_0022:  ldfld      "System.Action Outer.Inner"
              IL_0027:  call       "void System.Console.Write(object)"
              IL_002c:  nop
              IL_002d:  ret
            }
            """);
        }
    }
}