diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs index 1f814b661be04e1b4860fd520b1e435e3ae48ae8..da96bbd2cd03eeb92b94c598c66a53ee61e42ffe 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Constraints.cs @@ -227,8 +227,9 @@ internal partial class Binder { case SyntaxKind.PredefinedType: case SyntaxKind.NullableType: - break; case SyntaxKind.PointerType: + // Pointer error is reported by IsValidTypeConstraint + break; default: if (!SyntaxFacts.IsName(typeSyntax.Kind())) { @@ -401,7 +402,7 @@ private TypeParameterConstraintClause GetDefaultTypeParameterConstraintClause(Ty ArrayBuilder constraintTypes, DiagnosticBag diagnostics) { - if (!IsValidConstraintType(syntax, type, diagnostics)) + if (!isValidConstraintType(syntax, type, diagnostics)) { return false; } @@ -459,89 +460,91 @@ private TypeParameterConstraintClause GetDefaultTypeParameterConstraintClause(Ty } return true; - } - /// - /// Returns true if the type is a valid constraint type. - /// Otherwise returns false and generates a diagnostic. - /// - private static bool IsValidConstraintType(TypeConstraintSyntax syntax, TypeWithAnnotations typeWithAnnotations, DiagnosticBag diagnostics) - { - TypeSymbol type = typeWithAnnotations.Type; - - switch (type.SpecialType) + // Returns true if the type is a valid constraint type. + // Otherwise returns false and generates a diagnostic. + static bool isValidConstraintType(TypeConstraintSyntax syntax, TypeWithAnnotations typeWithAnnotations, DiagnosticBag diagnostics) { - 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: - case SpecialType.System_ValueType: - case SpecialType.System_Array: - // "Constraint cannot be special class '{0}'" - Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); - return false; - } + TypeSymbol type = typeWithAnnotations.Type; - switch (type.TypeKind) - { - case TypeKind.Error: - case TypeKind.TypeParameter: - return true; + 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: + case SpecialType.System_ValueType: + case SpecialType.System_Array: + // "Constraint cannot be special class '{0}'" + Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type); + return false; + } - case TypeKind.Interface: - break; + switch (type.TypeKind) + { + case TypeKind.Error: + case TypeKind.TypeParameter: + return true; - case TypeKind.Dynamic: - // "Constraint cannot be the dynamic type" - Error(diagnostics, ErrorCode.ERR_DynamicTypeAsBound, syntax); - return false; + case TypeKind.Interface: + break; - 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); + case TypeKind.Dynamic: + // "Constraint cannot be the dynamic type" + Error(diagnostics, ErrorCode.ERR_DynamicTypeAsBound, syntax); 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.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.Array: - case TypeKind.Pointer: - // CS0706 already reported by binding above. - return false; + 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.Submission: - // script class is synthesized, never used as a constraint + case TypeKind.Array: + // CS0706 already reported by binding above. + return false; - default: - throw ExceptionUtilities.UnexpectedValue(type.TypeKind); - } + case TypeKind.Pointer: + // "Invalid constraint type. A type used as a constraint must be an interface, a non-sealed class or a type parameter." + Error(diagnostics, ErrorCode.ERR_BadConstraintType, syntax.GetLocation()); + return false; - if (type.ContainsDynamic()) - { - // "Constraint cannot be a dynamic type '{0}'" - Error(diagnostics, ErrorCode.ERR_ConstructedDynamicTypeAsBound, syntax, type); - return false; - } + case TypeKind.Submission: + // script class is synthesized, never used as a constraint - return true; + 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; + } } } }