-
Notifications
You must be signed in to change notification settings - Fork 66
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
Create overload-resolution-priority.md #627
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
# Overload Resolution Priority | ||
|
||
## Summary | ||
[summary]: #summary | ||
|
||
We introduced a new attribute, `System.Runtime.CompilerServices.OverloadResolutionPriority`, that can be used by API authors to adjust the relative priority of | ||
overloads within a single type as a means of steering API consumers to use specific APIs, even if those APIs would normally be considered ambiguous or otherwise | ||
not be chosen by overload resolution rules. See [Overload Resolution Priority in C#](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-13.0/overload-resolution-priority.md). | ||
|
||
## Motivation | ||
[motivation]: #motivation | ||
|
||
API authors often run into an issue of what to do with a member after it has been obsoleted. For backwards compatibility purposes, many will keep the existing member around | ||
with `ObsoleteAttribute` set to error in perpetuity, in order to avoid breaking consumers who upgrade binaries at runtime. This particularly hits plugin systems, where the | ||
author of a plugin does not control the environment in which the plugin runs. The creator of the environment may want to keep an older method present, but block access to it | ||
for any newly developed code. However, `ObsoleteAttribute` by itself is not enough. The type or member is still visible in overload resolution, and may cause unwanted overload | ||
resolution failures when there is a perfectly good alternative, but that alternative is either ambiguous with the obsoleted member, or the presence of the obsoleted member causes | ||
overload resolution to end early without ever considering the good member. For this purpose, we want to have a way for API authors to guide overload resolution on resolving the | ||
ambiguity, so that they can evolve their API surface areas and steer users towards performant APIs without having to compromise the user experience. | ||
|
||
## Detailed Design | ||
[detailed-design]: #detailed-design | ||
|
||
### Overload resolution priority | ||
|
||
We define a new concept, ***overload_resolution_priority***, which is used during the process of overload resolution. ***overload_resolution_priority*** is a 32-bit integer | ||
value. All methods have an ***overload_resolution_priority*** of 0 by default, and this can be changed by applying | ||
[`OverloadResolutionPriorityAttribute`](#systemruntimecompilerservicesoverloadresolutionpriorityattribute) to a method. We update section | ||
[Overloaded Method Resolution](https://github.com/dotnet/vblang/blob/main/spec/overload-resolution.md#overloaded-method-resolution) of the VB specification as | ||
follows (change in **bold**): | ||
|
||
> 2. Next, eliminate all members from the set that are inaccessible or not applicable (Section [Applicability To Argument List](overload-resolution.md#applicability-to-argument-list)) to the argument list | ||
|
||
> **3. Then, the reduced set of candidate members is grouped by declaring type. | ||
> If the member is an override, the declaring type and the ***overload_resolution_priority*** come from the least-derived declaration of that member. | ||
> Within each group:** | ||
|
||
> - **A maximum ***overload_resolution_priority*** among candidates that do not utilize narrowing conversions or narrowing delegate relaxation is determined.** | ||
> - **All members that have a lower ***overload_resolution_priority*** than the maximum found during the previous step, if any, within its declaring type group are removed.** | ||
|
||
> **The reduced groups are then recombined into the set of candidates.** | ||
|
||
> **4**. Next, if one or more arguments are `AddressOf` or lambda expressions, then calculate the *delegate relaxation levels* for each such argument as below. If the worst (lowest) delegate relaxation level in `N` is worse than the lowest delegate relaxation level in `M`, then eliminate `N` from the set. The delegate relaxation levels are as follows: | ||
|
||
As an example, this feature would cause the following code snippet to print "I1", rather than failing compilation due to an ambiguity: | ||
|
||
```vb | ||
Public Interface I1 | ||
End Interface | ||
Public Interface I2 | ||
End Interface | ||
Public Interface I3 | ||
Inherits I1, I2 | ||
End Interface | ||
|
||
Public Class C | ||
<OverloadResolutionPriority(1)> | ||
Public Shared Sub M(x As I1) | ||
System.Console.WriteLine("I1") | ||
End Sub | ||
Public Shared Sub M(x As I2) | ||
System.Console.WriteLine("I2") | ||
End Sub | ||
End Class | ||
|
||
Public Class Program | ||
Shared Sub Main() | ||
Dim i3 As I3 = Nothing | ||
C.M(i3) | ||
End Sub | ||
End Class | ||
``` | ||
|
||
Negative numbers are allowed to be used, and can be used to mark a specific overload as worse than all other default overloads. | ||
|
||
The **overload_resolution_priority** of a member comes from the least-derived declaration of that member. **overload_resolution_priority** is not | ||
inherited or inferred from any interface members a type member may implement, and given a member `Mx` that implements an interface member `Mi`, no | ||
warning is issued if `Mx` and `Mi` have different **overload_resolution_priorities**. | ||
|
||
### `System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute` | ||
|
||
There is the following attribute in the BCL: | ||
|
||
```cs | ||
namespace System.Runtime.CompilerServices; | ||
|
||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property, AllowMultiple = false, Inherited = false)] | ||
public sealed class OverloadResolutionPriorityAttribute(int priority) : Attribute | ||
{ | ||
public int Priority => priority; | ||
} | ||
``` | ||
|
||
All methods in VB have a default ***overload_resolution_priority*** of 0, unless they are attributed with `OverloadResolutionPriorityAttribute`. If they are | ||
attributed with that attribute, then their ***overload_resolution_priority*** is the integer value provided to the first argument of the attribute. | ||
|
||
### Langversion Behavior | ||
|
||
Overload Resolution process does not perform filtering by ***overload_resolution_priority*** in VB < 17.13. | ||
No errors or warnings issued by the Overload Resolution process due to the fact that ***overload_resolution_priority*** | ||
was ignored in this case. | ||
|
||
|
||
## Open Questions | ||
|
||
### Should `OverloadResolutionPriorityAttribute` be dissallowed in some locations? | ||
|
||
By analogy with C# we could make it an error to apply `OverloadResolutionPriorityAttribute` to the following locations: | ||
|
||
* Property, or event accessors | ||
* Conversion operators | ||
* Finalizers | ||
* Shared constructors | ||
* Overriding properties | ||
* Overriding methods | ||
|
||
Attributes encountered on these locations in metadata effectively will have no impact in VB code. | ||
|
||
Reporting an error might be a breaking change because VB allowed the attribute at any location before. | ||
|
||
### Langversion Behavior | ||
|
||
Should a langversion errors be issued when `OverloadResolutionPriorityAttribute` is applied? | ||
|
||
Reporting the error might be a breaking change because VB allowed the attribute in the previous version. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: disallowed