Skip to content

Commit

Permalink
AbstractFlowPass.VisitIsPatternExpression - add handling for list-pat…
Browse files Browse the repository at this point in the history
…tern specific patterns (#59285)
  • Loading branch information
jcouv authored Feb 15, 2022
1 parent a405d25 commit 3294cef
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,12 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node
{
Debug.Assert(!IsConditionalState);

// Local functions below need to handle all patterns that come through here
Debug.Assert(node.Pattern is
BoundTypePattern or BoundRecursivePattern or BoundITuplePattern or BoundRelationalPattern or
BoundDeclarationPattern or BoundConstantPattern or BoundNegatedPattern or BoundBinaryPattern or
BoundDeclarationPattern or BoundDiscardPattern or BoundListPattern or BoundSlicePattern);

bool negated = node.Pattern.IsNegated(out var pattern);
Debug.Assert(negated == node.IsNegated);

Expand Down Expand Up @@ -976,6 +982,8 @@ static bool patternMatchesNull(BoundPattern pattern)
case BoundRelationalPattern:
case BoundDeclarationPattern { IsVar: false }:
case BoundConstantPattern { ConstantValue: { IsNull: false } }:
case BoundListPattern:
case BoundSlicePattern: // Only occurs in error cases
return false;
case BoundConstantPattern { ConstantValue: { IsNull: true } }:
return true;
Expand Down Expand Up @@ -1035,6 +1043,8 @@ static bool patternMatchesNull(BoundPattern pattern)
case BoundITuplePattern:
case BoundRelationalPattern:
case BoundDeclarationPattern:
case BoundListPattern:
case BoundSlicePattern: // Only occurs in error cases
return null;
default:
throw ExceptionUtilities.UnexpectedValue(pattern.Kind);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8380,4 +8380,81 @@ public void ListPattern_NullTestOnSlice()
Diagnostic(ErrorCode.ERR_SwitchCaseSubsumed, "[1,2,3]").WithLocation(15, 10)
);
}

[Fact, WorkItem(58738, "https://github.com/dotnet/roslyn/issues/58738")]
public void ListPattern_AbstractFlowPass_isBoolTest()
{
var source = @"
var a = new[] { 1 };
if (a is [var x] and x is [1])
{
}
if ((a is [var y] and y) is .. 1)
{
}
var b = new[] { true };
if ((b is [var z] and z) is [true])
{
}
";
var comp = CreateCompilationWithIndexAndRangeAndSpan(new[] { source, TestSources.GetSubArray });
comp.VerifyEmitDiagnostics(
// (4,22): error CS0029: Cannot implicitly convert type 'int' to 'int[]'
// if (a is [var x] and x is [1])
Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("int", "int[]").WithLocation(4, 22),
// (4,27): error CS0021: Cannot apply indexing with [] to an expression of type 'bool'
// if (a is [var x] and x is [1])
Diagnostic(ErrorCode.ERR_BadIndexLHS, "[1]").WithArguments("bool").WithLocation(4, 27),
// (8,23): error CS0029: Cannot implicitly convert type 'int' to 'int[]'
// if ((a is [var y] and y) is .. 1)
Diagnostic(ErrorCode.ERR_NoImplicitConv, "y").WithArguments("int", "int[]").WithLocation(8, 23),
// (8,29): error CS0021: Cannot apply indexing with [] to an expression of type 'bool'
// if ((a is [var y] and y) is .. 1)
Diagnostic(ErrorCode.ERR_BadIndexLHS, ".. 1").WithArguments("bool").WithLocation(8, 29),
// (13,23): error CS0029: Cannot implicitly convert type 'bool' to 'bool[]'
// if ((b is [var z] and z) is [true])
Diagnostic(ErrorCode.ERR_NoImplicitConv, "z").WithArguments("bool", "bool[]").WithLocation(13, 23),
// (13,29): error CS0021: Cannot apply indexing with [] to an expression of type 'bool'
// if ((b is [var z] and z) is [true])
Diagnostic(ErrorCode.ERR_BadIndexLHS, "[true]").WithArguments("bool").WithLocation(13, 29)
);
}

[Fact, WorkItem(58738, "https://github.com/dotnet/roslyn/issues/58738")]
public void ListPattern_AbstractFlowPass_patternMatchesNull()
{
var source = @"
var a = new[] { 1 };
if (a?.M(out var i) is [1])
i.ToString();
else
i.ToString(); // 1
if (a?.M(out var j) is .. 1) // 2, 3
j.ToString();
else
j.ToString();
public static class Extension
{
public static T M<T>(this T t, out int i) => throw null;
}
";
var comp = CreateCompilationWithIndexAndRangeAndSpan(new[] { source, TestSources.GetSubArray });
comp.VerifyEmitDiagnostics(
// (7,5): error CS0165: Use of unassigned local variable 'i'
// i.ToString(); // 1
Diagnostic(ErrorCode.ERR_UseDefViolation, "i").WithArguments("i").WithLocation(7, 5),
// (9,24): error CS8980: Slice patterns may only be used once and directly inside a list pattern.
// if (a?.M(out var j) is .. 1) // 2, 3
Diagnostic(ErrorCode.ERR_MisplacedSlicePattern, ".. 1").WithLocation(9, 24),
// (9,27): error CS0029: Cannot implicitly convert type 'int' to 'int[]'
// if (a?.M(out var j) is .. 1) // 2, 3
Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "int[]").WithLocation(9, 27)
);
}
}

0 comments on commit 3294cef

Please sign in to comment.