dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.18k stars 4.72k forks source link

Mono is calling derived class function instead of base class function when base's function is invoked using delegate. #102009

Open alhad-deshpande opened 5 months ago

alhad-deshpande commented 5 months ago

Description

Mono is calling derived class function instead of base class function when base's function is invoked using delegate. This is occurring on x86 Mono, ppc64le and s390x mono versions. The coreclr x86 version calls base class function correctly.

Reproduction Steps

Following is the program:

using System;

class A
{
    protected virtual void F() { Console.WriteLine(nameof(A)); }
}
class B : A
{
    protected override void F() { Console.WriteLine(nameof(B)); }
    static void Invoke(Delegate d) { d.DynamicInvoke(); }
    void M()
    {
        Invoke(base.F);
    }
    static void Main()
    {
        new B().M();
    }
}

Compile and Run the program on x86/ppc64le/s390x using Mono SDK.

Expected behavior

"Expected output for the program is "A"

Actual behavior

Actual output on x86 using mono sdk and on ppc64le/s390x using mono is "B".

x86_64 machine output: [root@dotnet-x86-cent-8-stream-node5 AandBProgram]# dotnet build MSBuild version 17.10.0-preview-24101-01+07fd5d51f for .NET Restore complete (0.7s) You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy AandBProgram succeeded (4.1s) → bin/Debug/net9.0/AandBProgram.dll

Build succeeded in 5.8s [root@dotnet-x86-cent-8-stream-node5 AandBProgram]# dotnet run Restore complete (0.7s) You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy AandBProgram succeeded (0.3s) → bin/Debug/net9.0/AandBProgram.dll

Build succeeded in 1.9s B

[root@dotnet-x86-cent-8-stream-node5 AandBProgram]# arch x86_64

[root@dotnet-x86-cent-8-stream-node5 AandBProgram]# dotnet --version 9.0.100-preview.1.24101.1

Power machine output: (base) root@p006vm101-ub20:~/AandBProgram# dotnet build MSBuild version 17.8.3+195e7f5a3 for .NET Determining projects to restore... All projects are up-to-date for restore. AandBProgram -> /root/AandBProgram/bin/Debug/net8.0/AandBProgram.dll

Build succeeded. 0 Warning(s) 0 Error(s)

Time Elapsed 00:00:09.91 (base) root@p006vm101-ub20:~/AandBProgram# dotnet run B (base) root@p006vm101-ub20:~/AandBProgram# arch ppc64le (base) root@p006vm101-ub20:~/AandBProgram# dotnet --version 8.0.100

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

No response

Cc: @uweigand

Neme12 commented 5 months ago

I would assume this is the expected behavior on every platform. I remember at one point having made a delegate over a virtual method and using that as a cheap-enough check as to whether the method is overridden in a derived class or not by checking the target object.

MichalStrehovsky commented 5 months ago

I would assume this is the expected behavior on every platform. I remember at one point having made a delegate over a virtual method and using that as a cheap-enough check as to whether the method is overridden in a derived class or not by checking the target object.

The base.F syntax in C# translates to using ldftn IL instruction instead of ldvirtftn that C# normally emits for delegate creation. The delegate should point to the base method directly, not to the result of virtual resolution. The CoreCLR behavior is expected/correct, Mono behavior looks like a bug.

janani66 commented 4 months ago

Any update on this issue?

lambdageek commented 4 months ago

@steveisok

kg commented 2 months ago

The fix for this is complex enough that I don't think we can fit it into 9. @BrzVlad and @lambdageek clued me in on how to fix it, so I think we can get to it in a future release.