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

Module initializers deterministic ordering #43964

Merged
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2811,7 +2811,10 @@ internal override bool CompileMethods(
filterOpt: filterOpt,
cancellationToken: cancellationToken);

GenerateModuleInitializer(moduleBeingBuilt, methodBodyDiagnosticBag);
if (!hasDeclarationErrors && !CommonCompiler.HasUnsuppressableErrors(methodBodyDiagnosticBag))
{
GenerateModuleInitializer(moduleBeingBuilt, methodBodyDiagnosticBag);
}

bool hasMethodBodyError = !FilterAndAppendAndFreeDiagnostics(diagnostics, ref methodBodyDiagnosticBag);

Expand All @@ -2832,8 +2835,7 @@ private void GenerateModuleInitializer(PEModuleBuilder moduleBeingBuilt, Diagnos
{
var ilBuilder = new ILBuilder(moduleBeingBuilt, new LocalSlotManager(slotAllocator: null), OptimizationLevel.Release, areLocalsZeroed: false);

// PROTOTYPE(module-initializers): require deterministic order
foreach (var method in _moduleInitializerMethods)
foreach (MethodSymbol method in _moduleInitializerMethods.OrderBy<MethodSymbol>(LexicalOrderSymbolComparer.Instance))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation for LexicalOrderSymbolComparer indicates it's only supported for Symbol instances that are declared in the same container:

(explicitly or explicitly declared in source within the same container)

Module initializers can be declared across containers though. Have you verified that LexicalOrderSymbolComparer is supported for this scenario? If so can you clean up the documentation to reflect the correctly supported behaviors?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, reading the source indicates this and ModuleInitializersTests.MultipleInitializers_MultipleFiles seems to demonstrate this. I will fix up the documentation.

{
ilBuilder.EmitOpCode(ILOpCode.Call, stackAdjustment: 0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@

namespace Microsoft.CodeAnalysis.CSharp
{
/// <summary> This is an implementation of a special symbol comparer, which is supposed to be used for
/// sorting original definition symbols (explicitly or explicitly declared in source within the same
/// container) in lexical order of their declarations. It will not work on anything that uses non-source locations.
/// </summary>
/// <summary>
/// This is an implementation of a special symbol comparer, which is supposed to be used for sorting
/// original definition symbols (explicitly or implicitly declared in source within the same compilation)
/// in lexical order of their declarations. It will not work on anything that uses non-source locations.
/// </summary>
internal class LexicalOrderSymbolComparer : IComparer<Symbol>
{
public static readonly LexicalOrderSymbolComparer Instance = new LexicalOrderSymbolComparer();
Expand All @@ -30,6 +31,7 @@ public int Compare(Symbol x, Symbol y)

var xSortKey = x.GetLexicalSortKey();
var ySortKey = y.GetLexicalSortKey();
Debug.Assert((object)x.DeclaringCompilation == y.DeclaringCompilation);

comparison = LexicalSortKey.Compare(xSortKey, ySortKey);
if (comparison != 0)
Expand Down
Loading