diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 548481b648ec77aaf0beeb7bbaf048d5c005a72e..d472ce859957017ce3aa49373aa844e1ccf76e8c 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -1584,7 +1584,7 @@ private TypeDeclarationSyntax ParseClassOrStructOrInterfaceDeclaration(SyntaxLis var saveTerm = _termState; _termState |= TerminatorState.IsPossibleAggregateClauseStartOrStop; var name = this.ParseIdentifierToken(); - var typeParameters = this.ParseTypeParameterList(allowVariance: classOrStructOrInterface.Kind == SyntaxKind.InterfaceKeyword); + var typeParameters = this.ParseTypeParameterList(); _termState = saveTerm; bool hasTypeParams = typeParameters != null; @@ -4985,7 +4985,7 @@ private bool IsLocalFunctionAfterIdentifier() try { - var typeParameterListOpt = this.ParseTypeParameterList(allowVariance: false); + var typeParameterListOpt = this.ParseTypeParameterList(); var paramList = ParseParenthesizedParameterList( allowThisKeyword: true, allowDefaults: true, allowAttributes: true); @@ -5078,7 +5078,7 @@ private DelegateDeclarationSyntax ParseDelegateDeclaration(SyntaxListBuilder); try @@ -5111,7 +5111,7 @@ private EnumDeclarationSyntax ParseEnumDeclaration(SyntaxListBuilder()" still makes sense, so don't force accept a local function if there's a type parameter list. ParameterListSyntax paramList = this.ParseParenthesizedParameterList(allowThisKeyword: true, allowDefaults: true, allowAttributes: true); // "await x()" is ambiguous (see note at start of this method), but we assume "await x(await y)" is meant to be a function if it's in a non-async context. diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 3deb8c961e8e91ac8a73d51d334bda52f59ebe8c..ff20712ca744cdd42a20c79f4632018ba24a7751 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -803,6 +803,11 @@ private ImmutableArray MakeTypeParameters(MethodDeclaration for (int ordinal = 0; ordinal < typeParameters.Count; ordinal++) { var parameter = typeParameters[ordinal]; + if (parameter.VarianceKeyword.Kind() != SyntaxKind.None) + { + diagnostics.Add(ErrorCode.ERR_IllegalVarianceSyntax, parameter.VarianceKeyword.GetLocation()); + } + var identifier = parameter.Identifier; var location = identifier.GetLocation(); var name = identifier.ValueText; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 0b6ef3ad0036a7400ea8320e24be72b861ac1c85..2be26cd359a9774875d7f2e8f7fdfe1210cfac8f 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -132,7 +132,8 @@ private ImmutableArray MakeTypeParameters(DiagnosticBag dia var syntaxTree = syntaxRef.SyntaxTree; TypeParameterListSyntax tpl; - switch (typeDecl.Kind()) + SyntaxKind typeKind = typeDecl.Kind(); + switch (typeKind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.StructDeclaration: @@ -150,11 +151,18 @@ private ImmutableArray MakeTypeParameters(DiagnosticBag dia throw ExceptionUtilities.UnexpectedValue(typeDecl.Kind()); } + bool isInterfaceOrDelegate = typeKind == SyntaxKind.InterfaceDeclaration || typeKind == SyntaxKind.DelegateDeclaration; var parameterBuilder = new List(); parameterBuilders1.Add(parameterBuilder); int i = 0; foreach (var tp in tpl.Parameters) { + if (tp.VarianceKeyword.Kind() != SyntaxKind.None && + !isInterfaceOrDelegate) + { + diagnostics.Add(ErrorCode.ERR_IllegalVarianceSyntax, tp.VarianceKeyword.GetLocation()); + } + var name = typeParameterNames[i]; var location = new SourceLocation(tp.Identifier); var varianceKind = typeParameterVarianceKeywords[i]; diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs index 8d22d6ed55f1e22d6f93a2301d7d0c9c3ca698cf..ab9987fcbaa86febadf8f20746ad1b4f14cc9168 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ParserErrorMessageTests.cs @@ -4138,26 +4138,34 @@ struct S { } delegate void D(); class B { } }"; - - ParseAndValidate(test, - // (3,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. - Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "in").WithLocation(3, 12), - // (4,12): error CS7002: Unexpected use of a generic name - Diagnostic(ErrorCode.ERR_UnexpectedGenericName, "this").WithLocation(4, 12), - // (4,17): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. - Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(4, 17), + CreateCompilationWithMscorlib(test).GetDeclarationDiagnostics().Verify( // (6,10): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // struct S Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(6, 10), // (8,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // void M(); Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(8, 12), + // (3,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // void M(); + Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "in").WithLocation(3, 12), + // (8,10): error CS0501: 'S.M()' must declare a body because it is not marked abstract, extern, or partial + // void M(); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M").WithArguments("S.M()").WithLocation(8, 10), // (11,9): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // class A Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(11, 9), - // (13, 12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // (13,12): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // void M(); Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(13, 12), - // (15, 14): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. - Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(15, 14), + // (13,10): error CS0501: 'A.M()' must declare a body because it is not marked abstract, extern, or partial + // void M(); + Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M").WithArguments("A.M()").WithLocation(13, 10), // (17,13): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. - Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(17, 13)); + // class B { } + Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(17, 13), + // (15,14): error CS1960: Invalid variance modifier. Only interface and delegate type parameters can be specified as variant. + // struct S { } + Diagnostic(ErrorCode.ERR_IllegalVarianceSyntax, "out").WithLocation(15, 14)); } [Fact]