internal SourceCustomEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, EventDeclarationSyntax syntax, DiagnosticBag diagnostics) : base(containingType, syntax, syntax.Modifiers, isFieldLike: false, interfaceSpecifierSyntaxOpt: syntax.ExplicitInterfaceSpecifier, nameTokenSyntax: syntax.Identifier, diagnostics: diagnostics) { ExplicitInterfaceSpecifierSyntax?interfaceSpecifier = syntax.ExplicitInterfaceSpecifier; SyntaxToken nameToken = syntax.Identifier; bool isExplicitInterfaceImplementation = interfaceSpecifier != null; string?aliasQualifierOpt; _name = ExplicitInterfaceHelpers.GetMemberNameAndInterfaceSymbol(binder, interfaceSpecifier, nameToken.ValueText, diagnostics, out _explicitInterfaceType, out aliasQualifierOpt); _type = BindEventType(binder, syntax.Type, diagnostics); var explicitlyImplementedEvent = this.FindExplicitlyImplementedEvent(_explicitInterfaceType, nameToken.ValueText, interfaceSpecifier, diagnostics); this.FindExplicitlyImplementedMemberVerification(explicitlyImplementedEvent, diagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations, we need to copy the custom // modifiers that are in the signatures of the overridden/implemented event accessors. // (From source, we know that there can only be one overridden/implemented event, so there // are no conflicts.) This is unnecessary for implicit implementations because, if the custom // modifiers don't match, we'll insert bridge methods for the accessors (explicit implementations // that delegate to the implicit implementations) with the correct custom modifiers // (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation). // Note: we're checking if the syntax indicates explicit implementation rather, // than if explicitInterfaceType is null because we don't want to look for an // overridden event if this is supposed to be an explicit implementation. if (!isExplicitInterfaceImplementation) { // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol?overriddenEvent = this.OverriddenEvent; if ((object?)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly); } } } else if ((object)explicitlyImplementedEvent != null) { CopyEventCustomModifiers(explicitlyImplementedEvent, ref _type, ContainingAssembly); } AccessorDeclarationSyntax?addSyntax = null; AccessorDeclarationSyntax?removeSyntax = null; if (syntax.AccessorList != null) { foreach (AccessorDeclarationSyntax accessor in syntax.AccessorList.Accessors) { bool checkBody = false; switch (accessor.Kind()) { case SyntaxKind.AddAccessorDeclaration: if (addSyntax == null) { addSyntax = accessor; checkBody = true; } else { diagnostics.Add(ErrorCode.ERR_DuplicateAccessor, accessor.Keyword.GetLocation()); } break; case SyntaxKind.RemoveAccessorDeclaration: if (removeSyntax == null) { removeSyntax = accessor; checkBody = true; } else { diagnostics.Add(ErrorCode.ERR_DuplicateAccessor, accessor.Keyword.GetLocation()); } break; case SyntaxKind.GetAccessorDeclaration: case SyntaxKind.SetAccessorDeclaration: case SyntaxKind.InitAccessorDeclaration: diagnostics.Add(ErrorCode.ERR_AddOrRemoveExpected, accessor.Keyword.GetLocation()); break; case SyntaxKind.UnknownAccessorDeclaration: // Don't need to handle UnknownAccessorDeclaration. An error will have // already been produced for it in the parser. break; default: throw ExceptionUtilities.UnexpectedValue(accessor.Kind()); } if (checkBody && !IsAbstract && accessor.Body == null && accessor.ExpressionBody == null && accessor.SemicolonToken.Kind() == SyntaxKind.SemicolonToken) { diagnostics.Add(ErrorCode.ERR_AddRemoveMustHaveBody, accessor.SemicolonToken.GetLocation()); } } if (IsAbstract) { if (!syntax.AccessorList.OpenBraceToken.IsMissing) { diagnostics.Add(ErrorCode.ERR_AbstractEventHasAccessors, syntax.AccessorList.OpenBraceToken.GetLocation(), this); } } else if ((addSyntax == null || removeSyntax == null) && (!syntax.AccessorList.OpenBraceToken.IsMissing || !isExplicitInterfaceImplementation)) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } else if (isExplicitInterfaceImplementation && !IsAbstract) { diagnostics.Add(ErrorCode.ERR_ExplicitEventFieldImpl, this.Locations[0]); } if (isExplicitInterfaceImplementation && IsAbstract && syntax.AccessorList == null) { Debug.Assert(containingType.IsInterface); Binder.CheckFeatureAvailability(syntax, MessageID.IDS_DefaultInterfaceImplementation, diagnostics, this.Locations[0]); if (!ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, this.Locations[0]); } _addMethod = new SynthesizedEventAccessorSymbol(this, isAdder: true, explicitlyImplementedEvent, aliasQualifierOpt); _removeMethod = new SynthesizedEventAccessorSymbol(this, isAdder: false, explicitlyImplementedEvent, aliasQualifierOpt); } else { _addMethod = CreateAccessorSymbol(DeclaringCompilation, addSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); _removeMethod = CreateAccessorSymbol(DeclaringCompilation, removeSyntax, explicitlyImplementedEvent, aliasQualifierOpt, diagnostics); } _explicitInterfaceImplementations = (object?)explicitlyImplementedEvent == null ? ImmutableArray <EventSymbol> .Empty : ImmutableArray.Create <EventSymbol>(explicitlyImplementedEvent); }
public DiscardSymbol(TypeWithAnnotations typeWithAnnotations) { Debug.Assert(typeWithAnnotations.Type is object); TypeWithAnnotations = typeWithAnnotations; }
internal Boxed(TypeWithAnnotations value) { Value = value; }
internal static void GetTypeOrReturnType(this Symbol symbol, out RefKind refKind, out TypeWithAnnotations returnType, out ImmutableArray <CustomModifier> refCustomModifiers) { switch (symbol.Kind) { case SymbolKind.Field: FieldSymbol field = (FieldSymbol)symbol; refKind = RefKind.None; returnType = field.TypeWithAnnotations; refCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; case SymbolKind.Method: MethodSymbol method = (MethodSymbol)symbol; refKind = method.RefKind; returnType = method.ReturnTypeWithAnnotations; refCustomModifiers = method.RefCustomModifiers; break; case SymbolKind.Property: PropertySymbol property = (PropertySymbol)symbol; refKind = property.RefKind; returnType = property.TypeWithAnnotations; refCustomModifiers = property.RefCustomModifiers; break; case SymbolKind.Event: EventSymbol @event = (EventSymbol)symbol; refKind = RefKind.None; returnType = @event.TypeWithAnnotations; refCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; case SymbolKind.Local: LocalSymbol local = (LocalSymbol)symbol; refKind = local.RefKind; returnType = local.TypeWithAnnotations; refCustomModifiers = ImmutableArray <CustomModifier> .Empty; break; case SymbolKind.Parameter: ParameterSymbol parameter = (ParameterSymbol)symbol; refKind = parameter.RefKind; returnType = parameter.TypeWithAnnotations; refCustomModifiers = parameter.RefCustomModifiers; break; default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } }
/// <summary> /// If the extension method is applicable based on the "this" argument type, return /// the method constructed with the inferred type arguments. If the method is not an /// unconstructed generic method, type inference is skipped. If the method is not /// applicable, or if constraints when inferring type parameters from the "this" type /// are not satisfied, the return value is null. /// </summary> private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { Debug.Assert(method.IsExtensionMethod); Debug.Assert((object)thisType != null); if (!method.IsGenericMethod || method != method.ConstructedFrom) { return(method); } // We never resolve extension methods on a dynamic receiver. if (thisType.IsDynamic()) { return(null); } var containingAssembly = method.ContainingAssembly; var errorNamespace = containingAssembly.GlobalNamespace; var conversions = new TypeConversions(containingAssembly.CorLibrary); // There is absolutely no plausible syntax/tree that we could use for these // synthesized literals. We could be speculatively binding a call to a PE method. var syntaxTree = CSharpSyntaxTree.Dummy; var syntax = (CSharpSyntaxNode)syntaxTree.GetRoot(); // Create an argument value for the "this" argument of specific type, // and pass the same bad argument value for all other arguments. var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType) { WasCompilerGenerated = true }; var otherArgumentType = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false); var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType) { WasCompilerGenerated = true }; var paramCount = method.ParameterCount; var arguments = new BoundExpression[paramCount]; for (int i = 0; i < paramCount; i++) { var argument = (i == 0) ? thisArgumentValue : otherArgumentValue; arguments[i] = argument; } var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument( conversions, method, arguments.AsImmutable(), useSiteDiagnostics: ref useSiteDiagnostics); if (typeArgs.IsDefault) { return(null); } // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument. ImmutableArray <TypeWithAnnotations> typeArgsForConstruct = typeArgs; if (typeArgs.Any(t => !t.HasType)) { typeArgsForConstruct = typeArgs.ZipAsArray( method.TypeParameters, (t, tp) => t.HasType ? t : TypeWithAnnotations.Create(tp)); } return(method.Construct(typeArgsForConstruct)); }
internal UpdatedContainingSymbolAndNullableAnnotationLocal(SourceLocalSymbol underlyingLocal, Symbol updatedContainingSymbol, TypeWithAnnotations updatedType) : this(underlyingLocal, updatedContainingSymbol, updatedType, assertContaining : true) { }
/// <summary> /// Called by <see cref="AbstractTypeMap.SubstituteType(TypeSymbol)"/> to perform substitution /// on types with TypeKind ErrorType. The general pattern is to use the type map /// to perform substitution on the wrapped type, if any, and then construct a new /// error type symbol from the result (if there was a change). /// </summary> internal TypeWithAnnotations Substitute(AbstractTypeMap typeMap) { return(TypeWithAnnotations.Create(typeMap.SubstituteNamedType(this))); }
/// <summary> /// If the extension method is applicable based on the "this" argument type, return /// the method constructed with the inferred type arguments. If the method is not an /// unconstructed generic method, type inference is skipped. If the method is not /// applicable, or if constraints when inferring type parameters from the "this" type /// are not satisfied, the return value is null. /// </summary> /// <param name="compilation">Compilation used to check constraints. The latest language version is assumed if this is null.</param> private static MethodSymbol InferExtensionMethodTypeArguments(MethodSymbol method, TypeSymbol thisType, CSharpCompilation compilation, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { Debug.Assert(method.IsExtensionMethod); Debug.Assert((object)thisType != null); if (!method.IsGenericMethod || method != method.ConstructedFrom) { return(method); } // We never resolve extension methods on a dynamic receiver. if (thisType.IsDynamic()) { return(null); } var containingAssembly = method.ContainingAssembly; var errorNamespace = containingAssembly.GlobalNamespace; var conversions = new TypeConversions(containingAssembly.CorLibrary); // There is absolutely no plausible syntax/tree that we could use for these // synthesized literals. We could be speculatively binding a call to a PE method. var syntaxTree = CSharpSyntaxTree.Dummy; var syntax = (CSharpSyntaxNode)syntaxTree.GetRoot(); // Create an argument value for the "this" argument of specific type, // and pass the same bad argument value for all other arguments. var thisArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, thisType) { WasCompilerGenerated = true }; var otherArgumentType = new ExtendedErrorTypeSymbol(errorNamespace, name: string.Empty, arity: 0, errorInfo: null, unreported: false); var otherArgumentValue = new BoundLiteral(syntax, ConstantValue.Bad, otherArgumentType) { WasCompilerGenerated = true }; var paramCount = method.ParameterCount; var arguments = new BoundExpression[paramCount]; for (int i = 0; i < paramCount; i++) { var argument = (i == 0) ? thisArgumentValue : otherArgumentValue; arguments[i] = argument; } var typeArgs = MethodTypeInferrer.InferTypeArgumentsFromFirstArgument( conversions, method, arguments.AsImmutable(), useSiteDiagnostics: ref useSiteDiagnostics); if (typeArgs.IsDefault) { return(null); } // For the purpose of constraint checks we use error type symbol in place of type arguments that we couldn't infer from the first argument. // This prevents constraint checking from failing for corresponding type parameters. int firstNullInTypeArgs = -1; var notInferredTypeParameters = PooledHashSet <TypeParameterSymbol> .GetInstance(); var typeParams = method.TypeParameters; var typeArgsForConstraintsCheck = typeArgs; for (int i = 0; i < typeArgsForConstraintsCheck.Length; i++) { if (!typeArgsForConstraintsCheck[i].HasType) { firstNullInTypeArgs = i; var builder = ArrayBuilder <TypeWithAnnotations> .GetInstance(); builder.AddRange(typeArgsForConstraintsCheck, firstNullInTypeArgs); for (; i < typeArgsForConstraintsCheck.Length; i++) { var typeArg = typeArgsForConstraintsCheck[i]; if (!typeArg.HasType) { notInferredTypeParameters.Add(typeParams[i]); builder.Add(TypeWithAnnotations.Create(ErrorTypeSymbol.UnknownResultType)); } else { builder.Add(typeArg); } } typeArgsForConstraintsCheck = builder.ToImmutableAndFree(); break; } } // Check constraints. var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); var substitution = new TypeMap(typeParams, typeArgsForConstraintsCheck); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var success = method.CheckConstraints(conversions, substitution, typeParams, typeArgsForConstraintsCheck, compilation, diagnosticsBuilder, nullabilityDiagnosticsBuilderOpt: null, ref useSiteDiagnosticsBuilder, ignoreTypeConstraintsDependentOnTypeParametersOpt: notInferredTypeParameters.Count > 0 ? notInferredTypeParameters : null); diagnosticsBuilder.Free(); notInferredTypeParameters.Free(); if (useSiteDiagnosticsBuilder != null && useSiteDiagnosticsBuilder.Count > 0) { if (useSiteDiagnostics == null) { useSiteDiagnostics = new HashSet <DiagnosticInfo>(); } foreach (var diag in useSiteDiagnosticsBuilder) { useSiteDiagnostics.Add(diag.DiagnosticInfo); } } if (!success) { return(null); } // For the purpose of construction we use original type parameters in place of type arguments that we couldn't infer from the first argument. ImmutableArray <TypeWithAnnotations> typeArgsForConstruct = typeArgs; if (typeArgs.Any(t => !t.HasType)) { typeArgsForConstruct = typeArgs.ZipAsArray( method.TypeParameters, (t, tp) => t.HasType ? t : TypeWithAnnotations.Create(tp)); } return(method.Construct(typeArgsForConstruct)); }
/// <summary> /// Create a new PointerTypeSymbol. /// </summary> /// <param name="pointedAtType">The type being pointed at.</param> internal PointerTypeSymbol(TypeWithAnnotations pointedAtType) { Debug.Assert(pointedAtType.HasType); _pointedAtType = pointedAtType; }
internal SubmissionEntryPoint(NamedTypeSymbol containingType, TypeWithAnnotations returnType, TypeSymbol submissionArrayType) : base(containingType) { Debug.Assert(containingType.IsSubmissionClass); Debug.Assert(!returnType.IsVoidType()); _parameters = ImmutableArray.Create(SynthesizedParameterSymbol.Create(this, TypeWithAnnotations.Create(submissionArrayType), 0, RefKind.None, "submissionArray")); _returnType = returnType; }
internal override BoundBlock CreateBody(DiagnosticBag diagnostics) { var syntax = DummySyntax(); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 1); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var submissionArrayParameter = new BoundParameter(syntax, _parameters[0]) { WasCompilerGenerated = true }; var submissionLocal = new BoundLocal( syntax, new SynthesizedLocal(this, TypeWithAnnotations.Create(_containingType), SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; // var submission = new Submission#N(submissionArray); var submissionAssignment = new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, submissionLocal, new BoundObjectCreationExpression( syntax, ctor, ImmutableArray.Create <BoundExpression>(submissionArrayParameter), default(ImmutableArray <string>), default(ImmutableArray <RefKind>), false, default(ImmutableArray <int>), null, null, null, _containingType) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }; // return submission.<Initialize>(); var initializeResult = CreateParameterlessCall( syntax, submissionLocal, initializer); Debug.Assert(TypeSymbol.Equals(initializeResult.Type, _returnType.Type, TypeCompareKind.ConsiderEverything2)); var returnStatement = new BoundReturnStatement( syntax, RefKind.None, initializeResult) { WasCompilerGenerated = true }; return(new BoundBlock(syntax, ImmutableArray.Create <LocalSymbol>(submissionLocal.LocalSymbol), ImmutableArray.Create <BoundStatement>(submissionAssignment, returnStatement)) { WasCompilerGenerated = true }); }
internal override BoundBlock CreateBody(DiagnosticBag diagnostics) { var syntax = DummySyntax(); var compilation = _containingType.DeclaringCompilation; // Creates a new top-level binder that just contains the global imports for the compilation. // The imports are required if a consumer of the scripting API is using a Task implementation // that uses extension methods. var binder = new InContainerBinder( container: null, next: new BuckStopsHereBinder(compilation), imports: compilation.GlobalImports); binder = new InContainerBinder(compilation.GlobalNamespace, binder); var ctor = _containingType.GetScriptConstructor(); Debug.Assert(ctor.ParameterCount == 0); var initializer = _containingType.GetScriptInitializer(); Debug.Assert(initializer.ParameterCount == 0); var scriptLocal = new BoundLocal( syntax, new SynthesizedLocal(this, TypeWithAnnotations.Create(_containingType), SynthesizedLocalKind.LoweringTemp), null, _containingType) { WasCompilerGenerated = true }; Debug.Assert(!initializer.ReturnType.IsDynamic()); var initializeCall = CreateParameterlessCall(syntax, scriptLocal, initializer); BoundExpression getAwaiterGetResultCall; if (!binder.GetAwaitableExpressionInfo(initializeCall, out getAwaiterGetResultCall, syntax, diagnostics)) { return(new BoundBlock( syntax: syntax, locals: ImmutableArray <LocalSymbol> .Empty, statements: ImmutableArray <BoundStatement> .Empty, hasErrors: true)); } return(new BoundBlock(syntax, ImmutableArray.Create <LocalSymbol>(scriptLocal.LocalSymbol), ImmutableArray.Create <BoundStatement>( // var script = new Script(); new BoundExpressionStatement( syntax, new BoundAssignmentOperator( syntax, scriptLocal, new BoundObjectCreationExpression( syntax, ctor, null) { WasCompilerGenerated = true }, _containingType) { WasCompilerGenerated = true }) { WasCompilerGenerated = true }, // script.<Initialize>().GetAwaiter().GetResult(); new BoundExpressionStatement(syntax, getAwaiterGetResultCall) { WasCompilerGenerated = true }, // return; new BoundReturnStatement( syntax, RefKind.None, null) { WasCompilerGenerated = true })) { WasCompilerGenerated = true }); }
public AnonymousTypeField(string name, Location location, TypeWithAnnotations typeWithAnnotations) { this.Name = name; this.Location = location; this.TypeWithAnnotations = typeWithAnnotations; }
public SynthesizedAccessorValueParameterSymbol(SourceMemberMethodSymbol accessor, TypeWithAnnotations paramType, int ordinal) : base(accessor, ordinal, paramType, RefKind.None, ParameterSymbol.ValueParameterName, accessor.Locations, syntaxRef: null, isParams: false, isExtensionMethodThis: false) { }
internal static UpdatedContainingSymbolAndNullableAnnotationLocal CreateForTest(SourceLocalSymbol underlyingLocal, Symbol updatedContainingSymbol, TypeWithAnnotations updatedType) { return(new UpdatedContainingSymbolAndNullableAnnotationLocal(underlyingLocal, updatedContainingSymbol, updatedType, assertContaining: false)); }
internal PointerTypeSymbol WithPointedAtType(TypeWithAnnotations newPointedAtType) { return(PointedAtTypeWithAnnotations.IsSameAs(newPointedAtType) ? this : new PointerTypeSymbol(newPointedAtType)); }
private UpdatedContainingSymbolAndNullableAnnotationLocal(SourceLocalSymbol underlyingLocal, Symbol updatedContainingSymbol, TypeWithAnnotations updatedType, bool assertContaining) { RoslynDebug.Assert(underlyingLocal is object); RoslynDebug.Assert(updatedContainingSymbol is object); Debug.Assert(!assertContaining || updatedContainingSymbol.Equals(underlyingLocal.ContainingSymbol, TypeCompareKind.AllNullableIgnoreOptions)); ContainingSymbol = updatedContainingSymbol; TypeWithAnnotations = updatedType; _underlyingLocal = underlyingLocal; }
internal void ComputeReturnType() { if (_lazyReturnType is object) { return; } var diagnostics = BindingDiagnosticBag.GetInstance(_declarationDiagnostics); TypeSyntax returnTypeSyntax = Syntax.ReturnType; TypeWithAnnotations returnType = _binder.BindType( returnTypeSyntax.SkipRef(), diagnostics ); var compilation = DeclaringCompilation; // Skip some diagnostics when the local function is not associated with a compilation // (specifically, local functions nested in expressions in the EE). if (compilation is object) { var location = returnTypeSyntax.Location; if (_refKind == RefKind.RefReadOnly) { compilation.EnsureIsReadOnlyAttributeExists( diagnostics, location, modifyCompilation: false ); } if (returnType.Type.ContainsNativeInteger()) { compilation.EnsureNativeIntegerAttributeExists( diagnostics, location, modifyCompilation: false ); } if ( compilation.ShouldEmitNullableAttributes(this) && returnType.NeedsNullableAttribute() ) { compilation.EnsureNullableAttributeExists( diagnostics, location, modifyCompilation: false ); // Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already } } // span-like types are returnable in general if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // The return type of a method, delegate, or function pointer cannot be '{0}' diagnostics.Add( ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type ); } Debug.Assert( _refKind == RefKind.None || !returnType.IsVoidType() || returnTypeSyntax.HasErrors ); lock (_declarationDiagnostics) { if (_lazyReturnType is object) { diagnostics.Free(); return; } _declarationDiagnostics.AddRangeAndFree(diagnostics); Interlocked.CompareExchange( ref _lazyReturnType, new TypeWithAnnotations.Boxed(returnType), null ); } }
internal SourceFieldLikeEventSymbol(SourceMemberContainerTypeSymbol containingType, Binder binder, SyntaxTokenList modifiers, VariableDeclaratorSyntax declaratorSyntax, DiagnosticBag diagnostics) : base(containingType, declaratorSyntax, modifiers, isFieldLike: true, interfaceSpecifierSyntaxOpt: null, nameTokenSyntax: declaratorSyntax.Identifier, diagnostics: diagnostics) { _name = declaratorSyntax.Identifier.ValueText; var declaratorDiagnostics = DiagnosticBag.GetInstance(); var declarationSyntax = (VariableDeclarationSyntax)declaratorSyntax.Parent; _type = BindEventType(binder, declarationSyntax.Type, declaratorDiagnostics); // The runtime will not treat the accessors of this event as overrides or implementations // of those of another event unless both the signatures and the custom modifiers match. // Hence, in the case of overrides and *explicit* implementations (not possible for field-like // events), we need to copy the custom modifiers that are in the signatures of the // overridden/implemented event accessors. (From source, we know that there can only be one // overridden/implemented event, so there are no conflicts.) This is unnecessary for implicit // implementations because, if the custom modifiers don't match, we'll insert bridge methods // for the accessors (explicit implementations that delegate to the implicit implementations) // with the correct custom modifiers (see SourceMemberContainerTypeSymbol.SynthesizeInterfaceMemberImplementation). // If this event is an override, we may need to copy custom modifiers from // the overridden event (so that the runtime will recognize it as an override). // We check for this case here, while we can still modify the parameters and // return type without losing the appearance of immutability. if (this.IsOverride) { EventSymbol overriddenEvent = this.OverriddenEvent; if ((object)overriddenEvent != null) { CopyEventCustomModifiers(overriddenEvent, ref _type, ContainingAssembly); } } bool hasInitializer = declaratorSyntax.Initializer != null; bool inInterfaceType = containingType.IsInterfaceType(); if (hasInitializer) { if (inInterfaceType && !this.IsStatic) { diagnostics.Add(ErrorCode.ERR_InterfaceEventInitializer, this.Locations[0], this); } else if (this.IsAbstract) { diagnostics.Add(ErrorCode.ERR_AbstractEventInitializer, this.Locations[0], this); } } // NOTE: if there's an initializer in source, we'd better create a backing field, regardless of // whether or not the initializer is legal. if (hasInitializer || !(this.IsExtern || this.IsAbstract)) { _associatedField = MakeAssociatedField(declaratorSyntax); // Don't initialize this.type - we'll just use the type of the field (which is lazy and handles var) } if (!IsStatic && ContainingType.IsReadOnly) { diagnostics.Add(ErrorCode.ERR_FieldlikeEventsInRoStruct, this.Locations[0]); } if (inInterfaceType) { if (this.IsExtern || this.IsStatic) { if (!ContainingAssembly.RuntimeSupportsDefaultInterfaceImplementation) { diagnostics.Add(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, this.Locations[0]); } } else if (!this.IsAbstract) { diagnostics.Add(ErrorCode.ERR_EventNeedsBothAccessors, this.Locations[0], this); } } // Accessors will assume that Type is available. _addMethod = new SynthesizedEventAccessorSymbol(this, isAdder: true); _removeMethod = new SynthesizedEventAccessorSymbol(this, isAdder: false); if (declarationSyntax.Variables[0] == declaratorSyntax) { // Don't report these diagnostics for every declarator in this declaration. diagnostics.AddRange(declaratorDiagnostics); } declaratorDiagnostics.Free(); }
internal static void AddDelegateMembers( SourceMemberContainerTypeSymbol delegateType, ArrayBuilder <Symbol> symbols, DelegateDeclarationSyntax syntax, DiagnosticBag diagnostics) { var compilation = delegateType.DeclaringCompilation; Binder binder = delegateType.GetBinder(syntax.ParameterList); RefKind refKind; TypeSyntax returnTypeSyntax = syntax.ReturnType.SkipRef(out refKind); var returnType = binder.BindType(returnTypeSyntax, diagnostics); // reuse types to avoid reporting duplicate errors if missing: var voidType = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Void, diagnostics, syntax)); // https://github.com/dotnet/roslyn/issues/30079: Should the 'object', IAsyncResult and AsyncCallback parameters be considered nullable or not nullable? var objectType = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_Object, diagnostics, syntax)); var intPtrType = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_IntPtr, diagnostics, syntax)); if (returnType.IsRestrictedType(ignoreSpanLikeTypes: true)) { // The return type of a method, delegate, or function pointer cannot be '{0}' diagnostics.Add(ErrorCode.ERR_MethodReturnCantBeRefAny, returnTypeSyntax.Location, returnType.Type); } // A delegate has the following members: (see CLI spec 13.6) // (1) a method named Invoke with the specified signature var invoke = new InvokeMethod(delegateType, refKind, returnType, syntax, binder, diagnostics); invoke.CheckDelegateVarianceSafety(diagnostics); symbols.Add(invoke); // (2) a constructor with argument types (object, System.IntPtr) symbols.Add(new Constructor(delegateType, voidType, objectType, intPtrType, syntax)); if (binder.Compilation.GetSpecialType(SpecialType.System_IAsyncResult).TypeKind != TypeKind.Error && binder.Compilation.GetSpecialType(SpecialType.System_AsyncCallback).TypeKind != TypeKind.Error && // WinRT delegates don't have Begin/EndInvoke methods !delegateType.IsCompilationOutputWinMdObj()) { var iAsyncResultType = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_IAsyncResult, diagnostics, syntax)); var asyncCallbackType = TypeWithAnnotations.Create(binder.GetSpecialType(SpecialType.System_AsyncCallback, diagnostics, syntax)); // (3) BeginInvoke symbols.Add(new BeginInvokeMethod(invoke, iAsyncResultType, objectType, asyncCallbackType, syntax)); // and (4) EndInvoke methods symbols.Add(new EndInvokeMethod(invoke, iAsyncResultType, syntax)); } if (delegateType.DeclaredAccessibility <= Accessibility.Private) { return; } HashSet <DiagnosticInfo> useSiteDiagnostics = null; if (!delegateType.IsNoMoreVisibleThan(invoke.ReturnTypeWithAnnotations, ref useSiteDiagnostics)) { // Inconsistent accessibility: return type '{1}' is less accessible than delegate '{0}' diagnostics.Add(ErrorCode.ERR_BadVisDelegateReturn, delegateType.Locations[0], delegateType, invoke.ReturnType); } foreach (var parameter in invoke.Parameters) { if (!parameter.TypeWithAnnotations.IsAtLeastAsVisibleAs(delegateType, ref useSiteDiagnostics)) { // Inconsistent accessibility: parameter type '{1}' is less accessible than delegate '{0}' diagnostics.Add(ErrorCode.ERR_BadVisDelegateParam, delegateType.Locations[0], delegateType, parameter.Type); } } diagnostics.Add(delegateType.Locations[0], useSiteDiagnostics); }
public static bool IsNoMoreVisibleThan(this Symbol symbol, TypeWithAnnotations type, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { return(type.IsAtLeastAsVisibleAs(symbol, ref useSiteDiagnostics)); }
internal TypeWithAnnotations SubstituteType(TypeWithAnnotations previous) { return previous.SubstituteType(this); }
static int customModifierCountForTypeWithAnnotations(TypeWithAnnotations typeWithAnnotations) => typeWithAnnotations.CustomModifiers.Length + typeWithAnnotations.Type.CustomModifierCount();
protected virtual TypeWithAnnotations SubstituteTypeParameter(TypeParameterSymbol typeParameter) { return TypeWithAnnotations.Create(typeParameter); }
internal override ImmutableArray <TypeWithAnnotations> GetConstraintTypes( ConsList <TypeParameterSymbol> inProgress ) { var constraintTypes = ArrayBuilder <TypeWithAnnotations> .GetInstance(); _map.SubstituteConstraintTypesDistinctWithoutModifiers( _underlyingTypeParameter, _underlyingTypeParameter.GetConstraintTypes(inProgress), constraintTypes, null ); TypeWithAnnotations bestObjectConstraint = default; // Strip all Object constraints. for (int i = constraintTypes.Count - 1; i >= 0; i--) { TypeWithAnnotations type = constraintTypes[i]; if (ConstraintsHelper.IsObjectConstraint(type, ref bestObjectConstraint)) { constraintTypes.RemoveAt(i); } } if (bestObjectConstraint.HasType) { // See if we need to put Object! or Object~ back in order to preserve nullability information for the type parameter. if ( ConstraintsHelper.IsObjectConstraintSignificant( CalculateIsNotNullableFromNonTypeConstraints(), bestObjectConstraint ) ) { Debug.Assert(!HasNotNullConstraint && !HasValueTypeConstraint); if (constraintTypes.Count == 0) { if ( bestObjectConstraint.NullableAnnotation.IsOblivious() && !HasReferenceTypeConstraint ) { bestObjectConstraint = default; } } else { foreach (TypeWithAnnotations constraintType in constraintTypes) { if ( !ConstraintsHelper.IsObjectConstraintSignificant( IsNotNullableFromConstraintType(constraintType, out _), bestObjectConstraint ) ) { bestObjectConstraint = default; break; } } } if (bestObjectConstraint.HasType) { constraintTypes.Insert(0, bestObjectConstraint); } } } return(constraintTypes.ToImmutableAndFree()); }
internal SynthesizedThrowMethod(SourceModuleSymbol containingModule, PrivateImplementationDetails privateImplType, TypeSymbol returnType, TypeSymbol paramType) : base(containingModule, privateImplType, returnType, PrivateImplementationDetails.SynthesizedThrowFunctionName) { this.SetParameters(ImmutableArray.Create <ParameterSymbol>(SynthesizedParameterSymbol.Create(this, TypeWithAnnotations.Create(paramType), 0, RefKind.None, "paramName"))); }
private ImmutableArray <ParameterSymbol> MakeParameters( CSharpCompilation compilation, UnboundLambda unboundLambda, ImmutableArray <TypeWithAnnotations> parameterTypes, ImmutableArray <RefKind> parameterRefKinds, DiagnosticBag diagnostics) { Debug.Assert(parameterTypes.Length == parameterRefKinds.Length); if (!unboundLambda.HasSignature || unboundLambda.ParameterCount == 0) { // The parameters may be omitted in source, but they are still present on the symbol. return(parameterTypes.SelectAsArray((type, ordinal, arg) => SynthesizedParameterSymbol.Create( arg.owner, type, ordinal, arg.refKinds[ordinal], GeneratedNames.LambdaCopyParameterName(ordinal)), // Make sure nothing binds to this. (owner: this, refKinds: parameterRefKinds))); } var builder = ArrayBuilder <ParameterSymbol> .GetInstance(unboundLambda.ParameterCount); var hasExplicitlyTypedParameterList = unboundLambda.HasExplicitlyTypedParameterList; var numDelegateParameters = parameterTypes.Length; for (int p = 0; p < unboundLambda.ParameterCount; ++p) { // If there are no types given in the lambda then used the delegate type. // If the lambda is typed then the types probably match the delegate types; // if they do not, use the lambda types for binding. Either way, if we // can, then we use the lambda types. (Whatever you do, do not use the names // in the delegate parameters; they are not in scope!) TypeWithAnnotations type; RefKind refKind; if (hasExplicitlyTypedParameterList) { type = unboundLambda.ParameterTypeWithAnnotations(p); refKind = unboundLambda.RefKind(p); } else if (p < numDelegateParameters) { type = parameterTypes[p]; refKind = parameterRefKinds[p]; } else { type = TypeWithAnnotations.Create(new ExtendedErrorTypeSymbol(compilation, name: string.Empty, arity: 0, errorInfo: null)); refKind = RefKind.None; } var name = unboundLambda.ParameterName(p); var location = unboundLambda.ParameterLocation(p); var locations = location == null ? ImmutableArray <Location> .Empty : ImmutableArray.Create <Location>(location); var parameter = new SourceSimpleParameterSymbol(owner: this, type, ordinal: p, refKind, name, unboundLambda.ParameterIsDiscard(p), locations); builder.Add(parameter); } var result = builder.ToImmutableAndFree(); return(result); }
/// <summary> /// Replaces references to underlying type with references to native integer type. /// </summary> internal TypeWithAnnotations SubstituteUnderlyingType(TypeWithAnnotations type) => type.SubstituteType(GetTypeMap());
// https://github.com/dotnet/roslyn/issues/30071: Replace with Construct(ImmutableArray<TypeWithAnnotations>). /// <summary> /// Apply type substitution to a generic method to create an method symbol with the given type parameters supplied. /// </summary> /// <param name="typeArguments"></param> /// <returns></returns> public MethodSymbol Construct(ImmutableArray <TypeSymbol> typeArguments) { return(Construct(typeArguments.SelectAsArray(a => TypeWithAnnotations.Create(a)))); }
internal ArrayTypeSymbol WithElementType(TypeWithAnnotations elementTypeWithAnnotations) { return(ElementTypeWithAnnotations.IsSameAs(elementTypeWithAnnotations) ? this : WithElementTypeCore(elementTypeWithAnnotations)); }