Скалярное сообщение об ошибке закрывающей фигурной скобки со странным номером строки

Поскольку я изучал Scala, мне часто вспоминают g++ ошибки компилятора при чтении загадочного вывода из scalac, Однако сегодня я столкнулся с чем-то, что, я сомневаюсь, случится даже в g++ Вселенная.

Друг прислал мне очень простой фрагмент кода с довольно распространенной ошибкой:

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

Полный исходный файл размещен здесь. Так как case class Var в объявлении класса отсутствует закрывающая фигурная скобка, вы можете подумать, что компилятор скажет вам, что в открывающей фигурной скобке для этого объявления (в строке 11) отсутствует закрывающая фигурная скобка. Тем не мение, scalac сообщает, что он "предполагает" отсутствие закрывающей скобки в середине предыдущего case class декларация (в строке 7). (Полный вывод ошибок включен внизу размещенного кода.)

Наиболее scalac Сообщения об ошибках имеют смысл, если вы понимаете внутренности языка, но я в полном недоумении. Как пропущенная закрывающая фигурная скобка в более позднем объявлении класса приводит к распространению ранее успешно проанализированного определения класса в файле?

Как, черт возьми, вы объясняете это новичку в Scala? Оставить закрывающую скобку - это именно та ошибка, которую обычно совершает кто-то новичок в Scala, но здесь появляется сообщение об ошибке, которое может привести пользователя в такое замешательство, что, вероятно, будет полезнее просто сообщить что-то вроде error: you seem to be missing a '}' somewhere вместо.

Примечание: я знаю, что обычный ответ на такие вопросы - просто "используйте IDE, и пошаговая компиляция сразу же отметит его" или "подсветка синтаксиса должна сделать эту ошибку очевидной", но мой вопрос касается именно scalac вывод, так что, пожалуйста, имейте в виду, что я знаю, что это правильные точки, но я действительно просто хочу понять, что здесь происходит с компилятором.

Обновить:

Позвольте мне попробовать другой подход к объяснению моей путаницы. Ошибка связана с отсутствующей закрывающей скобкой, поэтому, очевидно, это проблема с вложенностью фигурной скобки. Преобразуя текст (код) во фрагменте, который я разместил, в серию пар строка-номер + фигурные скобки, мы получаем это:

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?

2 ответа

Решение

Следуя предложению Йорга В. Миттага в его комментарии к моему вопросу, я снова открыл старый тикет в трекере проблем Scala: Confused Unmatched ошибки закрывающей скобки. Я добавил код из этого вопроса в качестве нового, короткого, воспроизводимого примера этого класса запутанных сообщений об ошибках.

Рассмотрим следующий пример (я специально удалил отступы):

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

Что соответствует третьему варианту.

Другие вопросы по тегам