From 560736db969238958ba9a3fa9752a005ffe87e09 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 5 May 2014 13:03:36 -0700 Subject: [PATCH] Report an error if an argument list is provided for an implemented interface. Fixes https://roslyn.codeplex.com/workitem/4. This is a port of https://roslyn.codeplex.com/SourceControl/changeset/f930b49714dc268a0e9df96d213d5516634a6450. (changeset 1250419) --- .../CSharp/Source/CSharpResources.Designer.cs | 9 ++ .../CSharp/Source/CSharpResources.resx | 3 + .../CSharp/Source/Compiler/MethodCompiler.cs | 67 +++++++----- .../CSharp/Source/Errors/ErrorCode.cs | 2 + .../Source/SourceNamedTypeSymbol_Bases.cs | 5 + .../Symbols/Source/PrimaryConstructors.cs | 101 +++++++++++++++++- 6 files changed, 154 insertions(+), 33 deletions(-) diff --git a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs index 3bf314c7a44..eec66353cc8 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs +++ b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs @@ -4452,6 +4452,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to Implemented interface cannot have arguments.. + /// + internal static string ERR_ImplementedInterfaceWithArguments { + get { + return ResourceManager.GetString("ERR_ImplementedInterfaceWithArguments", resourceCulture); + } + } + /// /// Looks up a localized string similar to No best type found for implicitly-typed array. /// diff --git a/Src/Compilers/CSharp/Source/CSharpResources.resx b/Src/Compilers/CSharp/Source/CSharpResources.resx index 82e720e92c3..ca6e37a8c1e 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.resx +++ b/Src/Compilers/CSharp/Source/CSharpResources.resx @@ -3813,4 +3813,7 @@ A ref or out parameter cannot have any field modifiers. + + Implemented interface cannot have arguments. + \ No newline at end of file diff --git a/Src/Compilers/CSharp/Source/Compiler/MethodCompiler.cs b/Src/Compilers/CSharp/Source/Compiler/MethodCompiler.cs index ebdda63266e..81965bbb59a 100644 --- a/Src/Compilers/CSharp/Source/Compiler/MethodCompiler.cs +++ b/Src/Compilers/CSharp/Source/Compiler/MethodCompiler.cs @@ -1242,40 +1242,41 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta var blockSyntax = sourceMethod.BlockSyntax; if (blockSyntax != null) { - var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree); - var inMethodBinder = factory.GetBinder(blockSyntax); - var binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder); - body = binder.BindBlock(blockSyntax, diagnostics); - if (generateDebugInfo) - { - debugImports = binder.ImportsList; - } - if (inMethodBinder.IsDirectlyInIterator) - { - foreach (var parameter in method.Parameters) + var factory = compilation.GetBinderFactory(sourceMethod.SyntaxTree); + var inMethodBinder = factory.GetBinder(blockSyntax); + var binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder); + body = binder.BindBlock(blockSyntax, diagnostics); + if (generateDebugInfo) { - if (parameter.RefKind != RefKind.None) + debugImports = binder.ImportsList; + } + + if (inMethodBinder.IsDirectlyInIterator) + { + foreach (var parameter in method.Parameters) { - diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]); + if (parameter.RefKind != RefKind.None) + { + diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, parameter.Locations[0]); + } + else if (parameter.Type.IsUnsafe()) + { + diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]); + } } - else if (parameter.Type.IsUnsafe()) + + if (sourceMethod.IsUnsafe && compilation.Options.AllowUnsafe) // Don't cascade { - diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, parameter.Locations[0]); + diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, sourceMethod.Locations[0]); } - } - if (sourceMethod.IsUnsafe && compilation.Options.AllowUnsafe) // Don't cascade - { - diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, sourceMethod.Locations[0]); - } - - if (sourceMethod.IsVararg) - { - // error CS1636: __arglist is not allowed in the parameter list of iterators - diagnostics.Add(ErrorCode.ERR_VarargsIterator, sourceMethod.Locations[0]); + if (sourceMethod.IsVararg) + { + // error CS1636: __arglist is not allowed in the parameter list of iterators + diagnostics.Add(ErrorCode.ERR_VarargsIterator, sourceMethod.Locations[0]); + } } } - } else // for [if (blockSyntax != null)] { var property = sourceMethod.AssociatedSymbol as SourcePropertySymbol; @@ -1426,8 +1427,18 @@ private static BoundExpression BindConstructorInitializer(MethodSymbol construct TypeSyntax baseTypeSyntax = classDecl.BaseList.Types[0]; if (baseTypeSyntax.Kind == SyntaxKind.BaseClassWithArguments) { - initializerArgumentListOpt = ((BaseClassWithArgumentsSyntax)baseTypeSyntax).ArgumentList; - } + var baseBinder = compilation.GetBinder(classDecl.BaseList); + baseBinder = baseBinder.WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags.SuppressConstraintChecks, constructor.ContainingType); + + var baseClassWithArguments = (BaseClassWithArgumentsSyntax)baseTypeSyntax; + TypeSymbol targetType = baseBinder.BindType(baseClassWithArguments.BaseClass, new DiagnosticBag()); + + // If types are different, an error has been reported elsewhere. + if (!targetType.IsErrorType() && baseType == targetType) + { + initializerArgumentListOpt = baseClassWithArguments.ArgumentList; + } + } } } else diff --git a/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs b/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs index 6da43fedc0e..27daea07da0 100644 --- a/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs +++ b/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs @@ -1275,6 +1275,8 @@ internal enum ErrorCode ERR_DeclarationExpressionOutsideOfAMethodBody = 8047, ERR_VariableUsedInTheSameArgumentList = 8048, + ERR_ImplementedInterfaceWithArguments = 8049, + // Values in the range 10000-14000 are used for "Code Analysis" issues previously reported by FXCop WRN_CA2000_DisposeObjectsBeforeLosingScope1 = 10000, WRN_CA2000_DisposeObjectsBeforeLosingScope2 = 10001, diff --git a/Src/Compilers/CSharp/Source/Symbols/Source/SourceNamedTypeSymbol_Bases.cs b/Src/Compilers/CSharp/Source/Symbols/Source/SourceNamedTypeSymbol_Bases.cs index 0026e45faef..97101d5a8cc 100644 --- a/Src/Compilers/CSharp/Source/Symbols/Source/SourceNamedTypeSymbol_Bases.cs +++ b/Src/Compilers/CSharp/Source/Symbols/Source/SourceNamedTypeSymbol_Bases.cs @@ -342,6 +342,11 @@ private static BaseListSyntax GetBaseListOpt(SingleTypeDeclaration decl) TypeSyntax baseClass = ((BaseClassWithArgumentsSyntax)typeSyntax).BaseClass; location = new SourceLocation(baseClass); baseType = baseBinder.BindType(baseClass, diagnostics, newBasesBeingResolved); + + if (baseType.TypeKind == TypeKind.Interface) + { + diagnostics.Add(ErrorCode.ERR_ImplementedInterfaceWithArguments, ((BaseClassWithArgumentsSyntax)typeSyntax).ArgumentList.GetLocation()); + } } else { diff --git a/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs b/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs index b905171ff5b..f7fba145607 100644 --- a/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs +++ b/Src/Compilers/CSharp/Test/Symbol/Symbols/Source/PrimaryConstructors.cs @@ -731,7 +731,7 @@ static class Derived(int x) } [Fact] - public void Class8() + public void Class8_01() { var comp = CreateCompilationWithMscorlib(@" class Base(int x) @@ -749,10 +749,43 @@ partial class Derived(int x) : Base(y) comp.VerifyDiagnostics( // (6,15): error CS0263: Partial declarations of 'Derived' must not specify different base classes // partial class Derived : object - Diagnostic(ErrorCode.ERR_PartialMultipleBases, "Derived").WithArguments("Derived"), - // (9,37): error CS0103: The name 'y' does not exist in the current context - // partial class Derived(int x) : Base(y) - Diagnostic(ErrorCode.ERR_NameNotInContext, "y").WithArguments("y") + Diagnostic(ErrorCode.ERR_PartialMultipleBases, "Derived").WithArguments("Derived") + ); + } + + [Fact] + public void Class8_02() + { + var comp = CreateCompilationWithMscorlib(@" +class Base1(int x) +{ +} + +class Base2 +{} + +partial class Derived1(int x) : Base1(y) +{ +} + +partial class Derived1 : Base2 +{} + +partial class Derived2 : Base2 +{} + +partial class Derived2(int x) : Base1(y) +{ +} +", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Experimental)); + + comp.VerifyDiagnostics( + // (16,15): error CS0263: Partial declarations of 'Derived2' must not specify different base classes + // partial class Derived2 : Base2 + Diagnostic(ErrorCode.ERR_PartialMultipleBases, "Derived2").WithArguments("Derived2").WithLocation(16, 15), + // (9,15): error CS0263: Partial declarations of 'Derived1' must not specify different base classes + // partial class Derived1(int x) : Base1(y) + Diagnostic(ErrorCode.ERR_PartialMultipleBases, "Derived1").WithArguments("Derived1").WithLocation(9, 15) ); } @@ -3977,5 +4010,63 @@ class Derived(private int v) Assert.Equal(parameter, field.AssociatedSymbol); } + [Fact, WorkItem(4)] + public void ArgumentsOnImplementedInterface_01() + { + var comp = CreateCompilationWithMscorlib(@" +using System; + +class C1() : IDisposable() +{ + public void Dispose() { } +} + +class C2() : IDisposable(2) +{ + public void Dispose() { } +} +", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Experimental)); + + comp.VerifyDiagnostics( + // (4,25): error CS9013: Implemented interface cannot have arguments. + // class C1() : IDisposable() + Diagnostic(ErrorCode.ERR_ImplementedInterfaceWithArguments, "()").WithLocation(4, 25), + // (9,25): error CS9013: Implemented interface cannot have arguments. + // class C2() : IDisposable(2) + Diagnostic(ErrorCode.ERR_ImplementedInterfaceWithArguments, "(2)").WithLocation(9, 25) + ); + } + + [Fact, WorkItem(4)] + public void ArgumentsOnImplementedInterface_02() + { + var comp = CreateCompilationWithMscorlib(@" +using System; + +class Base +{ + public Base(int x){} +} + +partial class Derived : Base +{ +} + +partial class Derived() : IDisposable(2) +{ + public void Dispose() { } +} +", parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.Experimental)); + + comp.VerifyDiagnostics( + // (13,38): error CS9013: Implemented interface cannot have arguments. + // partial class Derived() : IDisposable(2) + Diagnostic(ErrorCode.ERR_ImplementedInterfaceWithArguments, "(2)").WithLocation(13, 38), + // (13,22): error CS7036: There is no argument given that corresponds to the required formal parameter 'x' of 'Base.Base(int)' + // partial class Derived() : IDisposable(2) + Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "()").WithArguments("x", "Base.Base(int)").WithLocation(13, 22) + ); + } + } } \ No newline at end of file -- GitLab