Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge "improved definite assignment" to main #54004

Merged
merged 28 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e1bee98
Implement conditional expression changes in definite assignment (#51498)
RikkiGibson Mar 5, 2021
f0f4f1d
Merge pull request #51746 from dotnet/merges/main-to-features/improve…
Mar 9, 2021
8111455
Merge pull request #51866 from dotnet/merges/main-to-features/improve…
Mar 14, 2021
e236ed7
Merge pull request #52027 from dotnet/merges/main-to-features/improve…
Mar 22, 2021
91443c5
Null coalescing in definite assignment (#51567)
RikkiGibson Mar 22, 2021
b288f06
Merge pull request #52200 from dotnet/merges/main-to-features/improve…
Mar 28, 2021
377db42
Merge pull request #52404 from dotnet/merges/main-to-features/improve…
Apr 4, 2021
4dd9621
Merge pull request #52550 from dotnet/merges/main-to-features/improve…
Apr 11, 2021
0eea7b1
Learn from bool constants and conditional accesses inside ==/!= (#52425)
RikkiGibson Apr 12, 2021
0b02f3e
Merge remote-tracking branch 'upstream/main' into merges/main-to-feat…
RikkiGibson Apr 18, 2021
66fcef4
Merge pull request #52711 from dotnet/merges/main-to-features/improve…
Apr 18, 2021
667fb28
Handle 'is' operators and patterns in definite assignment (#52616)
RikkiGibson Apr 20, 2021
66381d0
Merge pull request #52900 from dotnet/merges/main-to-features/improve…
RikkiGibson Apr 25, 2021
7986515
Merge remote-tracking branch 'upstream/main' into merges/main-to-feat…
RikkiGibson May 2, 2021
fbac2e0
Merge pull request #53084 from dotnet/merges/main-to-features/improve…
May 2, 2021
884d730
Improved nullable '??' analysis (#52646)
RikkiGibson May 4, 2021
b8ed695
Merge pull request #53284 from dotnet/merges/main-to-features/improve…
May 9, 2021
182dd83
Improved nullable conditional operator analysis (#52783)
RikkiGibson May 10, 2021
c1d3c76
Merge pull request #53444 from dotnet/merges/main-to-features/improve…
RikkiGibson May 18, 2021
0e2bd9d
Merge remote-tracking branch 'upstream/main' into merges/main-to-feat…
RikkiGibson May 20, 2021
86c09bc
Merge pull request #53546 from dotnet/merges/main-to-features/improve…
RikkiGibson May 20, 2021
d5eed34
Improved nullable '=='/'!=' analysis (#53198)
RikkiGibson May 21, 2021
beea8f8
Merge pull request #53623 from dotnet/merges/main-to-features/improve…
RikkiGibson May 24, 2021
28cd063
Merge pull request #53775 from dotnet/merges/main-to-features/improve…
May 30, 2021
d56e659
Merge pull request #53901 from dotnet/merges/main-to-features/improve…
Jun 6, 2021
3a3cb9c
Merge pull request #53919 from dotnet/merges/main-to-features/improve…
RikkiGibson Jun 7, 2021
a442936
Fix region analysis of == containing ?. (#53687)
RikkiGibson Jun 8, 2021
2cca737
Improved nullable 'is' analysis (#53311)
RikkiGibson Jun 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
544 changes: 459 additions & 85 deletions src/Compilers/CSharp/Portable/FlowAnalysis/AbstractFlowPass.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,8 @@ public override BoundNode VisitLocal(BoundLocal node)
{
Diagnostics.Add(ErrorCode.ERR_FixedLocalInLambda, new SourceLocation(node.Syntax), localSymbol);
}

SplitIfBooleanConstant(node);
return null;
}

Expand Down
553 changes: 405 additions & 148 deletions src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ internal sealed partial class NullableWalker
/// Learn something about the input from a test of a given expression against a given pattern. The given
/// state is updated to note that any slots that are tested against `null` may be null.
/// </summary>
/// <returns>true if there is a top-level explicit null check</returns>
private void LearnFromAnyNullPatterns(
BoundExpression expression,
BoundPattern pattern)
Expand Down Expand Up @@ -57,7 +56,7 @@ public override BoundNode VisitRecursivePattern(BoundRecursivePattern node)

public override BoundNode VisitConstantPattern(BoundConstantPattern node)
{
Visit(node.Value);
VisitRvalue(node.Value);
return null;
}

Expand Down Expand Up @@ -216,7 +215,7 @@ protected override LocalState VisitSwitchStatementDispatch(BoundSwitchStatement
DeclareLocals(section.Locals);
}

var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState);
var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState, stateWhenNotNullOpt: null);
foreach (var section in node.SwitchSections)
{
foreach (var label in section.SwitchLabels)
Expand Down Expand Up @@ -287,7 +286,8 @@ public PossiblyConditionalState Clone()
SyntaxNode node,
BoundDecisionDag decisionDag,
BoundExpression expression,
TypeWithState expressionType)
TypeWithState expressionType,
PossiblyConditionalState? stateWhenNotNullOpt)
{
// We reuse the slot at the beginning of a switch (or is-pattern expression), pretending that we are
// not copying the input to evaluate the patterns. In this way we infer non-nullability of the original
Expand Down Expand Up @@ -512,7 +512,18 @@ public PossiblyConditionalState Clone()
break;
case BoundDagValueTest t:
Debug.Assert(t.Value != ConstantValue.Null);
if (inputSlot > 0)
// When we compare `bool?` inputs to bool constants, we follow a graph roughly like the following:
// [0]: t0 != null ? [1] : [5]
// [1]: t1 = (bool)t0; [2]
// [2] (this node): t1 == boolConstant ? [3] : [4]
// ...(remaining states)
if (stateWhenNotNullOpt is { } stateWhenNotNull
&& t.Input.Source is BoundDagTypeEvaluation { Input: { IsOriginalInput: true } })
{
SetPossiblyConditionalState(stateWhenNotNull);
Split();
}
else if (inputSlot > 0)
{
learnFromNonNullTest(inputSlot, ref this.StateWhenTrue);
}
Expand Down Expand Up @@ -600,6 +611,10 @@ public PossiblyConditionalState Clone()

void learnFromNonNullTest(int inputSlot, ref LocalState state)
{
if (stateWhenNotNullOpt is { } stateWhenNotNull && inputSlot == originalInputSlot)
{
state = CloneAndUnsplit(ref stateWhenNotNull);
}
LearnFromNonNullTest(inputSlot, ref state);
if (originalInputMap.TryGetValue(inputSlot, out var expression))
LearnFromNonNullTest(expression, ref state);
Expand Down Expand Up @@ -732,7 +747,7 @@ private void VisitSwitchExpressionCore(BoundSwitchExpression node, bool inferTyp

Visit(node.Expression);
var expressionState = ResultType;
var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState);
var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState, stateWhenNotNullOpt: null);
var endState = UnreachableState();

if (!node.ReportedNotExhaustive && node.DefaultLabel != null &&
Expand Down Expand Up @@ -840,9 +855,9 @@ public override BoundNode VisitIsPatternExpression(BoundIsPatternExpression node
Debug.Assert(!IsConditionalState);
LearnFromAnyNullPatterns(node.Expression, node.Pattern);
VisitPatternForRewriting(node.Pattern);
Visit(node.Expression);
var hasStateWhenNotNull = VisitPossibleConditionalAccess(node.Expression, out var conditionalStateWhenNotNull);
var expressionState = ResultType;
var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState);
var labelStateMap = LearnFromDecisionDag(node.Syntax, node.DecisionDag, node.Expression, expressionState, hasStateWhenNotNull ? conditionalStateWhenNotNull : null);
var trueState = labelStateMap.TryGetValue(node.IsNegated ? node.WhenFalseLabel : node.WhenTrueLabel, out var s1) ? s1.state : UnreachableState();
var falseState = labelStateMap.TryGetValue(node.IsNegated ? node.WhenTrueLabel : node.WhenFalseLabel, out var s2) ? s2.state : UnreachableState();
labelStateMap.Free();
Expand Down
Loading