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:
namespace One
type Foo() = class end
[<AutoOpen>]
module FooExt =
type Foo with
member _.GetString() = "Non-generic"
namespace Two
[<AutoOpen>]
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<obj> 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.)
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:
My expectation was that
foo.GetString()would resolve to the non-generic version ofGetString, but instead the compiler choseGetString<obj>with nary a peep. If I reverse the order of theopenstatements, 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
objtype parameter, even if the generic member is in a more recent namespace. Silently filling that type parameter withobjwhen 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
Footype (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.)