Addressed PR feedback.

上级 cdc368d1
......@@ -36,7 +36,8 @@ private BoundNode VisitBinaryOperatorBase(BoundBinaryOperatorBase binaryOperator
{
stack.Push(currentBinary);
currentBinary = currentBinary.Left as BoundBinaryOperatorBase;
} while (currentBinary != null);
}
while (currentBinary != null);
Debug.Assert(stack.Count > 0);
var leftChild = (BoundExpression)Visit(stack.Peek().Left);
......@@ -49,12 +50,15 @@ private BoundNode VisitBinaryOperatorBase(BoundBinaryOperatorBase binaryOperator
var right = (BoundExpression)Visit(currentBinary.Right);
var type = foundInfo ? infoAndType.Type : currentBinary.Type;
#pragma warning disable IDE0055 // Fix formatting
// PROTOTYPE(nullable-api): We'll need to update the symbols for the internal methods/operators used in the binary operators
currentBinary = currentBinary switch
{
BoundBinaryOperator binary => (BoundBinaryOperatorBase)binary.Update(binary.OperatorKind, binary.ConstantValueOpt, binary.MethodOpt, binary.ResultKind, leftChild, right, type),
BoundUserDefinedConditionalLogicalOperator logical => logical.Update(logical.OperatorKind, logical.LogicalOperator, logical.TrueOperator, logical.FalseOperator, logical.ResultKind, leftChild, right, type),
_ => throw ExceptionUtilities.UnexpectedValue(currentBinary.Kind),
};
{
BoundBinaryOperator binary => (BoundBinaryOperatorBase)binary.Update(binary.OperatorKind, binary.ConstantValueOpt, binary.MethodOpt, binary.ResultKind, leftChild, right, type),
BoundUserDefinedConditionalLogicalOperator logical => logical.Update(logical.OperatorKind, logical.LogicalOperator, logical.TrueOperator, logical.FalseOperator, logical.ResultKind, leftChild, right, type),
_ => throw ExceptionUtilities.UnexpectedValue(currentBinary.Kind),
};
#pragma warning restore IDE0055 // Fix formatting
if (foundInfo)
{
......@@ -62,7 +66,8 @@ private BoundNode VisitBinaryOperatorBase(BoundBinaryOperatorBase binaryOperator
}
leftChild = currentBinary;
} while (stack.Count > 0);
}
while (stack.Count > 0);
Debug.Assert(currentBinary != null);
return currentBinary;
......
......@@ -1590,11 +1590,11 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery)
using (_nodeMapLock.DisposableWrite())
{
BoundNode boundOuterExpression = this.Bind(incrementalBinder, nodeToBind, _ignoredDiagnostics);
nodes = GuardedAddBoundTreeAndGetBoundNodeFromMap(lambdaOrQuery, boundOuterExpression);
// If we're here, nullable analysis must be off, or we're in an error scenario and didn't find any
// nodes from this binding.
Debug.Assert(!EnableNullableAnalysis || nodes.IsDefaultOrEmpty);
// PROTOTYPE(nullable-api): Rewrite the above node and add a test that hits this path with nullable
// enabled
nodes = GuardedAddBoundTreeAndGetBoundNodeFromMap(lambdaOrQuery, boundOuterExpression);
}
if (!nodes.IsDefaultOrEmpty)
......@@ -1623,17 +1623,10 @@ private BoundNode GetBoundLambdaOrQuery(CSharpSyntaxNode lambdaOrQuery)
{
BoundNode boundOuterExpression = this.Bind(incrementalBinder, lambdaOrQuery, _ignoredDiagnostics);
if (EnableNullableAnalysis)
{
boundOuterExpression = RewriteNullableBoundNodes(boundOuterExpression, incrementalBinder.Conversions, _ignoredDiagnostics);
}
// PROTOTYPE(nullable-api): We need to do a rewrite here, and create a test that can hit this.
#if DEBUG
else
{
var diagnostics = new DiagnosticBag();
_ = RewriteNullableBoundNodes(boundOuterExpression, incrementalBinder.Conversions, diagnostics);
diagnostics.Free();
}
var diagnostics = new DiagnosticBag();
_ = RewriteNullableBoundNodes(boundOuterExpression, incrementalBinder.Conversions, diagnostics);
#endif
nodes = GuardedAddBoundTreeAndGetBoundNodeFromMap(lambdaOrQuery, boundOuterExpression);
......@@ -1822,7 +1815,8 @@ private void EnsureRootBoundForNullabilityIfNecessary()
DiagnosticBag diagnostics = _ignoredDiagnostics;
// If we're in DEBUG mode, always enable the analysis, but throw away the results
if (!EnableNullableAnalysis)
// PROTOTYPE(nullable-api): Disable speculative semantic models for now.
if (!EnableNullableAnalysis || IsSpeculativeSemanticModel)
{
#if DEBUG
diagnostics = new DiagnosticBag();
......@@ -1835,17 +1829,13 @@ private void EnsureRootBoundForNullabilityIfNecessary()
if (_guardedNodeMap.ContainsKey(Root)
#if DEBUG
// In DEBUG mode, we don't want to increase test run times by an insane length of
// time, so if nullable analysis isn't enabled and some node has already been bound
// In DEBUG mode, we don't want to increase test run times, so if
// nullable analysis isn't enabled and some node has already been bound
// we assume we've already done this test binding and just return
|| (!EnableNullableAnalysis && _guardedNodeMap.Count > 0)
#endif
)
{
#if DEBUG
if (!EnableNullableAnalysis) diagnostics.Free();
#endif
return;
}
......@@ -1858,7 +1848,7 @@ private void EnsureRootBoundForNullabilityIfNecessary()
// then take that state and run analysis on the statement or expression being speculated on.
// Currently, it will return incorrect info because it's just running analysis on the speculated
// part.
var binder = GetEnclosingBinder(GetAdjustedNodePosition(Root));
var binder = GetEnclosingBinder(GetAdjustedNodePosition(GetBindableSyntaxNode(Root)));
var boundRoot = Bind(binder, Root, diagnostics);
boundRoot = RewriteNullableBoundNodes(boundRoot, binder.Conversions, diagnostics);
......@@ -1866,12 +1856,6 @@ private void EnsureRootBoundForNullabilityIfNecessary()
{
GuardedAddBoundTreeForStandaloneSyntax(Root, boundRoot);
}
#if DEBUG
else
{
diagnostics.Free();
}
#endif
}
protected abstract BoundNode RewriteNullableBoundNodes(BoundNode boundRoot, Conversions conversions, DiagnosticBag diagnostics);
......
......@@ -70,18 +70,6 @@ public override BoundNode VisitDeconstructionAssignmentOperator(BoundDeconstruct
return null;
}
public override BoundNode VisitNewT(BoundNewT node)
{
// https://github.com/dotnet/roslyn/issues/33387 We're not currently
// examining child nodes correctly
if (node.InitializerExpressionOpt != null)
{
VerifyExpression(node.InitializerExpressionOpt, overrideSkippedExpression: true);
}
return null;
}
public override BoundNode VisitBadExpression(BoundBadExpression node)
{
// Regardless of what the BadExpression is, we need to add all of its direct children to the visited map. They
......
......@@ -1557,16 +1557,14 @@ private TypeWithState VisitRefExpression(BoundExpression expr, TypeWithAnnotatio
private bool TryGetReturnType(out TypeWithAnnotations type)
{
var method = _symbol as MethodSymbol;
var nullableReturnType = (_methodSignatureOpt ?? method)?.ReturnTypeWithAnnotations;
Debug.Assert(!nullableReturnType.HasValue || (object)nullableReturnType.Value != LambdaSymbol.ReturnTypeIsBeingInferred);
if (!nullableReturnType.HasValue)
if (method is null)
{
type = default;
return false;
}
var returnType = nullableReturnType.Value;
var returnType = (_methodSignatureOpt ?? method).ReturnTypeWithAnnotations;
Debug.Assert((object)returnType != LambdaSymbol.ReturnTypeIsBeingInferred);
if (returnType.SpecialType == SpecialType.System_Void)
{
......@@ -5187,9 +5185,9 @@ public override BoundNode VisitFixedLocalCollectionInitializer(BoundFixedLocalCo
}
VisitRvalue(initializer);
if (initializer.Kind == BoundKind.AddressOfOperator)
if (node.Expression.Kind == BoundKind.AddressOfOperator)
{
SetResultType(initializer, new TypeWithState(initializer.Type, ResultType.State));
SetResultType(node.Expression, new TypeWithState(node.Expression.Type, ResultType.State));
}
SetNotNullResult(node);
return null;
......
......@@ -627,5 +627,39 @@ void verifyCompilation(CSharpCompilation compilation)
AssertEx.Equal(expectedNullabilities, members.Select(nullabilityFunc));
}
}
[Fact]
public void LambdaBody_01()
{
var source = @"
using System;
class C
{
void M(Action a)
{
M(() =>
{
object? o = null;
if (o == null) return;
o.ToString();
});
}
}
";
var comp = CreateCompilation(source, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics();
var syntaxTree = comp.SyntaxTrees[0];
var root = syntaxTree.GetRoot();
var model = comp.GetSemanticModel(syntaxTree);
var invocation = root.DescendantNodes().OfType<InvocationExpressionSyntax>().Last();
var typeInfo = model.GetTypeInfo(((MemberAccessExpressionSyntax)invocation.Expression).Expression);
Assert.Equal(PublicNullableFlowState.NotNull, typeInfo.Nullability.FlowState);
// PROTOTYPE(nullable-api): This is incorrect. o should be Annotated, as you can assign
// null without a warning.
Assert.Equal(PublicNullableAnnotation.NotAnnotated, typeInfo.Nullability.Annotation);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册