You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I propose we have modifications to the overload resolution algorithm used by member constraints in SRTPs that fix the following situation where there are overloaded interface methods differing in return type only:
openSystem.CollectionsopenSystem.Collections.Genericleta:int seq = List<int>()leti1= a.GetEnumerator()// works fineleti2=(^T:(memberGetEnumerator: unit -> IEnumerator<int>) a)// error FS0043: A unique overload for method 'GetEnumerator' could not be determined based on type information prior to this program point. A type annotation may be needed.leti3=(^T:(memberGetEnumerator: unit -> #IEnumerator<int>) a)// same error
When the method is called directly, everything works, but with the member constraint, both overloads of GetEnumerator are taken into consideration, even though only one matches the return type.
It should be noted that if I remove : int seq, only the last line starts working, so the issue is not caused by variance (the type must match directly, not via a derived one unless specified by #).
A similar situation happens with properties:
leta:IEnumerator<int>= List<int>().GetEnumerator()letc1= a.Current // fineletc2=(^T:(memberCurrent: int) a)// error FS0043: A unique overload for method 'get_Current' could not be determined based on type information prior to this program point. A type annotation may be needed.
Removing : IEnumerator<int> once again makes the code compilable, correctly ignoring the get_Current method from interfaces.
The proposed changes to the algorithm are:
Methods/properties with return type incompatible with the type specified in the constraint are removed from the set of candidates.
In case of multiple candidates, the candidate methods/properties that would normally be shadowed by other candidates when called directly are removed.
The existing way of approaching this problem in F# is not to use member constraints in this situation. I am not aware of a solution using a type annotation, as the error message suggests.
Pros and Cons
The advantages of making this adjustment to F# are parity with normal overload resolution and less surprising behaviour in situations where an overload can be clearly determined.
The disadvantages of making this adjustment to F# are changing potentially complicated code with the risk of introducing silent behaviour changes.
This is not a question (e.g. like one you might ask on StackOverflow) and I have searched StackOverflow for discussions of this issue
This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to the compiler and tooling repository
This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it
This is not a breaking change to the F# language design (Probably. The proposed changes could be in effect only when there is already a conflict, to be sure.)
I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered:
Thank you! I noticed the linked issue before but did not realize it is connected to this too. I understand there are two ways to solve this; one by taking the return type into account (i.e. what you linked to), the other one being to use shadowing to remove ambiguous candidates. I will be happy to see this working either way.
I think shadowing will be a new mechanism for compiler (in a way that we don't do that for methods currently, we don't choose/shadow methods for user in majority of the cases). Taking return into account when resolving might be more straigtforward.
There's an issue for the tiebreakers as well, which might also change how things are getting chosen, theoretically: #905
I propose we have modifications to the overload resolution algorithm used by member constraints in SRTPs that fix the following situation where there are overloaded interface methods differing in return type only:
When the method is called directly, everything works, but with the member constraint, both overloads of
GetEnumerator
are taken into consideration, even though only one matches the return type.It should be noted that if I remove
: int seq
, only the last line starts working, so the issue is not caused by variance (the type must match directly, not via a derived one unless specified by#
).A similar situation happens with properties:
Removing
: IEnumerator<int>
once again makes the code compilable, correctly ignoring theget_Current
method from interfaces.The proposed changes to the algorithm are:
The existing way of approaching this problem in F# is not to use member constraints in this situation. I am not aware of a solution using a type annotation, as the error message suggests.
Pros and Cons
The advantages of making this adjustment to F# are parity with normal overload resolution and less surprising behaviour in situations where an overload can be clearly determined.
The disadvantages of making this adjustment to F# are changing potentially complicated code with the risk of introducing silent behaviour changes.
Extra information
Estimated cost (XS, S, M, L, XL, XXL): S
Related suggestions: #820
Affidavit (please submit!)
This is not a question (e.g. like one you might ask on StackOverflow) and I have searched StackOverflow for discussions of this issue
This is a language change and not purely a tooling change (e.g. compiler bug, editor support, warning/error messages, new warning, non-breaking optimisation) belonging to the compiler and tooling repository
This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it
I have searched both open and closed suggestions on this site and believe this is not a duplicate
This is not a breaking change to the F# language design (Probably. The proposed changes could be in effect only when there is already a conflict, to be sure.)
I or my company would be willing to help implement and/or test this
For Readers
If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.
The text was updated successfully, but these errors were encountered: