【问题标题】:Method Type Inference in the Java SpecificationJava 规范中的方法类型推断
【发布时间】:2012-05-21 19:01:52
【问题描述】:

我目前正在编写 Java 编译器并已实现第 15.12.2.7 节。 JLS7 (http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.7) ,规范中最烦人的部分之一。我仍然有一个问题,因为规范似乎没有明确说明或模棱两可。我的问题是这一行:

lcta(U) = ?如果 U 的上界是 Object,否则 ?扩展 lub(U,Object)

U 是任意类型的表达式。类型表达式的上限是多少?另外,为什么lcta总是通配符?

规范定义

CandidateInvocation(G) = lci(Inv(G)).

现在,例如,考虑 Inv(G) = { List } 的情况,即唯一可能的候选调用是单个参数化类型。现在,由于规则

lci(G) = G,

CandidateInvocation(G)的结果= lci( { List } ) 将被定义为:

列表

在我看来,lcta 应该在这里简单地返回 String,因为如果 List 是唯一可能的调用,那么推断 List 作为参数是个好主意。但是,lcta(U) 的定义表明结果是 ?或者 ?扩展 lub(...),所以结果总是一个通配符。这似乎很奇怪。我在这里误解了什么?

【问题讨论】:

    标签: java compiler-construction type-inference specifications


    【解决方案1】:

    这看起来像是规范的错误。 lcta(U) 的子句在 JSL3 中不存在。显然,当n=1 时,JLS3 对lci(e1..en) 的定义不完整,新规范试图修复它。但是,正如您所推理的那样,修复似乎是胡言乱语。

    Javac7 将lci( { List<String> } ) 计算为List<String>,忽略添加的子句。

    这个问题应该向规范维护者提出;不知道如何联系他们。你可以试试 openjdk compiler-dev 邮件列表;上面有一些知识渊博的人。

    【讨论】:

    • 我现在已经实现了 lcta(U) = U 这似乎工作正常。如果我发现任何这种实现产生令人惊讶的结果的情况,我会报告。顺便说一句:不是 lub(U,Object) 总是 U,因为 Object 总是 U 的超类,因此 {U, Object} 的最小化擦除候选 MEC 应该总是产生 U 或其子类之一?因此,该规则确实是完全废话。唯一可能有好处的就是转型?将对象扩展到 ?。然而,由于 U 是一个类型表达式,它不能包含通配符,所以这种情况可能永远不会出现......真的很奇怪。
    • 和邮件列表的好主意,我想我会在那里尝试
    • lub = 最小上限。我认为任何类型都应该比对象更低,即“更少”。否则,对 lub(U,Object) 的调用会更加愚蠢,因为它可以简单地被 Object 替换。
    【解决方案2】:

    我已经在编译器开发邮件列表中询问并收到了答案:

    是的,这里的规范是错误的。 lcta(U) 的规则完全是废话:)。此外,他们声称最好不要为单个参数调用 lcta(U) 而只使用 U(因为单个参数 U 的最不常见的类型参数应该始终是 U 本身)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      相关资源
      最近更新 更多