Member call resolves to generic overload even when matching non-generic overload is available
- 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
Assessment
This issue has not been assessed yet.