Improved nullable 'is' analysis#53311
Improved nullable 'is' analysis#53311RikkiGibson merged 8 commits intodotnet:features/improved-definite-assignmentfrom
Conversation
98c1fcc to
5fb0330
Compare
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
Outdated
Show resolved
Hide resolved
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs
Outdated
Show resolved
Hide resolved
jcouv
left a comment
There was a problem hiding this comment.
Done with review pass (iteration 1)
|
| 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); |
There was a problem hiding this comment.
Note that we want to only pass in the 'stateWhenNotNull' when 'VisitPossibleConditionalAccess' returns 'true'. Otherwise, we will mess up the x != null is true scenario--the value test node will end up using the 'stateWhenNotNull' instead of using the "original" conditional state.
| // [1]: t1 = (bool)t0; [2] | ||
| // [2] (this node): t1 == boolConstant ? [3] : [4] | ||
| // ...(remaining states) | ||
| if (stateWhenNotNullOpt is { } stateWhenNotNull |
There was a problem hiding this comment.
nit: We probably don't need a new local for this (stateWhenNotNullOpt is not null then use stateWhenNotNullOpt is sufficient)
| } | ||
| } | ||
|
|
||
| private static bool PatternMatchesNull(BoundPattern pattern) |
There was a problem hiding this comment.
nit: maybe leave as local function?
|
|
||
| void learnFromNonNullTest(int inputSlot, ref LocalState state) | ||
| { | ||
| if (stateWhenNotNullOpt is { } stateWhenNotNull && inputSlot == originalInputSlot) |
There was a problem hiding this comment.
Problem here is we can't take a ref to stateWhenNotNullOpt.Value.
| { | ||
| public string? Prop { get; set; } | ||
| }"; | ||
| // Ideally we would not issue diagnostic (1). |
There was a problem hiding this comment.
I thought this scenario might just fall out of the change to learnFromNonNullTest. Can you clarify what's missing?
There was a problem hiding this comment.
I didn't debug in a great amount of detail, but I suspect that when we create a slot for Prop we don't understand that its containing slot is the slot for b.C. Instead we either use some dag temp slot without relating it to the original input, or we create some slot that's accidentally linked to the conditional receiver (left side of ?.C).
…ures/interpolated-string * upstream/main: (95 commits) Update official build number in separate job Update Language Feature Status.md (#54015) Remove IRazorDocumentOptionsService inheritance interface (#54047) Fix comment Simplify Do not create a cache field for lambda if it depends on caller's type argument (#44939) Documentation Documentation Documentation Update test impls Just pass null Pull diagnostics should just request from the doc, not the whole project. Add test plan for file-scoped namespace (#54003) Add source build to official build Improved nullable 'is' analysis (#53311) Multi session service (#53762) Resolve Versions.props conflicts Revert "Revert "Require partial method signatures to match" (47576) (#47879)" (#53352) Broaden enforcement on prototype marker (#53886) Update Language Feature Status.md (#53926) ...
Related to #51463
Corresponding definite assignment PR: #52616
Relevant spec section: https://github.com/dotnet/csharplang/blob/main/proposals/improved-definite-assignment.md#is-operator-and-is-pattern-expressions