Skip to content

Commit 73f70f4

Browse files
author
Julien Couvreur
authored
Extensions: honor OverloadResolutionPriority attribute (#78219)
1 parent 0a6e36a commit 73f70f4

File tree

12 files changed

+606
-22
lines changed

12 files changed

+606
-22
lines changed

src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1878,7 +1878,8 @@ private void RemoveLowerPriorityMembers<TMemberResolution, TMember>(ArrayBuilder
18781878

18791879
foreach (var result in results)
18801880
{
1881-
Debug.Assert(result.MemberWithPriority is not null);
1881+
TMember memberWithPriority = result.MemberWithPriority;
1882+
Debug.Assert(memberWithPriority is not null);
18821883

18831884
// We don't filter out inapplicable members here, as we want to keep them in the list for diagnostics
18841885
// However, we don't want to take them into account for the priority filtering
@@ -1888,11 +1889,14 @@ private void RemoveLowerPriorityMembers<TMemberResolution, TMember>(ArrayBuilder
18881889
continue;
18891890
}
18901891

1891-
var containingType = result.MemberWithPriority.ContainingType; // Tracked by https://github.com/dotnet/roslyn/issues/76130 : how should ORPA apply to new extension methods?
1892+
NamedTypeSymbol containingType = memberWithPriority.GetIsNewExtensionMember()
1893+
? memberWithPriority.ContainingType.ContainingType
1894+
: memberWithPriority.ContainingType;
1895+
18921896
if (resultsByContainingType.TryGetValue(containingType, out var previousResults))
18931897
{
18941898
var previousPriority = previousResults.First().MemberWithPriority.GetOverloadResolutionPriority();
1895-
var currentPriority = result.MemberWithPriority.GetOverloadResolutionPriority();
1899+
var currentPriority = memberWithPriority.GetOverloadResolutionPriority();
18961900

18971901
if (currentPriority > previousPriority)
18981902
{

src/Compilers/CSharp/Portable/Symbols/Extensions/RewrittenLambdaOrLocalFunctionSymbol.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
3030
return true;
3131
}
3232

33+
internal override int TryGetOverloadResolutionPriority()
34+
=> _originalMethod.TryGetOverloadResolutionPriority();
35+
3336
protected override ImmutableArray<ParameterSymbol> MakeParameters()
3437
{
3538
return ImmutableArray<ParameterSymbol>.CastUp(_originalMethod.Parameters.SelectAsArray(static (p, @this) => new RewrittenMethodParameterSymbol(@this, p), this));

src/Compilers/CSharp/Portable/Symbols/Extensions/SourceExtensionImplementationMethodSymbol.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,17 @@ internal override int ParameterCount
6565

6666
internal sealed override void AddSynthesizedAttributes(PEModuleBuilder moduleBuilder, ref ArrayBuilder<CSharpAttributeData> attributes)
6767
{
68+
if (_originalMethod is SourcePropertyAccessorSymbol { AssociatedSymbol: SourcePropertySymbolBase extensionProperty })
69+
{
70+
foreach (CSharpAttributeData attr in extensionProperty.GetAttributes())
71+
{
72+
if (attr.IsTargetAttribute(AttributeDescription.OverloadResolutionPriorityAttribute))
73+
{
74+
AddSynthesizedAttribute(ref attributes, attr);
75+
}
76+
}
77+
}
78+
6879
base.AddSynthesizedAttributes(moduleBuilder, ref attributes);
6980
SourceMethodSymbol.AddSynthesizedAttributes(this, moduleBuilder, ref attributes);
7081
}
@@ -110,6 +121,16 @@ internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
110121
return true;
111122
}
112123

124+
internal override int TryGetOverloadResolutionPriority()
125+
{
126+
if (UnderlyingMethod is SourcePropertyAccessorSymbol { AssociatedSymbol: SourcePropertySymbol property })
127+
{
128+
return property.TryGetOverloadResolutionPriority();
129+
}
130+
131+
return UnderlyingMethod.TryGetOverloadResolutionPriority();
132+
}
133+
113134
private sealed class ExtensionMetadataMethodParameterSymbol : RewrittenMethodParameterSymbol
114135
{
115136
public ExtensionMetadataMethodParameterSymbol(SourceExtensionImplementationMethodSymbol containingMethod, ParameterSymbol sourceParameter) :

src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PEPropertySymbol.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1045,7 +1045,7 @@ internal override bool HasRuntimeSpecialName
10451045

10461046
internal override int TryGetOverloadResolutionPriority()
10471047
{
1048-
Debug.Assert(IsIndexer || IsIndexedProperty);
1048+
Debug.Assert(IsIndexer || IsIndexedProperty || this.GetIsNewExtensionMember());
10491049
if (!_flags.IsOverloadResolutionPriorityPopulated)
10501050
{
10511051
if (_containingType.ContainingPEModule.Module.TryGetOverloadResolutionPriorityValue(_handle, out int priority) &&

src/Compilers/CSharp/Portable/Symbols/NativeIntegerTypeSymbol.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,9 @@ internal sealed override bool HasAsyncMethodBuilderAttribute(out TypeSymbol? bui
399399
builderArgument = null;
400400
return false;
401401
}
402+
403+
internal override int TryGetOverloadResolutionPriority()
404+
=> UnderlyingMethod.TryGetOverloadResolutionPriority();
402405
}
403406

404407
internal sealed class NativeIntegerParameterSymbol : WrappedParameterSymbol

src/Compilers/CSharp/Portable/Symbols/PropertySymbol.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,8 @@ internal int OverloadResolutionPriority
356356

357357
internal abstract int TryGetOverloadResolutionPriority();
358358

359-
internal bool CanHaveOverloadResolutionPriority => !IsOverride && !IsExplicitInterfaceImplementation && (IsIndexer || IsIndexedProperty);
359+
internal bool CanHaveOverloadResolutionPriority
360+
=> !IsOverride && !IsExplicitInterfaceImplementation && (IsIndexer || IsIndexedProperty || this.GetIsNewExtensionMember());
360361

361362
/// <summary>
362363
/// Implements visitor pattern.

src/Compilers/CSharp/Portable/Symbols/Retargeting/RetargetingMethodSymbol.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ internal override bool TryGetThisParameter(out ParameterSymbol? thisParameter)
269269
: null;
270270
return true;
271271
}
272+
273+
internal override int TryGetOverloadResolutionPriority()
274+
=> _underlyingMethod.TryGetOverloadResolutionPriority();
272275
#nullable disable
273276

274277
public override AssemblySymbol ContainingAssembly

src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbolBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,7 +1470,7 @@ internal override (CSharpAttributeData?, BoundAttribute?) EarlyDecodeWellKnownAt
14701470

14711471
return (null, null);
14721472
}
1473-
else if (IsIndexer && CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.OverloadResolutionPriorityAttribute))
1473+
else if ((IsIndexer || this.GetIsNewExtensionMember()) && CSharpAttributeData.IsTargetEarlyAttribute(arguments.AttributeType, arguments.AttributeSyntax, AttributeDescription.OverloadResolutionPriorityAttribute))
14741474
{
14751475
(attributeData, boundAttribute) = arguments.Binder.GetAttribute(arguments.AttributeSyntax, arguments.AttributeType, beforeAttributePartBound: null, afterAttributePartBound: null, out var hasAnyDiagnostics);
14761476

@@ -1733,7 +1733,7 @@ private void ValidateIndexerNameAttribute(CSharpAttributeData attribute, Attribu
17331733

17341734
internal sealed override int TryGetOverloadResolutionPriority()
17351735
{
1736-
Debug.Assert(this.IsIndexer);
1736+
Debug.Assert(this.IsIndexer || this.GetIsNewExtensionMember());
17371737
return GetEarlyDecodedWellKnownAttributeData()?.OverloadResolutionPriority ?? 0;
17381738
}
17391739

src/Compilers/CSharp/Portable/Symbols/SubstitutedMethodSymbol.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,9 @@ internal sealed override bool TryGetThisParameter(out ParameterSymbol thisParame
329329
return true;
330330
}
331331

332+
internal override int TryGetOverloadResolutionPriority()
333+
=> OriginalDefinition.TryGetOverloadResolutionPriority();
334+
332335
private ImmutableArray<ParameterSymbol> SubstituteParameters()
333336
{
334337
var unsubstitutedParameters = OriginalDefinition.Parameters;

src/Compilers/CSharp/Portable/Symbols/Wrapped/WrappedMethodSymbol.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -364,10 +364,5 @@ internal override bool GenerateDebugInfo
364364
internal sealed override bool HasUnscopedRefAttribute => UnderlyingMethod.HasUnscopedRefAttribute;
365365

366366
internal sealed override bool UseUpdatedEscapeRules => UnderlyingMethod.UseUpdatedEscapeRules;
367-
368-
internal sealed override int TryGetOverloadResolutionPriority()
369-
{
370-
return UnderlyingMethod.TryGetOverloadResolutionPriority();
371-
}
372367
}
373368
}

0 commit comments

Comments
 (0)