Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Copy link
Member

Choose a reason for hiding this comment

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

Just curious what's the reason for this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is related to #78416 (management and validation of public APIs) and the discussion in LDM last week.
While investigating the issue looking at Stephen's assemblies, I noticed <>E__1 without a <>E__0 and was a bit surprised. I think it makes more sense to only count extensions and it may alleviate some of the public API management issue (if you managed your source file and extension block order, your extension metadata names will be stable).
The spec is vague on exactly how we number those, so didn't need to update.

Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,21 @@ internal override string ExtensionName
declaration = ((SourceNamespaceSymbol)this.ContainingSymbol).MergedDeclaration;
}

var index = declaration.Children.IndexOf(this.declaration);
return GeneratedNames.MakeExtensionName(index);
int index = 0;
foreach (Declaration child in declaration.Children)
{
if (child == this.declaration)
{
return GeneratedNames.MakeExtensionName(index);
}

if (child.Kind == DeclarationKind.Extension)
{
index++;
}
}

throw ExceptionUtilities.Unreachable();
}
}

Expand Down
19 changes: 10 additions & 9 deletions src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -919,7 +919,7 @@ public static partial class Extensions
}

[Fact]
public void ExtensionIndex_TwoExtensions_SameSignatures_01()
public void ExtensionIndex_TwoExtensions_01()
{
var src = """
public static class Extensions
Expand Down Expand Up @@ -1560,7 +1560,7 @@ [0] int32
}

[Fact]
public void ExtensionIndex_TwoExtensions_SameSignatures_02()
public void ExtensionIndex_TwoExtensions_02()
{
var src = """
public static class Extensions
Expand All @@ -1585,12 +1585,12 @@ class C { }
var extension2 = tree.GetRoot().DescendantNodes().OfType<ExtensionDeclarationSyntax>().Last();
var symbol2 = model.GetDeclaredSymbol(extension2);
var sourceExtension2 = symbol2.GetSymbol<SourceNamedTypeSymbol>();
Assert.Equal("<>E__2`1", symbol2.MetadataName);
Assert.Equal("Extensions.<>E__2<T>", symbol2.ToTestDisplayString());
Assert.Equal("<>E__1`1", symbol2.MetadataName);
Assert.Equal("Extensions.<>E__1<T>", symbol2.ToTestDisplayString());
}

[Fact]
public void ExtensionIndex_TwoExtensions_SameSignatures_03()
public void ExtensionIndex_TwoExtensions_03()
{
var src = """
extension<T>(T) { }
Expand Down Expand Up @@ -1618,12 +1618,12 @@ class C { }
var extension2 = tree.GetRoot().DescendantNodes().OfType<ExtensionDeclarationSyntax>().Last();
var symbol2 = model.GetDeclaredSymbol(extension2);
var sourceExtension2 = symbol2.GetSymbol<SourceNamedTypeSymbol>();
Assert.Equal("<>E__2`1", symbol2.MetadataName);
Assert.Equal("<>E__2<T>", symbol2.ToTestDisplayString());
Assert.Equal("<>E__1`1", symbol2.MetadataName);
Assert.Equal("<>E__1<T>", symbol2.ToTestDisplayString());
}

[Fact]
public void ExtensionIndex_TwoExtensions_DifferentSignatures_01()
public void ExtensionIndex_TwoExtensions_05()
{
var src = """
public static class Extensions
Expand Down Expand Up @@ -1652,7 +1652,7 @@ public static class Extensions
}

[Fact]
public void ExtensionIndex_TwoExtensions_DifferentSignatures_02()
public void ExtensionIndex_TwoExtensions_06()
{
var src = """
public static class Extensions
Expand Down Expand Up @@ -1695,6 +1695,7 @@ public static class Extensions
extension<T8>(T8 o8) { }
extension<T9>(T9 o9) { }
extension<T10>(T10 o10) { }
class C { }
extension<T11>(T11 o11) { }
}
""";
Expand Down
Loading