/// <summary> /// Given a type <paramref name="type"/>, which is either dynamic type OR is a constructed type with dynamic type present in it's type argument tree, /// returns a synthesized DynamicAttribute with encoded dynamic transforms array. /// </summary> /// <remarks>This method is port of AttrBind::CompileDynamicAttr from the native C# compiler.</remarks> internal SynthesizedAttributeData SynthesizeDynamicAttribute(TypeSymbol type, int customModifiersCount, RefKind refKindOpt = RefKind.None) { Debug.Assert((object)type != null); Debug.Assert(type.ContainsDynamic()); if (type.IsDynamic() && refKindOpt == RefKind.None && customModifiersCount == 0) { return(TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctor)); } else { NamedTypeSymbol booleanType = GetSpecialType(SpecialType.System_Boolean); Debug.Assert((object)booleanType != null); var transformFlags = DynamicTransformsEncoder.Encode(type, booleanType, customModifiersCount, refKindOpt); var boolArray = ArrayTypeSymbol.CreateSZArray(booleanType.ContainingAssembly, booleanType, customModifiers: ImmutableArray <CustomModifier> .Empty); var arguments = ImmutableArray.Create <TypedConstant>(new TypedConstant(boolArray, transformFlags)); return(TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_DynamicAttribute__ctorTransformFlags, arguments)); } }
/// <summary> /// Returns true if the type is a valid constraint type. /// Otherwise returns false and generates a diagnostic. /// </summary> private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeSymbol type, DiagnosticBag diagnostics) { switch (type.SpecialType) { case SpecialType.System_Object: case SpecialType.System_ValueType: case SpecialType.System_Enum: case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: case SpecialType.System_Array: // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); return(false); } switch (type.TypeKind) { case TypeKind.Error: case TypeKind.TypeParameter: return(true); case TypeKind.Interface: break; case TypeKind.DynamicType: // "Constraint cannot be the dynamic type" Error(diagnostics, ErrorCode.ERR_DynamicTypeAsBound, syntax); return(false); case TypeKind.Class: if (type.IsSealed) { goto case TypeKind.Struct; } else if (type.IsStatic) { // "'{0}': static classes cannot be used as constraints" Error(diagnostics, ErrorCode.ERR_ConstraintIsStaticClass, syntax, type); return(false); } break; case TypeKind.Delegate: case TypeKind.Enum: case TypeKind.Struct: // "'{0}' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter." Error(diagnostics, ErrorCode.ERR_BadBoundType, syntax, type); return(false); case TypeKind.ArrayType: case TypeKind.PointerType: // CS0706 already reported by parser. return(false); case TypeKind.Submission: // script class is synthetized, never used as a constraint default: Debug.Assert(false, "Unexpected type kind: " + type.TypeKind); return(false); } if (type.ContainsDynamic()) { // "Constraint cannot be a dynamic type '{0}'" Error(diagnostics, ErrorCode.ERR_ConstructedDynamicTypeAsBound, syntax, type); return(false); } return(true); }
/// <summary> /// Returns true if the type is a valid constraint type. /// Otherwise returns false and generates a diagnostic. /// </summary> private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeWithAnnotations typeWithAnnotations, DiagnosticBag diagnostics) { TypeSymbol type = typeWithAnnotations.Type; switch (type.SpecialType) { case SpecialType.System_Enum: CheckFeatureAvailability(syntax, MessageID.IDS_FeatureEnumGenericTypeConstraint, diagnostics); break; case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: CheckFeatureAvailability(syntax, MessageID.IDS_FeatureDelegateGenericTypeConstraint, diagnostics); break; case SpecialType.System_Object: if (typeWithAnnotations.NullableAnnotation.IsAnnotated()) { // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, typeWithAnnotations); return(false); } CheckFeatureAvailability(syntax, MessageID.IDS_FeatureObjectGenericTypeConstraint, diagnostics); break; case SpecialType.System_ValueType: case SpecialType.System_Array: // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); return(false); } switch (type.TypeKind) { case TypeKind.Error: case TypeKind.TypeParameter: return(true); case TypeKind.Interface: break; case TypeKind.Dynamic: // "Constraint cannot be the dynamic type" Error(diagnostics, ErrorCode.ERR_DynamicTypeAsBound, syntax); return(false); case TypeKind.Class: if (type.IsSealed) { goto case TypeKind.Struct; } else if (type.IsStatic) { // "'{0}': static classes cannot be used as constraints" Error(diagnostics, ErrorCode.ERR_ConstraintIsStaticClass, syntax, type); return(false); } break; case TypeKind.Delegate: case TypeKind.Enum: case TypeKind.Struct: // "'{0}' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter." Error(diagnostics, ErrorCode.ERR_BadBoundType, syntax, type); return(false); case TypeKind.Array: case TypeKind.Pointer: // CS0706 already reported by parser. return(false); case TypeKind.Submission: // script class is synthesized, never used as a constraint default: throw ExceptionUtilities.UnexpectedValue(type.TypeKind); } if (type.ContainsDynamic()) { // "Constraint cannot be a dynamic type '{0}'" Error(diagnostics, ErrorCode.ERR_ConstructedDynamicTypeAsBound, syntax, type); return(false); } return(true); }
/// <summary> /// Returns true if the type is a valid constraint type. /// Otherwise returns false and generates a diagnostic. /// </summary> private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeSymbol type, DiagnosticBag diagnostics) { switch (type.SpecialType) { case SpecialType.System_Object: case SpecialType.System_ValueType: case SpecialType.System_Enum: case SpecialType.System_Delegate: case SpecialType.System_MulticastDelegate: case SpecialType.System_Array: // "Constraint cannot be special class '{0}'" Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); return false; } switch (type.TypeKind) { case TypeKind.Error: case TypeKind.TypeParameter: return true; case TypeKind.Interface: break; case TypeKind.DynamicType: // "Constraint cannot be the dynamic type" Error(diagnostics, ErrorCode.ERR_DynamicTypeAsBound, syntax); return false; case TypeKind.Class: if (type.IsSealed) { goto case TypeKind.Struct; } else if (type.IsStatic) { // "'{0}': static classes cannot be used as constraints" Error(diagnostics, ErrorCode.ERR_ConstraintIsStaticClass, syntax, type); return false; } break; case TypeKind.Delegate: case TypeKind.Enum: case TypeKind.Struct: // "'{0}' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter." Error(diagnostics, ErrorCode.ERR_BadBoundType, syntax, type); return false; case TypeKind.ArrayType: case TypeKind.PointerType: // CS0706 already reported by parser. return false; case TypeKind.Submission: // script class is synthetized, never used as a constraint default: Debug.Assert(false, "Unexpected type kind: " + type.TypeKind); return false; } if (type.ContainsDynamic()) { // "Constraint cannot be a dynamic type '{0}'" Error(diagnostics, ErrorCode.ERR_ConstructedDynamicTypeAsBound, syntax, type); return false; } return true; }