Runtime: New API: ModuleInitializerAttribute

Created on 2 May 2020  路  9Comments  路  Source: dotnet/runtime

The module initializers feature for C# 9 enables a new attribute, [ModuleInitializer], to be applied to any number of static methods in a compilation. The marked methods are guaranteed to run before any other method is invoked or field is accessed in the whole module.

Usage example:

using System.Runtime.CompilerServices;

class C
{
    [ModuleInitializer]
    internal static void M()
    {
        // This code runs before any other code in the module
    }
}

API proposal

using System;

namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ModuleInitializerAttribute : Attribute { }
}

Compiler behavior

Module initializer methods (methods marked with [ModuleInitializer]) must be:

  • accessible outside the top-level containing type
  • ordinary member methods (not accessors, finalizers, operators, or local functions, even though AttributeTargets.Method includes these)
  • static, parameterless, and void-returning
  • not generic and not contained by a generic type

If any methods match these criteria, a module initializer (runtime term for <Module>..cctor) is emitted. This is a special static constructor that has additional runtime guarantees. It will execute before any other field access or method invocation within the entire module. The emitted body is a series of call instructions, one to each module initializer method in a deterministic but undefined order, followed by a ret instruction.

The VB strategy has not been determined. It would either behave the same way or error when System.Runtime.CompilerServices.ModuleInitializerAttribute is applied to a method.

References

Language proposal (credit to @RikkiGibson) with link to meeting notes:
https://github.com/dotnet/csharplang/blob/master/proposals/module-initializers.md

Compiler feature doc (credit to @RikkiGibson):
https://github.com/dotnet/roslyn/blob/mi-feature-doc/docs/features/module-initializers.md

Runtime spec: https://github.com/dotnet/runtime/blob/master/docs/design/specs/Ecma-335-Augments.md#module-initializer

Test plan umbrella: https://github.com/dotnet/roslyn/issues/40500
Implementation underway: https://github.com/dotnet/roslyn/commits/features/module-initializers

api-approved area-System.Runtime.CompilerServices untriaged

Most helpful comment

Video

@jaredpar presumably this feature won't have language syntax. Normally we don't use System.Runtime.CompilerServices for stuff that developers are expected to use directly. Normally, the namespace is for stuff the compiler generates calls for. However, in this case it seems on par with other very advanced features that we don't want the general public to use, so this feels OK.

C# namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class ModuleInitializerAttribute : Attribute { } }

All 9 comments

I couldn't figure out the best area label to add to this issue. Please help me learn by adding exactly one area label.

@GrabYourPitchforks what does the "blocking" label signify here?

It puts this issue to the front of the api-ready-for-review queue. The API Review meetings first review API requests that are labeled "blocking" before reviewing other requests.

Video

@jaredpar presumably this feature won't have language syntax. Normally we don't use System.Runtime.CompilerServices for stuff that developers are expected to use directly. Normally, the namespace is for stuff the compiler generates calls for. However, in this case it seems on par with other very advanced features that we don't want the general public to use, so this feels OK.

C# namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] public sealed class ModuleInitializerAttribute : Attribute { } }

What are next steps? Are we ready to open a PR to dotnet/runtime to add the API?

Yeah this is meant for really advanced users, not main stream use hence this namespace feels fine to me.

@RikkiGibson

What are next steps? Are we ready to open a PR to dotnet/runtime to add the API?

That is probably the easiest solution. You could ask @danmosemsft for a dev but attributes are basically trivial.

You can use https://github.com/dotnet/runtime/pull/454 as a template.

We'd planned on having @RikkiGibson do the work here so we'll get a PR out soon-ish for this.

Was this page helpful?
0 / 5 - 0 ratings