diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index 6c06f87c84b628b7114a82be82bc13e018722e15..137c953f8076ed1b4c15c8c3a7c7ee282f980909 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -112,7 +112,7 @@ public TypeWithAnnotations GetInferredReturnType(ConversionsBase conversions, Nu // will be called again from NullableWalker.ApplyConversion when the // BoundLambda is converted to an anonymous function. // https://github.com/dotnet/roslyn/issues/31752: Can we avoid generating extra - // diagnostics? And is this exponential when there are nested lambdas + // diagnostics? And is this exponential when there are nested lambdas? var returnTypes = ArrayBuilder<(BoundReturnStatement, TypeWithAnnotations)>.GetInstance(); var diagnostics = DiagnosticBag.GetInstance(); var delegateType = Type.GetDelegateType(); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.DebugVerifier.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.DebugVerifier.cs index 2a5314b5d7a7a2b2b92b1d2f44b23e8c06b7db0a..0a8026ed7c1caac4fdeaa3bd97e437c8b7995d54 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.DebugVerifier.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.DebugVerifier.cs @@ -56,7 +56,7 @@ protected override BoundExpression VisitExpressionWithoutStackGuard(BoundExpress public override BoundNode Visit(BoundNode node) { - // Ensure that we always have a checkpoint for every BoundExpression in the map + // Ensure that we always have a snapshot for every BoundExpression in the map if (_snapshotManager != null && node != null) { _snapshotManager.VerifyNode(node); diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.SnapshotManager.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.SnapshotManager.cs index 6a042a818aecb28a584f04fac7d67c19ff782f33..1cb6ccc2e309f6b7e38394816e01c4d48cecd86b 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.SnapshotManager.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.SnapshotManager.cs @@ -14,7 +14,7 @@ internal sealed partial class NullableWalker internal sealed class SnapshotManager { /// - /// The int key corresponds to . + /// The int key corresponds to . /// private readonly ImmutableArray _walkerGlobalStates; /// @@ -53,7 +53,7 @@ private SnapshotManager(ImmutableArray walkerGlobalStates, Im return null; } - var globalState = _walkerGlobalStates[incrementalSnapshot.GlobalStateIndex]; + var globalState = _walkerGlobalStates[incrementalSnapshot.SharedStateIndex]; var variableState = new VariableState(globalState.VariableSlot, globalState.VariableBySlot, globalState.VariableTypes, incrementalSnapshot.VariableState.Clone()); var method = globalState.Symbol as MethodSymbol; return new NullableWalker( @@ -79,7 +79,7 @@ internal void VerifyNode(BoundNode node) } Debug.Assert(_incrementalSnapshots.ContainsKey(node.Syntax.SpanStart), $"Did not find a snapshot for {node} `{node.Syntax}.`"); - Debug.Assert(_walkerGlobalStates.Length > _incrementalSnapshots[node.Syntax.SpanStart].GlobalStateIndex, $"Did not find global state for {node} `{node.Syntax}`."); + Debug.Assert(_walkerGlobalStates.Length > _incrementalSnapshots[node.Syntax.SpanStart].SharedStateIndex, $"Did not find global state for {node} `{node.Syntax}`."); } #endif @@ -89,6 +89,7 @@ internal void VerifyNode(BoundNode node) /// private sealed class DescendingIntComparer : IComparer { + internal static readonly DescendingIntComparer Singleton = new DescendingIntComparer(); public int Compare(int x, int y) => y.CompareTo(x); } @@ -99,7 +100,7 @@ internal sealed class Builder /// /// Snapshots are kept in a dictionary of position -> snapshot at that position. These are stored in descending order. /// - private readonly ImmutableSortedDictionary.Builder _incrementalSnapshots = ImmutableSortedDictionary.CreateBuilder(new DescendingIntComparer()); + private readonly ImmutableSortedDictionary.Builder _incrementalSnapshots = ImmutableSortedDictionary.CreateBuilder(DescendingIntComparer.Singleton); /// /// Every walker is walking a specific symbol, and can potentially walk each symbol multiple times /// to get to a stable state. Each of these symbols gets a single global state slot, which this @@ -161,7 +162,7 @@ internal void TakeIncrementalSnapshot(BoundNode node, LocalState currentState) } /// - /// Contains the shared state state used to restore the walker at a specific point + /// Contains the shared state used to restore the walker at a specific point /// internal struct SharedWalkerState { @@ -190,12 +191,12 @@ internal struct SharedWalkerState private readonly struct Snapshot { internal readonly LocalState VariableState; - internal readonly int GlobalStateIndex; + internal readonly int SharedStateIndex; internal Snapshot(LocalState variableState, int globalStateIndex) { VariableState = variableState; - GlobalStateIndex = globalStateIndex; + SharedStateIndex = globalStateIndex; } } } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index cd15c97d3c8f395915c277c16b2bd52ea0fbcd1b..f073b679c64ca14c2ba8a348abf6a05a7c52501d 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -1878,7 +1878,7 @@ private ArrayTypeSymbol VisitArrayInitializer(BoundArrayCreation node) (BoundExpression expressionNoConversion, Conversion conversion) = RemoveConversion(expression, includeExplicitConversions: false); expressionsNoConversions.Add(expressionNoConversion); conversions.Add(conversion); - SnapshotWalkerThroughConversionGroup(expression as BoundConversion, expressionNoConversion); + SnapshotWalkerThroughConversionGroup(expression, expressionNoConversion); var resultType = VisitRvalueWithState(expressionNoConversion); resultTypes.Add(resultType); placeholderBuilder.Add(CreatePlaceholderIfNecessary(expressionNoConversion, resultType.ToTypeWithAnnotations())); @@ -2685,7 +2685,7 @@ public override BoundNode VisitConditionalOperator(BoundConditionalOperator node BoundExpression operandNoConversion; (operandNoConversion, conversion) = RemoveConversion(operand, includeExplicitConversions: false); - SnapshotWalkerThroughConversionGroup(operand as BoundConversion, operandNoConversion); + SnapshotWalkerThroughConversionGroup(operand, operandNoConversion); Visit(operandNoConversion); return (operandNoConversion, conversion, ResultType); } @@ -3371,7 +3371,7 @@ void visitArgumentEvaluateAndUnsplit(int argumentIndex, bool assertsTrue, bool a (argument, conversion) = RemoveConversion(argument, includeExplicitConversions: false); if (argument != before) { - SnapshotWalkerThroughConversionGroup(before as BoundConversion, argument); + SnapshotWalkerThroughConversionGroup(before, argument); includedConversion = true; } } @@ -3875,7 +3875,7 @@ public override BoundNode VisitConversion(BoundConversion node) Debug.Assert(targetType.HasType); (BoundExpression operand, Conversion conversion) = RemoveConversion(node, includeExplicitConversions: true); - SnapshotWalkerThroughConversionGroup(node as BoundConversion, operand); + SnapshotWalkerThroughConversionGroup(node, operand); TypeWithState operandType = VisitRvalueWithState(operand); SetResultType(node, VisitConversion( @@ -3909,7 +3909,7 @@ private TypeWithState VisitOptionalImplicitConversion(BoundExpression expr, Type } (BoundExpression operand, Conversion conversion) = RemoveConversion(expr, includeExplicitConversions: false); - SnapshotWalkerThroughConversionGroup(expr as BoundConversion, operand); + SnapshotWalkerThroughConversionGroup(expr, operand); var operandType = VisitRvalueWithState(operand); // If an explicit conversion was used in place of an implicit conversion, the explicit // conversion was created by initial binding after reporting "error CS0266: @@ -4739,12 +4739,18 @@ static TypeWithState calculateResultType(TypeWithAnnotations targetTypeWithNulla return operandType; } - private void SnapshotWalkerThroughConversionGroup(BoundConversion conversionOpt, BoundExpression convertedNode) + private void SnapshotWalkerThroughConversionGroup(BoundExpression conversionExpression, BoundExpression convertedNode) { + if (_snapshotBuilderOpt is null) + { + return; + } + + var conversionOpt = conversionExpression as BoundConversion; var conversionGroup = conversionOpt?.ConversionGroupOpt; while (conversionOpt != null && conversionOpt != convertedNode && - conversionOpt.Syntax.SpanStart != conversionOpt.Syntax.SpanStart) + conversionOpt.Syntax.SpanStart != convertedNode.Syntax.SpanStart) { Debug.Assert(conversionOpt.ConversionGroupOpt == conversionGroup); TakeIncrementalSnapshot(conversionOpt); @@ -5751,7 +5757,7 @@ protected override void VisitForEachExpression(BoundForEachStatement node) } var (expr, conversion) = RemoveConversion(node.Expression, includeExplicitConversions: false); - SnapshotWalkerThroughConversionGroup(node.Expression as BoundConversion, expr); + SnapshotWalkerThroughConversionGroup(node.Expression, expr); // There are 7 ways that a foreach can be created: // 1. The collection type is an array type. For this, initial binding will generate an implicit reference conversion to diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs index c159ab6118ad994c04a38dfaaa9b0f3fe939f30e..dd07c63e354b8d74a68dabc77223d192f8de81fc 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs @@ -503,10 +503,10 @@ public override BoundNode VisitSwitchExpression(BoundSwitchExpression node) foreach (var arm in node.SwitchArms) { SetState(!arm.Pattern.HasErrors && labelStateMap.TryGetValue(arm.Label, out var labelState) ? labelState.state : UnreachableState()); - // https://github.com/dotnet/roslyn/issues/35836 Is this where we want to take the checkpoint? + // https://github.com/dotnet/roslyn/issues/35836 Is this where we want to take the snapshot? TakeIncrementalSnapshot(arm); (BoundExpression expression, Conversion conversion) = RemoveConversion(arm.Value, includeExplicitConversions: false); - SnapshotWalkerThroughConversionGroup(arm.Value as BoundConversion, expression); + SnapshotWalkerThroughConversionGroup(arm.Value, expression); expressions.Add(expression); conversions.Add(conversion); var armType = VisitRvalueWithState(expression);