Beispiel #1
0
        /// <summary>When boundRHS is a tuple literal, fix it up by inferring its types.</summary>
        private BoundExpression FixTupleLiteral(ArrayBuilder <DeconstructionVariable> checkedVariables, BoundExpression boundRHS, CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(diagnostics.DiagnosticBag is object);

            if (boundRHS.Kind == BoundKind.TupleLiteral)
            {
                // Let's fix the literal up by figuring out its type
                // For declarations, that means merging type information from the LHS and RHS
                // For assignments, only the LHS side matters since it is necessarily typed

                // If we already have diagnostics at this point, it is not worth collecting likely duplicate diagnostics from making the merged type
                bool       hadErrors       = diagnostics.HasAnyErrors();
                TypeSymbol?mergedTupleType = MakeMergedTupleType(checkedVariables, (BoundTupleLiteral)boundRHS, syntax, hadErrors ? null : diagnostics);
                if ((object?)mergedTupleType != null)
                {
                    boundRHS = GenerateConversionForAssignment(mergedTupleType, boundRHS, diagnostics);
                }
            }
            else if ((object?)boundRHS.Type == null)
            {
                Error(diagnostics, ErrorCode.ERR_DeconstructRequiresExpression, boundRHS.Syntax);
            }

            return(boundRHS);
        }
Beispiel #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.DiagnosticBag
                );

            if (diagnostics.HasAnyErrors())
            {
                // Avoid triggering assertions in further lowering.
                return(new BoundBadStatement(
                           F.Syntax,
                           ImmutableArray <BoundNode> .Empty,
                           hasErrors: true
                           ));
            }

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

            this.hoistedVariables = variablesToHoist;

            GenerateMethodImplementations();

            // Return a replacement body for the kickoff method
            return(GenerateKickoffMethodBody());
        }
        private ConcurrentSet <AssemblySymbol>?GetCompleteSetOfUsedAssemblies(
            CancellationToken cancellationToken
            )
        {
            if (!_usedAssemblyReferencesFrozen && !Volatile.Read(ref _usedAssemblyReferencesFrozen))
            {
                var diagnostics = new BindingDiagnosticBag(
                    DiagnosticBag.GetInstance(),
                    new ConcurrentSet <AssemblySymbol>()
                    );
                RoslynDebug.Assert(diagnostics.DiagnosticBag is object);

                GetDiagnosticsWithoutFiltering(
                    CompilationStage.Declare,
                    includeEarlierStages: true,
                    diagnostics,
                    cancellationToken
                    );

                bool seenErrors = diagnostics.HasAnyErrors();
                if (!seenErrors)
                {
                    diagnostics.DiagnosticBag.Clear();
                    GetDiagnosticsForAllMethodBodies(
                        diagnostics,
                        doLowering: true,
                        cancellationToken
                        );
                    seenErrors = diagnostics.HasAnyErrors();

                    if (!seenErrors)
                    {
                        AddUsedAssemblies(diagnostics.DependenciesBag);
                    }
                }

                completeTheSetOfUsedAssemblies(seenErrors, cancellationToken);

                diagnostics.DiagnosticBag.Free();
            }

            return(_lazyUsedAssemblyReferences);

            void addUsedAssembly(AssemblySymbol dependency, ArrayBuilder <AssemblySymbol> stack)
            {
                if (AddUsedAssembly(dependency))
                {
                    stack.Push(dependency);
                }
            }

            void addReferencedAssemblies(
                AssemblySymbol assembly,
                bool includeMainModule,
                ArrayBuilder <AssemblySymbol> stack
                )
            {
                for (int i = (includeMainModule ? 0 : 1); i < assembly.Modules.Length; i++)
                {
                    foreach (var dependency in assembly.Modules[i].ReferencedAssemblySymbols)
                    {
                        addUsedAssembly(dependency, stack);
                    }
                }
            }

            void completeTheSetOfUsedAssemblies(
                bool seenErrors,
                CancellationToken cancellationToken
                )
            {
                if (
                    _usedAssemblyReferencesFrozen ||
                    Volatile.Read(ref _usedAssemblyReferencesFrozen)
                    )
                {
                    return;
                }

                if (seenErrors)
                {
                    // Add all referenced assemblies
                    foreach (var assembly in SourceModule.ReferencedAssemblySymbols)
                    {
                        AddUsedAssembly(assembly);
                    }
                }
                else
                {
                    // Assume that all assemblies used by the added modules are also used
                    for (int i = 1; i < SourceAssembly.Modules.Length; i++)
                    {
                        foreach (
                            var dependency in SourceAssembly.Modules[i].ReferencedAssemblySymbols
                            )
                        {
                            AddUsedAssembly(dependency);
                        }
                    }

                    if (
                        _usedAssemblyReferencesFrozen ||
                        Volatile.Read(ref _usedAssemblyReferencesFrozen)
                        )
                    {
                        return;
                    }

                    // Assume that all assemblies used by the used assemblies are also used
                    // This, for example, takes care of including facade assemblies that forward types around.
                    if (_lazyUsedAssemblyReferences is object)
                    {
                        lock (_lazyUsedAssemblyReferences)
                        {
                            if (
                                _usedAssemblyReferencesFrozen ||
                                Volatile.Read(ref _usedAssemblyReferencesFrozen)
                                )
                            {
                                return;
                            }

                            var stack = ArrayBuilder <AssemblySymbol> .GetInstance(
                                _lazyUsedAssemblyReferences.Count
                                );

                            stack.AddRange(_lazyUsedAssemblyReferences);

                            while (stack.Count != 0)
                            {
                                AssemblySymbol current = stack.Pop();
                                ConcurrentSet <AssemblySymbol>?usedAssemblies;

                                switch (current)
                                {
                                case SourceAssemblySymbol sourceAssembly:
                                    // The set of assemblies used by the referenced compilation feels like
                                    // a reasonable approximation to the set of assembly references that would
                                    // be emitted into the resulting binary for that compilation. An alternative
                                    // would be to attempt to emit and get the exact set of emitted references
                                    // in case of success. This might be too slow though.
                                    usedAssemblies =
                                        sourceAssembly.DeclaringCompilation.GetCompleteSetOfUsedAssemblies(
                                            cancellationToken
                                            );
                                    if (usedAssemblies is object)
                                    {
                                        foreach (AssemblySymbol dependency in usedAssemblies)
                                        {
                                            Debug.Assert(!dependency.IsLinked);
                                            addUsedAssembly(dependency, stack);
                                        }
                                    }
                                    break;

                                case RetargetingAssemblySymbol retargetingAssembly:
                                    usedAssemblies =
                                        retargetingAssembly.UnderlyingAssembly.DeclaringCompilation.GetCompleteSetOfUsedAssemblies(
                                            cancellationToken
                                            );
                                    if (usedAssemblies is object)
                                    {
                                        foreach (
                                            AssemblySymbol underlyingDependency in retargetingAssembly.UnderlyingAssembly.SourceModule.ReferencedAssemblySymbols
                                            )
                                        {
                                            if (
                                                !underlyingDependency.IsLinked &&
                                                usedAssemblies.Contains(underlyingDependency)
                                                )
                                            {
                                                AssemblySymbol dependency;

                                                if (
                                                    !(
                                                        (RetargetingModuleSymbol)retargetingAssembly.Modules[
                                                            0
                                                        ]
                                                        ).RetargetingDefinitions(
                                                        underlyingDependency,
                                                        out dependency
                                                        )
                                                    )
                                                {
                                                    Debug.Assert(
                                                        retargetingAssembly.Modules[
                                                            0
                                                        ].ReferencedAssemblySymbols.Contains(
                                                            underlyingDependency
                                                            )
                                                        );
                                                    dependency = underlyingDependency;
                                                }

                                                addUsedAssembly(dependency, stack);
                                            }
                                        }
                                    }

                                    addReferencedAssemblies(
                                        retargetingAssembly,
                                        includeMainModule: false,
                                        stack
                                        );
                                    break;

                                default:
                                    addReferencedAssemblies(
                                        current,
                                        includeMainModule: true,
                                        stack
                                        );
                                    break;
                                }
                            }

                            stack.Free();
                        }
                    }

                    if (SourceAssembly.CorLibrary is object)
                    {
                        // Add core library
                        AddUsedAssembly(SourceAssembly.CorLibrary);
                    }
                }

                _usedAssemblyReferencesFrozen = true;
            }
        }
Beispiel #4
0
        private BoundDeconstructionAssignmentOperator BindDeconstructionAssignment(
            CSharpSyntaxNode node,
            ExpressionSyntax left,
            BoundExpression boundRHS,
            ArrayBuilder <DeconstructionVariable> checkedVariables,
            bool resultIsUsed,
            BindingDiagnosticBag diagnostics)
        {
            Debug.Assert(diagnostics.DiagnosticBag is object);
            uint rightEscape = GetValEscape(boundRHS, this.LocalScopeDepth);

            if ((object?)boundRHS.Type == null || boundRHS.Type.IsErrorType())
            {
                // we could still not infer a type for the RHS
                FailRemainingInferencesAndSetValEscape(checkedVariables, diagnostics, rightEscape);
                var voidType = GetSpecialType(SpecialType.System_Void, diagnostics, node);

                var type = boundRHS.Type ?? voidType;
                return(new BoundDeconstructionAssignmentOperator(
                           node,
                           DeconstructionVariablesAsTuple(left, checkedVariables, diagnostics, ignoreDiagnosticsFromTuple: true),
                           new BoundConversion(boundRHS.Syntax, boundRHS, Conversion.Deconstruction, @checked: false, explicitCastInCode: false, conversionGroupOpt: null,
                                               constantValueOpt: null, type: type, hasErrors: true),
                           resultIsUsed,
                           voidType,
                           hasErrors: true));
            }

            Conversion conversion;
            bool       hasErrors = !MakeDeconstructionConversion(
                boundRHS.Type,
                node,
                boundRHS.Syntax,
                diagnostics,
                checkedVariables,
                out conversion);

            if (conversion.Method != null)
            {
                CheckImplicitThisCopyInReadOnlyMember(boundRHS, conversion.Method, diagnostics);
            }

            FailRemainingInferencesAndSetValEscape(checkedVariables, diagnostics, rightEscape);

            var lhsTuple = DeconstructionVariablesAsTuple(left, checkedVariables, diagnostics, ignoreDiagnosticsFromTuple: diagnostics.HasAnyErrors() || !resultIsUsed);

            Debug.Assert(hasErrors || lhsTuple.Type is object);
            TypeSymbol returnType = hasErrors ? CreateErrorType() : lhsTuple.Type !;

            uint leftEscape = GetBroadestValEscape(lhsTuple, this.LocalScopeDepth);

            boundRHS = ValidateEscape(boundRHS, leftEscape, isByRef: false, diagnostics: diagnostics);

            var boundConversion = new BoundConversion(
                boundRHS.Syntax,
                boundRHS,
                conversion,
                @checked: false,
                explicitCastInCode: false,
                conversionGroupOpt: null,
                constantValueOpt: null,
                type: returnType,
                hasErrors: hasErrors)
            {
                WasCompilerGenerated = true
            };

            return(new BoundDeconstructionAssignmentOperator(node, lhsTuple, boundConversion, resultIsUsed, returnType));
        }
Beispiel #5
0
        internal static BoundBlock ConstructFieldLikeEventAccessorBody_WinRT(SourceEventSymbol eventSymbol, bool isAddMethod, CSharpCompilation compilation, BindingDiagnosticBag diagnostics)
        {
            CSharpSyntaxNode syntax = eventSymbol.CSharpSyntaxNode;

            MethodSymbol accessor = isAddMethod ? eventSymbol.AddMethod : eventSymbol.RemoveMethod;

            Debug.Assert((object)accessor != null);

            FieldSymbol field = eventSymbol.AssociatedField;

            Debug.Assert((object)field != null);

            NamedTypeSymbol fieldType = (NamedTypeSymbol)field.Type;

            Debug.Assert(fieldType.Name == "EventRegistrationTokenTable");

            MethodSymbol getOrCreateMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__GetOrCreateEventRegistrationTokenTable,
                diagnostics,
                syntax: syntax);

            if ((object)getOrCreateMethod == null)
            {
                Debug.Assert(diagnostics.DiagnosticBag is null || diagnostics.HasAnyErrors());
                return(null);
            }

            getOrCreateMethod = getOrCreateMethod.AsMember(fieldType);

            WellKnownMember processHandlerMember = isAddMethod
                ? WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__AddEventHandler
                : WellKnownMember.System_Runtime_InteropServices_WindowsRuntime_EventRegistrationTokenTable_T__RemoveEventHandler;

            MethodSymbol processHandlerMethod = (MethodSymbol)Binder.GetWellKnownTypeMember(
                compilation,
                processHandlerMember,
                diagnostics,
                syntax: syntax);

            if ((object)processHandlerMethod == null)
            {
                Debug.Assert(diagnostics.DiagnosticBag is null || diagnostics.HasAnyErrors());
                return(null);
            }

            processHandlerMethod = processHandlerMethod.AsMember(fieldType);

            // _tokenTable
            BoundFieldAccess fieldAccess = new BoundFieldAccess(
                syntax,
                field.IsStatic ? null : new BoundThisReference(syntax, accessor.ThisParameter.Type),
                field,
                constantValueOpt: null)
            {
                WasCompilerGenerated = true
            };

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable)
            BoundCall getOrCreateCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: null,
                method: getOrCreateMethod,
                arg0: fieldAccess);

            // value
            BoundParameter parameterAccess = new BoundParameter(
                syntax,
                accessor.Parameters[0]);

            // EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value) // or RemoveHandler
            BoundCall processHandlerCall = BoundCall.Synthesized(
                syntax,
                receiverOpt: getOrCreateCall,
                method: processHandlerMethod,
                arg0: parameterAccess);

            if (isAddMethod)
            {
                // {
                //     return EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).AddHandler(value);
                // }
                BoundStatement returnStatement = BoundReturnStatement.Synthesized(syntax, RefKind.None, processHandlerCall);
                return(BoundBlock.SynthesizedNoLocals(syntax, returnStatement));
            }
            else
            {
                // {
                //     EventRegistrationTokenTable<Event>.GetOrCreateEventRegistrationTokenTable(ref _tokenTable).RemoveHandler(value);
                //     return;
                // }
                BoundStatement callStatement   = new BoundExpressionStatement(syntax, processHandlerCall);
                BoundStatement returnStatement = new BoundReturnStatement(syntax, RefKind.None, expressionOpt: null, @checked: false);
                return(BoundBlock.SynthesizedNoLocals(syntax, callStatement, returnStatement));
            }
        }