Also set flow state for `if (dict.TryGetValue(key, out var val))` (with out variable declaration).
This commit is contained in:
Родитель
2c7e2d335f
Коммит
10c09d85b3
|
@ -129,6 +129,31 @@ class DataStructure
|
|||
return node;
|
||||
}
|
||||
|
||||
}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetOrCreateNodeWithOutVarDecl()
|
||||
{
|
||||
// 'node' local variable must be nullable, but GetNode return type can be non-nullable.
|
||||
AssertNullabilityInference(@"
|
||||
using System.Collections.Generic;
|
||||
class DataStructure
|
||||
{
|
||||
class Node { }
|
||||
|
||||
Dictionary<string, Node> mapping = new Dictionary<string, Node>();
|
||||
|
||||
Node GetNode(string element)
|
||||
{
|
||||
if (!mapping.TryGetValue(element, out Node? node))
|
||||
{
|
||||
node = new Node();
|
||||
mapping.Add(element, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}");
|
||||
}
|
||||
|
||||
|
|
|
@ -84,6 +84,16 @@ namespace ICSharpCode.NullabilityInference
|
|||
return new AccessPath(root, list.ToImmutable());
|
||||
}
|
||||
|
||||
public static AccessPath? FromRefArgument(IOperation? operation)
|
||||
{
|
||||
// also handle `out var decl`
|
||||
if (operation is IDeclarationExpressionOperation { Expression: ILocalReferenceOperation { Local: var local } }) {
|
||||
return new AccessPath(AccessPathRoot.Local, ImmutableArray.Create<ISymbol>(local));
|
||||
} else {
|
||||
return FromOperation(operation);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals(object obj) => obj is AccessPath p && Equals(p);
|
||||
|
||||
public override int GetHashCode()
|
||||
|
|
|
@ -957,7 +957,7 @@ namespace ICSharpCode.NullabilityInference
|
|||
// multiple parameters uses the same nullability nodes for all occurrences.
|
||||
var variance = (param.RefKind.ToVariance(), VarianceKind.In).Combine();
|
||||
tsBuilder.CreateTypeEdge(source: argumentType, target: parameterType, substitution, variance, new EdgeLabel("Argument", arg));
|
||||
if (isLValue && AccessPath.FromOperation(arg.Value) is AccessPath path) {
|
||||
if (isLValue && AccessPath.FromRefArgument(arg.Value) is AccessPath path) {
|
||||
// Processing of the flow-state is delayed until after all arguments were visited.
|
||||
afterCall += delegate {
|
||||
if (invocationContext == EdgeBuildingContext.Condition) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче