Skip to content

Commit ec48412

Browse files
author
msftbot[bot]
authored
Merge pull request #45104 from dotnet/merges/release/dev16.7-preview3-to-release/dev16.7-preview3-vs-deps
Merge release/dev16.7-preview3 to release/dev16.7-preview3-vs-deps
2 parents 7869637 + 5cddfce commit ec48412

File tree

4 files changed

+257
-47
lines changed

4 files changed

+257
-47
lines changed

src/Compilers/CSharp/Portable/Binder/Binder_Patterns.cs

+9-7
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private BoundExpression BindIsPatternExpression(IsPatternExpressionSyntax node,
3636

3737
Debug.Assert(expression.Type is { });
3838
uint inputValEscape = GetValEscape(expression, LocalScopeDepth);
39-
BoundPattern pattern = BindPattern(node.Pattern, expression.Type, inputValEscape, permitDesignations: true, hasErrors, diagnostics);
39+
BoundPattern pattern = BindPattern(node.Pattern, expression.Type, inputValEscape, permitDesignations: true, hasErrors, diagnostics, underIsPattern: true);
4040
hasErrors |= pattern.HasErrors;
4141
return MakeIsPatternExpression(
4242
node, expression, pattern, GetSpecialType(SpecialType.System_Boolean, diagnostics, node),
@@ -140,7 +140,8 @@ internal BoundPattern BindPattern(
140140
uint inputValEscape,
141141
bool permitDesignations,
142142
bool hasErrors,
143-
DiagnosticBag diagnostics)
143+
DiagnosticBag diagnostics,
144+
bool underIsPattern = false)
144145
{
145146
return node switch
146147
{
@@ -149,9 +150,9 @@ internal BoundPattern BindPattern(
149150
ConstantPatternSyntax p => BindConstantPatternWithFallbackToTypePattern(p, inputType, hasErrors, diagnostics),
150151
RecursivePatternSyntax p => BindRecursivePattern(p, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics),
151152
VarPatternSyntax p => BindVarPattern(p, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics),
152-
ParenthesizedPatternSyntax p => BindPattern(p.Pattern, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics),
153+
ParenthesizedPatternSyntax p => BindPattern(p.Pattern, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics, underIsPattern),
153154
BinaryPatternSyntax p => BindBinaryPattern(p, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics),
154-
UnaryPatternSyntax p => BindUnaryPattern(p, inputType, inputValEscape, hasErrors, diagnostics),
155+
UnaryPatternSyntax p => BindUnaryPattern(p, inputType, inputValEscape, hasErrors, diagnostics, underIsPattern),
155156
RelationalPatternSyntax p => BindRelationalPattern(p, inputType, hasErrors, diagnostics),
156157
TypePatternSyntax p => BindTypePattern(p, inputType, hasErrors, diagnostics),
157158
_ => throw ExceptionUtilities.UnexpectedValue(node.Kind()),
@@ -1315,10 +1316,11 @@ private BoundPattern BindUnaryPattern(
13151316
TypeSymbol inputType,
13161317
uint inputValEscape,
13171318
bool hasErrors,
1318-
DiagnosticBag diagnostics)
1319+
DiagnosticBag diagnostics,
1320+
bool underIsPattern)
13191321
{
1320-
const bool permitDesignations = false; // prevent designators under 'not'
1321-
var subPattern = BindPattern(node.Pattern, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics);
1322+
bool permitDesignations = underIsPattern; // prevent designators under 'not' except under an is-pattern
1323+
var subPattern = BindPattern(node.Pattern, inputType, inputValEscape, permitDesignations, hasErrors, diagnostics, underIsPattern);
13221324
return new BoundNegatedPattern(node, subPattern, inputType: inputType, convertedType: inputType, hasErrors);
13231325
}
13241326

src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs

+15-1
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,16 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node
959959
{
960960
Debug.Assert(!IsConditionalState);
961961
VisitRvalue(node.Expression);
962-
VisitPattern(node.Pattern);
962+
963+
var pattern = node.Pattern;
964+
bool negated = false;
965+
while (pattern is BoundNegatedPattern n)
966+
{
967+
negated = !negated;
968+
pattern = n.Negated;
969+
}
970+
971+
VisitPattern(pattern);
963972
var reachableLabels = node.DecisionDag.ReachableLabels;
964973
if (!reachableLabels.Contains(node.WhenTrueLabel))
965974
{
@@ -972,6 +981,11 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node
972981
SetConditionalState(this.State, UnreachableState());
973982
}
974983

984+
if (negated)
985+
{
986+
SetConditionalState(this.StateWhenFalse, this.StateWhenTrue);
987+
}
988+
975989
return node;
976990
}
977991

src/Compilers/CSharp/Test/Emit/Emit/EndToEndTests.cs

+9-8
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,15 @@ public void DeeplyNestedGeneric()
154154
{
155155
int nestingLevel = (ExecutionConditionUtil.Architecture, ExecutionConditionUtil.Configuration) switch
156156
{
157-
(ExecutionArchitecture.x64, ExecutionConfiguration.Debug) when ExecutionConditionUtil.IsMacOS => 200,
158-
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) when ExecutionConditionUtil.IsMacOS => 520,
159-
_ when ExecutionConditionUtil.IsCoreClrUnix => 1200,
160-
_ when ExecutionConditionUtil.IsMonoDesktop => 730,
161-
(ExecutionArchitecture.x86, ExecutionConfiguration.Debug) => 460,
162-
(ExecutionArchitecture.x86, ExecutionConfiguration.Release) => 1350,
163-
(ExecutionArchitecture.x64, ExecutionConfiguration.Debug) => 260,
164-
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) => 750,
157+
// Legacy baselines are indicated by comments
158+
(ExecutionArchitecture.x64, ExecutionConfiguration.Debug) when ExecutionConditionUtil.IsMacOS => 200, // 100
159+
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) when ExecutionConditionUtil.IsMacOS => 520, // 100
160+
_ when ExecutionConditionUtil.IsCoreClrUnix => 1200, // 1200
161+
_ when ExecutionConditionUtil.IsMonoDesktop => 730, // 730
162+
(ExecutionArchitecture.x86, ExecutionConfiguration.Debug) => 460, // 270
163+
(ExecutionArchitecture.x86, ExecutionConfiguration.Release) => 1320, // 1290
164+
(ExecutionArchitecture.x64, ExecutionConfiguration.Debug) => 260, // 170
165+
(ExecutionArchitecture.x64, ExecutionConfiguration.Release) => 750, // 730
165166
_ => throw new Exception($"Unexpected configuration {ExecutionConditionUtil.Architecture} {ExecutionConditionUtil.Configuration}")
166167
};
167168

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

+224-31
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,9 @@ void Good(object o)
19501950
if (o is 1 and int x3) { }
19511951
if (o is (1 or 2) and int x4) { }
19521952
if (o is not (1 or 2) and int x5) { }
1953+
1954+
if (o is not int x6) { }
1955+
if (o is not (1 and int x7)) { }
19531956
}
19541957
19551958
void Bad(object o)
@@ -1958,11 +1961,9 @@ void Bad(object o)
19581961
if (o is int y2 or (1 or 2)) { }
19591962
if (o is 1 or int y3) { }
19601963
if (o is (1 or 2) or int y4) { }
1961-
if (o is not int y5) { }
1962-
if (o is not (1 and int y6)) { }
1963-
if (o is Point { X: var y7 } or Animal _) { }
1964-
if (o is Point(var y8, _) or Animal _) { }
1965-
if (o is object or (1 or var y9)) { }
1964+
if (o is Point { X: var y5 } or Animal _) { }
1965+
if (o is Point(var y6, _) or Animal _) { }
1966+
if (o is object or (1 or var y7)) { }
19661967
}
19671968
19681969
void NotBad(object o)
@@ -1984,36 +1985,30 @@ class Animal { }
19841985
";
19851986
var compilation = CreateCompilation(source, parseOptions: TestOptions.RegularPreview);
19861987
compilation.VerifyDiagnostics(
1987-
// (16,22): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
1988+
// (19,22): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
19881989
// if (o is int y1 or 1) { }
1989-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y1").WithLocation(16, 22),
1990-
// (17,22): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
1990+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y1").WithLocation(19, 22),
1991+
// (20,22): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
19911992
// if (o is int y2 or (1 or 2)) { }
1992-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y2").WithLocation(17, 22),
1993-
// (18,27): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
1993+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y2").WithLocation(20, 22),
1994+
// (21,27): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
19941995
// if (o is 1 or int y3) { }
1995-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y3").WithLocation(18, 27),
1996-
// (19,34): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
1996+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y3").WithLocation(21, 27),
1997+
// (22,34): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
19971998
// if (o is (1 or 2) or int y4) { }
1998-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y4").WithLocation(19, 34),
1999-
// (20,26): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2000-
// if (o is not int y5) { }
2001-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y5").WithLocation(20, 26),
2002-
// (21,33): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2003-
// if (o is not (1 and int y6)) { }
2004-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y6").WithLocation(21, 33),
2005-
// (22,33): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2006-
// if (o is Point { X: var y7 } or Animal _) { }
2007-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y7").WithLocation(22, 33),
2008-
// (23,28): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2009-
// if (o is Point(var y8, _) or Animal _) { }
2010-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y8").WithLocation(23, 28),
2011-
// (24,13): warning CS8794: An expression of type 'object' always matches the provided pattern.
2012-
// if (o is object or (1 or var y9)) { }
2013-
Diagnostic(ErrorCode.WRN_IsPatternAlways, "o is object or (1 or var y9)").WithArguments("object").WithLocation(24, 13),
2014-
// (24,38): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2015-
// if (o is object or (1 or var y9)) { }
2016-
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y9").WithLocation(24, 38)
1999+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y4").WithLocation(22, 34),
2000+
// (23,33): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2001+
// if (o is Point { X: var y5 } or Animal _) { }
2002+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y5").WithLocation(23, 33),
2003+
// (24,28): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2004+
// if (o is Point(var y6, _) or Animal _) { }
2005+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y6").WithLocation(24, 28),
2006+
// (25,13): warning CS8794: An expression of type 'object' always matches the provided pattern.
2007+
// if (o is object or (1 or var y7)) { }
2008+
Diagnostic(ErrorCode.WRN_IsPatternAlways, "o is object or (1 or var y7)").WithArguments("object").WithLocation(25, 13),
2009+
// (25,38): error CS8780: A variable may not be declared within a 'not' or 'or' pattern.
2010+
// if (o is object or (1 or var y7)) { }
2011+
Diagnostic(ErrorCode.ERR_DesignatorBeneathPatternCombinator, "y7").WithLocation(25, 38)
20172012
);
20182013
}
20192014

@@ -5641,5 +5636,203 @@ public void M() {
56415636
Diagnostic(ErrorCode.ERR_IntDivByZero, "0/0").WithLocation(4, 22)
56425637
);
56435638
}
5639+
5640+
[Fact]
5641+
public void IsNot_01()
5642+
{
5643+
var source =
5644+
@"using System;
5645+
class C
5646+
{
5647+
static void Main()
5648+
{
5649+
object o = ""s"";
5650+
if (o is not string s) return;
5651+
Console.WriteLine(s);
5652+
}
5653+
}";
5654+
string expectedOutput = "s";
5655+
var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
5656+
compilation.VerifyDiagnostics(
5657+
);
5658+
var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
5659+
}
5660+
5661+
[Fact]
5662+
public void IsNot_02()
5663+
{
5664+
var source =
5665+
@"using System;
5666+
class C
5667+
{
5668+
static void Main()
5669+
{
5670+
object o = ""s"";
5671+
if (o is (not (string s))) return;
5672+
Console.WriteLine(s);
5673+
}
5674+
}";
5675+
string expectedOutput = "s";
5676+
var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
5677+
compilation.VerifyDiagnostics(
5678+
);
5679+
var compVerifier = CompileAndVerify(compilation, expectedOutput: expectedOutput);
5680+
}
5681+
5682+
[Fact]
5683+
public void IsNot_03()
5684+
{
5685+
var source =
5686+
@"class C
5687+
{
5688+
static void Main()
5689+
{
5690+
object o = ""s"";
5691+
{
5692+
if (o is string s)
5693+
_ = s;
5694+
else
5695+
_ = s; // 1
5696+
}
5697+
{
5698+
if (o is not string s)
5699+
_ = s; // 2
5700+
else
5701+
_ = s;
5702+
}
5703+
{
5704+
if (o is not not string s)
5705+
_ = s;
5706+
else
5707+
_ = s; // 3
5708+
}
5709+
{
5710+
if (o is not not not string s)
5711+
_ = s; // 4
5712+
else
5713+
_ = s;
5714+
}
5715+
}
5716+
}";
5717+
var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
5718+
compilation.VerifyDiagnostics(
5719+
// (10,21): error CS0165: Use of unassigned local variable 's'
5720+
// _ = s; // 1
5721+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(10, 21),
5722+
// (14,21): error CS0165: Use of unassigned local variable 's'
5723+
// _ = s; // 2
5724+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(14, 21),
5725+
// (22,21): error CS0165: Use of unassigned local variable 's'
5726+
// _ = s; // 3
5727+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(22, 21),
5728+
// (26,21): error CS0165: Use of unassigned local variable 's'
5729+
// _ = s; // 4
5730+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(26, 21)
5731+
);
5732+
}
5733+
5734+
[Fact]
5735+
public void IsNot_04()
5736+
{
5737+
var source =
5738+
@"class C
5739+
{
5740+
static void Main()
5741+
{
5742+
object o = ""s"";
5743+
{
5744+
if (o is (string s))
5745+
_ = s;
5746+
else
5747+
_ = s; // 1
5748+
}
5749+
{
5750+
if (o is (not (string s)))
5751+
_ = s; // 2
5752+
else
5753+
_ = s;
5754+
}
5755+
{
5756+
if (o is (not (not (string s))))
5757+
_ = s;
5758+
else
5759+
_ = s; // 3
5760+
}
5761+
{
5762+
if (o is (not (not (not (string s)))))
5763+
_ = s; // 4
5764+
else
5765+
_ = s;
5766+
}
5767+
}
5768+
}";
5769+
var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
5770+
compilation.VerifyDiagnostics(
5771+
// (10,21): error CS0165: Use of unassigned local variable 's'
5772+
// _ = s; // 1
5773+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(10, 21),
5774+
// (14,21): error CS0165: Use of unassigned local variable 's'
5775+
// _ = s; // 2
5776+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(14, 21),
5777+
// (22,21): error CS0165: Use of unassigned local variable 's'
5778+
// _ = s; // 3
5779+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(22, 21),
5780+
// (26,21): error CS0165: Use of unassigned local variable 's'
5781+
// _ = s; // 4
5782+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(26, 21)
5783+
);
5784+
}
5785+
5786+
[Fact]
5787+
public void IsNot_05()
5788+
{
5789+
var source =
5790+
@"class C
5791+
{
5792+
static void Main()
5793+
{
5794+
(object, object) o = (1, 2);
5795+
{
5796+
if (o is (1, string s))
5797+
_ = s;
5798+
else
5799+
_ = s; // 1
5800+
}
5801+
{
5802+
if (o is (not (1, string s)))
5803+
_ = s; // 2
5804+
else
5805+
_ = s;
5806+
}
5807+
{
5808+
if (o is (not (not (1, string s))))
5809+
_ = s;
5810+
else
5811+
_ = s; // 3
5812+
}
5813+
{
5814+
if (o is (not (not (not (1, string s)))))
5815+
_ = s; // 4
5816+
else
5817+
_ = s;
5818+
}
5819+
}
5820+
}";
5821+
var compilation = CreateCompilation(source, options: TestOptions.ReleaseExe, parseOptions: TestOptions.RegularWithPatternCombinators);
5822+
compilation.VerifyDiagnostics(
5823+
// (10,21): error CS0165: Use of unassigned local variable 's'
5824+
// _ = s; // 1
5825+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(10, 21),
5826+
// (14,21): error CS0165: Use of unassigned local variable 's'
5827+
// _ = s; // 2
5828+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(14, 21),
5829+
// (22,21): error CS0165: Use of unassigned local variable 's'
5830+
// _ = s; // 3
5831+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(22, 21),
5832+
// (26,21): error CS0165: Use of unassigned local variable 's'
5833+
// _ = s; // 4
5834+
Diagnostic(ErrorCode.ERR_UseDefViolation, "s").WithArguments("s").WithLocation(26, 21)
5835+
);
5836+
}
56445837
}
56455838
}

0 commit comments

Comments
 (0)