// Returns deterministically ordered list of variables that ought to be hoisted.
        public static OrderedSet <Symbol> Analyze(CSharpCompilation compilation, MethodSymbol method, BoundNode node, DiagnosticBag diagnostics)
        {
            var initiallyAssignedVariables = UnassignedVariablesWalker.Analyze(compilation, method, node, convertInsufficientExecutionStackExceptionToCancelledByStackGuardException: true);
            var walker = new IteratorAndAsyncCaptureWalker(compilation, method, node, new NeverEmptyStructTypeCache(), initiallyAssignedVariables);

            walker._convertInsufficientExecutionStackExceptionToCancelledByStackGuardException = true;

            bool badRegion = false;

            walker.Analyze(ref badRegion);
            Debug.Assert(!badRegion);

            if (!method.IsStatic && method.ContainingType.TypeKind == TypeKind.Struct)
            {
                // It is possible that the enclosing method only *writes* to the enclosing struct, but in that
                // case it should be considered captured anyway so that we have a proxy for it to write to.
                walker.CaptureVariable(method.ThisParameter, node.Syntax);
            }

            var variablesToHoist       = walker._variablesToHoist;
            var lazyDisallowedCaptures = walker._lazyDisallowedCaptures;
            var allVariables           = walker.variableBySlot;

            walker.Free();

            if (lazyDisallowedCaptures != null)
            {
                foreach (var kvp in lazyDisallowedCaptures)
                {
                    var variable = kvp.Key;
                    var type     = (variable.Kind == SymbolKind.Local) ? ((LocalSymbol)variable).Type.TypeSymbol : ((ParameterSymbol)variable).Type.TypeSymbol;

                    if (variable is SynthesizedLocal local && local.SynthesizedKind == SynthesizedLocalKind.Spill)
                    {
                        Debug.Assert(local.Type.IsRestrictedType());
                        diagnostics.Add(ErrorCode.ERR_ByRefTypeAndAwait, local.Locations[0], local.Type);
                    }
                    else
                    {
                        foreach (CSharpSyntaxNode syntax in kvp.Value)
                        {
                            // CS4013: Instance of type '{0}' cannot be used inside an anonymous function, query expression, iterator block or async method
                            diagnostics.Add(ErrorCode.ERR_SpecialByRefInLambda, syntax.Location, type);
                        }
                    }
                }
Пример #2
0
        protected BoundStatement Rewrite()
        {
            if (this.body.HasErrors)
            {
                return(this.body);
            }

            F.OpenNestedType(stateMachineType);

            GenerateControlFields();

            if (PreserveInitialParameterValuesAndThreadId && CanGetThreadId())
            {
                // if it is an enumerable or async-enumerable, and either Environment.CurrentManagedThreadId or Thread.ManagedThreadId are available
                // add a field: int initialThreadId
                initialThreadIdField = F.StateMachineField(F.SpecialType(SpecialType.System_Int32), GeneratedNames.MakeIteratorCurrentThreadIdFieldName());
            }

            // fields for the initial values of all the parameters of the method
            if (PreserveInitialParameterValuesAndThreadId)
            {
                initialParameters = new Dictionary <Symbol, CapturedSymbolReplacement>();
            }

            // fields for the captured variables of the method
            var variablesToHoist = IteratorAndAsyncCaptureWalker.Analyze(F.Compilation, method, body, diagnostics);

            CreateNonReusableLocalProxies(variablesToHoist, out this.nonReusableLocalProxies, out this.nextFreeHoistedLocalSlot);

            this.hoistedVariables = variablesToHoist;

            GenerateMethodImplementations();

            // Return a replacement body for the kickoff method
            return(GenerateKickoffMethodBody());
        }