Skip to content

Latest commit

 

History

History
125 lines (90 loc) · 6.54 KB

overload-resolution-priority.md

File metadata and controls

125 lines (90 loc) · 6.54 KB

Overload Resolution Priority

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#.

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

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 to a method. We update section Overloaded Method Resolution of the VB specification as follows (change in bold):

  1. Next, eliminate all members from the set that are inaccessible or not applicable (Section 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:

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:

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 disallowed 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.