完全合格的名称,带有导入声明的不合格名称以不同的方式解析 [英] Fully qualified name, unqualified name with import declaration resolve differently

查看:92
本文介绍了完全合格的名称,带有导入声明的不合格名称以不同的方式解析的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这有效

open System
let f = Action(fun () -> Unchecked.defaultof<_>)

但是这个

let f = System.Action(fun () -> Unchecked.defaultof<_>)

产生编译错误

存在多个称为动作"的类型,它们具有不同数量的通用参数.提供类型实例化以消除类型解析的歧义,例如'动作< ,_,,_,,_>'.

Multiple types exist called 'Action', taking different numbers of generic parameters. Provide a type instantiation to disambiguate the type resolution, e.g. 'Action<,,_,,,_,,,_>'.

我知道我可以通过添加类型参数占位符(System.Action<_>(...))来解决此问题,但是知道为什么它们的行为有所不同吗?

I know I can fix it by adding a type parameter placeholder (System.Action<_>(...)), but any idea why they behave differently?

在规范的第14.1.9节中找到了这一点:

Found this in the spec, section 14.1.9:

打开模块或名称空间声明组F时,会将项目添加到名称环境,如下所示:

When a module or namespace declaration group F is opened, items are added to the name environment as follows:

  • 将类型添加到 TypeNames 表中.如果该类型具有CLI拼写的通用名称,例如List'1,则在ListList'1下都将添加一个条目.
  • 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 both List and List'1.

此行为是否已针对完全限定的类型(具有省略的类型参数)进行了复制?看来并非如此.

Is this behavior replicated for fully-qualified types (with omitted type parameters)? It doesn't appear so.

推荐答案

我同意@James的说法,这与Connect上提交的错误有关,但我认为情况稍有不同.无论如何,我认为这不是预期的行为.您能否将其报告给 microsoft com 上的 fsbugs ?

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:

似乎编译器使用不同的代码路径来解析名称Action和名称System.Action.当解析另一个时,它会在所有加载的模块(即程序集)中搜索名为System.Action的类型(请参见

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).

这将找到Action的两个定义(在mscorlib中一个,在System.Core中另一个).我认为问题出在以下事实:名称解析只是对结果进行迭代-它找到第一个(来自System.Core),没有可用的重载(因为它的范围从Action<_,_,_,_,_>到具有大约15个类型参数).找到此类型后,它将报告错误,甚至没有查看是否有其他类型(在另一个程序集中)可以使用.

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.

如果您不引用系统程序集,则F#编译器可以很好地解决重载问题.在不带参数的情况下运行编译器会引用默认的程序集,因此无法正常工作:

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 

但是如果我添加--noframework标志,那么它将编译而不会出现问题:

but if I add the --noframework flag, then it compiles without issues:

fsc --noframework test.fs

这篇关于完全合格的名称,带有导入声明的不合格名称以不同的方式解析的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆