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

NativeAOT: Usage of static virtual method from interface gets miscompiled as infinite loop #110932

Open
ZingBallyhoo opened this issue Dec 24, 2024 · 1 comment
Labels
area-NativeAOT-coreclr untriaged New issue has not been triaged by the area owner

Comments

@ZingBallyhoo
Copy link

Description

In .NET9 NativeAOT, usage of a static virtual method from an interface sometimes gets miscompiled to an infinte loop.

Reproduction Steps

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net9.0</TargetFramework>
        <PublishAot>true</PublishAot>
    </PropertyGroup>
</Project>
using System;

Do<Primary>();
Do<Secondary>();

static void Do<T>() where T: Interface
{
    if (T.IsSecondary())
    {
        Console.Out.WriteLine("IsSecondary");
    } else
    {
        Console.Out.WriteLine("Isn't Secondary");
    }
}

interface Interface
{
    public static virtual bool IsSecondary() => false; // does not work under NativeAOT
    //public static abstract bool IsSecondary(); // works under NativeAOT and CoreCLR
}
    
struct Primary : Interface
{
    public static bool IsSecondary() => false;
}
    
struct Secondary : Interface
{
    public static bool IsSecondary() => true;
}

Or on gotbolt: https://godbolt.org/z/7P1rsMs4x

Expected behavior

Isn't Secondary
IsSecondary

Actual behavior

Isn't Secondary
(hangs)

Regression?

Yes, the same code does not hang on .NET 8 NativeAOT.

Known Workarounds

  • Use static abstract instead of static virtual.
  • Add [MethodImpl(MethodImplOptions.NoInlining)] to the abstract method.

Configuration

.NET 9.0.100
Windows 10 x64

Other information

Using a larger method body still triggers the issue (the normal body runs before entering the infinite loop).
Implementing the interface on a class instead of a struct still triggers the issue.

@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Dec 24, 2024
Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-NativeAOT-coreclr untriaged New issue has not been triaged by the area owner
Projects
Status: No status
Development

No branches or pull requests

1 participant