dotnet/roslyn
View on GitHubConsider improving diagnostics when all equally specific implementation candidates are re-abstractions
Open
#35,915 opened on May 23, 2019
Area-CompilersBugConcept-Diagnostic ClarityFeature - Default Interface Implhelp wanted
Repository metrics
- Stars
- (20,414 stars)
- PR merge metrics
- (Avg merge 6d 17h) (256 merged PRs in 30d)
Description
[Fact]
public void MethodReAbstraction_09()
{
var source1 =
@"
public interface I1
{
void M1() {}
}
public interface I2 : I1
{
abstract void I1.M1();
}
public interface I3 : I1
{
abstract void I1.M1();
}
";
var source2 =
@"
class Test1 : I2, I3
{
}
";
ValidateMethodReAbstraction_09(source1, source2);
}
private void ValidateMethodReAbstraction_09(string source1, string source2)
{
var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugDll,
parseOptions: TestOptions.Regular,
targetFramework: TargetFramework.NetStandardLatest);
validate(compilation1.SourceModule);
var expected = new DiagnosticDescription[]
{
// (2,15): error CS8705: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific.
// class Test1 : I2, I3
Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(2, 15)
};
compilation1.VerifyDiagnostics(expected);
var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll,
parseOptions: TestOptions.Regular,
targetFramework: TargetFramework.NetStandardLatest);
compilation2.VerifyDiagnostics();
foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() })
{
var compilation3 = CreateCompilation(source2, options: TestOptions.DebugDll, references: new[] { reference },
parseOptions: TestOptions.Regular,
targetFramework: TargetFramework.NetStandardLatest);
validate(compilation3.SourceModule);
compilation3.VerifyDiagnostics(expected);
}
static void validate(ModuleSymbol m)
{
var test1 = m.GlobalNamespace.GetTypeMember("Test1");
var i1m1 = test1.InterfacesNoUseSiteDiagnostics().First().ContainingNamespace.GetTypeMember("I1").GetMember<MethodSymbol>("M1");
Assert.Equal("void I1.M1()", i1m1.ToTestDisplayString());
Assert.Null(test1.FindImplementationForInterfaceMember(i1m1));
}
}
Observed:
// (2,15): error CS8705: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific.
// class Test1 : I2, I3
Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(2, 15)
Suggested: Perhaps we should simply say that I1.M1() is not implemented as long as all conflicting candidates are re-abstractions.