fsharp / fsharp/fslang-suggestions

Overloaded interface methods/properties in member constraints differing in return type only are rejected

Open
#1,402 3 comments 0 reactions 0 assignees View on GitHub
area: object-programming area: srtp-and-constraints
Dominant language
No language data
Stars
373
Forks
21
PR merge metrics
No merged PRs in 30d

Description

**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:
```fs
open System.Collections
open System.Collections.Generic
let a: int seq = List()
let i1 = a.GetEnumerator() // works fine
let i2 = (^T: (member GetEnumerator: unit -> IEnumerator) 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.
let i3 = (^T: (member GetEnumerator: unit -> #IEnumerator) 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:
```fs
let a: IEnumerator = List().GetEnumerator()
let c1 = a.Current // fine
let c2 = (^T: (member Current: 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` 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.

## Extra information

**Estimated cost (XS, S, M, L, XL, XXL):** S

**Related suggestions:** #820

## Affidavit (please submit!)

* [x] This is not a question (e.g. like one you might ask on [StackOverflow](http://stackoverflow.com)) and I have searched StackOverflow for discussions of this issue
* [x] 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](https://github.com/dotnet/fsharp)
* [x] 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
* [x] I have [searched both open and closed suggestions on this site](http://github.com/fsharp/fslang-suggestions/issues) and believe this is not a duplicate

* [x] 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 :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

Contributor guide

No contributing guide indexed for this repository

Research direction

The issue gives F# examples involving SRTP member constraints, overloaded interface methods, and properties, but names no implementation files, tests, or compiler entry points. Start by locating the member-constraint overload-resolution implementation in the F# compiler and existing regression tests for SRTP overloads. Done means incompatible return-type candidates and normally shadowed candidates are resolved consistently with direct calls, with coverage for the shown method and property cases.

Written by the indexing model from the issue text.

Assessment

Tech stack
fsharp
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.