/// <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); }
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; } }
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)); }
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)); } }