public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            CheckRefReadOnlySymbols(node.Symbol);

            var typeParameters = node.Symbol.TypeParameters;

            if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
            }

            bool constraintsNeedNullableAttribute = typeParameters.Any(
                typeParameter => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute());

            bool returnTypeNeedsNullableAttribute = node.Symbol.ReturnTypeWithAnnotations.NeedsNullableAttribute();
            bool parametersNeedNullableAttribute  = node.Symbol.ParameterTypesWithAnnotations.Any(parameter => parameter.NeedsNullableAttribute());

            if (constraintsNeedNullableAttribute || returnTypeNeedsNullableAttribute || parametersNeedNullableAttribute)
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists();
            }

            var oldContainingSymbol = _factory.CurrentFunction;

            try
            {
                _factory.CurrentFunction = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
            }
        }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     if (IsInside)
     {
         _interactsWithLocalFunction = true;
     }
     MakeSlots(node.Symbol.Parameters);
     return(base.VisitLocalFunctionStatement(node));
 }
Exemple #3
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var oldCurrentFunction = _F.CurrentFunction;

            _F.CurrentFunction = node.Symbol;
            var result = base.VisitLocalFunctionStatement(node);

            _F.CurrentFunction = oldCurrentFunction;
            return(result);
        }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            if (IsInside && !node.WasCompilerGenerated)
            {
                foreach (var parameter in node.Symbol.Parameters)
                {
                    _variablesDeclared.Add(parameter);
                }
            }

            return base.VisitLocalFunctionStatement(node);
        }
Exemple #5
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            if (IsInside && !node.WasCompilerGenerated)
            {
                foreach (var parameter in node.Symbol.Parameters)
                {
                    _variablesDeclared.Add(parameter);
                }
            }

            return(base.VisitLocalFunctionStatement(node));
        }
Exemple #6
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var outerLocalFunction = _staticLocalFunction;

            if (node.Symbol.IsStaticLocalFunction)
            {
                _staticLocalFunction = node.Symbol;
            }
            var result = base.VisitLocalFunctionStatement(node);

            _staticLocalFunction = outerLocalFunction;
            return(result);
        }
            public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
            {
                var origLabels    = this.currentLabels;
                var origSeenAwait = _seenAwait;

                this.currentLabels = null;
                _seenAwait         = false;

                base.VisitLocalFunctionStatement(node);

                this.currentLabels = origLabels;
                _seenAwait         = origSeenAwait;

                return(null);
            }
Exemple #8
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            var oldContainingSymbol = _factory.CurrentMethod;

            try
            {
                _factory.CurrentMethod = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentMethod = oldContainingSymbol;
            }
        }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var oldContainingSymbol  = _F.CurrentFunction;
            var oldAwaitFinallyFrame = _currentAwaitFinallyFrame;

            _F.CurrentFunction        = node.Symbol;
            _currentAwaitFinallyFrame = new AwaitFinallyFrame();

            var result = base.VisitLocalFunctionStatement(node);

            _F.CurrentFunction        = oldContainingSymbol;
            _currentAwaitFinallyFrame = oldAwaitFinallyFrame;

            return(result);
        }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            ExecutableCodeBinder.ValidateIteratorMethod(_compilation, node.Symbol, _diagnostics);

            var outerLocalFunction = _staticLocalFunction;

            if (node.Symbol.IsStatic)
            {
                _staticLocalFunction = node.Symbol;
            }
            var result = base.VisitLocalFunctionStatement(node);

            _staticLocalFunction = outerLocalFunction;
            return(result);
        }
Exemple #11
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;

            var localFunction = node.Symbol;

            CheckRefReadOnlySymbols(localFunction);

            var typeParameters = localFunction.TypeParameters;

            if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
            }

            if (_factory.CompilationState.Compilation.ShouldEmitNullableAttributes(localFunction))
            {
                bool constraintsNeedNullableAttribute = typeParameters.Any(
                    typeParameter => ((SourceTypeParameterSymbolBase)typeParameter).ConstraintsNeedNullableAttribute());

                bool returnTypeNeedsNullableAttribute = localFunction.ReturnTypeWithAnnotations.NeedsNullableAttribute();
                bool parametersNeedNullableAttribute  = localFunction.ParameterTypesWithAnnotations.Any(parameter => parameter.NeedsNullableAttribute());

                if (constraintsNeedNullableAttribute || returnTypeNeedsNullableAttribute || parametersNeedNullableAttribute)
                {
                    _factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists();
                }
            }

            var oldContainingSymbol = _factory.CurrentFunction;
            var oldInstrumenter     = _instrumenter;

            try
            {
                _factory.CurrentFunction = localFunction;
                if (localFunction.IsDirectlyExcludedFromCodeCoverage)
                {
                    _instrumenter = RemoveDynamicAnalysisInjectors(oldInstrumenter);
                }
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
                _instrumenter            = oldInstrumenter;
            }
        }
Exemple #12
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            CheckRefReadOnlySymbols(node.Symbol);

            var oldContainingSymbol = _factory.CurrentFunction;

            try
            {
                _factory.CurrentFunction = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
            }
        }
Exemple #13
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            CheckRefReadOnlySymbols(node.Symbol);

            if (node.Symbol.TypeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
            }

            var oldContainingSymbol = _factory.CurrentFunction;

            try
            {
                _factory.CurrentFunction = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
            }
        }
Exemple #14
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            _sawLocalFunctions = true;
            CheckRefReadOnlySymbols(node.Symbol);

            var typeParameters = node.Symbol.TypeParameters;

            if (typeParameters.Any(typeParameter => typeParameter.HasUnmanagedTypeConstraint))
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureIsUnmanagedAttributeExists();
            }

            bool hasConstraintsWithNullableReferenceTypes = typeParameters.Any(
                typeParameter => typeParameter.ReferenceTypeConstraintIsNullable == true ||
                typeParameter.ConstraintTypesNoUseSiteDiagnostics.Any(
                    typeConstraint => typeConstraint.ContainsNullableReferenceTypes()));

            bool hasReturnTypeWithNullableReferenceTypes = node.Symbol.ReturnType.ContainsNullableReferenceTypes();
            bool hasParametersWithNullableReferenceTypes = node.Symbol.ParameterTypes.Any(parameter => parameter.ContainsNullableReferenceTypes());

            if (hasConstraintsWithNullableReferenceTypes || hasReturnTypeWithNullableReferenceTypes || hasParametersWithNullableReferenceTypes)
            {
                _factory.CompilationState.ModuleBuilderOpt?.EnsureNullableAttributeExists();
            }

            var oldContainingSymbol = _factory.CurrentFunction;

            try
            {
                _factory.CurrentFunction = node.Symbol;
                return(base.VisitLocalFunctionStatement(node));
            }
            finally
            {
                _factory.CurrentFunction = oldContainingSymbol;
            }
        }
Exemple #15
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldMethodOrLambda = this.currentMethodOrLambda;

            this.currentMethodOrLambda = localFunc.Symbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // Local functions don't affect outer state and are analyzed
            // with everything unassigned and reachable
            var savedState = this.State;

            this.State = this.ReachableState();

            var usages   = GetOrCreateLocalFuncUsages(localFunc.Symbol);
            var oldReads = usages.ReadVars;

            usages.ReadVars = BitVector.Empty;

            if (!localFunc.WasCompilerGenerated)
            {
                EnterParameters(localFunc.Symbol.Parameters);
            }

            var oldPending2 = SavePending();

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray <PendingBranch> pendingReturns = RemoveReturns();

            RestorePending(oldPending);

            Location location = null;

            if (!localFunc.Symbol.Locations.IsDefaultOrEmpty)
            {
                location = localFunc.Symbol.Locations[0];
            }

            LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, location);

            LocalState stateAtReturn = this.State;

            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;
                if (branch.Kind == BoundKind.ReturnStatement)
                {
                    // ensure out parameters are definitely assigned at each return
                    LeaveParameters(localFunc.Symbol.Parameters, branch.Syntax,
                                    branch.WasCompilerGenerated ? location : null);
                    IntersectWith(ref stateAtReturn, ref this.State);
                }
                else
                {
                    // other ways of branching out of a lambda are errors, previously reported in control-flow analysis
                }
            }

            // Check for changes to the read and write sets
            if (RecordChangedVars(ref usages.WrittenVars,
                                  ref stateAtReturn.Assigned,
                                  ref oldReads,
                                  ref usages.ReadVars) &&
                usages.LocalFuncVisited)
            {
                stateChangedAfterUse    = true;
                usages.LocalFuncVisited = false;
            }

            this.State = savedState;
            this.currentMethodOrLambda = oldMethodOrLambda;

            return(null);
        }
Exemple #16
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     MakeSlots(node.Symbol.Parameters);
     return(base.VisitLocalFunctionStatement(node));
 }
Exemple #17
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
 {
     return(null);
 }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     MakeSlots(node.Symbol.Parameters);
     return base.VisitLocalFunctionStatement(node);
 }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     VariableScope[node.Symbol] = _currentScope;
     return VisitLambdaOrFunction(node);
 }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     return VisitLocalFunctionOrLambda(node.Body);
 }
            public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
            {
                var origLabels = this.currentLabels;
                var origSeenAwait = _seenAwait;

                this.currentLabels = null;
                _seenAwait = false;

                base.VisitLocalFunctionStatement(node);

                this.currentLabels = origLabels;
                _seenAwait = origSeenAwait;

                return null;
            }
Exemple #22
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     // Do not recurse into nested lambdas; we don't want their returns.
     return null;
 }
Exemple #23
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     return(VisitLocalFunctionOrLambda(node.Body));
 }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
        {
            var oldContainingSymbol = _F.CurrentMethod;
            var oldAwaitFinallyFrame = _currentAwaitFinallyFrame;

            _F.CurrentMethod = node.Symbol;
            _currentAwaitFinallyFrame = new AwaitFinallyFrame();

            var result = base.VisitLocalFunctionStatement(node);

            _F.CurrentMethod = oldContainingSymbol;
            _currentAwaitFinallyFrame = oldAwaitFinallyFrame;

            return result;
        }
Exemple #25
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 => VisitClosure(node.Symbol.OriginalDefinition, node.Body);
        public override BoundNode?VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldSymbol       = this.CurrentSymbol;
            var localFuncSymbol = localFunc.Symbol;

            this.CurrentSymbol = localFuncSymbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // SPEC: The entry point to a local function is always reachable.
            // Captured variables are definitely assigned if they are definitely assigned on
            // all branches into the local function.

            var savedState = this.State;

            this.State = this.TopState();

            if (!localFunc.WasCompilerGenerated)
            {
                EnterParameters(localFuncSymbol.Parameters);
            }

            // State changes to captured variables are recorded, as calls to local functions
            // transition the state of captured variables if the variables have state changes
            // across all branches leaving the local function

            var localFunctionState      = GetOrCreateLocalFuncUsages(localFuncSymbol);
            var savedLocalFunctionState = LocalFunctionStart(localFunctionState);

            var oldPending2 = SavePending();

            // If this is an iterator, there's an implicit branch before the first statement
            // of the function where the enumerable is returned.
            if (localFuncSymbol.IsIterator)
            {
                PendingBranches.Add(new PendingBranch(null, this.State, null));
            }

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray <PendingBranch> pendingReturns = RemoveReturns();

            RestorePending(oldPending);

            Location?location = null;

            if (!localFuncSymbol.Locations.IsDefaultOrEmpty)
            {
                location = localFuncSymbol.Locations[0];
            }

            LeaveParameters(localFuncSymbol.Parameters, localFunc.Syntax, location);

            // Intersect the state of all branches out of the local function
            var stateAtReturn = this.State;

            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;

                // Pass the local function identifier as a location if the branch
                // is null or compiler generated.
                LeaveParameters(localFuncSymbol.Parameters,
                                branch?.Syntax,
                                branch?.WasCompilerGenerated == false ? null : location);

                Join(ref stateAtReturn, ref this.State);
            }

            // Record any changes to the state of captured variables
            if (RecordStateChange(
                    savedLocalFunctionState,
                    localFunctionState,
                    ref stateAtReturn) &&
                localFunctionState.Visited)
            {
                // If the sets have changed and we already used the results
                // of this local function in another computation, the previous
                // calculations may be invalid. We need to analyze until we
                // reach a fixed-point.
                stateChangedAfterUse       = true;
                localFunctionState.Visited = false;
            }

            this.State         = savedState;
            this.CurrentSymbol = oldSymbol;

            return(null);
        }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldMethodOrLambda = this.currentMethodOrLambda;
            this.currentMethodOrLambda = localFunc.Symbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // Local functions don't affect outer state and are analyzed
            // with everything unassigned and reachable
            var savedState = this.State;
            this.State = this.ReachableState();

            var usages = GetOrCreateLocalFuncUsages(localFunc.Symbol);
            var oldReads = usages.ReadVars;
            usages.ReadVars = BitVector.Empty;

            if (!localFunc.WasCompilerGenerated) EnterParameters(localFunc.Symbol.Parameters);

            var oldPending2 = SavePending();

            // If this is an iterator, there's an implicit branch before the first statement
            // of the function where the enumerable is returned.
            if (localFunc.Symbol.IsIterator)
            {
                PendingBranches.Add(new PendingBranch(null, this.State));
            }

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray<PendingBranch> pendingReturns = RemoveReturns();
            RestorePending(oldPending);

            Location location = null;

            if (!localFunc.Symbol.Locations.IsDefaultOrEmpty)
            {
                location = localFunc.Symbol.Locations[0];
            }

            LeaveParameters(localFunc.Symbol.Parameters, localFunc.Syntax, location);

            LocalState stateAtReturn = this.State;
            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;
                LeaveParameters(localFunc.Symbol.Parameters, branch?.Syntax,
                                branch?.WasCompilerGenerated == true
                                    ? location : null);
                IntersectWith(ref stateAtReturn, ref this.State);
            }

            // Check for changes to the read and write sets
            if (RecordChangedVars(ref usages.WrittenVars,
                                  ref stateAtReturn.Assigned,
                                  ref oldReads,
                                  ref usages.ReadVars) &&
                usages.LocalFuncVisited)
            {
                stateChangedAfterUse = true;
                usages.LocalFuncVisited = false;
            }

            this.State = savedState;
            this.currentMethodOrLambda = oldMethodOrLambda;

            return null;
        }
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldMethodOrLambda = this.currentMethodOrLambda;
            var localFuncSymbol   = localFunc.Symbol;

            this.currentMethodOrLambda = localFuncSymbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // Local functions don't affect outer state and are analyzed
            // with everything unassigned and reachable
            var savedState = this.State;

            this.State = this.ReachableState();

            var usages   = GetOrCreateLocalFuncUsages(localFuncSymbol);
            var oldReads = usages.ReadVars;

            usages.ReadVars = BitVector.Empty;

            if (!localFunc.WasCompilerGenerated)
            {
                EnterParameters(localFuncSymbol.Parameters);
            }

            var oldPending2 = SavePending();

            // If this is an iterator, there's an implicit branch before the first statement
            // of the function where the enumerable is returned.
            if (localFuncSymbol.IsIterator)
            {
                PendingBranches.Add(new PendingBranch(null, this.State));
            }

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray <PendingBranch> pendingReturns = RemoveReturns();

            RestorePending(oldPending);

            Location location = null;

            if (!localFuncSymbol.Locations.IsDefaultOrEmpty)
            {
                location = localFuncSymbol.Locations[0];
            }

            LeaveParameters(localFuncSymbol.Parameters, localFunc.Syntax, location);

            LocalState stateAtReturn = this.State;

            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;
                LeaveParameters(localFuncSymbol.Parameters, branch?.Syntax,
                                branch?.WasCompilerGenerated == true
                                    ? location : null);
                IntersectWith(ref stateAtReturn, ref this.State);
            }

            // Check for changes to the read and write sets
            if (RecordChangedVars(ref usages.WrittenVars,
                                  ref stateAtReturn,
                                  ref oldReads,
                                  ref usages.ReadVars) &&
                usages.LocalFuncVisited)
            {
                stateChangedAfterUse    = true;
                usages.LocalFuncVisited = false;
            }

            this.State = savedState;
            this.currentMethodOrLambda = oldMethodOrLambda;

            return(null);
        }
Exemple #29
0
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     // Do not recurse into nested lambdas; we don't want their returns.
     return(null);
 }
Exemple #30
0
        public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement localFunc)
        {
            var oldSymbol       = this.currentSymbol;
            var localFuncSymbol = localFunc.Symbol;

            this.currentSymbol = localFuncSymbol;

            var oldPending = SavePending(); // we do not support branches into a lambda

            // SPEC: The entry point to a local function is always reachable.
            // Captured variables are definitely assigned if they are definitely assigned on
            // all branches into the local function.

            var savedState = this.State;

            this.State = this.TopState();

            if (!localFunc.WasCompilerGenerated)
            {
                EnterParameters(localFuncSymbol.Parameters);
            }

            // Captured variables are definitely assigned if they are assigned on
            // all branches into the local function, so we store all reads from
            // possibly unassigned captured variables and later report definite
            // assignment errors if any of the captured variables is not assigned
            // on a particular branch.
            //
            // Assignments to captured variables are also recorded, as calls to local functions
            // definitely assign captured variables if the variables are definitely assigned at
            // all branches out of the local function.

            var usages   = GetOrCreateLocalFuncUsages(localFuncSymbol);
            var oldReads = usages.ReadVars.Clone();

            usages.ReadVars.Clear();

            var oldPending2 = SavePending();

            // If this is an iterator, there's an implicit branch before the first statement
            // of the function where the enumerable is returned.
            if (localFuncSymbol.IsIterator)
            {
                PendingBranches.Add(new PendingBranch(null, this.State, null));
            }

            VisitAlways(localFunc.Body);
            RestorePending(oldPending2); // process any forward branches within the lambda body
            ImmutableArray <PendingBranch> pendingReturns = RemoveReturns();

            RestorePending(oldPending);

            Location location = null;

            if (!localFuncSymbol.Locations.IsDefaultOrEmpty)
            {
                location = localFuncSymbol.Locations[0];
            }

            LeaveParameters(localFuncSymbol.Parameters, localFunc.Syntax, location);

            // Intersect the state of all branches out of the local function
            LocalState stateAtReturn = this.State;

            foreach (PendingBranch pending in pendingReturns)
            {
                this.State = pending.State;
                BoundNode branch = pending.Branch;

                // Pass the local function identifier as a location if the branch
                // is null or compiler generated.
                LeaveParameters(localFuncSymbol.Parameters,
                                branch?.Syntax,
                                branch?.WasCompilerGenerated == false ? null : location);

                Join(ref stateAtReturn, ref this.State);
            }

            // Check for changes to the possibly unassigned and assigned sets
            // of captured variables
            if (RecordChangedVars(ref usages.WrittenVars,
                                  ref stateAtReturn,
                                  ref oldReads,
                                  ref usages.ReadVars) &&
                usages.LocalFuncVisited)
            {
                // If the sets have changed and we already used the results
                // of this local function in another computation, the previous
                // calculations may be invalid. We need to analyze until we
                // reach a fixed-point. The previous writes are always valid,
                // so they are stored in usages.WrittenVars, while the reads
                // may be invalidated by new writes, so we throw the results out.
                stateChangedAfterUse    = true;
                usages.LocalFuncVisited = false;
            }

            this.State         = savedState;
            this.currentSymbol = oldSymbol;

            return(null);
        }
 public override BoundNode VisitLocalFunctionStatement(BoundLocalFunctionStatement node)
 {
     VariableScope[node.Symbol] = _currentScope;
     return(VisitLambdaOrFunction(node));
 }