`FindImplementationForInterfaceMember` incorrectly treats non-virtual public method in metadata as an interface implementation
- Dominant language
- C#
- Stars
- 20.7k
- Forks
- 4.3k
- PR merge metrics
- PR metrics pending
Description
```
[Fact]
public void Test()
{
/*
public interface I1
{
void M1();
}
public class C1 : I1
{
void I1.M1()
{
System.Console.Write(1);
}
}
public class C2 : C1, I1
{
public NOTVIRTUAL void M1()
{
System.Console.Write(2);
}
}
*/
var ilSource = @"
.class interface public auto ansi abstract beforefieldinit I1
{
.method public hidebysig newslot abstract virtual
instance void M1 () cil managed
{
}
}
.class public auto ansi beforefieldinit C1
extends [mscorlib]System.Object
implements I1
{
.method private final hidebysig newslot virtual
instance void I1.M1 () cil managed
{
.override method instance void I1::M1()
.maxstack 8
IL_0000: ldc.i4.1
IL_0001: call void [mscorlib]System.Console::Write(int32)
IL_0006: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
}
}
.class public auto ansi beforefieldinit C2
extends C1
implements I1
{
.method public hidebysig
instance void M1 () cil managed
{
.maxstack 8
IL_0000: ldc.i4.2
IL_0001: call void [mscorlib]System.Console::Write(int32)
IL_0006: ret
}
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void C1::.ctor()
IL_0006: ret
}
}
";
var source1 =
@"
class Program
{
static void Main()
{
I1 x = new C2();
x.M1();
}
}";
var compilation1 = CreateCompilationWithIL(source1, ilSource, options: TestOptions.DebugExe);
CompileAndVerify(compilation1, expectedOutput: "1").VerifyDiagnostics();
var i1M1 = compilation1.GetMember("I1.M1");
var c2 = compilation1.GetTypeByMetadataName("C2");
// Expected: C1.I1.M1 because that is what is getting called
AssertEx.Equal("void C2.M1()", c2.FindImplementationForInterfaceMember(i1M1).ToTestDisplayString());
}
```
Note, rules for methods declared in source are different.
Should check behavior in VB as well.
Contributor guide
Research direction
Start with the embedded IL and the Test method in the issue, then run the regression through FindImplementationForInterfaceMember and inspect the returned symbol for C2. Compare the behavior with source-declared methods and add the requested Visual Basic check; done means the API identifies the interface implementation that is actually invoked rather than the non-virtual metadata method.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100