This works
open System
let f = Action(fun () -> Unchecked.defaultof<_>)
But this
let f = System.Action(fun () -> Unchecked.defaultof<_>)
produces the compilation error
Multiple types exist called 'Action', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'Action<,,_,,,_,,,_>'.
I know I can fix it by adding a type parameter placeholder (System.Action<_>(...)
), but any idea why they behave differently?
Found this in the spec, section 14.1.9:
When a module or namespace declaration group
F
is opened, items are added to the name environment as follows:
- Add the type to the TypeNames table. If the type has a CLI-mangled generic name such as
List'1
then an entry is added under bothList
andList'1
.
Is this behavior replicated for fully-qualified types (with omitted type parameters)? It doesn't appear so.
I agree with @James that this is related to the bug submitted on Connect, but I think it is a slightly different case. Anyway, I think this is not the intended behaviour. Could you report it to fsbugs at microsoft dot com?
Anyway - I did some debugging and here is what I found so far:
It seems that the compiler uses different code paths to resolve the name Action
and the name System.Action
. When resolving the other, it searches all loaded modules (i.e. assemblies) for a type named System.Action
(see ResolveLongIndentAsModuleOrNamespaceThen
function in the nameres.fs
file of the open-source release).
This finds the two definitions of Action
(one in mscorlib
and another in System.Core
). I think the issue comes from the fact that the name resolution simply iterates over the results - it finds the first one (from System.Core
), which doesn't have a usable overload (because it ranges from Action<_,_,_,_,_>
to a version with about 15 type parameters). After finding this type, it reports an error without even looking whether there is another type (in another assembly) that could be used.
If you don't reference system assemblies, then the F# compiler resolves the overload just fine. Running the compiler without parameters references the default assembly set, so this doesn't work:
fsc test.fs
but if I add the --noframework
flag, then it compiles without issues:
fsc --noframework test.fs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With