Skip to content

mono AOT compiler cannot resolve and inline static virtual calls in gshared methods #75801

@vargaz

Description

@vargaz

Testcase:

using System;
using System.Diagnostics;
using System.Numerics;

public class Tests
{
        private interface INegator<T> where T : struct
        {
            static abstract bool NegateIfNeeded(bool equals);
        }

        private readonly struct DontNegate<T> : INegator<T> where T : struct
        {
            public static bool NegateIfNeeded(bool equals) => equals;
        }

        private readonly struct Negate<T> : INegator<T> where T : struct
        {
            public static bool NegateIfNeeded(bool equals) => !equals;
        }

    private static int IndexOfValueType<TValue, TNegator>()
            where TValue : struct, INumber<TValue>
            where TNegator : struct, INegator<TValue>
    {
        for (int j = 0; j < 1000; ++j) {
            for (int i = 0; i < 100000; ++i)
                TNegator.NegateIfNeeded (true);
        }
        return 0;
    }

    public static void Main () {
        var w = Stopwatch.StartNew ();
        IndexOfValueType<byte, DontNegate<byte>> ();
        w.Stop ();
        Console.WriteLine (w.ElapsedMilliseconds);
    }
}

When calling IndexOfValueType<byte, DontNegate<byte>>, the AOT compiler will compile a shared instance for bytes/enums with byte basetype, but inside the shared method it can't resolve the

constrained. !!TNegator
 call       bool class Tests/INegator`1<!!TValue>::NegateIfNeeded(bool)

call to DontNegate so it doesn't get inlined.

This is hit with the recent BCL changes to SpanHelpers.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions