Scala SBT 编译挂起(SBT 1.5.0、Scala 2.13.5、Java 11.0.10)

Scala SBT compile hangs (SBT 1.5.0, Scala 2.13.5, Java 11.0.10)

在我的项目中,Scala/SBT 构建在 compile 步骤中无限挂起。重现:

git clone https://github.com/gdiet/backup.git
cd backup
# fist the good case - compiles in less than 30s (when dependencies are fetched etc. etc.)
git checkout e8bdc8a1e878bd15129f08b20df51d54ebd86e4a
sbt compile
# now the problem - compile hangs infinitely
git checkout b273a531c19ad68600026429643e13c6d2761c16
sbt compile

(抱歉,我无法创建最小的演示示例。)“​​干净”无济于事。我可以使用 SBT、IntelliJ IDEA 和 Docker 在我的 Linux 系统上重现该问题。对于 Docker、运行

# reproduce the problem in Docker - compile hangs infinitely
git checkout b273a531c19ad68600026429643e13c6d2761c16
./build-app.sh

问题:

  1. 如何确定这是一个 scalac 问题还是 SBT 问题,以便我可以打开一个错误?
  2. 如何获取有关构建挂起原因的更多信息,以便尝试避免该问题?

我怎样才能...? 我只需要将问题缩小到最小范围。这就是我到达那里的方式:

  • 找到一个最小 更改,其中编译之前工作,之后挂起。
  • 将问题代码隔离到单独的 scala class/object/project.
  • 检查是只有 sbt compile 挂起还是 scalac 也挂起(的确如此)。在后一种情况下 scalac 是罪魁祸首。
  • 至于避免问题:详细调查显示我使用了 Vector,而类型系统应该需要 LazyList。将其更改为 LazyList,一切都会按预期进行。 (请参阅下面的最小示例。)

我现在导致 scalac (scala 2.13.5) 挂起的最小示例是:

object CompileHangs {
  def read1(): LazyList[Either[(Int, Int), String]] = ???
  def read2(): Option[LazyList[Either[(Int, Int), String]]] = ???

  def read(): LazyList[Either[(Int, Int), String]] =
    read1().flatMap {
      case Right(_) => LazyList()
      case Left(value) =>
        read2().getOrElse(
          // LazyList instead of Vector would be the correct thing here.
          // Use it and everything works as expected.
          Vector(Left(value))
        )
    }
}

有趣的侧面观察:如果我将 Either[(Int, Int), String] 切换为 Either[Int, String],编译工作正常,即使使用 Vector,尽管我预计会出现类型检查错误。

我现在将为 scalac 创建错误报告。