未验证 提交 ceb656c9 编写于 作者: C Caio Saldanha 提交者: GitHub

Implicit implementation errors may be reported in interface reference (#24438)

The GetImplicitImplementationDiagnosticLocation method was added in TypeSymbol class in order to find the correct diagnostic location for implicit implementation related errors. Some tests were updated.
上级 eb5aba16
......@@ -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];
}
}
/// <summary>
/// Search the declared members of a type for one that could be an implementation
/// of a given interface member (depending on interface declarations).
......
......@@ -1749,8 +1749,9 @@ public static void Main()
Derived.Method()");
comp.VerifyDiagnostics(
// (17,17): warning CS1956: Member 'Derived<int, string>.Method(int)' implements interface member 'Interface<int>.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<int, string>.Method(int)", "Interface<int>.Method(int)", "Derived")); // No errors
// (20,58): warning CS1956: Member 'Derived<int, string>.Method(int)' implements interface member 'Interface<int>.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<int, string>, Interface<string>, Interface<int>
Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int>").WithArguments("Derived<int, string>.Method(int)", "Interface<int>.Method(int)", "Derived").WithLocation(20, 58)); // No errors
}
[Fact]
......
......@@ -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)
);
}
......
......@@ -4247,9 +4247,9 @@ public class Derived : Base<int>, Interface<int, int>
}
";
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<int>, Interface<int, int>
";
// CONSIDER: Dev10 doesn't report these warnings - not sure why
CreateStandardCompilation(text).VerifyDiagnostics(
// (12,17): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>.this[int]", "Interface<int, int>.this[int]", "Derived"),
// (12,17): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>.this[int]", "Interface<int, int>.this[int]", "Derived"),
// (12,17): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>.this[int]", "Interface<int, int>.this[int]", "Derived"));
// (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>, Interface<int, int>
Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35),
// (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>, Interface<int, int>
Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35),
// (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.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<int>, Interface<int, int>
Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35));
}
[Fact]
......
......@@ -496,6 +496,57 @@ class Derived : Base, I
Assert.Equal(derivedGetter, derivedClass.FindImplementationForInterfaceMember(interfaceMethod));
}
[Fact]
public void ImplementingAccessorWithNonAccessorMayReportInInterfaceReference()
{
var source = @"
interface I<T>
{
T P { get; }
}
class Base
{
public int get_P() { return 1; }
}
class Derived : Base, I<int> // CS0470 must be reported in ""I<int>""
{
}
";
var comp = CreateStandardCompilation(source);
comp.VerifyDiagnostics(
// (10,23): error CS0470: Method 'Base.get_P()' cannot implement interface accessor 'I<int>.P.get' for type 'Derived'. Use an explicit interface implementation.
// class Derived : Base, I<int>
Diagnostic(ErrorCode.ERR_MethodImplementingAccessor, "I<int>").WithArguments("Base.get_P()", "I<int>.P.get", "Derived").WithLocation(10, 23),
// (10,23): error CS0535: 'Derived' does not implement interface member 'I<int>.P'
// class Derived : Base, I<int>
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I<int>").WithArguments("Derived", "I<int>.P").WithLocation(10, 23));
}
[Fact]
public void ImplementingNonAccessorWithAccessorMayReportInInterfaceReference()
{
var source = @"
interface I<T>
{
T get_P();
}
class Base
{
public int P { get; }
}
class Derived : Base, I<int> // CS0686 must be reported in ""I<int>""
{
}
";
var comp = CreateStandardCompilation(source);
comp.VerifyDiagnostics(
// (10,23): error CS0686: Accessor 'Base.P.get' cannot implement interface member 'I<int>.get_P()' for type 'Derived'. Use an explicit interface implementation.
// class Derived : Base, I<int>
Diagnostic(ErrorCode.ERR_AccessorImplementingMethod, "I<int>").WithArguments("Base.P.get", "I<int>.get_P()", "Derived").WithLocation(10, 23));
}
[Fact]
public void PropertyHidesBetterImplementation()
{
......
......@@ -1816,9 +1816,11 @@ class B2 : A<object>, I<object>
}";
CreateStandardCompilation(source).VerifyDiagnostics(
// (14,17): error CS0425: The constraints for type parameter 'T' of method 'B1.M2<T>()' must match the constraints for type parameter 'U' of interface method 'I<object>.M2<U>()'. Consider using an explicit interface implementation instead.
// public void M2<T>() { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M2").WithArguments("T", "B1.M2<T>()", "U", "I<object>.M2<U>()").WithLocation(14, 17),
// (16,7): error CS0425: The constraints for type parameter 'U' of method 'A<object>.M2<U>()' must match the constraints for type parameter 'U' of interface method 'I<object>.M2<U>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "A<object>.M2<U>()", "U", "I<object>.M2<U>()").WithLocation(16, 7));
// (16,23): error CS0425: The constraints for type parameter 'U' of method 'A<object>.M2<U>()' must match the constraints for type parameter 'U' of interface method 'I<object>.M2<U>()'. Consider using an explicit interface implementation instead.
// class B2 : A<object>, I<object>
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I<object>").WithArguments("U", "A<object>.M2<U>()", "U", "I<object>.M2<U>()").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<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()").WithLocation(16, 7),
// (23,7): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B3").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()").WithLocation(23, 7),
// (16,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B2 : A2, I
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()").WithLocation(16, 16),
// (23,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B3 : A3, I
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()").WithLocation(23, 16),
// (28,17): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// public void M<T>() { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(28, 17),
// (30,7): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B4").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(30, 7));
// (30,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B4 : A4, I
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(30, 16));
}
/// <summary>
......@@ -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<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()"),
// (3,7): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B3").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()"),
// (4,7): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B4").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()"),
// (5,7): error CS0535: 'B5' does not implement interface member 'I.M<T>()'
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("B5", "I.M<T>()"));
// (2,16): error CS0425: The constraints for type parameter 'T' of method 'A2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B2 : A2, I { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A2.M<T>()", "T", "I.M<T>()").WithLocation(2, 16),
// (3,16): error CS0425: The constraints for type parameter 'T' of method 'A3.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B3 : A3, I { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A3.M<T>()", "T", "I.M<T>()").WithLocation(3, 16),
// (4,16): error CS0425: The constraints for type parameter 'T' of method 'A4.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class B4 : A4, I { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "A4.M<T>()", "T", "I.M<T>()").WithLocation(4, 16),
// (5,16): error CS0535: 'B5' does not implement interface member 'I.M<T>()'
// class B5 : A5, I { }
Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I").WithArguments("B5", "I.M<T>()").WithLocation(5, 16));
}
/// <summary>
......@@ -3143,9 +3153,11 @@ class C2 : A, I
public new void M<T>() { }
}";
CreateStandardCompilation(source).VerifyDiagnostics(
// (13,7): error CS0425: The constraints for type parameter 'T' of method 'B.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "C1").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(13, 7),
// (13,15): error CS0425: The constraints for type parameter 'T' of method 'B.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class C1 : B, I
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(13, 15),
// (18,21): error CS0425: The constraints for type parameter 'T' of method 'C2.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// public new void M<T>() { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "M").WithArguments("T", "C2.M<T>()", "T", "I.M<T>()").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<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "C2").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(1, 7));
// (1,15): error CS0425: The constraints for type parameter 'T' of method 'B.M<T>()' must match the constraints for type parameter 'T' of interface method 'I.M<T>()'. Consider using an explicit interface implementation instead.
// class C2 : B, I { }
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "I").WithArguments("T", "B.M<T>()", "T", "I.M<T>()").WithLocation(1, 15));
// Arguably, B.M<T> should not be considered an implementation of
// I.M<T> since the CLR does not consider it so. For now, however,
......
......@@ -4924,14 +4924,18 @@ class B2<T> : B<T>, IB<T>
{
}";
CreateStandardCompilation(source).VerifyDiagnostics(
// (30,7): error CS0425: The constraints for type parameter 'V' of method 'A<T, U>.A1<V>()' must match the constraints for type parameter 'V' of interface method 'IA<T, U>.A1<V>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "A2").WithArguments("V", "A<T, U>.A1<V>()", "V", "IA<T, U>.A1<V>()").WithLocation(30, 7),
// (30,7): error CS0425: The constraints for type parameter 'V' of method 'A<T, U>.A2<V>()' must match the constraints for type parameter 'V' of interface method 'IA<T, U>.A2<V>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "A2").WithArguments("V", "A<T, U>.A2<V>()", "V", "IA<T, U>.A2<V>()").WithLocation(30, 7),
// (36,7): error CS0425: The constraints for type parameter 'U' of method 'B<T>.B1<U>()' must match the constraints for type parameter 'U' of interface method 'IB<T>.B1<U>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "B<T>.B1<U>()", "U", "IB<T>.B1<U>()").WithLocation(36, 7),
// (36,7): error CS0425: The constraints for type parameter 'U' of method 'B<T>.B2<U, V>()' must match the constraints for type parameter 'U' of interface method 'IB<T>.B2<U, V>()'. Consider using an explicit interface implementation instead.
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "B2").WithArguments("U", "B<T>.B2<U, V>()", "U", "IB<T>.B2<U, V>()").WithLocation(36, 7));
// (30,27): error CS0425: The constraints for type parameter 'V' of method 'A<T, U>.A2<V>()' must match the constraints for type parameter 'V' of interface method 'IA<T, U>.A2<V>()'. Consider using an explicit interface implementation instead.
// class A2<T, U> : A<T, U>, IA<T, U>
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IA<T, U>").WithArguments("V", "A<T, U>.A2<V>()", "V", "IA<T, U>.A2<V>()").WithLocation(30, 27),
// (30,27): error CS0425: The constraints for type parameter 'V' of method 'A<T, U>.A1<V>()' must match the constraints for type parameter 'V' of interface method 'IA<T, U>.A1<V>()'. Consider using an explicit interface implementation instead.
// class A2<T, U> : A<T, U>, IA<T, U>
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IA<T, U>").WithArguments("V", "A<T, U>.A1<V>()", "V", "IA<T, U>.A1<V>()").WithLocation(30, 27),
// (36,21): error CS0425: The constraints for type parameter 'U' of method 'B<T>.B2<U, V>()' must match the constraints for type parameter 'U' of interface method 'IB<T>.B2<U, V>()'. Consider using an explicit interface implementation instead.
// class B2<T> : B<T>, IB<T>
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IB<T>").WithArguments("U", "B<T>.B2<U, V>()", "U", "IB<T>.B2<U, V>()").WithLocation(36, 21),
// (36,21): error CS0425: The constraints for type parameter 'U' of method 'B<T>.B1<U>()' must match the constraints for type parameter 'U' of interface method 'IB<T>.B1<U>()'. Consider using an explicit interface implementation instead.
// class B2<T> : B<T>, IB<T>
Diagnostic(ErrorCode.ERR_ImplBadConstraints, "IB<T>").WithArguments("U", "B<T>.B1<U>()", "U", "IB<T>.B1<U>()").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<T>
{
void M(T x);
}
class Base
{
[Conditional(""debug"")]
public void M(int x) {}
}
class Derived : Base, I<int>
{
}
";
var comp = CreateStandardCompilation(source);
comp.VerifyDiagnostics(
// (13,23): error CS0629: Conditional member 'Base.M(int)' cannot implement interface member 'I<int>.M(int)' in type 'Derived'
// class Derived : Base, I<int>
Diagnostic(ErrorCode.ERR_InterfaceImplementedByConditional, "I<int>").WithArguments("Base.M(int)", "I<int>.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]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册