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?
EDIT
Found this in the spec, section 14.1.9:
When a module or namespace declaration group
Fis 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'1then an entry is added under bothListandList'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
Actionand the nameSystem.Action. When resolving the other, it searches all loaded modules (i.e. assemblies) for a type namedSystem.Action(seeResolveLongIndentAsModuleOrNamespaceThenfunction in thenameres.fsfile of the open-source release).This finds the two definitions of
Action(one inmscorliband another inSystem.Core). I think the issue comes from the fact that the name resolution simply iterates over the results – it finds the first one (fromSystem.Core), which doesn’t have a usable overload (because it ranges fromAction<_,_,_,_,_>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:
but if I add the
--noframeworkflag, then it compiles without issues: