Skip to content

Commit ac4fef2

Browse files
committed
Document break for negative Length tests
1 parent d7c97c6 commit ac4fef2

File tree

2 files changed

+166
-0
lines changed

2 files changed

+166
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
## This document lists known breaking changes in Roslyn after .NET 6 all the way to .NET 7.
2+
3+
1. Beginning with C# 11.0, `Length` and `Count` properties on countable and indexable types
4+
are assumed to be non-negative for purpose of subsumption and exhaustiveness analysis of patterns and switches.
5+
Those types can be used with implicit Index indexer and list patterns.
6+
7+
```csharp
8+
void M(int[] i)
9+
{
10+
if (i is { Length: -1 }) {} // error: impossible under assumption of non-negative length
11+
}
12+
```

src/Compilers/CSharp/Test/Semantic/Semantics/PatternMatchingTests_ListPatterns.cs

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5023,6 +5023,160 @@ .locals init (int V_0)
50235023
verifier.VerifyIL("C.Test2", expectedIl);
50245024
}
50255025

5026+
[Fact]
5027+
public void LengthPattern_NegativeLengthTest()
5028+
{
5029+
var src = @"
5030+
int[] a = null;
5031+
_ = a is { Length: -1 }; // 1
5032+
_ = a is { Length: -1 or 1 };
5033+
_ = a is { Length: -1 } or { Length: 1 };
5034+
5035+
_ = a switch // 2
5036+
{
5037+
{ Length: -1 } => 0, // 3
5038+
};
5039+
5040+
_ = a switch // 4
5041+
{
5042+
{ Length: -1 or 1 } => 0,
5043+
};
5044+
5045+
_ = a switch // 5
5046+
{
5047+
{ Length: -1 } or { Length: 1 } => 0,
5048+
};
5049+
5050+
_ = a switch // 6
5051+
{
5052+
{ Length: -1 } => 0, // 7
5053+
{ Length: 1 } => 0,
5054+
};
5055+
";
5056+
var comp = CreateCompilation(src);
5057+
comp.VerifyDiagnostics(
5058+
// (3,5): error CS8518: An expression of type 'int[]' can never match the provided pattern.
5059+
// _ = a is { Length: -1 }; // 1
5060+
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is { Length: -1 }").WithArguments("int[]").WithLocation(3, 5),
5061+
// (7,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '_' is not covered.
5062+
// _ = a switch // 2
5063+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("_").WithLocation(7, 7),
5064+
// (9,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5065+
// { Length: -1 } => 0, // 3
5066+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: -1 }").WithLocation(9, 5),
5067+
// (12,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '{ Length: 0 }' is not covered.
5068+
// _ = a switch // 4
5069+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("{ Length: 0 }").WithLocation(12, 7),
5070+
// (17,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '{ Length: 0 }' is not covered.
5071+
// _ = a switch // 5
5072+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("{ Length: 0 }").WithLocation(17, 7),
5073+
// (22,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '{ Length: 0 }' is not covered.
5074+
// _ = a switch // 6
5075+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("{ Length: 0 }").WithLocation(22, 7),
5076+
// (24,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5077+
// { Length: -1 } => 0, // 7
5078+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: -1 }").WithLocation(24, 5)
5079+
);
5080+
}
5081+
5082+
[Fact]
5083+
public void LengthPattern_NegativeNullHandling_WithNullHandling()
5084+
{
5085+
var src = @"
5086+
int[] a = null;
5087+
_ = a is null or { Length: -1 };
5088+
5089+
_ = a switch // 1
5090+
{
5091+
null => 0,
5092+
{ Length: -1 } => 0, // 2
5093+
};
5094+
";
5095+
var comp = CreateCompilation(src);
5096+
comp.VerifyDiagnostics(
5097+
// (5,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern 'not null' is not covered.
5098+
// _ = a switch // 1
5099+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("not null").WithLocation(5, 7),
5100+
// (8,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5101+
// { Length: -1 } => 0, // 2
5102+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: -1 }").WithLocation(8, 5)
5103+
);
5104+
}
5105+
5106+
[Fact]
5107+
public void LengthPattern_NegativeNullHandling_DuplicateTest()
5108+
{
5109+
var src = @"
5110+
int[] a = null;
5111+
_ = a is { Length: -1 } or { Length: -1 };
5112+
5113+
_ = a switch
5114+
{
5115+
{ Length: -1 } => 1,
5116+
{ Length: -1 } => 2,
5117+
_ => 3,
5118+
};
5119+
";
5120+
var comp = CreateCompilation(src);
5121+
comp.VerifyDiagnostics(
5122+
// (3,5): error CS8518: An expression of type 'int[]' can never match the provided pattern.
5123+
// _ = a is { Length: -1 } or { Length: -1 };
5124+
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is { Length: -1 } or { Length: -1 }").WithArguments("int[]").WithLocation(3, 5),
5125+
// (7,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5126+
// { Length: -1 } => 1,
5127+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: -1 }").WithLocation(7, 5),
5128+
// (8,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5129+
// { Length: -1 } => 2,
5130+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: -1 }").WithLocation(8, 5)
5131+
);
5132+
}
5133+
5134+
[Fact]
5135+
public void LengthPattern_NegativeRangeTest()
5136+
{
5137+
var src = @"
5138+
int[] a = null;
5139+
_ = a is { Length: < 0 }; // 1
5140+
5141+
_ = a switch // 2
5142+
{
5143+
{ Length: < 0 } => 0, // 3
5144+
};
5145+
";
5146+
var comp = CreateCompilation(src);
5147+
comp.VerifyDiagnostics(
5148+
// (3,5): error CS8518: An expression of type 'int[]' can never match the provided pattern.
5149+
// _ = a is { Length: < 0 }; // 1
5150+
Diagnostic(ErrorCode.ERR_IsPatternImpossible, "a is { Length: < 0 }").WithArguments("int[]").WithLocation(3, 5),
5151+
// (5,7): warning CS8509: The switch expression does not handle all possible values of its input type (it is not exhaustive). For example, the pattern '_' is not covered.
5152+
// _ = a switch // 2
5153+
Diagnostic(ErrorCode.WRN_SwitchExpressionNotExhaustive, "switch").WithArguments("_").WithLocation(5, 7),
5154+
// (7,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5155+
// { Length: < 0 } => 0, // 3
5156+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: < 0 }").WithLocation(7, 5)
5157+
);
5158+
}
5159+
5160+
[Fact]
5161+
public void LengthPattern_Switch_NegativeRangeTestByElimination()
5162+
{
5163+
var src = @"
5164+
int[] a = null;
5165+
_ = a switch
5166+
{
5167+
{ Length: 0 } => 1,
5168+
{ Length: <= 0 } => 2,
5169+
_ => 3,
5170+
};
5171+
";
5172+
var comp = CreateCompilation(src);
5173+
comp.VerifyDiagnostics(
5174+
// (6,5): error CS8510: The pattern is unreachable. It has already been handled by a previous arm of the switch expression or it is impossible to match.
5175+
// { Length: <= 0 } => 2,
5176+
Diagnostic(ErrorCode.ERR_SwitchArmSubsumed, "{ Length: <= 0 }").WithLocation(6, 5)
5177+
);
5178+
}
5179+
50265180
[Fact, WorkItem(51801, "https://github.com/dotnet/roslyn/issues/51801")]
50275181
public void IndexerOverrideLacksAccessor()
50285182
{

0 commit comments

Comments
 (0)