File: Semantics\NullableReferenceTypesVsPatterns.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Semantic\Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Semantics
{
    [CompilerTrait(CompilerFeature.NullableReferenceTypes, CompilerFeature.Patterns)]
    public class NullableReferenceTypesVsPatterns : CSharpTestBase
    {
        private CSharpCompilation CreateNullableCompilation(string source)
        {
            return CreateCompilation(new[] { source }, options: WithNullableEnable());
        }
 
        [Fact]
        public void VarPatternInfersNullableType()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
public class C
{
    public string Field = null!;
    void M1()
    {
        if (this is { Field: var s })
        {
            s.ToString();
            s = null;
        }
    }
 
    void M2()
    {
        if (this is (var s) _)
        {
            s.ToString();
            s = null;
        }
    }
    void Deconstruct(out string s) => throw null!;
}
");
 
            c.VerifyDiagnostics();
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_Null()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        if (x is null)
        {
            x.ToString(); // warn
        }
        else
        {
            x.ToString();
        }
    }
}
");
 
            c.VerifyDiagnostics(
                // (8,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_NullInverted()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        if (!(x is null))
        {
            x.ToString();
        }
        else
        {
            x.ToString(); // warn
        }
    }
}
");
            c.VerifyDiagnostics(
                // (12,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(12, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_NonNull()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        const string nonNullConstant = ""hello"";
        if (x is nonNullConstant)
        {
            x.ToString();
        }
        else
        {
            x.ToString(); // warn
        }
    }
}
");
            c.VerifyDiagnostics(
                // (13,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_NullConstant()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        const string? nullConstant = null;
        if (x is nullConstant)
        {
            x.ToString(); // warn
        }
        else
        {
            x.ToString();
        }
    }
}
");
            c.VerifyDiagnostics(
                // (9,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(9, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_NonConstant()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        string nonConstant = ""hello"";
        if (x is nonConstant)
        {
            x.ToString();
        }
    }
}
");
            c.VerifyDiagnostics(
                // (7,18): error CS0150: A constant value is expected
                //         if (x is nonConstant)
                Diagnostic(ErrorCode.ERR_ConstantExpected, "nonConstant").WithLocation(7, 18)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_Null_AlreadyTestedAsNonNull()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        if (x != null)
        {
            if (x is null)
            {
                x.ToString(); // warn
            }
            else
            {
                x.ToString();
            }
        }
    }
}
");
            c.VerifyDiagnostics(
                // (10,17): warning CS8602: Dereference of a possibly null reference.
                //                 x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 17)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsConstantPattern_Null_AlreadyTestedAsNull()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test(object? x)
    {
        if (x == null)
        {
            if (x is null)
            {
                x.ToString(); // warn
            }
            else
            {
                x.ToString();
            }
        }
    }
}
");
            c.VerifyDiagnostics(
                // (10,17): warning CS8602: Dereference of a possibly null reference.
                //                 x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(10, 17)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsDeclarationPattern_02()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test1(object? x)
    {
        if (x is C c)
        {
            x.ToString();
            c.ToString();
        }
        else
        {
            x.ToString(); // warn
        }
    }
    void Test2(object x)
    {
        if (x is C c)
        {
            x.ToString();
            c.ToString();
        }
        else
        {
            x.ToString();
        }
    }
}
");
            c.VerifyDiagnostics(
                // (13,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(13, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsVarDeclarationPattern()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test1(object? x)
    {
        if (x is var c)
        {
            x.ToString(); // warn 1
            c /*T:object?*/ .ToString(); // warn 2
            c = null;
        }
        else
        {
            x.ToString();
        }
    }
    void Test2(object x)
    {
        if (x is var c)
        {
            x.ToString();
            c /*T:object!*/ .ToString();
        }
        else
        {
            x.ToString();
        }
    }
}
");
            c.VerifyTypes();
            c.VerifyDiagnostics(
                // (8,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // warn 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13),
                // (9,13): warning CS8602: Dereference of a possibly null reference.
                //             c /*T:object?*/ .ToString(); // warn 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(9, 13)
                );
        }
 
        [Fact]
        public void ConditionalBranching_IsVarDeclarationPattern_Discard()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test1(object? x)
    {
        if (x is var _)
        {
            x.ToString(); // 1
        }
        else
        {
            x.ToString();
        }
    }
    void Test2(object x)
    {
        if (x is var _)
        {
            x.ToString();
        }
        else
        {
            x.ToString();
        }
    }
}
");
            c.VerifyTypes();
            c.VerifyDiagnostics(
                // (8,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 13)
                );
        }
 
        [Fact]
        [WorkItem(40477, "https://github.com/dotnet/roslyn/issues/40477")]
        public void ConditionalBranching_IsVarDeclarationPattern_AlreadyTestedAsNonNull()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class C
{
    void Test1(object? x)
    {
        if (x != null)
        {
            if (x is var c)
            {
                c /*T:object!*/ .ToString();
                c = null;
            }
        }
    }
    void Test2(object x)
    {
        if (x != null)
        {
            if (x is var c)
            {
                c /*T:object!*/ .ToString();
                c = null;
            }
        }
    }
}
");
            c.VerifyTypes();
            c.VerifyDiagnostics();
        }
 
        [Fact]
        public void IsPattern_01()
        {
            var source =
@"class C
{
    static void F(object x) { }
    static void G(string s)
    {
        F(s is var o);
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(29909, "https://github.com/dotnet/roslyn/issues/29909")]
        public void IsPattern_02()
        {
            var source =
@"class C
{
    static void F(string s) { }
    static void G(string? s)
    {
        if (s is string t)
        {
            F(t);
            F(s);
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void IsPattern_AffectsNullConditionalOperator_DeclarationPattern()
        {
            var source =
@"class C
{
    static void G1(string? s)
    {
        if (s?.ToString() is string t)
        {
            s.ToString();
        }
        else
        {
            s.ToString(); // 1
        }
    }
    static void G2(string s)
    {
        if (s?.ToString() is string t)
        {
            s.ToString();
        }
        else
        {
            s.ToString(); // 2
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): warning CS8602: Dereference of a possibly null reference.
                //             s.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(11, 13),
                // (22,13): warning CS8602: Dereference of a possibly null reference.
                //             s.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(22, 13));
        }
 
        [Fact]
        public void IsPattern_AffectsNullConditionalOperator_NullableValueType()
        {
            var source =
@"class C
{
    static void G1(int? i)
    {
        if (i?.ToString() is string t)
        {
            i.Value.ToString();
        }
        else
        {
            i.Value.ToString(); // 1
        }
    }
    static void G2(int? i)
    {
        i = 1;
        if (i?.ToString() is string t)
        {
            i.Value.ToString();
        }
        else
        {
            i.Value.ToString(); // 2
        }
    }
    static void G3(int? i)
    {
        i = 1;
        if (i is int q)
        {
            i.Value.ToString();
        }
        else
        {
            i.Value.ToString();
        }
    }
}";
            var comp = CreateCompilation(new[] { source }, options: WithNullableEnable());
            comp.VerifyDiagnostics(
                // (11,13): warning CS8629: Nullable value type may be null.
                //             i.Value.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "i").WithLocation(11, 13),
                // (23,13): warning CS8629: Nullable value type may be null.
                //             i.Value.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "i").WithLocation(23, 13));
        }
 
        [Fact]
        public void IsPattern_AffectsNullConditionalOperator_NullableValueType_Nested()
        {
            var source = @"
public struct S
{
    public int? field;
}
class C
{
    static void G(S? s)
    {
        if (s?.field?.ToString() is string t)
        {
            s.Value.ToString();
            s.Value.field.Value.ToString();
        }
        else
        {
            s.Value.ToString(); // warn
            s.Value.field.Value.ToString(); // warn
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (17,13): warning CS8629: Nullable value type may be null.
                //             s.Value.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s").WithLocation(17, 13),
                // (18,13): warning CS8629: Nullable value type may be null.
                //             s.Value.field.Value.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "s.Value.field").WithLocation(18, 13)
                );
        }
 
        [Fact, WorkItem(28798, "https://github.com/dotnet/roslyn/issues/28798")]
        public void IsPattern_AffectsNullConditionalOperator_VarPattern()
        {
            var source =
@"class C
{
    static void G(string? s)
    {
        if (s?.ToString() is var t)
        {
            s.ToString(); // 1
        }
        else
        {
            s.ToString();
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (7,13): warning CS8602: Dereference of a possibly null reference.
                //             s.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13)
                );
        }
 
        [Fact]
        public void IsPattern_AffectsNullConditionalOperator_NullConstantPattern()
        {
            var source =
@"class C
{
    static void G(string? s)
    {
        if (s?.ToString() is null)
        {
            s.ToString(); // warn
        }
        else
        {
            s.ToString();
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (7,13): warning CS8602: Dereference of a possibly null reference.
                //             s.ToString(); // warn
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(7, 13)
                );
        }
 
        [Fact]
        [WorkItem(29909, "https://github.com/dotnet/roslyn/issues/29909")]
        [WorkItem(23944, "https://github.com/dotnet/roslyn/issues/23944")]
        public void PatternSwitch()
        {
            var source =
@"class C
{
    static void F(object o) { }
    static void G(object? x)
    {
        switch (x)
        {
            case string s:
                F(s);
                F(x);
                break;
            case object y when y is string t:
                F(y);
                F(t);
                F(x);
                break;
            case null:
                F(x); // 1
                break;
            default:
                F(x);
                break;
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (18,19): warning CS8604: Possible null reference argument for parameter 'o' in 'void C.F(object o)'.
                //                 F(x); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "x").WithArguments("o", "void C.F(object o)").WithLocation(18, 19));
        }
 
        [Fact]
        public void IsDeclarationPattern_01()
        {
            var source =
@"class Program
{
    static void F1(object x1)
    {
        if (x1 is string y1)
        {
            x1/*T:object!*/.ToString();
            y1/*T:string!*/.ToString();
        }
        x1/*T:object!*/.ToString();
    }
    static void F2(object? x2)
    {
        if (x2 is string y2)
        {
            x2/*T:object!*/.ToString();
            y2/*T:string!*/.ToString();
        }
        x2/*T:object?*/.ToString(); // 1
    }
    static void F3(object x3)
    {
        x3 = null; // 2
        if (x3 is string y3)
        {
            x3/*T:object!*/.ToString();
            y3/*T:string!*/.ToString();
        }
        x3/*T:object?*/.ToString(); // 3
    }
    static void F4(object? x4)
    {
        if (x4 == null) return;
        if (x4 is string y4)
        {
            x4/*T:object!*/.ToString();
            y4/*T:string!*/.ToString();
        }
        x4/*T:object!*/.ToString();
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (19,9): warning CS8602: Dereference of a possibly null reference.
                //         x2.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(19, 9),
                // (23,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         x3 = null; // 2
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(23, 14),
                // (29,9): warning CS8602: Dereference of a possibly null reference.
                //         x3.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(29, 9));
            comp.VerifyTypes();
        }
 
        [Fact]
        [WorkItem(30952, "https://github.com/dotnet/roslyn/issues/30952")]
        public void IsDeclarationPattern_02()
        {
            var source =
@"class Program
{
    static void F1<T, U>(T t1)
        where T : class
        where U : class
    {
        if (t1 is U u1)
        {
            t1.ToString();
            u1.ToString();
        }
        t1.ToString();
    }
    static void F2<T, U>(T t2)
        where T : class?
        where U : class
    {
        if (t2 is U u2)
        {
            t2.ToString();
            u2.ToString();
        }
        t2.ToString(); // 1
    }
    static void F3<T, U>(T t3)
        where T : class
        where U : class
    {
        t3 = null; // 2
        if (t3 is U u3)
        {
            t3.ToString();
            u3.ToString();
        }
        t3.ToString(); // 3
    }
    static void F4<T, U>(T t4)
        where T : class?
        where U : class
    {
        if (t4 == null) return;
        if (t4 is U u4)
        {
            t4.ToString();
            u4.ToString();
        }
        t4.ToString();
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (23,9): warning CS8602: Dereference of a possibly null reference.
                //         t2.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(23, 9),
                // (29,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         t3 = null; // 2
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(29, 14),
                // (35,9): warning CS8602: Dereference of a possibly null reference.
                //         t3.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t3").WithLocation(35, 9));
        }
 
        [Fact]
        public void IsDeclarationPattern_03()
        {
            var source =
@"class Program
{
    static void F1<T, U>(T t1)
    {
        if (t1 is U u1)
        {
            t1.ToString();
            u1.ToString();
        }
        t1.ToString(); // 1
    }
    static void F2<T, U>(T t2)
    {
        if (t2 == null) return;
        if (t2 is U u2)
        {
            t2.ToString();
            u2.ToString();
        }
        t2.ToString();
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (10,9): warning CS8602: Dereference of a possibly null reference.
                //         t1.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(10, 9));
        }
 
        [Fact]
        public void IsDeclarationPattern_NeverNull_01()
        {
            var source =
@"class Program
{
    static void F1(object x1)
    {
        if (x1 is string y1)
        {
            x1.ToString();
            x1?.ToString();
            y1.ToString();
            y1?.ToString();
        }
        x1.ToString(); // 1 (because of x1?. above)
    }
    static void F2(object? x2)
    {
        if (x2 is string y2)
        {
            x2.ToString();
            x2?.ToString();
            y2.ToString();
            y2?.ToString();
        }
        x2.ToString(); // 2
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (12,9): warning CS8602: Dereference of a possibly null reference.
                //         x1.ToString(); // 1 (because of x1?. above)
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x1").WithLocation(12, 9),
                // (23,9): warning CS8602: Dereference of a possibly null reference.
                //         x2.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(23, 9));
        }
 
        [Fact]
        public void IsDeclarationPattern_Unassigned_01()
        {
            var source =
@"class Program
{
    static void F1(object x1)
    {
        if (x1 is string y1)
        {
        }
        else
        {
            x1.ToString();
            y1.ToString(); // 1
        }
    }
    static void F2(object? x2)
    {
        if (x2 is string y2)
        {
        }
        else
        {
            x2.ToString(); // 2
            y2.ToString(); // 3
        }
    }
    static void F3(object x3)
    {
        x3 = null; // 4
        if (x3 is string y3)
        {
        }
        else
        {
            x3.ToString(); // 5
            y3.ToString(); // 6
        }
    }
    static void F4(object? x4)
    {
        if (x4 == null) return;
        if (x4 is string y4)
        {
        }
        else
        {
            x4.ToString();
            y4.ToString(); // 7
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): error CS0165: Use of unassigned local variable 'y1'
                //             y1.ToString(); // 1
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y1").WithArguments("y1").WithLocation(11, 13),
                // (21,13): warning CS8602: Dereference of a possibly null reference.
                //             x2.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(21, 13),
                // (22,13): error CS0165: Use of unassigned local variable 'y2'
                //             y2.ToString(); // 3
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y2").WithArguments("y2").WithLocation(22, 13),
                // (27,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         x3 = null; // 4
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(27, 14),
                // (33,13): warning CS8602: Dereference of a possibly null reference.
                //             x3.ToString(); // 5
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(33, 13),
                // (34,13): error CS0165: Use of unassigned local variable 'y3'
                //             y3.ToString(); // 6
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y3").WithArguments("y3").WithLocation(34, 13),
                // (46,13): error CS0165: Use of unassigned local variable 'y4'
                //             y4.ToString(); // 7
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y4").WithArguments("y4").WithLocation(46, 13));
        }
 
        [Fact]
        public void IsDeclarationPattern_Unassigned_02()
        {
            var source =
@"class Program
{
    static void F1(object x1)
    {
        if (x1 is string y1) { }
        x1.ToString();
        y1.ToString(); // 1
    }
    static void F2(object? x2)
    {
        if (x2 is string y2) { }
        x2.ToString(); // 2
        y2.ToString(); // 3
    }
    static void F3(object x3)
    {
        x3 = null; // 4
        if (x3 is string y3) { }
        x3.ToString(); // 5
        y3.ToString(); // 6
    }
    static void F4(object? x4)
    {
        if (x4 == null) return;
        if (x4 is string y4) { }
        x4.ToString();
        y4.ToString(); // 7
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (7,9): error CS0165: Use of unassigned local variable 'y1'
                //         y1.ToString(); // 1
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y1").WithArguments("y1").WithLocation(7, 9),
                // (12,9): warning CS8602: Dereference of a possibly null reference.
                //         x2.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x2").WithLocation(12, 9),
                // (13,9): error CS0165: Use of unassigned local variable 'y2'
                //         y2.ToString(); // 3
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y2").WithArguments("y2").WithLocation(13, 9),
                // (17,14): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         x3 = null; // 4
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(17, 14),
                // (19,9): warning CS8602: Dereference of a possibly null reference.
                //         x3.ToString(); // 5
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x3").WithLocation(19, 9),
                // (20,9): error CS0165: Use of unassigned local variable 'y3'
                //         y3.ToString(); // 6
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y3").WithArguments("y3").WithLocation(20, 9),
                // (27,9): error CS0165: Use of unassigned local variable 'y4'
                //         y4.ToString(); // 7
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y4").WithArguments("y4").WithLocation(27, 9));
        }
 
        [Fact]
        public void UnconstrainedTypeParameter_PatternMatching()
        {
            var source =
@"
class C
{
    static void F1<T>(object o, T tin)
    {
        if (o is T t1)
        {
            t1.ToString();
        }
        else
        {
            t1 = default;
        }
 
        t1.ToString(); // 1
 
        if (!(o is T t2))
        {
            t2 = tin;
        }
        else
        {
            t2.ToString();
        }
        t2.ToString(); // 2
 
        if (!(o is T t3)) return;
        t3.ToString();
    }
}
";
            var comp = CreateCompilation(source, options: WithNullableEnable(), parseOptions: TestOptions.Regular8);
            comp.VerifyDiagnostics(
                // (15,9): warning CS8602: Dereference of a possibly null reference.
                //         t1.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t1").WithLocation(15, 9),
                // (25,9): warning CS8602: Dereference of a possibly null reference.
                //         t2.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t2").WithLocation(25, 9)
                );
        }
 
        [WorkItem(32503, "https://github.com/dotnet/roslyn/issues/32503")]
        [Fact]
        public void PatternDeclarationBreaksNullableAnalysis()
        {
            var source = @"
class A { }
class B : A
{
    A M()
    {
        var s = new A();
        if (s is B b) {}
        return s; 
    }
} 
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void InferenceWithITuplePattern()
        {
            var source = @"
class A { }
class B : A
{
    A M()
    {
        var s = new A();
        if (s is B b) {}
        return s; 
    }
} 
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void RecursivePatternNullInferenceWithDowncast_01()
        {
            var source = @"
class Base
{
    public object Value = """";
}
class Derived : Base
{
    public new object Value = """";
}
class Program
{
    void M(Base? b)
    {
        if (b is Derived { Value: null })
            b.Value.ToString();
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void RecursivePatternNullInferenceWithDowncast_02()
        {
            var source = @"
class Base
{
    public object Value = """";
}
class Derived : Base
{
}
class Program
{
    void M(Base? b)
    {
        if (b is Derived { Value: null })
            b.Value.ToString(); // 1
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (14,13): warning CS8602: Dereference of a possibly null reference.
                //             b.Value.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "b.Value").WithLocation(14, 13));
        }
 
        [Fact]
        public void TuplePatternNullInference_01()
        {
            var source = @"
class Program
{
    void M((object, object) t)
    {
        if (t is (1, null))
        {
        }
        else
        {
            t.Item2.ToString(); // 1
            t.Item1.ToString();
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): warning CS8602: Dereference of a possibly null reference.
                //             t.Item2.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "t.Item2").WithLocation(11, 13));
        }
 
        [Fact]
        public void MultiplePathsThroughDecisionDag_01()
        {
            var source = @"
class Program
{
    bool M1(object? o, bool cond = true)
    {
        o = 1;
        switch (o)
        {
            case null:
                throw null!;
            case """" when M1(o = null):
                break;
            default:
                if (cond) o.ToString(); // 1
                break;
        }
 
        return cond;
    }
    bool M2(object? o, bool cond = true)
    {
        o = 1;
        switch (o)
        {
            case """" when M2(o = null):
                break;
            default:
                if (cond) o.ToString(); // 2
                break;
        }
 
        return cond;
    }
    bool M3(object? o, bool cond = true)
    {
        o = 1;
        switch (o)
        {
            case null:
                throw null!;
            default:
                if (cond) o.ToString();
                break;
        }
 
        return cond;
    }
    bool M4(object? o, bool cond = true)
    {
        o = 1;
        switch (o)
        {
            case null:
                throw null!;
            case """" when M4(o = null):
                break;
            case var q:
                q.ToString(); // 3 (!?)
                break;
        }
 
        return cond;
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (14,27): warning CS8602: Dereference of a possibly null reference.
                //                 if (cond) o.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(14, 27),
                // (28,27): warning CS8602: Dereference of a possibly null reference.
                //                 if (cond) o.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "o").WithLocation(28, 27),
                // (58,17): warning CS8602: Dereference of a possibly null reference.
                //                 q.ToString(); // 3 (!?)
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "q").WithLocation(58, 17));
        }
 
        [Fact]
        [WorkItem(30597, "https://github.com/dotnet/roslyn/issues/30597")]
        [WorkItem(32414, "https://github.com/dotnet/roslyn/issues/32414")]
        public void NotExhaustiveForNull_01()
        {
            var source = @"
class Program
{
    void M0(object o)
    {
        var t = (o, o);
        _ = t switch
        {
            (null, null) => 1,
            (null, {}) => 2,
            ({}, null) => 3,
            ({}, {}) => 4,
        };
    }
    void M1(object o)
    {
        var t = (o, o);
        _ = t switch // 1 not exhaustive
        {
            (null, 2) => 1,
            ({}, {}) => 2,
        };
    }
    void M2(object o)
    {
        var t = (o, o);
        _ = t switch // 2 not exhaustive
        {
            (1, 2) => 1,
            ({}, {}) => 2,
        };
    }
    void M3(object o)
    {
        var t = (o, o);
        _ = t switch // 3 not exhaustive
        {
            (null, 2) => 1,
            ({}, {}) => 2,
            (null, {}) => 3,
        };
    }
    void M4(object o)
    {
        var t = (o, o);
        _ = t switch // 4 not exhaustive
        {
            { Item1: null, Item2: 2 } => 1,
            { Item1: {}, Item2: {} } => 2,
        };
    }
    void M5(object o)
    {
        var t = (o, o);
        _ = t switch // 5 not exhaustive
        {
            { Item1: 1, Item2: 2 } => 1,
            { Item1: {}, Item2: {} } => 2,
        };
    }
    void M6(object o)
    {
        var t = (o, o);
        _ = t switch // 6 not exhaustive
        {
            { Item1: null, Item2: 2 } => 1,
            { Item1: {}, Item2: {} } => 2,
            { Item1: null, Item2: {} } => 3,
        };
    }
    void M7(object o, bool b)
    {
        _ = o switch // 7 not exhaustive
        {
            null when b => 1,
            {} => 2,
        };
    }
    void M8(object o, bool b)
    {
        _ = o switch
        {
            null when b => 1,
            {} => 2,
            null => 3,
        };
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (18,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         _ = t switch // 1 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(18, 15),
                // (27,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         _ = t switch // 2 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(27, 15),
                // (36,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(not null, null)' is not covered.
                //         _ = t switch // 3 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(not null, null)").WithLocation(36, 15),
                // (46,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         _ = t switch // 4 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(46, 15),
                // (55,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         _ = t switch // 5 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(55, 15),
                // (64,15): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(not null, null)' is not covered.
                //         _ = t switch // 6 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(not null, null)").WithLocation(64, 15),
                // (73,15): warning CS8847: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern 'null' is not covered. However, a pattern with a 'when' clause might successfully match this value.
                //         _ = o switch // 7 not exhaustive
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNullWithWhen, "switch").WithArguments("null").WithLocation(73, 15));
        }
 
        [Fact]
        [WorkItem(30597, "https://github.com/dotnet/roslyn/issues/30597")]
        [WorkItem(32414, "https://github.com/dotnet/roslyn/issues/32414")]
        public void NotExhaustiveForNull_02()
        {
            var source = @"
class Test
{
    int M1(string s1, string s2)
    {
        return (s1, s2) switch {
            (string x, string y) => x.Length + y.Length
            };
    }
    int M2(string? s1, string s2)
    {
        return (s1, s2) switch { // 1
            (string x, string y) => x.Length + y.Length
            };
    }
    int M3(string s1, string? s2)
    {
        return (s1, s2) switch { // 2
            (string x, string y) => x.Length + y.Length
            };
    }
    int M4(string? s1, string? s2)
    {
        return (s1, s2) switch { // 3
            (string x, string y) => x.Length + y.Length
            };
    }
    int M5(string s1, string s2)
    {
        return (s1, s2) switch { // 4
            (null, ""x"") => 1,
            (string x, string y) => x.Length + y.Length
            };
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (12,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         return (s1, s2) switch { // 1
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(12, 25),
                // (18,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         return (s1, s2) switch { // 2
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(18, 25),
                // (24,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, _)' is not covered.
                //         return (s1, s2) switch { // 3
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, _)").WithLocation(24, 25),
                // (30,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(null, "")' is not covered.
                //         return (s1, s2) switch { // 4
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(null, \"\")").WithLocation(30, 25));
        }
 
        [Fact, WorkItem(31881, "https://github.com/dotnet/roslyn/issues/31881")]
        public void NullableVsPattern_31881()
        {
            var source = @"
using System;
 
public class C
{
    public object? AProperty { get; set; }
    public void M(C? input, int i)
    {
        if (input?.AProperty is string str)
        {
            Console.WriteLine(str.ToString());
 
            switch (i)
            {
                case 1:
                    Console.WriteLine(input?.AProperty.ToString());
                    break;
                case 2:
                    Console.WriteLine(input.AProperty.ToString());
                    break;
                case 3:
                    Console.WriteLine(input.ToString());
                    break;
            }
        }
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(33499, "https://github.com/dotnet/roslyn/issues/33499")]
        [WorkItem(40477, "https://github.com/dotnet/roslyn/issues/40477")]
        public void PatternVariablesAreNotOblivious_33499()
        {
            var source = @"
class Test
{
    static void M(object o)
    {
        if (o is string s) { }
        s = null;
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (7,13): warning CS8600: Converting null literal or possible null value to non-nullable type.
                //         s = null;
                Diagnostic(ErrorCode.WRN_ConvertingNullableToNonNullable, "null").WithLocation(7, 13)
                );
        }
 
        [Fact]
        public void IsPatternAlwaysFalse()
        {
            var source = @"
class Test
{
    void M1(ref object o)
    {
        if (2 is 3)
            o = null;
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (6,13): warning CS8519: The given expression never matches the provided pattern.
                //         if (2 is 3)
                Diagnostic(ErrorCode.WRN_GivenExpressionNeverMatchesPattern, "2 is 3").WithLocation(6, 13));
        }
 
        [Fact]
        [WorkItem(29619, "https://github.com/dotnet/roslyn/issues/29619")]
        public void StructWithNotBackedProperty()
        {
            var source = @"
struct Point
{
    public object X, Y;
    public Point Mirror => new Point { X = Y, Y = X };
    bool Test => this is { X: 1, Y: 2, Mirror: { X: 2, Y: 1 } };
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void LearnFromNullPattern_01()
        {
            var source = @"
class Node
{
    public Node Next = null!;
}
class Program
{
    void M1(Node n)
    {
        if (n is null) {}
        n.Next.Next.Next.ToString(); // 1
    }
    void M2(Node n)
    {
        if (n is {Next: null}) {}
        n.Next.Next.Next.ToString(); // 2
    }
    void M3(Node n)
    {
        if (n is {Next: {Next: null}}) {}
        n.Next.Next.Next.ToString(); // 3
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n").WithLocation(11, 9),
                // (16,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(16, 9),
                // (21,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(21, 9));
        }
 
        [Fact]
        public void LearnFromNullPattern_02()
        {
            var source = @"
class Node
{
    public Node Next = null!;
}
class Program
{
    void M1(Node n)
    {
        switch (n) { case null: break; }
        n.Next.Next.Next.ToString(); // 1
    }
    void M2(Node n)
    {
        switch (n) { case {Next: null}: break; }
        n.Next.Next.Next.ToString(); // 2
    }
    void M3(Node n)
    {
        switch (n) { case {Next: {Next: null}}: break; }
        n.Next.Next.Next.ToString(); // 3
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n").WithLocation(11, 9),
                // (16,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(16, 9),
                // (21,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(21, 9));
        }
 
        [Fact]
        public void LearnFromNullPattern_03()
        {
            var source = @"
class Node
{
    public Node Next = null!;
}
class Program
{
    void M1(Node n)
    {
        _ = n switch { null => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 1
    }
    void M2(Node n)
    {
        _ = n switch { {Next: null} => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 2
    }
    void M3(Node n)
    {
        _ = n switch { {Next: {Next: null}} => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 3
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n").WithLocation(11, 9),
                // (16,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(16, 9),
                // (21,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(21, 9));
        }
 
        [Fact]
        public void LearnFromNullPattern_04()
        {
            var source = @"
#nullable disable
class Node
{
    public Node Next = null!;
}
#nullable enable
class Program
{
#nullable disable
    void M1(Node n)
#nullable enable
    {
        _ = n switch { null => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 1
    }
#nullable disable
    void M2(Node n)
#nullable enable
    {
        _ = n switch { {Next: null} => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 2
    }
#nullable disable
    void M3(Node n)
#nullable enable
    {
        _ = n switch { {Next: {Next: null}} => 1, _ => 2 };
        n.Next.Next.Next.ToString(); // 3
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (15,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n").WithLocation(15, 9),
                // (22,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(22, 9),
                // (29,9): warning CS8602: Dereference of a possibly null reference.
                //         n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(29, 9));
        }
 
        [Fact]
        public void LearnFromNullPattern_05()
        {
            var source = @"
class Program
{
    void M1((string s1, string s2) n)
    {
        _ = n switch {
            (_, null) => n.s1.ToString(),
            var q => n.s1.ToString(),
            };
        n.s1.ToString();
        n.s2.ToString(); // 1
    }
    void M2((string s1, string s2) n)
    {
        _ = n switch {
            (null, _) => n.s1.ToString(), // 2
            (_, _)  => n.s1.ToString(),
            };
        n.s1.ToString(); // 3
        n.s2.ToString();
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,9): warning CS8602: Dereference of a possibly null reference.
                //         n.s2.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.s2").WithLocation(11, 9),
                // (16,26): warning CS8602: Dereference of a possibly null reference.
                //             (null, _) => n.s1.ToString(), // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.s1").WithLocation(16, 26));
        }
 
        [Fact]
        public void LearnFromNonNullPattern_01()
        {
            var source = @"
class Node
{
    public Node? Next = null;
}
class Program
{
    void M1(Node? n)
    {
        if (n is {} q)
            n.Next.ToString(); // 1
    }
    void M2(Node? n)
    {
        if (n is {Next: {}} q)
            n.Next.Next.ToString(); // 2
    }
    void M3(Node? n)
    {
        if (n is {Next: {Next: {}}} q)
            n.Next.Next.Next.ToString(); // 3
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(11, 13),
                // (16,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(16, 13),
                // (21,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next.Next").WithLocation(21, 13));
        }
 
        [Fact]
        public void LearnFromNonNullPattern_02()
        {
            var source = @"
class Node
{
    public Node? Next = null;
}
class Program
{
    void M1(Node? n)
    {
        switch (n) { case {} q:
            n.Next.ToString(); // 1
        break; }
    }
    void M2(Node? n)
    {
        switch (n) { case {Next: {}} q:
            n.Next.Next.ToString(); // 2
        break; }
    }
    void M3(Node? n)
    {
        switch (n) { case {Next: {Next: {}}} q:
            n.Next.Next.Next.ToString(); // 3
        break; }
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(11, 13),
                // (17,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(17, 13),
                // (23,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.Next.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next.Next").WithLocation(23, 13));
        }
 
        [Fact]
        public void LearnFromNonNullPattern_03()
        {
            var source = @"
class Node
{
    public Node? Next = null;
}
class Program
{
    void M1(Node? n)
    {
        _ = n switch { {} q =>
            n.Next.ToString(), // 1
            _ => string.Empty };
    }
    void M2(Node? n)
    {
        _ = n switch { {Next: {}} q =>
            n.Next.Next.ToString(), // 2
            _ => string.Empty };
    }
    void M3(Node? n)
    {
        _ = n switch { {Next: {Next: {}}} q =>
            n.Next.Next.Next.ToString(), // 3
            _ => string.Empty };
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (11,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.ToString(), // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next").WithLocation(11, 13),
                // (17,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.ToString(), // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next").WithLocation(17, 13),
                // (23,13): warning CS8602: Dereference of a possibly null reference.
                //             n.Next.Next.Next.ToString(), // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Next.Next.Next").WithLocation(23, 13));
        }
 
        [Fact]
        public void LearnFromNonNullPattern_04()
        {
            var source = @"
class Program
{
    void M1((string? s1, string? s2)? n)
    {
        _ = n switch {
            var q => n.Value.ToString(), // 1: n
            };
    }
    void M2((string? s1, string? s2)? n)
    {
        _ = n switch {
            (_, _) => n.Value.s1.ToString(), // 2: n.Value.s1
            _      => n.Value.ToString(), // 3: n
            };
    }
    void M3((string? s1, string? s2)? n)
    {
        _ = n switch {
            ({}, _) => n.Value.s1.ToString(),
            (_, _)  => n.Value.s1.ToString(), // 4: n.Value.s1
            _       => n.Value.ToString(), // 5: n
            };
    }
    void M4((string? s1, string? s2)? n)
    {
        _ = n switch {
            (null, _) => n.Value.s2.ToString(), // 6: n.Value.s2
            (_, null) => n.Value.s1.ToString(),
            (_, _)    => n.Value.s1.ToString() + n.Value.s2.ToString(),
            _         => n.Value.ToString(), // 7: n
            };
    }
}
";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics(
                // (7,22): warning CS8629: Nullable value type may be null.
                //             var q => n.Value.ToString(), // 1: n
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "n").WithLocation(7, 22),
                // (13,23): warning CS8602: Dereference of a possibly null reference.
                //             (_, _) => n.Value.s1.ToString(), // 2: n.Value.s1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Value.s1").WithLocation(13, 23),
                // (14,23): warning CS8629: Nullable value type may be null.
                //             _      => n.Value.ToString(), // 3: n
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "n").WithLocation(14, 23),
                // (21,24): warning CS8602: Dereference of a possibly null reference.
                //             (_, _)  => n.Value.s1.ToString(), // 4: n.Value.s1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Value.s1").WithLocation(21, 24),
                // (22,24): warning CS8629: Nullable value type may be null.
                //             _       => n.Value.ToString(), // 5: n
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "n").WithLocation(22, 24),
                // (28,26): warning CS8602: Dereference of a possibly null reference.
                //             (null, _) => n.Value.s2.ToString(), // 6: n.Value.s2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "n.Value.s2").WithLocation(28, 26),
                // (31,26): warning CS8629: Nullable value type may be null.
                //             _         => n.Value.ToString(), // 7: n
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "n").WithLocation(31, 26));
        }
 
        [Fact]
        [WorkItem(34246, "https://github.com/dotnet/roslyn/issues/34246")]
        public void LearnFromConstantPattern_01()
        {
            var source = @"
class Program
{
    static void M(string? s)
    {
        switch (s?.Length)
        {
            case 0:
                s.ToString();
                break;
        }
    }
}";
            var comp = CreateNullableCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(34233, "https://github.com/dotnet/roslyn/issues/34233")]
        [WorkItem(39888, "https://github.com/dotnet/roslyn/issues/39888")]
        public void SwitchExpressionResultType_01()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
class Test
{
    void Test1(int i, object? x, object y)
    {
        _ = i switch { 1 => x, _ => y }/*T:object?*/;
        _ = i switch { 1 when x != null => x, _ => y }/*T:object!*/;
        _ = i switch { 1 => y, _ => x }/*T:object?*/;
        _ = i switch { 1 => x!, _ => y }/*T:object!*/;
        _ = i switch { 1 => y, _ => x! }/*T:object!*/;
    }
 
    void Test2(int i, C x, D y)
    {
        _ = i switch { 2 => x, _ => y }/*T:D?*/;
        _ = i switch { 2 => y, _ => x }/*T:D?*/;
    }
 
    void Test3(int i, IIn<string> x, IIn<object>? y)
    {
        _ = i switch { 3 => x, _ => y }/*T:IIn<string!>?*/;
        _ = i switch { 3 => y, _ => x }/*T:IIn<string!>?*/;
    }
 
    void Test4(int i, IOut<string> x, IOut<object>? y)
    {
        _ = i switch { 4 => x, _ => y }/*T:IOut<object!>?*/;
        _ = i switch { 4 => y, _ => x }/*T:IOut<object!>?*/;
    }
 
    void Test5(int i, I<string> x, I<object>? y)
    {
        _ = i switch { 5 => x, _ => y }/*T:!*//*CT:!*/; // 1
        _ = i switch { 5 => y, _ => x }/*T:!*//*CT:!*/; // 2
    }
 
    void Test6(int i, I<string> x, I<string?> y)
    {
        _ = i switch { 6 => x, _ => y }/*T:I<string!>!*/; // 3
        _ = i switch { 6 => y, _ => x }/*T:I<string!>!*/; // 4
    }
 
    void Test7<T>(int i, T x)
    {
        _ = i switch { 7 => x, _ => default }/*T:T*/;
        _ = i switch { 7 => default, _ => x }/*T:T*/;
    }
}
 
class B {
    public static implicit operator D?(B? b) => throw null!;
}
class C : B {}
class D {}
 
public interface I<T> { }
public interface IIn<in T> { }
public interface IOut<out T> { }
");
            c.VerifyTypes();
            c.VerifyDiagnostics(
                // (33,15): error CS8506: No best type was found for the switch expression.
                //         _ = i switch { 5 => x, _ => y }/*T:<null>!*//*CT:!*/; // 1
                Diagnostic(ErrorCode.ERR_SwitchExpressionNoBestType, "switch").WithLocation(33, 15),
                // (34,15): error CS8506: No best type was found for the switch expression.
                //         _ = i switch { 5 => y, _ => x }/*T:<null>!*//*CT:!*/; // 2
                Diagnostic(ErrorCode.ERR_SwitchExpressionNoBestType, "switch").WithLocation(34, 15),
                // (39,37): warning CS8619: Nullability of reference types in value of type 'I<string?>' doesn't match target type 'I<string>'.
                //         _ = i switch { 6 => x, _ => y }/*T:I<string!>!*/; // 3
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I<string?>", "I<string>").WithLocation(39, 37),
                // (40,29): warning CS8619: Nullability of reference types in value of type 'I<string?>' doesn't match target type 'I<string>'.
                //         _ = i switch { 6 => y, _ => x }/*T:I<string!>!*/; // 4
                Diagnostic(ErrorCode.WRN_NullabilityMismatchInAssignment, "y").WithArguments("I<string?>", "I<string>").WithLocation(40, 29)
            );
        }
 
        [Fact]
        [WorkItem(39264, "https://github.com/dotnet/roslyn/issues/39264")]
        public void IsPatternSplitState_01()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
#nullable enable
class C
{
    string? field = string.Empty;
    string? otherField = string.Empty;
 
    void M1(C c)
    {
        if (c.field == null) return;
        
        c.field.ToString();
    }
 
    void M2(C c)
    {
        if (c is { field: null }) return;
        
        c.field.ToString();
    }
 
    void M3(C c)
    {
        switch (c)
        {
            case { field: null }:
                break;
            default:
                c.field.ToString();
                break;
        }
    }
 
    void M4(C c)
    {
        _ = c switch
        {
            { field: null } => string.Empty,
            _ => c.field.ToString(),
        };
    }
 
    void M5(C c)
    {
        if (c is { field: null }) return;
        
        c.otherField.ToString(); // W
    }
}
");
            c.VerifyDiagnostics(
                // (47,9): warning CS8602: Dereference of a possibly null reference.
                //         c.otherField.ToString(); // W
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.otherField").WithLocation(47, 9)
                );
        }
 
        [Fact]
        [WorkItem(39264, "https://github.com/dotnet/roslyn/issues/39264")]
        public void IsPatternSplitState_02()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
#nullable enable
class C
{
    C? c = null;
 
    void M1(C c)
    {
        if (c is { c: null })
        {
            if (c.c != null)
            {
                c.c.c.c.ToString();
            }
        }
    }
}
");
            c.VerifyDiagnostics(
                // (13,17): warning CS8602: Dereference of a possibly null reference.
                //                 c.c.c.c.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.c.c").WithLocation(13, 17),
                // (13,17): warning CS8602: Dereference of a possibly null reference.
                //                 c.c.c.c.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.c.c.c").WithLocation(13, 17));
        }
 
        [Fact]
        [WorkItem(39264, "https://github.com/dotnet/roslyn/issues/39264")]
        public void IsPatternSplitState_03()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
#nullable enable
public class C {
    C? c = null;
 
    public static void Main()
    {
        C c = new C();
        M1(c, new C());
    }
 
    static void M1(C c, C c2)
    {
        if (c is { c : null } && c2 is { c: null })
        {
            c.c = c2;
            if (c.c != null)
            {
                c.c.c.ToString(); // warning
            }
        }
    }
}
");
            c.VerifyDiagnostics(
                // (19,17): warning CS8602: Dereference of a possibly null reference.
                //                 c.c.c.ToString(); // warning
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c.c.c").WithLocation(19, 17)
                );
        }
 
        [Fact]
        [WorkItem(40629, "https://github.com/dotnet/roslyn/issues/40629")]
        public void NullTestInSwitch_01()
        {
            CSharpCompilation c = CreateNullableCompilation(@"
#nullable enable
class C
{
    void M(object? p)
    {
        switch (p)
        {
            case null:
                return;
        }
 
        p.ToString();
    }
}
");
            c.VerifyDiagnostics();
        }
 
        [Fact]
        public void NotNullIsAPureNullTest()
        {
            var source =
@"#nullable enable
class C
{
    void M1(C? x)
    {
        if (x is not null)
            x.ToString();
        x.ToString(); // 1
    }
    void M2(C x)
    {
        if (x is not null)
            x.ToString();
        x.ToString(); // 2
    }
    void M3(C x)
    {
        if (x is not null or _)
            x.ToString(); // 3
        x.ToString();
    }
    void M4(C x)
    {
        if (x is null or _)
            x.ToString(); // 4
        x.ToString();
    }
    void M5(C x)
    {
        if (x is _ or not null)
            x.ToString(); // 5
        x.ToString();
    }
    void M6(C x)
    {
        if (x is _ or null)
            x.ToString(); // 6
        x.ToString();
    }
    void M7(C x)
    {
        if (x is _ and null)
            x.ToString(); // 7
        x.ToString();
    }
    void M8(C x)
    {
        if (x is _ and not null)
            x.ToString();
        x.ToString(); // 8
    }
    void M9(C x)
    {
        if (x is not null and _)
            x.ToString();
        x.ToString(); // 9
    }
    void M10(int? x)
    {
        if (x is < 0)
            x.Value.ToString();
        x.Value.ToString(); // 10
    }
    void M11(C x)
    {
        if (x is not object)
            x.ToString(); // 11
        else
            x.ToString();
    }
}
";
            var comp = CreateCompilation(source, parseOptions: TestOptions.RegularWithPatternCombinators);
            comp.VerifyDiagnostics(
                // (8,9): warning CS8602: Dereference of a possibly null reference.
                //         x.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(8, 9),
                // (14,9): warning CS8602: Dereference of a possibly null reference.
                //         x.ToString(); // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(14, 9),
                // (18,13): warning CS8794: An expression of type 'C' always matches the provided pattern.
                //         if (x is not null or _)
                Diagnostic(ErrorCode.WRN_IsPatternAlways, "x is not null or _").WithArguments("C").WithLocation(18, 13),
                // (19,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(19, 13),
                // (24,13): warning CS8794: An expression of type 'C' always matches the provided pattern.
                //         if (x is null or _)
                Diagnostic(ErrorCode.WRN_IsPatternAlways, "x is null or _").WithArguments("C").WithLocation(24, 13),
                // (25,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 4
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(25, 13),
                // (30,13): warning CS8794: An expression of type 'C' always matches the provided pattern.
                //         if (x is _ or not null)
                Diagnostic(ErrorCode.WRN_IsPatternAlways, "x is _ or not null").WithArguments("C").WithLocation(30, 13),
                // (31,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 5
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(31, 13),
                // (36,13): warning CS8794: An expression of type 'C' always matches the provided pattern.
                //         if (x is _ or null)
                Diagnostic(ErrorCode.WRN_IsPatternAlways, "x is _ or null").WithArguments("C").WithLocation(36, 13),
                // (37,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 6
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(37, 13),
                // (43,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 7
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(43, 13),
                // (50,9): warning CS8602: Dereference of a possibly null reference.
                //         x.ToString(); // 8
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(50, 9),
                // (56,9): warning CS8602: Dereference of a possibly null reference.
                //         x.ToString(); // 9
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(56, 9),
                // (62,9): warning CS8629: Nullable value type may be null.
                //         x.Value.ToString(); // 10
                Diagnostic(ErrorCode.WRN_NullableValueTypeMayBeNull, "x").WithLocation(62, 9),
                // (67,13): warning CS8602: Dereference of a possibly null reference.
                //             x.ToString(); // 11
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "x").WithLocation(67, 13)
                );
        }
 
        [Fact]
        [WorkItem(50161, "https://github.com/dotnet/roslyn/issues/50161")]
        public void NestedPattern_Field_01()
        {
            var source =
@"#nullable enable
class E
{
    public E F = new E();
}
class Test
{
    static void M(E e)
    {
        switch (e)
        {
            case { F: { F: { F: { F: null } } } }: break;
        }
        e.F.F.F.F.ToString();
    }
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (14,9): warning CS8602: Dereference of a possibly null reference.
                //         e.F.F.F.F.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e.F.F.F.F").WithLocation(14, 9));
        }
 
        [Fact]
        [WorkItem(50161, "https://github.com/dotnet/roslyn/issues/50161")]
        public void NestedPattern_Field_02()
        {
            var source =
@"#nullable enable
class E
{
    public E F = new E();
}
class Test
{
    static void M(E e)
    {
        switch (e)
        {
            case { F: { F: { F: { F: { F: null } } } } }: break;
        }
        e.F.F.F.F.F.ToString();
    }
}";
            // No warning because MaxSlotDepth exceeded.
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(50161, "https://github.com/dotnet/roslyn/issues/50161")]
        public void NestedPattern_Property_01()
        {
            var source =
@"#nullable enable
class E
{
    public E P => new E();
}
class Test
{
    static void M(E e)
    {
        switch (e)
        {
            case { P: { P: { P: { P: null } } } }: break;
        }
        e.P.P.P.P.ToString();
    }
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (14,9): warning CS8602: Dereference of a possibly null reference.
                //         e.P.P.P.P.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "e.P.P.P.P").WithLocation(14, 9));
        }
 
        [Fact]
        [WorkItem(50161, "https://github.com/dotnet/roslyn/issues/50161")]
        public void NestedPattern_Property_02()
        {
            var source =
@"#nullable enable
class E
{
    public E P => new E();
}
class Test
{
    static void M(E e)
    {
        switch (e)
        {
            case { P: { P: { P: { P: { P: null } } } } }: break;
        }
        e.P.P.P.P.P.ToString();
    }
}";
            // No warning because MaxSlotDepth exceeded.
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void NestedLambdaArm_DoesNotObserveStateFromOtherArms()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    public void M(object? o, Action? action) {
        _ = o switch
        {
            null => () => { action(); },
            _ => action = new Action(() => {}),
        };
    }
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics(
                // (8,29): warning CS8602: Dereference of a possibly null reference.
                //             null => () => { action(); },
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "action").WithLocation(8, 29)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_01()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    static void M(bool b)
    {
        string? s = null;
        Func<string> a = b switch { true => () => s.ToString(), false => () => s?.ToString() };
    }
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics(
                // (8,51): warning CS8602: Dereference of a possibly null reference.
                //         Func<string> a = b switch { true => () => s.ToString(), false => () => s?.ToString() };
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 51),
                // (8,80): warning CS8603: Possible null reference return.
                //         Func<string> a = b switch { true => () => s.ToString(), false => () => s?.ToString() };
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s?.ToString()").WithLocation(8, 80)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_02()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    static void M(bool b)
    {
        string? s = null;
        var a = (Func<string>)(b switch { true => () => s.ToString(), false => () => s?.ToString() });
    }
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics(
                // (8,57): warning CS8602: Dereference of a possibly null reference.
                //         var a = (Func<string>)(b switch { true => () => s.ToString(), false => () => s?.ToString() });
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(8, 57),
                // (8,86): warning CS8603: Possible null reference return.
                //         var a = (Func<string>)(b switch { true => () => s.ToString(), false => () => s?.ToString() });
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s?.ToString()").WithLocation(8, 86)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_03()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    static void M(bool b)
    {
        Func<string>? s = () => """";
        Func<object>? a = (b switch { true => s = null, false => () => s() });
    }
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_04()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    static void M(bool b)
    {
        Func<string>? s = () => """";
        Func<object>? a = (b switch { true => () => s(), false => s = null });
    }
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_05()
        {
            var source =
@"#nullable enable
class C
{
    static void M(bool b)
    {
        string? s = null;
        object a = b switch
        { 
            true => () => s.ToString(),
            false => () => s?.ToString()
        };
    }
}";
 
            var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
            comp.VerifyDiagnostics(
                // (9,24): error CS1660: Cannot convert lambda expression to type 'object' because it is not a delegate type
                //             true => () => s.ToString(),
                Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "=>").WithArguments("lambda expression", "object").WithLocation(9, 24),
                // (9,27): warning CS8602: Dereference of a possibly null reference.
                //             true => () => s.ToString(),
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 27),
                // (10,25): error CS1660: Cannot convert lambda expression to type 'object' because it is not a delegate type
                //             false => () => s?.ToString()
                Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "=>").WithArguments("lambda expression", "object").WithLocation(10, 25));
 
            comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (9,27): warning CS8602: Dereference of a possibly null reference.
                //             true => () => s.ToString(),
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s").WithLocation(9, 27));
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_06()
        {
            var comp = CreateCompilation(@"
using System;
class C
{
    static void M(bool b)
    {
        string? s1 = null;
        string? s2 = """";
        M1(s2, b switch
               {
                   true => () => s1.ToString(),
                   false => () => s1?.ToString()
               }).ToString();
    }
 
    static T M1<T>(T t1, Func<T> t2) => t1;
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics(
                // (11,34): warning CS8602: Dereference of a possibly null reference.
                //                    true => () => s1.ToString(),
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "s1").WithLocation(11, 34),
                // (12,35): warning CS8603: Possible null reference return.
                //                    false => () => s1?.ToString()
                Diagnostic(ErrorCode.WRN_NullReferenceReturn, "s1?.ToString()").WithLocation(12, 35)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461")]
        public void TargetTypedSwitch_07()
        {
            var comp = CreateCompilation(@"
interface I {}
class A : I {}
class B : I {}
class C
{
    static void M(I i, A a, B? b, bool @bool)
    {
        M1(i, @bool switch { true => a, false => b }).ToString();
    }
 
    static T M1<T>(T t1, T t2) => t1;
}
", options: WithNullableEnable());
 
            comp.VerifyDiagnostics(
                // (9,15): warning CS8604: Possible null reference argument for parameter 't2' in 'I C.M1<I>(I t1, I t2)'.
                //         M1(i, @bool switch { true => a, false => b }).ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceArgument, "@bool switch { true => a, false => b }").WithArguments("t2", "I C.M1<I>(I t1, I t2)").WithLocation(9, 15)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461"), WorkItem(49735, "https://github.com/dotnet/roslyn/issues/49735")]
        public void TargetTypedSwitch_08()
        {
            var comp = CreateCompilation(@"
C? c = """".Length switch { > 0 => new A(), _ => new B() };
c.ToString();
 
class C { }
class A { public static implicit operator C?(A a) => null; }
class B { public static implicit operator C?(B b) => null; }
", options: WithNullableEnable(TestOptions.ReleaseExe));
 
            comp.VerifyDiagnostics(
                // (3,1): warning CS8602: Dereference of a possibly null reference.
                // c.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "c").WithLocation(3, 1)
            );
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461"), WorkItem(49735, "https://github.com/dotnet/roslyn/issues/49735")]
        public void TargetTypedSwitch_09()
        {
            var comp = CreateCompilation(@"
C? c = true switch { true => new A(), false => new B() };
c.ToString();
 
class C { }
class A { public static implicit operator C(A a) => new C(); }
class B { public static implicit operator C?(B b) => null; }
", options: WithNullableEnable(TestOptions.ReleaseExe));
 
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(51461, "https://github.com/dotnet/roslyn/issues/51461"), WorkItem(49735, "https://github.com/dotnet/roslyn/issues/49735")]
        public void TargetTypedSwitch_10()
        {
            var comp = CreateCompilation(@"
C? c = false switch { true => new A(), false => new B() };
c.ToString();
 
class C { }
class A { public static implicit operator C?(A a) => null; }
class B { public static implicit operator C(B b) => new C(); }
", options: WithNullableEnable(TestOptions.ReleaseExe));
 
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(51904, "https://github.com/dotnet/roslyn/issues/51904")]
        public void TupleSwitchWithSuppression()
        {
            // When an input value is suppressed, it will get a dedicated
            // slot during DAG analysis, instead of re-using the slot we might
            // get from the expression
 
            var comp = CreateCompilation(@"
#nullable enable
 
public class C
{
    public string M1(C? a)
        => a! switch
        {
            C => a.ToString() // 1
        };
 
    public string M11(C? a)
        => a! switch
        {
            null => string.Empty,
            C => a.ToString() // 2
        };
 
    public string M111(C? a)
        => a! switch
        {
            null => string.Empty,
            _ => a.ToString() // 3
        };
 
    public string M2(C? a)
        => (1, a!) switch
        {
            (_, C) => a.ToString() // 4
        };
 
    public string M22(C? a)
        => (1, a!) switch
        {
            (_, null) => string.Empty,
            (_, C) => a.ToString() // 5
        };
 
    public string M222(C? a)
        => (1, a!) switch
        {
            (_, null) => string.Empty,
            (_, _) => a.ToString() // 6
        };
 
    public int M2222(C? a)
        => (1, a!) switch
        {
            (_, null) => 0,
            (_, _) => 1
        };
 
    public string M3(C? a)
        => (1, a)! switch // 7
        {
            (_, C) => a.ToString()
        };
 
    public string M4(C? a)
        => (1, (1, a!)) switch
        {
            (_, (_, C)) => a.ToString() // 8
        };
 
    public string M5(C? a)
        => (1, (1, a)!) switch  // 9
        {
            (_, (_, C)) => a.ToString() // 10
        };
 
    public string M6(C? a)
        => (1, (1, a))! switch  // 11
        {
            (_, (_, C)) => a.ToString() // 12
        };
}
");
 
            comp.VerifyDiagnostics(
                // (9,18): warning CS8602: Dereference of a possibly null reference.
                //             C => a.ToString() // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(9, 18),
                // (16,18): warning CS8602: Dereference of a possibly null reference.
                //             C => a.ToString() // 2
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(16, 18),
                // (23,18): warning CS8602: Dereference of a possibly null reference.
                //             _ => a.ToString() // 3
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(23, 18),
                // (29,23): warning CS8602: Dereference of a possibly null reference.
                //             (_, C) => a.ToString() // 4
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(29, 23),
                // (36,23): warning CS8602: Dereference of a possibly null reference.
                //             (_, C) => a.ToString() // 5
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(36, 23),
                // (43,23): warning CS8602: Dereference of a possibly null reference.
                //             (_, _) => a.ToString() // 6
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(43, 23),
                // (54,20): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, null)' is not covered.
                //         => (1, a)! switch // 7
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, null)").WithLocation(54, 20),
                // (62,28): warning CS8602: Dereference of a possibly null reference.
                //             (_, (_, C)) => a.ToString() // 8
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(62, 28),
                // (66,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, (_, null))' is not covered.
                //         => (1, (1, a)!) switch  // 9
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, (_, null))").WithLocation(66, 25),
                // (68,28): warning CS8602: Dereference of a possibly null reference.
                //             (_, (_, C)) => a.ToString() // 10
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(68, 28),
                // (72,25): warning CS8655: The switch expression does not handle some null inputs (it is not exhaustive). For example, the pattern '(_, (_, null))' is not covered.
                //         => (1, (1, a))! switch  // 11
                Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustiveForNull, "switch").WithArguments("(_, (_, null))").WithLocation(72, 25),
                // (74,28): warning CS8602: Dereference of a possibly null reference.
                //             (_, (_, C)) => a.ToString() // 12
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "a").WithLocation(74, 28)
                );
        }
 
        [Fact, WorkItem(59804, "https://github.com/dotnet/roslyn/issues/59804")]
        public void NestedTypeUsedInPropertyPattern()
        {
            var source = @"
public class Class1
{
    public class Inner1
    {
    }
}
 
public class Class2
{
    public bool Test()
    {
        Class1 test = null;
        test switch { { Inner1: """" } => """" };
    }
}
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (11,17): error CS0161: 'Class2.Test()': not all code paths return a value
                //     public bool Test()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "Test").WithArguments("Class2.Test()").WithLocation(11, 17),
                // (14,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                //         test switch { { Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_IllegalStatement, @"test switch { { Inner1: """" } => """" }").WithLocation(14, 9),
                // (14,25): error CS0572: 'Inner1': cannot reference a type through an expression; try 'Class1.Inner1' instead
                //         test switch { { Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_BadTypeReference, "Inner1").WithArguments("Inner1", "Class1.Inner1").WithLocation(14, 25),
                // (14,25): error CS0154: The property or indexer 'Inner1' cannot be used in this context because it lacks the get accessor
                //         test switch { { Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_PropertyLacksGet, "Inner1").WithArguments("Inner1").WithLocation(14, 25)
                );
        }
 
        [Fact, WorkItem(59804, "https://github.com/dotnet/roslyn/issues/59804")]
        public void NestedTypeUsedInPropertyPattern_ExtendedProperty()
        {
            var source = @"
public class Class1
{
    public Class1 Next { get; set; }
 
    public class Inner1
    {
    }
}
 
public class Class2
{
    public bool Test()
    {
        Class1 test = null;
        test switch { { Next.Inner1: """" } => """" };
    }
}
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (13,17): error CS0161: 'Class2.Test()': not all code paths return a value
                //     public bool Test()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "Test").WithArguments("Class2.Test()").WithLocation(13, 17),
                // (16,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                //         test switch { { Next.Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_IllegalStatement, @"test switch { { Next.Inner1: """" } => """" }").WithLocation(16, 9),
                // (16,30): error CS0572: 'Inner1': cannot reference a type through an expression; try 'Class1.Inner1' instead
                //         test switch { { Next.Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_BadTypeReference, "Inner1").WithArguments("Inner1", "Class1.Inner1").WithLocation(16, 30),
                // (16,30): error CS0154: The property or indexer 'Inner1' cannot be used in this context because it lacks the get accessor
                //         test switch { { Next.Inner1: "" } => "" };
                Diagnostic(ErrorCode.ERR_PropertyLacksGet, "Inner1").WithArguments("Inner1").WithLocation(16, 30)
                );
        }
 
        [Fact, WorkItem(59804, "https://github.com/dotnet/roslyn/issues/59804")]
        public void MethodUsedInPropertyPattern()
        {
            var source = @"
public class Class1
{
    public void Method()
    {
    }
}
 
public class Class2
{
    public bool Test()
    {
        Class1 test = null;
        test switch { { Method: """" } => """" };
    }
}
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (11,17): error CS0161: 'Class2.Test()': not all code paths return a value
                //     public bool Test()
                Diagnostic(ErrorCode.ERR_ReturnExpected, "Test").WithArguments("Class2.Test()").WithLocation(11, 17),
                // (14,9): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement
                //         test switch { { Method: "" } => "" };
                Diagnostic(ErrorCode.ERR_IllegalStatement, @"test switch { { Method: """" } => """" }").WithLocation(14, 9),
                // (14,25): error CS0154: The property or indexer 'Method' cannot be used in this context because it lacks the get accessor
                //         test switch { { Method: "" } => "" };
                Diagnostic(ErrorCode.ERR_PropertyLacksGet, "Method").WithArguments("Method").WithLocation(14, 25)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
class C
{
    void M()
    {
        string? s = "";
 
        for (var x = 0; x < 10; x++)
        {
            var a = Infer(s);
            if (a[0] is var z)
            {
                z.ToString();
            }
 
            s = null;
        }
    }
 
    List<T> Infer<T>(T t) => new() { t };
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (15,17): warning CS8602: Dereference of a possibly null reference.
                //                 z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(15, 17)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration_Tuple()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
class C
{
    void M()
    {
        string? s = "";
 
        for (var x = 0; x < 10; x++)
        {
            var a = Infer(s);
            if ((a[0], 1) is (var z, var z2))
            {
                z.ToString();
            }
 
            s = null;
        }
    }
 
    List<T> Infer<T>(T t) => new() { t };
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (15,17): warning CS8602: Dereference of a possibly null reference.
                //                 z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(15, 17)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration_ListPattern()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var a = Infer(s);
    if (a is [var z])
    {
        z.ToString();
    }
 
    s = null;
}
 
List<T> Infer<T>(T t) => new() { t };
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyDiagnostics(
                // (11,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(11, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration_ListPattern_Inline()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    if (Infer(s) is [var z])
    {
        z.ToString();
    }
 
    s = null;
}
 
List<T> Infer<T>(T t) => new() { t };
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyDiagnostics(
                // (10,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration_SlicePattern()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var a = Infer(s);
    if (a is [_, .. var z, _])
    {
        z.ToString();
    }
 
    s = null;
}
 
Collection<T> Infer<T>(T t) => throw null!;
 
class Collection<T>
{
    public int Length => throw null!;
    public T this[System.Index i] => throw null!;
    public T this[System.Range r] => throw null!;
}
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyDiagnostics();
            // Slice is assumed to be never null
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPatternDeclaration_SlicePattern_NestedNullability()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var a = Infer(s);
    if (a is [_, .. var z, _])
    {
        z.Element.ToString();
    }
 
    s = null;
}
 
Collection<T> Infer<T>(T t) => throw null!;
 
class Collection<T>
{
    public T Element => throw null!;
    public int Length => throw null!;
    public T this[System.Index i] => throw null!;
    public Collection<T> this[System.Range r] => throw null!;
}
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyDiagnostics(
                // (10,9): warning CS8602: Dereference of a possibly null reference.
                //         z.Element.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z.Element").WithLocation(10, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithDeconstructionPattern()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    if (Infer(s) is (var z, var z2))
    {
        z.ToString(); // 1
    }
 
    s = null;
}
 
s = "";
if (Infer(s) is (var y, var y2))
{
    y.ToString();
}
 
s = null;
if (Infer(s) is (var w, var w2))
{
    w.ToString(); // 2
}
 
Container<T> Infer<T>(T t) => throw null!;
 
class Container<T>
{
    public void Deconstruct(out T t1, out T t2) => throw null!;
}
""";
            // Need to re-infer Deconstruct method https://github.com/dotnet/roslyn/issues/34232
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics();
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithFieldPattern()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var a = Infer(s);
    if (a is { field: var z })
    {
        z.ToString(); // 1
    }
 
    s = null;
}
 
 
Container<T> Infer<T>(T t) => throw null!;
 
class Container<T>
{
    public T field = default!;
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (10,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithFieldPattern_Inline()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    if (Infer(s) is { field: var z })
    {
        z.ToString(); // 1
    }
 
    s = null;
}
 
 
Container<T> Infer<T>(T t) => throw null!;
 
class Container<T>
{
    public T field = default!;
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (9,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithPropertyPattern()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var a = Infer(s);
    if (a is { field: var z })
    {
        z.ToString(); // 1
    }
 
    s = null;
}
 
 
Container<T> Infer<T>(T t) => throw null!;
 
class Container<T>
{
    public T field => default!;
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (10,9): warning CS8602: Dereference of a possibly null reference.
                //         z.ToString(); // 1
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(10, 9)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithLocalDeclaration()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    var z = Infer(s)[0];
    z.ToString();
 
    s = null;
}
 
List<T> Infer<T>(T t) => new() { t };
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (9,5): warning CS8602: Dereference of a possibly null reference.
                //     z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 5)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithDeconstructionDeclaration()
        {
            var source = """
#nullable enable
using System.Collections.Generic;
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    (var z, var z2) = (Infer(s)[0], 1);
    z.ToString();
 
    s = null;
}
 
List<T> Infer<T>(T t) => new() { t };
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (9,5): warning CS8602: Dereference of a possibly null reference.
                //     z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(9, 5)
                );
        }
 
        [Fact, WorkItem(65976, "https://github.com/dotnet/roslyn/issues/65976")]
        public void LoopWithDeconstructionDeclaration_CustomType()
        {
            var source = """
#nullable enable
 
string? s = "";
 
for (var x = 0; x < 10; x++)
{
    (var z, var z2) = Infer(s);
    z.ToString();
 
    s = null;
}
 
Container<T> Infer<T>(T t) => throw null!;
 
class Container<T>
{
    public void Deconstruct(out T t1, out T t2) => throw null!;
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (8,5): warning CS8602: Dereference of a possibly null reference.
                //     z.ToString();
                Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "z").WithLocation(8, 5)
                );
        }
    }
}