public static bool CheckAllConstraints( this TypeSymbol type, ConversionsBase conversions) { var diagnostics = DiagnosticBag.GetInstance(); type.CheckAllConstraints(conversions, NoLocation.Singleton, diagnostics); bool ok = !diagnostics.HasAnyErrors(); diagnostics.Free(); return(ok); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { var location = this.Locations[0]; this.CheckModifiersAndType(diagnostics); this.Type.CheckAllConstraints(DeclaringCompilation, conversions, location, diagnostics); if (this.TypeWithAnnotations.NeedsNullableAttribute()) { this.DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } }
private static bool SatisfiesConstraintType( ConversionsBase conversions, TypeSymbol typeArgument, TypeSymbol constraintType, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { if (constraintType.IsErrorType()) { return(false); } // Spec 4.4.4 describes the valid conversions from // type argument A to constraint type C: // "An identity conversion (6.1.1). // An implicit reference conversion (6.1.6). ..." if (conversions.HasIdentityOrImplicitReferenceConversion(typeArgument, constraintType, ref useSiteDiagnostics)) { return(true); } // "... A boxing conversion (6.1.7), provided that type A is a non-nullable value type. ..." // NOTE: we extend this to allow, for example, a conversion from Nullable<T> to object. if (typeArgument.IsValueType && conversions.HasBoxingConversion(typeArgument.IsNullableType() ? ((NamedTypeSymbol)typeArgument).ConstructedFrom : typeArgument, constraintType, ref useSiteDiagnostics)) { return(true); } if (typeArgument.TypeKind == TypeKind.TypeParameter) { var typeParameter = (TypeParameterSymbol)typeArgument; // "... An implicit reference, boxing, or type parameter conversion // from type parameter A to C." if (conversions.HasImplicitTypeParameterConversion(typeParameter, constraintType, ref useSiteDiagnostics)) { return(true); } // TypeBind::SatisfiesBound allows cases where one of the // type parameter constraints satisfies the constraint. foreach (var typeArgumentConstraint in typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics)) { if (SatisfiesConstraintType(conversions, typeArgumentConstraint, constraintType, ref useSiteDiagnostics)) { return(true); } } } return(false); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if (_refKind == RefKind.RefReadOnly) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, syntax.ReturnType.GetLocation(), modifyCompilationForRefReadOnly: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } }
public bool CheckAllConstraints( LanguageCompilation compilation, ConversionsBase conversions) { var diagnostics = DiagnosticBag.GetInstance(); // Nullability checks can only add warnings here so skip them for this check as we are only // concerned with errors. CheckAllConstraints(compilation, conversions, NoLocation.Singleton, diagnostics); bool ok = !diagnostics.HasAnyErrors(); diagnostics.Free(); return(ok); }
internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, BindingDiagnosticBag diagnostics) { var compilation = DeclaringCompilation; var location = ErrorLocation; if (compilation.ShouldEmitNativeIntegerAttributes(Type)) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true); } if (compilation.ShouldEmitNullableAttributes(this) && TypeWithAnnotations.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, BindingDiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); var location = ReturnTypeLocation; var compilation = DeclaringCompilation; Debug.Assert(location != null); // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. CheckConstraintsForExplicitInterfaceType(conversions, diagnostics); this.ReturnType.CheckAllConstraints(compilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(compilation, conversions, parameter.Locations[0], diagnostics); } PartialMethodChecks(diagnostics); if (RefKind == RefKind.RefReadOnly) { compilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNativeIntegerAttributes(ReturnType)) { compilation.EnsureNativeIntegerAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNativeIntegerAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); ParameterHelpers.EnsureLifetimeAnnotationAttributeExists(compilation, Parameters, diagnostics, modifyCompilation: true); if (compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute()) { compilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(compilation, this, Parameters, diagnostics, modifyCompilation: true); }
public static bool CheckConstraints( this NamedTypeSymbol type, CSharpCompilation currentCompilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { // We do not report element locations in method parameters and return types // so we will simply unwrap the type if it was a tuple. We are relying on // TypeSymbolExtensions.VisitType to dig into the "Rest" tuple so that they // will be recursively unwrapped as well. type = (NamedTypeSymbol)type.TupleUnderlyingTypeOrSelf(); if (!RequiresChecking(type)) { return(true); } var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); // we only check for distinct interfaces when the type is not from source, as we // trust that types that are from source have already been checked by the compiler // to prevent this from happening in the first place. if (!(currentCompilation != null && type.IsFromCompilation(currentCompilation)) && HasDuplicateInterfaces(type, null)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, location, type); } return(result); }
/// <summary> /// Infer return type. If `nullableState` is non-null, nullability is also inferred and `NullableWalker.Analyze` /// uses that state to set the inferred nullability of variables in the enclosing scope. `conversions` is /// only needed when nullability is inferred. /// </summary> public TypeWithAnnotations GetInferredReturnType(ConversionsBase conversions, NullableWalker.VariableState nullableState, ref HashSet <DiagnosticInfo> useSiteDiagnostics) { if (!InferredReturnType.UseSiteDiagnostics.IsEmpty) { if (useSiteDiagnostics == null) { useSiteDiagnostics = new HashSet <DiagnosticInfo>(); } foreach (var info in InferredReturnType.UseSiteDiagnostics) { useSiteDiagnostics.Add(info); } } if (nullableState == null) { return(InferredReturnType.TypeWithAnnotations); } else { Debug.Assert(conversions != null); // Diagnostics from NullableWalker.Analyze can be dropped here since Analyze // will be called again from NullableWalker.ApplyConversion when the // BoundLambda is converted to an anonymous function. // https://github.com/dotnet/roslyn/issues/31752: Can we avoid generating extra // diagnostics? And is this exponential when there are nested lambdas? var returnTypes = ArrayBuilder <(BoundReturnStatement, TypeWithAnnotations)> .GetInstance(); var diagnostics = DiagnosticBag.GetInstance(); var delegateType = Type.GetDelegateType(); var compilation = Binder.Compilation; NullableWalker.Analyze(compilation, lambda: this, (Conversions)conversions, diagnostics, delegateInvokeMethod: delegateType?.DelegateInvokeMethod, initialState: nullableState, analyzedNullabilityMapOpt: null, updatedMethodSymbolMapOpt: null, snapshotBuilderOpt: null, returnTypes); diagnostics.Free(); var inferredReturnType = InferReturnType(returnTypes, node: this, compilation, conversions, delegateType, Symbol.IsAsync); returnTypes.Free(); return(inferredReturnType.TypeWithAnnotations); } }
private static bool CheckTypeConstraints( NamedTypeSymbol type, ConversionsBase conversions, Compilation currentCompilation, ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder) { return(CheckConstraints( type, conversions, type.TypeSubstitution, type.OriginalDefinition.TypeParameters, type.TypeArgumentsNoUseSiteDiagnostics, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder)); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; RoslynDebug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(DeclaringCompilation, conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } if (!_explicitInterfaceImplementations.IsEmpty) { // Note: we delayed nullable-related checks that could pull on NonNullTypes EventSymbol explicitlyImplementedEvent = _explicitInterfaceImplementations[0]; TypeSymbol.CheckNullableReferenceTypeMismatchOnImplementingMember(this.ContainingType, this, explicitlyImplementedEvent, isExplicit: true, diagnostics); } }
public static bool CheckConstraints( this NamedTypeSymbol type, ConversionsBase conversions, CSharpSyntaxNode typeSyntax, SeparatedSyntaxList <TypeSyntax> typeArgumentsSyntax, // may be omitted in synthesized invocations Compilation currentCompilation, ConsList <Symbol> basesBeingResolved, DiagnosticBag diagnostics) { Debug.Assert(typeArgumentsSyntax.Count == 0 /*omitted*/ || typeArgumentsSyntax.Count == type.Arity - type.ImplicitTypeParameterCount /* @t-mawind part-inferred */ || typeArgumentsSyntax.Count == type.Arity); if (!RequiresChecking(type)) { return(true); } var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = !typeSyntax.HasErrors && CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { int ordinal = pair.TypeParameter.Ordinal; var location = new SourceLocation(ordinal < typeArgumentsSyntax.Count ? typeArgumentsSyntax[ordinal] : typeSyntax); diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); if (HasDuplicateInterfaces(type, basesBeingResolved)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, typeSyntax.Location, type); } return(result); }
public static Conversion ClassifyConversionFromExpression( this ConversionsBase conversions, BoundExpression sourceExpression, TypeSymbol destination, ref HashSet <DiagnosticInfo> useSiteDiagnostics, bool forCast = false ) { CompoundUseSiteInfo <AssemblySymbol> useSiteInfo = default; Conversion result = conversions.ClassifyConversionFromExpression( sourceExpression, destination, ref useSiteInfo, forCast ); AddDiagnosticInfos(ref useSiteDiagnostics, useSiteInfo); return(result); }
private static bool CheckMethodConstraints( MethodSymbol method, ConversionsBase conversions, Compilation currentCompilation, ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder, BitVector skipParameters = default(BitVector)) { return(CheckConstraints( method, conversions, method.TypeSubstitution, ((MethodSymbol)method.OriginalDefinition).TypeParameters, method.TypeArguments, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, skipParameters)); }
public static bool CheckConstraints( this NamedTypeSymbol type, ConversionsBase conversions, CSharpSyntaxNode typeSyntax, SeparatedSyntaxList <TypeSyntax> typeArgumentsSyntax, Compilation currentCompilation, DiagnosticBag diagnostics) { Debug.Assert(typeArgumentsSyntax.Count == type.Arity); if (!RequiresChecking(type)) { return(true); } var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { int ordinal = pair.TypeParameter.Ordinal; var location = new SourceLocation(typeArgumentsSyntax[ordinal]); diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); if (!InterfacesAreDistinct(type)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, typeSyntax.Location, type); } return(result); }
public static bool CheckConstraints( this NamedTypeSymbol type, CSharpCompilation currentCompilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { if (!RequiresChecking(type)) { return(true); } var diagnosticsBuilder = ArrayBuilder <TypeParameterDiagnosticInfo> .GetInstance(); ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); // we only check for distinct interfaces when the type is not from source, as we // trust that types that are from source have already been checked by the compiler // to prevent this from happening in the first place. if (!(currentCompilation != null && type.IsFromCompilation(currentCompilation)) && HasDuplicateInterfaces(type, null)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, location, type); } return(result); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { var syntax = (DelegateDeclarationSyntax)SyntaxRef.GetSyntax(); var location = syntax.ReturnType.GetLocation(); Debug.Assert(location != null); base.AfterAddingTypeMembersChecks(conversions, diagnostics); if (_refKind == RefKind.RefReadOnly) { DeclaringCompilation.EnsureIsReadOnlyAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); if (ReturnTypeWithAnnotations.NeedsNullableAttribute()) { this.DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); }
/// <summary> /// Check type parameter constraints for the containing type or method symbol. /// </summary> /// <param name="containingSymbol">The generic type or method.</param> /// <param name="conversions">Conversions instance.</param> /// <param name="substitution">The map from type parameters to type arguments.</param> /// <param name="typeParameters">Containing symbol type parameters.</param> /// <param name="typeArguments">Containing symbol type arguments.</param> /// <param name="currentCompilation">Improves error message detail.</param> /// <param name="diagnosticsBuilder">Diagnostics.</param> /// <param name="skipParameters">Parameters to skip.</param> /// <param name="useSiteDiagnosticsBuilder"/> /// <param name="ignoreTypeConstraintsDependentOnTypeParametersOpt">If an original form of a type constraint /// depends on a type parameter from this set, do not verify this type constraint.</param> /// <returns>True if the constraints were satisfied, false otherwise.</returns> public static bool CheckConstraints( this Symbol containingSymbol, ConversionsBase conversions, TypeMap substitution, ImmutableArray <TypeParameterSymbol> typeParameters, ImmutableArray <TypeSymbol> typeArguments, Compilation currentCompilation, ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder, BitVector skipParameters = default(BitVector), HashSet <TypeParameterSymbol> ignoreTypeConstraintsDependentOnTypeParametersOpt = null) { Debug.Assert(typeParameters.Length == typeArguments.Length); Debug.Assert(typeParameters.Length > 0); int n = typeParameters.Length; bool succeeded = true; for (int i = 0; i < n; i++) { if (skipParameters[i]) { continue; } var typeArgument = typeArguments[i]; var typeParameter = typeParameters[i]; if (!CheckConstraints(containingSymbol, conversions, substitution, typeParameter, typeArgument, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, ignoreTypeConstraintsDependentOnTypeParametersOpt)) { succeeded = false; } } return(succeeded); }
internal sealed override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. this.ReturnType.CheckAllConstraints(DeclaringCompilation, conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(DeclaringCompilation, conversions, parameter.Locations[0], diagnostics); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilation: true); var location = ReturnTypeSyntax.Location; if (ReturnTypeWithAnnotations.NeedsNullableAttribute()) { this.DeclaringCompilation.EnsureNullableAttributeExists(diagnostics, location, modifyCompilation: true); } ParameterHelpers.EnsureNullableAttributeExists(Parameters, diagnostics, modifyCompilation: true); }
public CheckConstraintsArgs(CSharpCompilation currentCompilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { this.CurrentCompilation = currentCompilation; this.Conversions = conversions; this.Location = location; this.Diagnostics = diagnostics; }
public static bool CheckAllConstraints( this TypeSymbol type, ConversionsBase conversions) { var diagnostics = DiagnosticBag.GetInstance(); type.CheckAllConstraints(conversions, NoLocation.Singleton, diagnostics); bool ok = !diagnostics.HasAnyErrors(); diagnostics.Free(); return ok; }
/// <summary> /// Check all generic constraints on the given type and any containing types /// (such as A<T> in A<T>.B<U>). This includes checking constraints /// on generic types within the type (such as B<T> in A<B<T>[]>). /// </summary> public static void CheckAllConstraints( this TypeSymbol type, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { type.VisitType(s_checkConstraintsSingleTypeFunc, new CheckConstraintsArgs(type.DeclaringCompilation, conversions, location, diagnostics)); }
// See TypeBind::CheckSingleConstraint. private static bool CheckConstraints( Symbol containingSymbol, ConversionsBase conversions, TypeMap substitution, TypeParameterSymbol typeParameter, TypeSymbol typeArgument, Compilation currentCompilation, ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder, HashSet<TypeParameterSymbol> ignoreTypeConstraintsDependentOnTypeParametersOpt) { Debug.Assert(substitution != null); // The type parameters must be original definitions of type parameters from the containing symbol. Debug.Assert(ReferenceEquals(typeParameter.ContainingSymbol, containingSymbol.OriginalDefinition)); if (typeArgument.IsErrorType()) { return true; } if (typeArgument.IsPointerType() || typeArgument.IsRestrictedType() || typeArgument.SpecialType == SpecialType.System_Void) { // "The type '{0}' may not be used as a type argument" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BadTypeArgument, typeArgument))); return false; } if (typeArgument.IsStatic) { // "'{0}': static types cannot be used as type arguments" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_GenericArgIsStaticClass, typeArgument))); return false; } if (typeParameter.HasReferenceTypeConstraint && !typeArgument.IsReferenceType) { // "The type '{2}' must be a reference type in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_RefConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return false; } if (typeParameter.HasValueTypeConstraint && !typeArgument.IsNonNullableValueType()) { // "The type '{2}' must be a non-nullable value type in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ValConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return false; } // The type parameters for a constructed type/method are the type parameters of // the ConstructedFrom type/method, so the constraint types are not substituted. // For instance with "class C<T, U> where T : U", the type parameter for T in "C<object, int>" // has constraint "U", not "int". We need to substitute the constraints from the // original definition of the type parameters using the map from the constructed symbol. var constraintTypes = ArrayBuilder<TypeSymbol>.GetInstance(); HashSet<DiagnosticInfo> useSiteDiagnostics = null; substitution.SubstituteTypesDistinctWithoutModifiers(typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), constraintTypes, ignoreTypeConstraintsDependentOnTypeParametersOpt); bool hasError = false; foreach (var constraintType in constraintTypes) { if (SatisfiesConstraintType(conversions, typeArgument, constraintType, ref useSiteDiagnostics)) { continue; } ErrorCode errorCode; if (typeArgument.IsReferenceType) { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType; } else if (typeArgument.IsNullableType()) { errorCode = constraintType.IsInterfaceType() ? ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface : ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum; } else if (typeArgument.TypeKind == TypeKind.TypeParameter) { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar; } else { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedValType; } SymbolDistinguisher distinguisher = new SymbolDistinguisher(currentCompilation, constraintType, typeArgument); diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(errorCode, containingSymbol.ConstructedFrom(), distinguisher.First, typeParameter, distinguisher.Second))); hasError = true; } if (AppendUseSiteDiagnostics(useSiteDiagnostics, typeParameter, ref useSiteDiagnosticsBuilder)) { hasError = true; } constraintTypes.Free(); // Check the constructor constraint. if (typeParameter.HasConstructorConstraint && !SatisfiesConstructorConstraint(typeArgument)) { // "'{2}' must be a non-abstract type with a public parameterless constructor in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_NewConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return false; } return !hasError; }
private static bool CheckMethodConstraints( MethodSymbol method, ConversionsBase conversions, Compilation currentCompilation, ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder, BitVector skipParameters = default(BitVector)) { return CheckConstraints( method, conversions, method.TypeSubstitution, ((MethodSymbol)method.OriginalDefinition).TypeParameters, method.TypeArguments, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, skipParameters); }
public static bool CheckConstraints( this MethodSymbol method, ConversionsBase conversions, Location location, Compilation currentCompilation, DiagnosticBag diagnostics) { if (!RequiresChecking(method)) { return true; } var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckMethodConstraints(method, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); return result; }
// See TypeBind::CheckSingleConstraint. private static bool CheckConstraints( Symbol containingSymbol, ConversionsBase conversions, TypeMap substitution, TypeParameterSymbol typeParameter, TypeSymbol typeArgument, Compilation currentCompilation, ArrayBuilder <TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder <TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder) { Debug.Assert(substitution != null); // The type parameters must be original definitions of type parameters from the containing symbol. Debug.Assert(ReferenceEquals(typeParameter.ContainingSymbol, containingSymbol.OriginalDefinition)); if (typeArgument.IsErrorType()) { return(true); } if (typeArgument.IsPointerType() || typeArgument.IsRestrictedType() || typeArgument.SpecialType == SpecialType.System_Void) { // "The type '{0}' may not be used as a type argument" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_BadTypeArgument, typeArgument))); return(false); } if (typeArgument.IsStatic) { // "'{0}': static types cannot be used as type arguments" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_GenericArgIsStaticClass, typeArgument))); return(false); } if (typeParameter.HasReferenceTypeConstraint && !typeArgument.IsReferenceType) { // "The type '{2}' must be a reference type in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_RefConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return(false); } if (typeParameter.HasValueTypeConstraint && !typeArgument.IsNonNullableValueType()) { // "The type '{2}' must be a non-nullable value type in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_ValConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return(false); } // The type parameters for a constructed type/method are the type parameters of // the ConstructedFrom type/method, so the constraint types are not substituted. // For instance with "class C<T, U> where T : U", the type parameter for T in "C<object, int>" // has constraint "U", not "int". We need to substitute the constraints from the // original definition of the type parameters using the map from the constructed symbol. var constraintTypes = ArrayBuilder <TypeSymbol> .GetInstance(); HashSet <DiagnosticInfo> useSiteDiagnostics = null; substitution.SubstituteTypesDistinctWithoutModifiers(typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics), constraintTypes); bool hasError = false; foreach (var constraintType in constraintTypes) { if (SatisfiesConstraintType(conversions, typeArgument, constraintType, ref useSiteDiagnostics)) { continue; } ErrorCode errorCode; if (typeArgument.IsReferenceType) { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedRefType; } else if (typeArgument.IsNullableType()) { errorCode = constraintType.IsInterfaceType() ? ErrorCode.ERR_GenericConstraintNotSatisfiedNullableInterface : ErrorCode.ERR_GenericConstraintNotSatisfiedNullableEnum; } else if (typeArgument.TypeKind == TypeKind.TypeParameter) { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedTyVar; } else { errorCode = ErrorCode.ERR_GenericConstraintNotSatisfiedValType; } SymbolDistinguisher distinguisher = new SymbolDistinguisher(currentCompilation, constraintType, typeArgument); diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(errorCode, containingSymbol.ConstructedFrom(), distinguisher.First, typeParameter, distinguisher.Second))); hasError = true; } if (AppendUseSiteDiagnostics(useSiteDiagnostics, typeParameter, ref useSiteDiagnosticsBuilder)) { hasError = true; } constraintTypes.Free(); // Check the constructor constraint. if (typeParameter.HasConstructorConstraint && !SatisfiesConstructorConstraint(typeArgument)) { // "'{2}' must be a non-abstract type with a public parameterless constructor in order to use it as parameter '{1}' in the generic type or method '{0}'" diagnosticsBuilder.Add(new TypeParameterDiagnosticInfo(typeParameter, new CSDiagnosticInfo(ErrorCode.ERR_NewConstraintNotSatisfied, containingSymbol.ConstructedFrom(), typeParameter, typeArgument))); return(false); } return(!hasError); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); ParameterHelpers.EnsureIsReadOnlyAttributeExists(Parameters, diagnostics, modifyCompilationForRefReadOnly: true); }
internal sealed override void AfterAddingTypeMembersChecks( ConversionsBase conversions, BindingDiagnosticBag diagnostics ) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. var compilation = DeclaringCompilation; this.ReturnType.CheckAllConstraints( compilation, conversions, this.Locations[0], diagnostics ); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints( compilation, conversions, parameter.Locations[0], diagnostics ); } ParameterHelpers.EnsureIsReadOnlyAttributeExists( compilation, Parameters, diagnostics, modifyCompilation: true ); if (ReturnType.ContainsNativeInteger()) { compilation.EnsureNativeIntegerAttributeExists( diagnostics, ReturnTypeLocation, modifyCompilation: true ); } ParameterHelpers.EnsureNativeIntegerAttributeExists( compilation, Parameters, diagnostics, modifyCompilation: true ); if ( compilation.ShouldEmitNullableAttributes(this) && ReturnTypeWithAnnotations.NeedsNullableAttribute() ) { compilation.EnsureNullableAttributeExists( diagnostics, ReturnTypeLocation, modifyCompilation: true ); } ParameterHelpers.EnsureNullableAttributeExists( compilation, this, Parameters, diagnostics, modifyCompilation: true ); }
protected abstract void CheckConstraintsForExplicitInterfaceType(ConversionsBase conversions, BindingDiagnosticBag diagnostics);
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { this.CheckModifiersAndType(diagnostics); this.Type.CheckAllConstraints(conversions, this.Locations[0], diagnostics); }
public static bool CheckConstraints( this MethodSymbol method, ConversionsBase conversions, CSharpSyntaxNode syntaxNode, Compilation currentCompilation, DiagnosticBag diagnostics, BitVector skipParameters = default(BitVector)) { if (!RequiresChecking(method)) { return true; } var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckMethodConstraints(method, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, skipParameters); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { var location = new SourceLocation(syntaxNode); diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); return result; }
public static bool CheckConstraints( this NamedTypeSymbol type, ConversionsBase conversions, SyntaxNode typeSyntax, SeparatedSyntaxList<TypeSyntax> typeArgumentsSyntax, // may be omitted in synthesized invocations Compilation currentCompilation, ConsList<Symbol> basesBeingResolved, DiagnosticBag diagnostics) { Debug.Assert(typeArgumentsSyntax.Count == 0 /*omitted*/ || typeArgumentsSyntax.Count == type.Arity); if (!RequiresChecking(type)) { return true; } var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = !typeSyntax.HasErrors && CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { int ordinal = pair.TypeParameter.Ordinal; var location = new SourceLocation(ordinal < typeArgumentsSyntax.Count ? typeArgumentsSyntax[ordinal] : typeSyntax); diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); if (HasDuplicateInterfaces(type, basesBeingResolved)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, typeSyntax.Location, type); } return result; }
public static bool CheckConstraints( this NamedTypeSymbol type, CSharpCompilation currentCompilation, ConversionsBase conversions, Location location, DiagnosticBag diagnostics) { if (!RequiresChecking(type)) { return true; } var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); // we only check for distinct interfaces when the type is not from source, as we // trust that types that are from source have already been checked by the compiler // to prevent this from happening in the first place. if (!(currentCompilation != null && type.IsFromCompilation(currentCompilation)) && HasDuplicateInterfaces(type, null)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, location, type); } return result; }
/// <summary> /// Returns true if type a is encompassed by type b (spec 6.4.3), /// and returns false otherwise. /// </summary> private static bool IsEncompassedBy(ConversionsBase conversions, TypeSymbol a, TypeSymbol b, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert(IsValidEncompassedByArgument(a)); Debug.Assert(IsValidEncompassedByArgument(b)); return conversions.HasIdentityOrImplicitReferenceConversion(a, b, ref useSiteDiagnostics) || conversions.HasBoxingConversion(a, b, ref useSiteDiagnostics); }
private static bool CheckTypeConstraints( NamedTypeSymbol type, ConversionsBase conversions, Compilation currentCompilation, ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder) { return CheckConstraints( type, conversions, type.TypeSubstitution, type.OriginalDefinition.TypeParameters, type.TypeArgumentsNoUseSiteDiagnostics, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); }
protected sealed override void CheckConstraintsForExplicitInterfaceType(ConversionsBase conversions, DiagnosticBag diagnostics) { }
/// <summary> /// Check type parameter constraints for the containing type or method symbol. /// </summary> /// <param name="containingSymbol">The generic type or method.</param> /// <param name="conversions">Conversions instance.</param> /// <param name="substitution">The map from type parameters to type arguments.</param> /// <param name="typeParameters">Containing symbol type parameters.</param> /// <param name="typeArguments">Containing symbol type arguments.</param> /// <param name="currentCompilation">Improves error message detail.</param> /// <param name="diagnosticsBuilder">Diagnostics.</param> /// <param name="skipParameters">Parameters to skip.</param> /// <param name="useSiteDiagnosticsBuilder"/> /// <param name="ignoreTypeConstraintsDependentOnTypeParametersOpt">If an original form of a type constraint /// depends on a type parameter from this set, do not verify this type constraint.</param> /// <returns>True if the constraints were satisfied, false otherwise.</returns> public static bool CheckConstraints( this Symbol containingSymbol, ConversionsBase conversions, TypeMap substitution, ImmutableArray<TypeParameterSymbol> typeParameters, ImmutableArray<TypeSymbol> typeArguments, Compilation currentCompilation, ArrayBuilder<TypeParameterDiagnosticInfo> diagnosticsBuilder, ref ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder, BitVector skipParameters = default(BitVector), HashSet<TypeParameterSymbol> ignoreTypeConstraintsDependentOnTypeParametersOpt = null) { Debug.Assert(typeParameters.Length == typeArguments.Length); Debug.Assert(typeParameters.Length > 0); int n = typeParameters.Length; bool succeeded = true; for (int i = 0; i < n; i++) { if (skipParameters[i]) { continue; } var typeArgument = typeArguments[i]; var typeParameter = typeParameters[i]; if (!CheckConstraints(containingSymbol, conversions, substitution, typeParameter, typeArgument, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder, ignoreTypeConstraintsDependentOnTypeParametersOpt)) { succeeded = false; } } return succeeded; }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { base.AfterAddingTypeMembersChecks(conversions, diagnostics); if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = this.ExplicitInterfaceSpecifier; Debug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } }
private static bool SatisfiesConstraintType( ConversionsBase conversions, TypeSymbol typeArgument, TypeSymbol constraintType, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { if (constraintType.IsErrorType()) { return false; } // Spec 4.4.4 describes the valid conversions from // type argument A to constraint type C: // "An identity conversion (6.1.1). // An implicit reference conversion (6.1.6). ..." if (conversions.HasIdentityOrImplicitReferenceConversion(typeArgument, constraintType, ref useSiteDiagnostics)) { return true; } // "... A boxing conversion (6.1.7), provided that type A is a non-nullable value type. ..." // NOTE: we extend this to allow, for example, a conversion from Nullable<T> to object. if (typeArgument.IsValueType && conversions.HasBoxingConversion(typeArgument.IsNullableType() ? ((NamedTypeSymbol)typeArgument).ConstructedFrom : typeArgument, constraintType, ref useSiteDiagnostics)) { return true; } if (typeArgument.TypeKind == TypeKind.TypeParameter) { var typeParameter = (TypeParameterSymbol)typeArgument; // "... An implicit reference, boxing, or type parameter conversion // from type parameter A to C." if (conversions.HasImplicitTypeParameterConversion(typeParameter, constraintType, ref useSiteDiagnostics)) { return true; } // TypeBind::SatisfiesBound allows cases where one of the // type parameter constraints satisfies the constraint. foreach (var typeArgumentConstraint in typeParameter.ConstraintTypesWithDefinitionUseSiteDiagnostics(ref useSiteDiagnostics)) { if (SatisfiesConstraintType(conversions, typeArgumentConstraint, constraintType, ref useSiteDiagnostics)) { return true; } } } return false; }
private static void CheckEffectiveAndDeducedBaseTypes(ConversionsBase conversions, TypeSymbol effectiveBase, TypeSymbol deducedBase) { Debug.Assert((object)deducedBase != null); Debug.Assert((object)effectiveBase != null); HashSet<DiagnosticInfo> useSiteDiagnostics = null; Debug.Assert(deducedBase.IsErrorType() || effectiveBase.IsErrorType() || conversions.HasIdentityOrImplicitReferenceConversion(deducedBase, effectiveBase, ref useSiteDiagnostics) || conversions.HasBoxingConversion(deducedBase, effectiveBase, ref useSiteDiagnostics)); }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // property name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. if ((object)_explicitInterfaceType != null) { var explicitInterfaceSpecifier = GetExplicitInterfaceSpecifier(this.CSharpSyntaxNode); Debug.Assert(explicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(explicitInterfaceSpecifier.Name), diagnostics); } }
internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, DiagnosticBag diagnostics) { // Check constraints on return type and parameters. Note: Dev10 uses the // method name location for any such errors. We'll do the same for return // type errors but for parameter errors, we'll use the parameter location. if ((object)_explicitInterfaceType != null) { var syntax = this.GetSyntax(); Debug.Assert(syntax.ExplicitInterfaceSpecifier != null); _explicitInterfaceType.CheckAllConstraints(conversions, new SourceLocation(syntax.ExplicitInterfaceSpecifier.Name), diagnostics); } this.ReturnType.CheckAllConstraints(conversions, this.Locations[0], diagnostics); foreach (var parameter in this.Parameters) { parameter.Type.CheckAllConstraints(conversions, parameter.Locations[0], diagnostics); } var implementingPart = this.SourcePartialImplementation; if ((object)implementingPart != null) { PartialMethodChecks(this, implementingPart, diagnostics); } }
public static bool CheckConstraints( this NamedTypeSymbol type, ConversionsBase conversions, CSharpSyntaxNode typeSyntax, SeparatedSyntaxList<TypeSyntax> typeArgumentsSyntax, Compilation currentCompilation, DiagnosticBag diagnostics) { Debug.Assert(typeArgumentsSyntax.Count == type.Arity); if (!RequiresChecking(type)) { return true; } var diagnosticsBuilder = ArrayBuilder<TypeParameterDiagnosticInfo>.GetInstance(); ArrayBuilder<TypeParameterDiagnosticInfo> useSiteDiagnosticsBuilder = null; var result = CheckTypeConstraints(type, conversions, currentCompilation, diagnosticsBuilder, ref useSiteDiagnosticsBuilder); if (useSiteDiagnosticsBuilder != null) { diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder); } foreach (var pair in diagnosticsBuilder) { int ordinal = pair.TypeParameter.Ordinal; var location = new SourceLocation(typeArgumentsSyntax[ordinal]); diagnostics.Add(new CSDiagnostic(pair.DiagnosticInfo, location)); } diagnosticsBuilder.Free(); if (!InterfacesAreDistinct(type)) { result = false; diagnostics.Add(ErrorCode.ERR_BogusType, typeSyntax.Location, type); } return result; }