【问题标题】:scalac missing closing brace error reports with weird line numberscalac缺少带有奇怪行号的右括号错误报告
【发布时间】:2012-08-21 07:31:38
【问题描述】:

由于我一直在学习 Scala,因此在读取来自 scalac 的神秘输出时,我经常会想起 g++ 编译器错误。但是,今天我遇到了一些我怀疑即使在 g++ 宇宙中也会发生的事情。

一个朋友给我发了一个非常简单的代码 sn-p 一个相当常见的错误:

case class Var(name: String) extends ArithExpr {
  override def eval(env: Env) =  env.lookup(name) match {
    case Some(d) => d
    case None => throw new IllegalArgumentException("Env " + env + " does not contain a binding for " + name)
  }
  override def exprString = name
// } // <-- MISSING THIS BRACE

完整的源文件is posted here。由于case class Var 类声明缺少右大括号,您会认为编译器会告诉您该声明的左大括号(第 11 行)缺少右大括号。但是,scalac 报告它“假定”在先前的 case class 声明(第 7 行)中间缺少右括号。 (完整的错误输出包含在发布代码的底部。)

如果您了解语言的内部原理,大多数scalac 错误消息都是有意义的,但我在这里完全不知所措。后面的类声明中缺少的右大括号如何最终传播到文件前面已经成功解析的类定义?

您到底是如何向 Scala 初学者解释这一点的?省略右括号正是 Scala 新手通常会犯的那种错误,但这里的错误消息似乎会让用户误入歧途,因此报告类似 error: you seem to be missing a '}' somewhere 的内容可能会更有帮助.

注意:我知道此类问题的通常答案只是“使用 IDE,增量编译会立即标记它”或“语法突出显示应该使这个错误显而易见”——但我的问题是专门问的关于scalac 的输出,所以请记住,我知道这些是有效的点,但我真的只是想了解这里的编译器发生了什么。

更新:

让我尝试一种不同的方法来解释我的困惑。该错误源于缺少右大括号,因此显然是大括号嵌套的问题。将我发布的 sn-p 中的文本(代码)转换为一系列行号+大括号对,我们得到:

1{ 4}
6{ 9}
11{ 12{ 15}
    19{ 22}
    24{ 26}
    28{ 33}

我们显然缺少一个右括号。我可以理解scalac 猜测丢失的大括号可能会出现在这些地方的任何一个地方(每个地方都由x 表示):

1{ 4}
6{ 9}
11{ x 12{ x 15} x <-- HERE OR HERE OR HERE
      19{ x 22} x <-- OR HERE OR HERE
      24{ x 26} x <-- OR HERE OR HERE
      28{ x 33} x <-- OR HERE OR HERE

但是,scalac 的输出是这样说的:

   +----- I THINK YOU ARE MISSING A
   |      CLOSING BRACE RIGHT HERE!
1{ V 4}
6{ x 9} 
11{ 12{ 15}
    19{ 22}
    24{ 26}
    28{ 33}

输入的那部分已经嵌套好!在那里添加另一个右括号怎么可能有意义?

编辑:我觉得我应该再次重申我的主要问题:您将如何解释此错误消息(以及如何在源代码中找到错误的根源) Scala 的新手?

【问题讨论】:

  • 顺便说一句:Scala 团队认为良好的编译器错误消息非常重要。事实上,如果他们无法弄清楚如何在保持良好错误消息的同时实现这些功能,那么他们就不会为语言添加有用的功能。因此,您绝对应该在 scala-dev 邮件列表中提出这个问题,并可能在 Scala issue tracker 中提交错误。
  • @Jörg W Mittag - 感谢您的意见。在我在这里发布之后,我意识到邮件列表可能会是一个更好的地方,但是由于我已经发布了,我想我会等待,看看我是否在这里得到了一个好的答案,然后再重复发布到邮件列表。我喜欢 Scala,但我认为从 Java 的过渡非常重要。我很高兴听到社区如此强调清晰的编译器错误消息。再次感谢您的建议!

标签: parsing scala compiler-construction scalac


【解决方案1】:

考虑以下示例(我故意删除了缩进):

case class Foo( i: Int ) {
case class Bar( d: Double ) {
def get = d 
}

它无法编译,但有几个可能的正确代码:

case class Foo( i: Int ) {
}
case class Bar( d: Double ) {
  def get = d 
}

//OR

case class Foo( i: Int ) {
  case class Bar( d: Double ) {
    def get = d 
  }
}

//OR even (still won't compile but the structure is correct so the compiler will proceed with
//another error)

case class Foo( i: Int ) {
  case class Bar( d: Double ) { }
  def get = d 
}

那么编译器应该如何猜测哪个版本是正确的呢?在这种情况下,它会选择第一个有意义的位置:

hello.scala:3: error: Missing closing brace `}' assumed here
def get = d

对应第三个选项。

【讨论】:

  • 这在您给出的示例中是有道理的,但不适用于我发布的代码。我已经更新了我的问题,以便更清楚地说明这一点。
  • -1 因为尽管您的回答提供了丰富的信息,但它实际上并没有解决我发布的代码中奇怪的行号。
【解决方案2】:

根据 Jörg W Mittag 在他对我的问题的评论中提出的建议,我在 Scala 问题跟踪器中重新打开一张旧票:Confusing Unmatched closing brace errors。我已将来自这个问题的代码添加为此类令人困惑的错误消息的一个新的、简短的、可重现的示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-31
    • 1970-01-01
    • 2016-10-23
    • 2016-02-14
    • 1970-01-01
    相关资源
    最近更新 更多