我如何解决Scala编译器崩溃问题?

时间:2011-11-12 22:42:59

标签: scala

我正在使用Scala 2.9.1编译项目并获取

java.lang.AssertionError: assertion failed
    at scala.Predef$.assert(Predef.scala:89)
    at scala.tools.nsc.symtab.Symbols$Symbol.accessed(Symbols.scala:1142)
    at scala.tools.nsc.symtab.Symbols$Symbol.accessed(Symbols.scala:1138)
    at scala.tools.nsc.transform.Mixin$MixinTransformer$$anonfun$buildFieldPositions$1$1.apply(Mixin.scala:1006)

我想这是一个错误,但我没有时间修复它或等待其他人修复它,所以我想改变我正在做的任何事情所以我没有碰到这个bug

但是我很难过,因为我不知道我的代码的哪个部分导致了这个问题。我有什么策略可以用来隔离问题吗?

为了方便调查的人,以下是源代码的链接:

4 个答案:

答案 0 :(得分:2)

我没有解决Scala编译器崩溃问题,具体而言,我已解决过其他编译器崩溃问题。你想要做的是尝试缩小造成问题的原因。在大多数项目中,最简单的方法是通过注释进行二进制搜索。也就是说,注释掉大约一半的代码并查看错误是否仍然发生。如果没有,取消注释那一半并评论另一半并查看错误是否仍然发生。然后,假设这是有效的,你发现它发生了哪一半,通过评论将其分成两半。重复这个过程,直到你找到仍然可以破坏的最小代码段。 (显然,由于代码依赖性,你可能并不总是能够做到一半,但是想办法将它打破,至少是大块)。

当你到达那里时,你可能会发现,通过检查,该代码中存在一个错误,因为根据我的经验,编译器崩溃更可能是由于错误形成的代码错误地形成的,编译器作者没想到。例如,我为工作编写的我自己的智能感知Java模块会在foo(super).bar上崩溃,因为我从来没有想过任何人不会在句号或开放状态下跟随超级但是它可能会因为如何语法设计。当你编写var x:int : 10;而不是var x:int = 10;时,Adobe的Actionscript编译器会崩溃(他们现在可能已经修复了,但是在我上次使用它时会崩溃)。因此,如果您确实在代码中发现了错误,请修复它。如果没有,只是尝试重写该代码,以便它不同。希望您能够找到一个不会导致编译器崩溃的版本。

答案 1 :(得分:2)

如果您可以在编译时让代码执行println ,我相信您可以立即缩小范围。那么为什么不做同等的事呢?

0.0.0                                 // Lexer will choke on this (I think)
val var;                              // Parser will choke on this
val Some(x) = None;                   // Second pass will, I think, choke on this
Option(2) match { case Some(x) => x } // Will emit warning in late phase and continue

您可以将这些代码放在代码中的各个位置作为测试,以查看编译器在阻塞之前获取的距离;这应该让你缩小到几行,评论/取消注释代码块可能更实用。

另外,当你遇到这样的事情时,确保你从头开始构建;编译器有时会在存在不兼容的版本时死亡,并且它无法识别它需要重新编译以获取更改。

答案 2 :(得分:1)

如果你一直在使用源代码控制并逐步工作(你已经一直在使用源代码控制并逐步工作,是吗?)那么你已经知道是什么导致了这个问题 - 这是你改变的最后一件事。因为你一直在增量工作,这将是一个很小的改变,因为你一直在使用源代码控制,你确切地知道它是什么,因为你已经掌握了你所做的一切的完整历史。

将此更改缩减为仍然可以再现问题的最小更改(最有可能通过使用二进制印章)。关于这种变化的东西将是“奇怪的”,这就是编译器的混乱。找到一种解决问题的方法,而不使用任何“奇怪”的东西,你已经得到了解决方法。

但在你这样做之前,请报告错误(编译器崩溃的任何场合肯定是一个错误),以及一个说明它的小例子。

如果你没有以增量方式工作并使用源代码管理,那么你就会有一个更乏味的任务:

  1. 首先,找出导致问题的文件(使用二进制文件缩小范围,直到找到单个文件)。
  2. 接下来,确定此文件的哪个位导致问题(再次使用二进制文件)。
  3. 保持二进制斩波,直到您完成单一,简单的更改。

答案 3 :(得分:1)

Scala trunk会打印更多信息,因此如果您可以使用trunk编译它以获得更好的错误消息,那么它会有所帮助。当然,主干可能没有这个bug,但值得一试。

如果使用trunk进行编译没有帮助,这就是我所知道的。这与getter和setter有关。从代码中,它可以是setter或getter。它似乎是在使用使用的getter或setter时调用的东西,未定义。你可以查一下。

另外,请注意getter和setter规则。 getter 必须至少具有与setter一样多的可见性(即,如果setter是公共的,则为public)。而且,由于我们在这里谈论编译器错误,我会避免奇怪的可见性(即,任何非公开或私有的),继承或混合可见性(例如,setter private和getter public)。

编辑:我刚刚注意到堆栈跟踪也提到了mixin。因此,它与一个getter或setter有关,它在一个特征中定义并在一个类上使用,或者在一个特征上使用。

编辑2:仍在调查中。你有懒惰的val的重载getter / setter,或者懒惰的val重载getter / setter吗?或者,只是懒惰的特征?我在痕迹的第三行看到了一些似乎指向懒惰的东西。

如果您确实找到了更多信息,请尝试重现一小部分内容,以便提交问题。