Skip to content

Mono's behavior around .beforefieldinit #77513

@EgorBo

Description

@EgorBo

The following program:

using System;
using System.Runtime.CompilerServices;

C.TestMethod(false);
Console.WriteLine("Done");

static class C
{
    [MethodImpl(MethodImplOptions.NoInlining)] // doesn't matter, but JIC
    public static int TestMethod(bool cond)
    {
        if (cond)
        {
            // never invoked in this program
            return ClassB.X;
        }
        // always taken
        return 0;
    }
}

public class ClassB
{
    public static readonly int X = GetX();

    static int GetX()
    {
        Console.WriteLine("GetX call!"); // not expected to be invoked in this program
        return 42;
    }
}

Output on Mono:

GetX call!
Done

Output on CoreCLR:

Done

It's not wrong according to ECMA-335:

: BeforeFieldInit behavior is intended for initialization code with no interesting sideeffects, 
where exact timing does not matter. Also, under BeforeFieldInit semantics, type
initializers are allowed to be executed at or before first access to any static field of that type,
at the discretion of the CLI.

However, it'd be nice to align this behavior with CoreCLR to avoid potential issues like the one I've hit in #77398 (comment). And, obviously, in this case Mono executed completely redundant code (did more work). I think I've hit the same issue in the past where static initialization in Mono triggered DllImport leading to DllNotFoundException while CoreCLR didn't, can't find the issue.

Related issue: #4346 (see #4346 (comment))

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions