dotnet / dotnet/fsharp

Member call resolves to generic overload even when matching non-generic overload is available

Open
#19,890 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
F#
Stars
4.3k
Forks
876
Avg merge
4d 11h
Merged PRs (30d)
131

Description

I'm not calling this a bug, because I think it functions as designed, but I found it very surprising when I ran into it the wild:

```fsharp
namespace One

type Foo() = class end

[]
module FooExt =
type Foo with
member _.GetString() = "Non-generic"

namespace Two

[]
module FooExt =
type One.Foo with
member _.GetString<'t>() = $"Generic: {typeof<'t>.Name}"

namespace Three

open One
open Two

module Program =

let foo = Foo()
printfn $"{foo.GetString()}" // output: "Generic: Object"
```

My expectation was that `foo.GetString()` would resolve to the non-generic version of `GetString`, but instead the compiler chose `GetString` with nary a peep. If I reverse the order of the `open` statements, then it resolves to the non-generic version, so I guess it's a case of "last namespace wins".

Suggestion: If the compiler can match a non-generic call with a non-generic member, that should probably take precedence over matching a generic member with an implicit `obj` type parameter, even if the generic member is in a more recent namespace. Silently filling that type parameter with `obj` when a non-generic match is available is at least worth a warning, I would think.

Note: In the real world, I was simply the consumer of the `Foo` type (which lives in an external NuGet package), so I had no visibility into exactly how it was defined across namespaces. Thus, the example code above ruins the surprise that I actually experienced. (IntelliSense gives no hint that they are in different namespaces.)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.