File: Semantics\PatternMatchingTests_NullableTypes.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit3\Microsoft.CodeAnalysis.CSharp.Emit3.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit3.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.
 
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests;
 
public class PatternMatchingTests_NullableTypes : PatternMatchingTestBase
{
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternCombinations()
    {
        var source = """
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    if (obj is int? or string?) { }
                    if (obj is int? i1 or string? s) { }
                    if (obj is int? and { }) { }
                    if (obj is int? i2 and { }) { }
                    if (obj is int? i3 and (1, 2)) { }
                    if (obj is int? i4 and []) { }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (7,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? or string?) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(7, 20),
            // (7,28): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (obj is int? or string?) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(7, 28),
            // (8,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? i1 or string? s) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(8, 20),
            // (8,25): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (obj is int? i1 or string? s) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i1").WithLocation(8, 25),
            // (8,31): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (obj is int? i1 or string? s) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(8, 31),
            // (8,39): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (obj is int? i1 or string? s) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s").WithLocation(8, 39),
            // (9,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? and { }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(9, 20),
            // (10,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? i2 and { }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(10, 20),
            // (11,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(11, 20),
            // (11,32): error CS1061: 'int' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
            //         if (obj is int? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "(1, 2)").WithArguments("int", "Deconstruct").WithLocation(11, 32),
            // (11,32): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'int', with 2 out parameters and a void return type.
            //         if (obj is int? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(1, 2)").WithArguments("int", "2").WithLocation(11, 32),
            // (12,20): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (obj is int? i4 and []) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 20),
            // (12,32): error CS8985: List patterns may not be used for a value of type 'int'. No suitable 'Length' or 'Count' property was found.
            //         if (obj is int? i4 and []) { }
            Diagnostic(ErrorCode.ERR_ListPatternRequiresLength, "[]").WithArguments("int").WithLocation(12, 32),
            // (12,32): error CS0518: Predefined type 'System.Index' is not defined or imported
            //         if (obj is int? i4 and []) { }
            Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[]").WithArguments("System.Index").WithLocation(12, 32),
            // (12,32): error CS0021: Cannot apply indexing with [] to an expression of type 'int'
            //         if (obj is int? i4 and []) { }
            Diagnostic(ErrorCode.ERR_BadIndexLHS, "[]").WithArguments("int").WithLocation(12, 32));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternCombinations_Arrays()
    {
        var source = """
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    if (obj is int[]? or string[]?) { }
                    if (obj is int[]? i1 or string[]? s) { }
                    if (obj is int[]? and { }) { }
                    if (obj is int[]? i2 and { }) { }
                    if (obj is int[]? i3 and (1, 2)) { }
                    if (obj is int[]? i4 and []) { }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (7,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? or string[]?) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(7, 20),
            // (7,30): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (obj is int[]? or string[]?) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(7, 30),
            // (8,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? i1 or string[]? s) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(8, 20),
            // (8,27): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (obj is int[]? i1 or string[]? s) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i1").WithLocation(8, 27),
            // (8,33): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (obj is int[]? i1 or string[]? s) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(8, 33),
            // (8,43): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (obj is int[]? i1 or string[]? s) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s").WithLocation(8, 43),
            // (9,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? and { }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(9, 20),
            // (10,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? i2 and { }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(10, 20),
            // (11,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(11, 20),
            // (11,34): error CS1061: 'int[]' does not contain a definition for 'Deconstruct' and no accessible extension method 'Deconstruct' accepting a first argument of type 'int[]' could be found (are you missing a using directive or an assembly reference?)
            //         if (obj is int[]? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "(1, 2)").WithArguments("int[]", "Deconstruct").WithLocation(11, 34),
            // (11,34): error CS8129: No suitable 'Deconstruct' instance or extension method was found for type 'int[]', with 2 out parameters and a void return type.
            //         if (obj is int[]? i3 and (1, 2)) { }
            Diagnostic(ErrorCode.ERR_MissingDeconstruct, "(1, 2)").WithArguments("int[]", "2").WithLocation(11, 34),
            // (12,20): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (obj is int[]? i4 and []) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 20),
            // (12,34): error CS0518: Predefined type 'System.Index' is not defined or imported
            //         if (obj is int[]? i4 and []) { }
            Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "[]").WithArguments("System.Index").WithLocation(12, 34));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternsInSwitchStatement()
    {
        var source = """
            using System.Threading.Tasks;
 
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    var x = 0;
                    switch (obj)
                    {
                        case int?:
                            break;
                        case Task?:
                            break;
                        case int? i1:
                            break;
                        case Task? t1:
                            break;
                        case int? when x > 0:
                            break;
                        case Task? when x > 0:
                            break;
                        case int? i2 when x > 0:
                            break;
                        case Task? t2 when x > 0:
                            break;
                        case (int? when) when x > 0:
                            break;
                        case (Task? when) when x > 0:
                            break;
                    }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (12,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             case int?:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 18),
            // (14,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             case Task?:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(14, 18),
            // (16,21): error CS1003: Syntax error, ':' expected
            //             case int? i1:
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(16, 21),
            // (16,21): error CS1513: } expected
            //             case int? i1:
            Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(16, 21),
            // (16,23): warning CS0164: This label has not been referenced
            //             case int? i1:
            Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i1").WithLocation(16, 23),
            // (18,18): error CS0119: 'Task' is a type, which is not valid in the given context
            //             case Task? t1:
            Diagnostic(ErrorCode.ERR_BadSKunknown, "Task").WithArguments("System.Threading.Tasks.Task", "type").WithLocation(18, 18),
            // (18,24): error CS0103: The name 't1' does not exist in the current context
            //             case Task? t1:
            Diagnostic(ErrorCode.ERR_NameNotInContext, "t1").WithArguments("t1").WithLocation(18, 24),
            // (18,27): error CS1525: Invalid expression term 'break'
            //             case Task? t1:
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, "").WithArguments("break").WithLocation(18, 27),
            // (18,27): error CS1003: Syntax error, ':' expected
            //             case Task? t1:
            Diagnostic(ErrorCode.ERR_SyntaxError, "").WithArguments(":").WithLocation(18, 27),
            // (20,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             case int? when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(20, 18),
            // (22,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             case Task? when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(22, 18),
            // (24,18): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             case int? i2 when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(24, 18),
            // (26,18): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             case Task? t2 when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(26, 18),
            // (28,19): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             case (int? when) when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(28, 19),
            // (30,19): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             case (Task? when) when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(30, 19));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternsInSwitchStatement_Arrays()
    {
        var source = """
            using System.Threading.Tasks;
 
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    var x = 0;
                    switch (obj)
                    {
                        case int[]?:
                            break;
                        case Task[]?:
                            break;
                        case int[]? i1:
                            break;
                        case Task[]? t1:
                            break;
                        case int[]? when x > 0:
                            break;
                        case Task[]? when x > 0:
                            break;
                        case int[]? i2 when x > 0:
                            break;
                        case Task[]? t2 when x > 0:
                            break;
                        case (int[]? when) when x > 0:
                            break;
                        case (Task[]? when) when x > 0:
                            break;
                    }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (12,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             case int[]?:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 18),
            // (14,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             case Task[]?:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(14, 18),
            // (16,23): error CS1003: Syntax error, ':' expected
            //             case int[]? i1:
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(16, 23),
            // (16,23): error CS1513: } expected
            //             case int[]? i1:
            Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(16, 23),
            // (16,25): warning CS0164: This label has not been referenced
            //             case int[]? i1:
            Diagnostic(ErrorCode.WRN_UnreferencedLabel, "i1").WithLocation(16, 25),
            // (18,24): error CS1003: Syntax error, ':' expected
            //             case Task[]? t1:
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments(":").WithLocation(18, 24),
            // (18,24): error CS1513: } expected
            //             case Task[]? t1:
            Diagnostic(ErrorCode.ERR_RbraceExpected, "?").WithLocation(18, 24),
            // (18,26): warning CS0164: This label has not been referenced
            //             case Task[]? t1:
            Diagnostic(ErrorCode.WRN_UnreferencedLabel, "t1").WithLocation(18, 26),
            // (20,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             case int[]? when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(20, 18),
            // (22,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             case Task[]? when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(22, 18),
            // (24,18): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             case int[]? i2 when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(24, 18),
            // (26,18): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             case Task[]? t2 when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(26, 18),
            // (28,19): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             case (int[]? when) when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(28, 19),
            // (30,19): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             case (Task[]? when) when x > 0:
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(30, 19));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternsInSwitchExpression()
    {
        var source = """
            using System.Threading.Tasks;
 
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    var x = 0;
                    _ = obj switch
                    {
                        int? => 1,
                        Task? => 2,
                        int? i1 => 3,
                        Task? t1 => 4,
                        int? when x > 0 => 5,
                        Task? when x > 0 => 6,
                        int? i2 when x > 0 => 7,
                        Task? t2 when x > 0 => 8,
                        (int? when) when x > 0 => 9,
                        (Task? when) when x > 0 => 10
                    };
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (12,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             int? => 1,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(12, 13),
            // (13,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             Task? => 2,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(13, 13),
            // (14,16): error CS1003: Syntax error, '=>' expected
            //             int? i1 => 3,
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(14, 16),
            // (14,16): error CS1525: Invalid expression term '?'
            //             int? i1 => 3,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(14, 16),
            // (14,25): error CS1003: Syntax error, ':' expected
            //             int? i1 => 3,
            Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(14, 25),
            // (14,25): error CS1525: Invalid expression term ','
            //             int? i1 => 3,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(14, 25),
            // (15,17): error CS1003: Syntax error, '=>' expected
            //             Task? t1 => 4,
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(15, 17),
            // (15,17): error CS1525: Invalid expression term '?'
            //             Task? t1 => 4,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(15, 17),
            // (15,26): error CS1003: Syntax error, ':' expected
            //             Task? t1 => 4,
            Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(15, 26),
            // (15,26): error CS1525: Invalid expression term ','
            //             Task? t1 => 4,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(15, 26),
            // (16,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             int? when x > 0 => 5,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(16, 13),
            // (17,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             Task? when x > 0 => 6,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(17, 13),
            // (18,13): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             int? i2 when x > 0 => 7,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(18, 13),
            // (19,13): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             Task? t2 when x > 0 => 8,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(19, 13),
            // (20,14): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //             (int? when) when x > 0 => 9,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(20, 14),
            // (21,14): error CS8116: It is not legal to use nullable type 'Task?' in a pattern; use the underlying type 'Task' instead.
            //             (Task? when) when x > 0 => 10
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task?").WithArguments("System.Threading.Tasks.Task").WithLocation(21, 14));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PatternsInSwitchExpression_Arrays()
    {
        var source = """
            using System.Threading.Tasks;
 
            #nullable enable
 
            class C
            {
                void M(object obj)
                {
                    var x = 0;
                    _ = obj switch
                    {
                        int[]? => 1,
                        Task[]? => 2,
                        int[]? i1 => 3,
                        Task[]? t1 => 4,
                        int[]? when x > 0 => 5,
                        Task[]? when x > 0 => 6,
                        int[]? i2 when x > 0 => 7,
                        Task[]? t2 when x > 0 => 8,
                        (int[]? when) when x > 0 => 9,
                        (Task[]? when) when x > 0 => 10
                    };
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (12,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             int[]? => 1,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(12, 13),
            // (13,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             Task[]? => 2,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(13, 13),
            // (14,18): error CS1003: Syntax error, '=>' expected
            //             int[]? i1 => 3,
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(14, 18),
            // (14,18): error CS1525: Invalid expression term '?'
            //             int[]? i1 => 3,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(14, 18),
            // (14,27): error CS1003: Syntax error, ':' expected
            //             int[]? i1 => 3,
            Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(14, 27),
            // (14,27): error CS1525: Invalid expression term ','
            //             int[]? i1 => 3,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(14, 27),
            // (15,19): error CS1003: Syntax error, '=>' expected
            //             Task[]? t1 => 4,
            Diagnostic(ErrorCode.ERR_SyntaxError, "?").WithArguments("=>").WithLocation(15, 19),
            // (15,19): error CS1525: Invalid expression term '?'
            //             Task[]? t1 => 4,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, "?").WithArguments("?").WithLocation(15, 19),
            // (15,28): error CS1003: Syntax error, ':' expected
            //             Task[]? t1 => 4,
            Diagnostic(ErrorCode.ERR_SyntaxError, ",").WithArguments(":").WithLocation(15, 28),
            // (15,28): error CS1525: Invalid expression term ','
            //             Task[]? t1 => 4,
            Diagnostic(ErrorCode.ERR_InvalidExprTerm, ",").WithArguments(",").WithLocation(15, 28),
            // (16,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             int[]? when x > 0 => 5,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(16, 13),
            // (17,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             Task[]? when x > 0 => 6,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(17, 13),
            // (18,13): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             int[]? i2 when x > 0 => 7,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(18, 13),
            // (19,13): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             Task[]? t2 when x > 0 => 8,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(19, 13),
            // (20,14): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //             (int[]? when) when x > 0 => 9,
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(20, 14),
            // (21,14): error CS8116: It is not legal to use nullable type 'Task[]?' in a pattern; use the underlying type 'Task[]' instead.
            //             (Task[]? when) when x > 0 => 10
            Diagnostic(ErrorCode.ERR_PatternNullableType, "Task[]?").WithArguments("System.Threading.Tasks.Task[]").WithLocation(21, 14));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PropertySubpatterns()
    {
        var source = """
            #nullable enable
 
            class E
            {
                public object? Prop { get; set; }
                public object? Prop2 { get; set; }
            }
 
            class C
            {
                void M(E e)
                {
                    if (e is { Prop: int? }) { }
                    if (e is { Prop: int? i1 }) { }
                    if (e is { Prop: int? or string? }) { }
                    if (e is { Prop: int? i2 or string? s1 }) { }
                    if (e is { Prop: int?, Prop2: string? }) { }
                    if (e is { Prop: int? i3, Prop2: string? s2 }) { }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (13,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(13, 26),
            // (14,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int? i1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(14, 26),
            // (15,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int? or string? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(15, 26),
            // (15,34): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (e is { Prop: int? or string? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(15, 34),
            // (16,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int? i2 or string? s1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(16, 26),
            // (16,31): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (e is { Prop: int? i2 or string? s1 }) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i2").WithLocation(16, 31),
            // (16,37): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (e is { Prop: int? i2 or string? s1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(16, 37),
            // (16,45): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (e is { Prop: int? i2 or string? s1 }) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s1").WithLocation(16, 45),
            // (17,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int?, Prop2: string? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(17, 26),
            // (17,39): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (e is { Prop: int?, Prop2: string? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(17, 39),
            // (18,26): error CS8116: It is not legal to use nullable type 'int?' in a pattern; use the underlying type 'int' instead.
            //         if (e is { Prop: int? i3, Prop2: string? s2 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int?").WithArguments("int").WithLocation(18, 26),
            // (18,42): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (e is { Prop: int? i3, Prop2: string? s2 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(18, 42));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void PropertySubpatterns_Arrays()
    {
        var source = """
            #nullable enable
 
            class E
            {
                public object? Prop { get; set; }
                public object? Prop2 { get; set; }
            }
 
            class C
            {
                void M(E e)
                {
                    if (e is { Prop: int[]? }) { }
                    if (e is { Prop: int[]? i1 }) { }
                    if (e is { Prop: int[]? or string[]? }) { }
                    if (e is { Prop: int[]? i2 or string[]? s1 }) { }
                    if (e is { Prop: int[]?, Prop2: string[]? }) { }
                    if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
                }
            }
            """;
 
        var comp = CreateCompilation(source);
        comp.VerifyDiagnostics(
            // (13,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(13, 26),
            // (14,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]? i1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(14, 26),
            // (15,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]? or string[]? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(15, 26),
            // (15,36): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (e is { Prop: int[]? or string[]? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(15, 36),
            // (16,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]? i2 or string[]? s1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(16, 26),
            // (16,33): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (e is { Prop: int[]? i2 or string[]? s1 }) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "i2").WithLocation(16, 33),
            // (16,39): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (e is { Prop: int[]? i2 or string[]? s1 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(16, 39),
            // (16,49): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
            //         if (e is { Prop: int[]? i2 or string[]? s1 }) { }
            Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "s1").WithLocation(16, 49),
            // (17,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]?, Prop2: string[]? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(17, 26),
            // (17,41): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (e is { Prop: int[]?, Prop2: string[]? }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(17, 41),
            // (18,26): error CS8116: It is not legal to use nullable type 'int[]?' in a pattern; use the underlying type 'int[]' instead.
            //         if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "int[]?").WithArguments("int[]").WithLocation(18, 26),
            // (18,44): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (e is { Prop: int[]? i3, Prop2: string[]? s2 }) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(18, 44));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void ListPatterns()
    {
        var source = """
            #nullable enable
 
            class C
            {
                void M2(string s)
                {
                    if (s is [.. string?]) { }
                    if (s is [.. string? slice1]) { }
                    if (s is [.. string? slice2, ')']) { }
                }
            }
            """;
 
        var comp = CreateCompilationWithIndexAndRange(source);
        comp.VerifyDiagnostics(
            // (7,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (s is [.. string?]) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(7, 22),
            // (8,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (s is [.. string? slice1]) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(8, 22),
            // (9,22): error CS8116: It is not legal to use nullable type 'string?' in a pattern; use the underlying type 'string' instead.
            //         if (s is [.. string? slice2, ')']) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string?").WithArguments("string").WithLocation(9, 22));
    }
 
    [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72720")]
    public void ListPatterns_Arrays()
    {
        var source = """
            #nullable enable
 
            class C
            {
                void M(string[] s)
                {
                    if (s is [.. string[]?]) { }
                    if (s is [.. string[]? slice1]) { }
                    if (s is [.. string[]? slice2, ")"]) { }
                }
            }
            """;
 
        var comp = CreateCompilationWithIndexAndRange([source, TestSources.GetSubArray]);
        comp.VerifyDiagnostics(
            // (7,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (s is [.. string[]?]) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(7, 22),
            // (8,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (s is [.. string[]? slice1]) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(8, 22),
            // (9,22): error CS8116: It is not legal to use nullable type 'string[]?' in a pattern; use the underlying type 'string[]' instead.
            //         if (s is [.. string[]? slice2, ')']) { }
            Diagnostic(ErrorCode.ERR_PatternNullableType, "string[]?").WithArguments("string[]").WithLocation(9, 22));
    }
}