Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of a static virtual method in a derived type is not found when there is a re-abstraction of the same method higher in inheritance hierarchy #80350

Closed
AlekseyTs opened this issue Jan 8, 2023 · 8 comments
Assignees
Milestone

Comments

@AlekseyTs
Copy link
Contributor

Description

Implementation of a static virtual method in a derived type is not found when there is a re-abstraction of the same method higher in inheritance hierarchy

Reproduction Steps

https://sharplab.io/#v2:C4LgTgrgdgPgAgJgAQBUCmBnYBGJIkCSCAsAFADeZZSNSc2AbHQCxICyAhgJZQAUAlNVqVStMakzAAPOizYAfAIDcQmgF8qo2vSZxWs6VwUCkAdwAWaMGiRG8hbKqQinYowDo22ZU42knOiwOnt6CWjQi4trY7vQAnLwARAYxXon8KuFIfn5kcADMtlDAVgBmHADGNgSOFAGMSBwARlhglcBBXj6kuaQFRSVg5VWEyPg1ZJHRTM2t7UE1Id1+QA=

Compile and run:

class Test1 : I2
{

    static void Main()
    {
        Test<Test1>();
    }

    static void Test<i1>() where i1 : I1
    {

        i1.M1();
    }

    static void I1.M1()
    {
        System.Console.WriteLine("Test1.M1");
    }
}

public interface I1
{
    static abstract void M1();
}

public interface I2 : I1
{
    static abstract void I1.M1();
}

Expected behavior

"Test1.M1" is printed

Actual behavior

System.MissingMethodException: Method not found: 'Void I1.M1()'.
at System.Reflection.RuntimeAssembly.get_EntryPoint()
at SharpLab.Container.Execution.ExecuteCommandHandler.ExecuteAssembly(Byte[] assemblyBytes) in

Regression?

No response

Known Workarounds

Remove re-abstraction of the method in I2 to observe expected behavior.

Configuration

No response

Other information

Here is another flavor of the problem:
https://sharplab.io/#v2:C4LgTgrgdgPgAgJgAQBUCmBnYBGJIkCSAzALABQA3ueUrUnNgGz0AsSAsgIYCWUAFAEoadKmTrjUmYAB50WbAD5BAbmG0AvtTF0GzOGzkzuiwUgDuACzRg0SY3kLY1SUc/HGAdO2wrnmsv7kcER2UMDWAGacAMa2BE6UzrpInABGWGAxwKwcPgKqAVrBoeFgUbGEyPjx5KLiyWkZWTnxXnkFgWTFvKXlcSHVCLVJTC3YbYLOdRK0DB4MAJx8AETEbcv5fuT+QA==

class Test1 : I3
{

    static void Main()
    {
        Test<Test1>();
    }

    static void Test<i1>() where i1 : I1
    {

        i1.M1();
    }
}

public interface I1
{
    static abstract void M1();
}

public interface I2 : I1
{
    static abstract void I1.M1();
}

public interface I3 : I2
{
    static void I1.M1()
    {
        System.Console.WriteLine("I3.M1");
    }
}

Expected:

I3.M1

Actual:

System.MissingMethodException: Method not found: 'Void I1.M1()'.
   at System.Reflection.RuntimeAssembly.get_EntryPoint()
   at SharpLab.Container.Execution.ExecuteCommandHandler.ExecuteAssembly(Byte[] assemblyBytes) in 
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Jan 8, 2023
@AlekseyTs
Copy link
Contributor Author

@davidwrighton, @trylek FYI

@trylek
Copy link
Member

trylek commented Jan 9, 2023

A have taken the bug, I plan to start looking into the static virtual bugs this week. I think I have a similar bug from @MichalStrehovsky but I have yet to figure out whether they're really duplicates or just similar.

@trylek
Copy link
Member

trylek commented Jan 17, 2023

I have created a CoreCLR regression test for this and I now understand this a bit better. There are two easy-to-fix bugs around type attribute checks that are the first hit in this case but after that the situation becomes a bit more interesting - namely, the CoreCLR runtime now perceives Test1.M1 as an override of the reabstracted override I2.M1. I'm working on figuring out how to make that transitively land on the primary static virtual.

trylek added a commit to trylek/runtime that referenced this issue Feb 17, 2023
trylek added a commit to trylek/runtime that referenced this issue Feb 17, 2023
This change fixes the issue dotnet#80350 that uncovered several
inconsistencies in the CoreCLR runtime w.r.t. static virtual methods.
In particular, reabstraction (declaring an abstract explicit override
of a static virtual method in a derived interface) turned out to be
causing runtime issues. As part of the change I'm also fixing the
reabstraction unit test svm_diamondshape as it turns out Roslyn emits
the method flags in a slightly different manner than I originally
expected in the hand-written IL test.

Thanks

Tomas
trylek added a commit to trylek/runtime that referenced this issue Feb 17, 2023
Based on offline discussion with Vlad Brezae I have temporarily
disabled the svm_diamondshape test on Mono where it is causing
crashes in VTable construction that might take a bit to fix.

Thanks

Tomas
trylek added a commit that referenced this issue Feb 17, 2023
… static virtual method reabstraction (#80987)

This change fixes the issue #80350 that uncovered several
inconsistencies in the CoreCLR runtime w.r.t. static virtual methods.
In particular, reabstraction (declaring an abstract explicit override
of a static virtual method in a derived interface) turned out to be
causing runtime issues. As part of the change I'm also fixing the
reabstraction unit test svm_diamondshape as it turns out Roslyn emits
the method flags in a slightly different manner than I originally
expected in the hand-written IL test. Based on discussion with the
Mono team I have had to temporarily disable the svm_diamondshape
test on Mono before the correct fix is found.

Thanks

Tomas
@trylek
Copy link
Member

trylek commented Feb 17, 2023

The CoreCLR fix for the issue has been merged in. For now I am keeping this issue open to track the remaining Mono work.

@trylek trylek assigned BrzVlad and unassigned trylek Feb 17, 2023
@lambdageek
Copy link
Member

I'm not actually sure there's a Mono issue.

using System;

public interface I1 {
    public static virtual void M1() {
        Console.WriteLine("I1.M1");
    }
}

public interface I2 : I1 {
        static abstract void I1.M1();
}

public interface I3 : I2 {
    static void I1.M1() { Console.WriteLine ("I3.M1"); }
}

public interface I4 : I3 {
        static abstract void I1.M1();
}

public class C : I2 {
    public static void Main() {
        Foo<C>();
    }
    static void Foo<T>() where T : I1
    {
        T.M1();
    }
    static void I1.M1() {
        Console.WriteLine("C.I1.M1");
    }
}

Running this with a .NET 8 preview 1 nightly I get this:

% dotnet run --self-contained -p:UseMonoRuntime=true -r osx-arm64
C.I1.M1

@MichalStrehovsky
Copy link
Member

The meaning of this issue is now overloaded. I think Tomas refers to this #80987 (comment).

Maybe we should have closed this issue and opened another one for the issue with different repro steps.

davidwrighton added a commit that referenced this issue Jul 11, 2023
… implementations (#88639)

- Move the handling for variance so that it is in the same place as it is for instance methods
- Validate the behavior of such dispatch is equivalent to the dispatch behavior involving instance variant default dispatch
- Rework the fix for #80350 to avoid violating an invariant of the type system (which is that all MethodDef's of a TypeDef are loaded as MethodDescs when loading the open type).

Fixes #78621
@mangod9
Copy link
Member

mangod9 commented Aug 4, 2023

assume this is ok to close?

@BrzVlad
Copy link
Member

BrzVlad commented Aug 7, 2023

Closing since this issue is superseded by #83189 and #67540, which better describe the problem. We still have svm_diamondshape disabled on mono, with this issue in description. To be removed once those other issues are addressed.

@BrzVlad BrzVlad closed this as completed Aug 7, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Sep 6, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants