diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs index 14ac1557d56134b5980500d0133d90f2a62ff80f..be19e421cc4f86a794d198c5b34bf644cf86759c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbol.cs @@ -1048,11 +1048,11 @@ private static void ReportImplicitImplementationMatchDiagnostics(Symbol interfac if (interfaceMethodIsAccessor && !implicitImplIsAccessor && !interfaceMethod.IsIndexedPropertyAccessor()) { - diagnostics.Add(ErrorCode.ERR_MethodImplementingAccessor, implicitImpl.Locations[0], implicitImpl, interfaceMethod, implementingType); + diagnostics.Add(ErrorCode.ERR_MethodImplementingAccessor, GetImplicitImplementationDiagnosticLocation(interfaceMember, implementingType, implicitImpl), implicitImpl, interfaceMethod, implementingType); } else if (!interfaceMethodIsAccessor && implicitImplIsAccessor) { - diagnostics.Add(ErrorCode.ERR_AccessorImplementingMethod, implicitImpl.Locations[0], implicitImpl, interfaceMethod, implementingType); + diagnostics.Add(ErrorCode.ERR_AccessorImplementingMethod, GetImplicitImplementationDiagnosticLocation(interfaceMember, implementingType, implicitImpl), implicitImpl, interfaceMethod, implementingType); } else { @@ -1061,7 +1061,7 @@ private static void ReportImplicitImplementationMatchDiagnostics(Symbol interfac if (implicitImplMethod.IsConditional) { // CS0629: Conditional member '{0}' cannot implement interface member '{1}' in type '{2}' - diagnostics.Add(ErrorCode.ERR_InterfaceImplementedByConditional, implicitImpl.Locations[0], implicitImpl, interfaceMethod, implementingType); + diagnostics.Add(ErrorCode.ERR_InterfaceImplementedByConditional, GetImplicitImplementationDiagnosticLocation(interfaceMember, implementingType, implicitImpl), implicitImpl, interfaceMethod, implementingType); } else { @@ -1073,7 +1073,7 @@ private static void ReportImplicitImplementationMatchDiagnostics(Symbol interfac if (implicitImpl.ContainsTupleNames() && MemberSignatureComparer.ConsideringTupleNamesCreatesDifference(implicitImpl, interfaceMember)) { // it is ok to implement implicitly with no tuple names, for compatibility with C# 6, but otherwise names should match - diagnostics.Add(ErrorCode.ERR_ImplBadTupleNames, implicitImpl.Locations[0], implicitImpl, interfaceMember); + diagnostics.Add(ErrorCode.ERR_ImplBadTupleNames, GetImplicitImplementationDiagnosticLocation(interfaceMember, implementingType, implicitImpl), implicitImpl, interfaceMember); } // In constructed types, it is possible to see multiple members with the same (runtime) signature. @@ -1090,7 +1090,7 @@ private static void ReportImplicitImplementationMatchDiagnostics(Symbol interfac else if (MemberSignatureComparer.RuntimeImplicitImplementationComparer.Equals(interfaceMember, member) && !member.IsAccessor()) { // CONSIDER: Dev10 does not seem to report this for indexers or their accessors. - diagnostics.Add(ErrorCode.WRN_MultipleRuntimeImplementationMatches, member.Locations[0], member, interfaceMember, implementingType); + diagnostics.Add(ErrorCode.WRN_MultipleRuntimeImplementationMatches, GetImplicitImplementationDiagnosticLocation(interfaceMember, implementingType, member), member, interfaceMember, implementingType); } } } @@ -1107,7 +1107,7 @@ private static void ReportImplicitImplementationMismatchDiagnostics(Symbol inter { var @interface = interfaceMember.ContainingType; SourceMemberContainerTypeSymbol snt = implementingType as SourceMemberContainerTypeSymbol; - interfaceLocation = snt.GetImplementsLocation(@interface) ?? implementingType.Locations[0]; + interfaceLocation = snt?.GetImplementsLocation(@interface) ?? implementingType.Locations[0]; } else { @@ -1207,15 +1207,26 @@ private static void ReportAnyMismatchedConstraints(MethodSymbol interfaceMethod, // A.M that it does not satisfy I.M even though A does not implement I. Furthermore if // A is defined in metadata, there is no location for A.M. Instead, we simply report the // error on B if the match to I.M is in a base class.) - var location = (implicitImpl.ContainingType == implementingType) ? - implicitImpl.Locations[0] : - implementingType.Locations[0]; - diagnostics.Add(ErrorCode.ERR_ImplBadConstraints, location, typeParameter2.Name, implicitImpl, typeParameter1.Name, interfaceMethod); + diagnostics.Add(ErrorCode.ERR_ImplBadConstraints, GetImplicitImplementationDiagnosticLocation(interfaceMethod, implementingType, implicitImpl), typeParameter2.Name, implicitImpl, typeParameter1.Name, interfaceMethod); } } } } + private static Location GetImplicitImplementationDiagnosticLocation(Symbol interfaceMember, TypeSymbol implementingType, Symbol member) + { + if (member.ContainingType == implementingType) + { + return member.Locations[0]; + } + else + { + var @interface = interfaceMember.ContainingType; + SourceMemberContainerTypeSymbol snt = implementingType as SourceMemberContainerTypeSymbol; + return snt?.GetImplementsLocation(@interface) ?? implementingType.Locations[0]; + } + } + /// /// Search the declared members of a type for one that could be an implementation /// of a given interface member (depending on interface declarations). diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenImplicitImplementationTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenImplicitImplementationTests.cs index d7438a13d37ed4c181387c537fdaaf9c337b4e1b..a11766ca215b5f87e7449770e44f0857e384e0ec 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenImplicitImplementationTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenImplicitImplementationTests.cs @@ -1749,8 +1749,9 @@ public static void Main() Derived.Method()"); comp.VerifyDiagnostics( - // (17,17): warning CS1956: Member 'Derived.Method(int)' implements interface member 'Interface.Method(int)' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. - Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Method").WithArguments("Derived.Method(int)", "Interface.Method(int)", "Derived")); // No errors + // (20,58): warning CS1956: Member 'Derived.Method(int)' implements interface member 'Interface.Method(int)' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. + // class Derived : Derived, Interface, Interface + Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface").WithArguments("Derived.Method(int)", "Interface.Method(int)", "Derived").WithLocation(20, 58)); // No errors } [Fact] diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs index 3a15e87cbe0d202b69e06b927bafa9869d302738..7ff77c8d5a361cab8072c87e7533b8d6c83ea341 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs @@ -22997,9 +22997,9 @@ class Derived : Base, I<(int notA, int notB)> "; var comp = CreateStandardCompilation(source, references: s_valueTupleRefs); comp.VerifyDiagnostics( - // (8,27): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int notA, int notB)>.M()' (including on the return type). - // public (int a, int b) M() { return (1, 2); } - Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "M").WithArguments("Base.M()", "I<(int notA, int notB)>.M()").WithLocation(8, 27) + // (10,23): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int notA, int notB)>.M()' (including on the return type). + // class Derived : Base, I<(int notA, int notB)> + Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "I<(int notA, int notB)>").WithArguments("Base.M()", "I<(int notA, int notB)>.M()").WithLocation(10, 23) ); } @@ -23023,9 +23023,9 @@ class Derived : Base, I<(int notA, int notB)> "; var comp = CreateStandardCompilation(source, references: s_valueTupleRefs); comp.VerifyDiagnostics( - // (8,27): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int notA, int notB)>.M()' (including on the return type). - // public (int a, int b) M() { return (1, 2); } - Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "M").WithArguments("Base.M()", "I<(int notA, int notB)>.M()").WithLocation(8, 27) + // (10,23): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int notA, int notB)>.M()' (including on the return type). + // class Derived : Base, I<(int notA, int notB)> + Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "I<(int notA, int notB)>").WithArguments("Base.M()", "I<(int notA, int notB)>.M()").WithLocation(10, 23) ); } @@ -23049,9 +23049,9 @@ class Derived : Base, I<(int, int)> "; var comp = CreateStandardCompilation(source, references: s_valueTupleRefs); comp.VerifyDiagnostics( - // (8,27): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int, int)>.M()' (including on the return type). - // public (int a, int b) M() { return (1, 2); } - Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "M").WithArguments("Base.M()", "I<(int, int)>.M()").WithLocation(8, 27) + // (10,23): error CS8141: The tuple element names in the signature of method 'Base.M()' must match the tuple element names of interface method 'I<(int, int)>.M()' (including on the return type). + // class Derived : Base, I<(int, int)> + Diagnostic(ErrorCode.ERR_ImplBadTupleNames, "I<(int, int)>").WithArguments("Base.M()", "I<(int, int)>.M()").WithLocation(10, 23) ); } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs index d20eb5114280aa47ff464e3766c8060cbbb2d74c..0c313e4b6b434517fa307d6f36988f0b7230f76a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InheritanceBindingTests.cs @@ -4247,9 +4247,9 @@ public class Derived : Base, Interface } "; CompileAndVerifyDiagnostics(text, new ErrorDescription[] { - new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 12, Column = 17, IsWarning = true }, //Both Base methods implement Interface.Method(int) - new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 12, Column = 17, IsWarning = true }, //Both Base methods implement Interface.Method(T) - new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 12, Column = 17, IsWarning = true }, //Both Base methods implement Interface.Method(U) + new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 15, Column = 35, IsWarning = true }, //Both Base methods implement Interface.Method(int) + new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 15, Column = 35, IsWarning = true }, //Both Base methods implement Interface.Method(T) + new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 15, Column = 35, IsWarning = true }, //Both Base methods implement Interface.Method(U) }); } @@ -4276,12 +4276,15 @@ public class Derived : Base, Interface "; // CONSIDER: Dev10 doesn't report these warnings - not sure why CreateStandardCompilation(text).VerifyDiagnostics( - // (12,17): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. - Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "this").WithArguments("Base.this[int]", "Interface.this[int]", "Derived"), - // (12,17): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. - Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "this").WithArguments("Base.this[int]", "Interface.this[int]", "Derived"), - // (12,17): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. - Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "this").WithArguments("Base.this[int]", "Interface.this[int]", "Derived")); + // (15,35): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. + // public class Derived : Base, Interface + Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface").WithArguments("Base.this[int]", "Interface.this[int]", "Derived").WithLocation(15, 35), + // (15,35): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. + // public class Derived : Base, Interface + Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface").WithArguments("Base.this[int]", "Interface.this[int]", "Derived").WithLocation(15, 35), + // (15,35): warning CS1956: Member 'Base.this[int]' implements interface member 'Interface.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called. + // public class Derived : Base, Interface + Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface").WithArguments("Base.this[int]", "Interface.this[int]", "Derived").WithLocation(15, 35)); } [Fact] diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/AccessorOverriddenOrHiddenMembersTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/AccessorOverriddenOrHiddenMembersTests.cs index 4ef30e89c6c1977dde703263f27412ba2a9bb683..17b7520254306205edb77c074d0c0ce3723df5a1 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/AccessorOverriddenOrHiddenMembersTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/AccessorOverriddenOrHiddenMembersTests.cs @@ -496,6 +496,57 @@ class Derived : Base, I Assert.Equal(derivedGetter, derivedClass.FindImplementationForInterfaceMember(interfaceMethod)); } + [Fact] + public void ImplementingAccessorWithNonAccessorMayReportInInterfaceReference() + { + var source = @" +interface I +{ + T P { get; } +} +class Base +{ + public int get_P() { return 1; } +} +class Derived : Base, I // CS0470 must be reported in ""I"" +{ +} +"; + + var comp = CreateStandardCompilation(source); + comp.VerifyDiagnostics( + // (10,23): error CS0470: Method 'Base.get_P()' cannot implement interface accessor 'I.P.get' for type 'Derived'. Use an explicit interface implementation. + // class Derived : Base, I + Diagnostic(ErrorCode.ERR_MethodImplementingAccessor, "I").WithArguments("Base.get_P()", "I.P.get", "Derived").WithLocation(10, 23), + // (10,23): error CS0535: 'Derived' does not implement interface member 'I.P' + // class Derived : Base, I + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("Derived", "I.P").WithLocation(10, 23)); + } + + [Fact] + public void ImplementingNonAccessorWithAccessorMayReportInInterfaceReference() + { + var source = @" +interface I +{ + T get_P(); +} +class Base +{ + public int P { get; } +} +class Derived : Base, I // CS0686 must be reported in ""I"" +{ +} +"; + + var comp = CreateStandardCompilation(source); + comp.VerifyDiagnostics( + // (10,23): error CS0686: Accessor 'Base.P.get' cannot implement interface member 'I.get_P()' for type 'Derived'. Use an explicit interface implementation. + // class Derived : Base, I + Diagnostic(ErrorCode.ERR_AccessorImplementingMethod, "I").WithArguments("Base.P.get", "I.get_P()", "Derived").WithLocation(10, 23)); + } + [Fact] public void PropertyHidesBetterImplementation() { diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs index ac11591049da90a08f6e4d9fad4d47c30db57e0e..8cd33110a899c5baef3976457b6d00b8eb615502 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/GenericConstraintTests.cs @@ -1816,9 +1816,11 @@ class B2 : A, I }"; CreateStandardCompilation(source).VerifyDiagnostics( // (14,17): error CS0425: The constraints for type parameter 'T' of method 'B1.M2()' must match the constraints for type parameter 'U' of interface method 'I.M2()'. Consider using an explicit interface implementation instead. + // public void M2() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M2").WithArguments("T", "B1.M2()", "U", "I.M2()").WithLocation(14, 17), - // (16,7): error CS0425: The constraints for type parameter 'U' of method 'A.M2()' must match the constraints for type parameter 'U' of interface method 'I.M2()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "A.M2()", "U", "I.M2()").WithLocation(16, 7)); + // (16,23): error CS0425: The constraints for type parameter 'U' of method 'A.M2()' must match the constraints for type parameter 'U' of interface method 'I.M2()'. Consider using an explicit interface implementation instead. + // class B2 : A, I + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("U", "A.M2()", "U", "I.M2()").WithLocation(16, 23)); } [Fact] @@ -1937,14 +1939,18 @@ class B4 : A4, I { }"; CreateStandardCompilation(source).VerifyDiagnostics( - // (16,7): error CS0425: The constraints for type parameter 'T' of method 'A2.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("T", "A2.M()", "T", "I.M()").WithLocation(16, 7), - // (23,7): error CS0425: The constraints for type parameter 'T' of method 'A3.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B3").WithArguments("T", "A3.M()", "T", "I.M()").WithLocation(23, 7), + // (16,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B2 : A2, I + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M()", "T", "I.M()").WithLocation(16, 16), + // (23,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B3 : A3, I + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M()", "T", "I.M()").WithLocation(23, 16), // (28,17): error CS0425: The constraints for type parameter 'T' of method 'A4.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // public void M() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "A4.M()", "T", "I.M()").WithLocation(28, 17), - // (30,7): error CS0425: The constraints for type parameter 'T' of method 'A4.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B4").WithArguments("T", "A4.M()", "T", "I.M()").WithLocation(30, 7)); + // (30,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B4 : A4, I + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M()", "T", "I.M()").WithLocation(30, 16)); } /// @@ -1991,14 +1997,18 @@ class B3 : A3, I { } class B4 : A4, I { } class B5 : A5, I { }"; CreateCompilationWithCustomILSource(csharpSource, ilSource).VerifyDiagnostics( - // (2,7): error CS0425: The constraints for type parameter 'T' of method 'A2.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("T", "A2.M()", "T", "I.M()"), - // (3,7): error CS0425: The constraints for type parameter 'T' of method 'A3.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B3").WithArguments("T", "A3.M()", "T", "I.M()"), - // (4,7): error CS0425: The constraints for type parameter 'T' of method 'A4.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B4").WithArguments("T", "A4.M()", "T", "I.M()"), - // (5,7): error CS0535: 'B5' does not implement interface member 'I.M()' - Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("B5", "I.M()")); + // (2,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B2 : A2, I { } + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M()", "T", "I.M()").WithLocation(2, 16), + // (3,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B3 : A3, I { } + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M()", "T", "I.M()").WithLocation(3, 16), + // (4,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class B4 : A4, I { } + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M()", "T", "I.M()").WithLocation(4, 16), + // (5,16): error CS0535: 'B5' does not implement interface member 'I.M()' + // class B5 : A5, I { } + Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("B5", "I.M()").WithLocation(5, 16)); } /// @@ -3143,9 +3153,11 @@ class C2 : A, I public new void M() { } }"; CreateStandardCompilation(source).VerifyDiagnostics( - // (13,7): error CS0425: The constraints for type parameter 'T' of method 'B.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "C1").WithArguments("T", "B.M()", "T", "I.M()").WithLocation(13, 7), + // (13,15): error CS0425: The constraints for type parameter 'T' of method 'B.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class C1 : B, I + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M()", "T", "I.M()").WithLocation(13, 15), // (18,21): error CS0425: The constraints for type parameter 'T' of method 'C2.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // public new void M() { } Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C2.M()", "T", "I.M()").WithLocation(18, 21)); } @@ -3187,8 +3199,9 @@ static void M2() }"; var compilation = CreateCompilationWithCustomILSource(csharpSource, ilSource); compilation.VerifyDiagnostics( - // (1,7): error CS0425: The constraints for type parameter 'T' of method 'B.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "C2").WithArguments("T", "B.M()", "T", "I.M()").WithLocation(1, 7)); + // (1,15): error CS0425: The constraints for type parameter 'T' of method 'B.M()' must match the constraints for type parameter 'T' of interface method 'I.M()'. Consider using an explicit interface implementation instead. + // class C2 : B, I { } + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M()", "T", "I.M()").WithLocation(1, 15)); // Arguably, B.M should not be considered an implementation of // I.M since the CLR does not consider it so. For now, however, diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs index 2fcfff836d321936fba4bdf847920b16f0748256..4741fea7e1050fc643850efc314b20ed4a53a7b4 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/SymbolErrorTests.cs @@ -4924,14 +4924,18 @@ class B2 : B, IB { }"; CreateStandardCompilation(source).VerifyDiagnostics( - // (30,7): error CS0425: The constraints for type parameter 'V' of method 'A.A1()' must match the constraints for type parameter 'V' of interface method 'IA.A1()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "A2").WithArguments("V", "A.A1()", "V", "IA.A1()").WithLocation(30, 7), - // (30,7): error CS0425: The constraints for type parameter 'V' of method 'A.A2()' must match the constraints for type parameter 'V' of interface method 'IA.A2()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "A2").WithArguments("V", "A.A2()", "V", "IA.A2()").WithLocation(30, 7), - // (36,7): error CS0425: The constraints for type parameter 'U' of method 'B.B1()' must match the constraints for type parameter 'U' of interface method 'IB.B1()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "B.B1()", "U", "IB.B1()").WithLocation(36, 7), - // (36,7): error CS0425: The constraints for type parameter 'U' of method 'B.B2()' must match the constraints for type parameter 'U' of interface method 'IB.B2()'. Consider using an explicit interface implementation instead. - Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "B.B2()", "U", "IB.B2()").WithLocation(36, 7)); + // (30,27): error CS0425: The constraints for type parameter 'V' of method 'A.A2()' must match the constraints for type parameter 'V' of interface method 'IA.A2()'. Consider using an explicit interface implementation instead. + // class A2 : A, IA + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IA").WithArguments("V", "A.A2()", "V", "IA.A2()").WithLocation(30, 27), + // (30,27): error CS0425: The constraints for type parameter 'V' of method 'A.A1()' must match the constraints for type parameter 'V' of interface method 'IA.A1()'. Consider using an explicit interface implementation instead. + // class A2 : A, IA + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IA").WithArguments("V", "A.A1()", "V", "IA.A1()").WithLocation(30, 27), + // (36,21): error CS0425: The constraints for type parameter 'U' of method 'B.B2()' must match the constraints for type parameter 'U' of interface method 'IB.B2()'. Consider using an explicit interface implementation instead. + // class B2 : B, IB + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IB").WithArguments("U", "B.B2()", "U", "IB.B2()").WithLocation(36, 21), + // (36,21): error CS0425: The constraints for type parameter 'U' of method 'B.B1()' must match the constraints for type parameter 'U' of interface method 'IB.B1()'. Consider using an explicit interface implementation instead. + // class B2 : B, IB + Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IB").WithArguments("U", "B.B1()", "U", "IB.B1()").WithLocation(36, 21)); } [Fact] @@ -10941,7 +10945,7 @@ class C // CS0625: See AttributeTests_StructLayout.ExplicitFieldLayout_Errors [Fact] - public void CS0629ERR_InterfaceImplementedByConditional() + public void CS0629ERR_InterfaceImplementedByConditional01() { var text = @"interface MyInterface { @@ -10964,6 +10968,33 @@ public static void Main() new ErrorDescription { Code = (int)ErrorCode.ERR_InterfaceImplementedByConditional, Line = 9, Column = 17 }); } + [Fact] + public void CS0629ERR_InterfaceImplementedByConditional02() + { + var source = @" +using System.Diagnostics; + +interface I +{ + void M(T x); +} +class Base +{ + [Conditional(""debug"")] + public void M(int x) {} +} +class Derived : Base, I +{ +} +"; + + var comp = CreateStandardCompilation(source); + comp.VerifyDiagnostics( + // (13,23): error CS0629: Conditional member 'Base.M(int)' cannot implement interface member 'I.M(int)' in type 'Derived' + // class Derived : Base, I + Diagnostic(ErrorCode.ERR_InterfaceImplementedByConditional, "I").WithArguments("Base.M(int)", "I.M(int)", "Derived").WithLocation(13, 23)); + } + [Fact] public void CS0633ERR_BadArgumentToAttribute() { @@ -17819,7 +17850,7 @@ static void Main() } "; var comp = DiagnosticsUtils.VerifyErrorsAndGetCompilationWithMscorlib(text, - new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 9, Column = 24, IsWarning = true }); + new ErrorDescription { Code = (int)ErrorCode.WRN_MultipleRuntimeImplementationMatches, Line = 20, Column = 33, IsWarning = true }); } [Fact]