从伴侣导入的类不可用作构造函数参数的默认值

Sum*_*uma 7 scala companion-object

考虑以下代码:

object Main extends App {
  object Project {
    case class Config(rules: Seq[String] = Seq.empty)
  }

  import Project._

  //case class Project(root: String, config: Config) // compiles fine

  //case class Project(root: String, config: Project.Config = Project.Config()) // compiles fine

  case class Project(root: String, config: Config = Config()) // error: not found: type Config

}
Run Code Online (Sandbox Code Playgroud)

为什么最后一个版本没有编译(与之相同Config = Config.apply())?

Mat*_*ler 2

我不清楚这是否是一个错误,但这就是它产生错误的原因:

考虑一下这个,它有效:

import Project._

object Project {
  case class Config()
}

case class Project(config: Config = Config())
Run Code Online (Sandbox Code Playgroud)

当您添加默认参数时,编译器会生成一个方法来计算该值。当该值是构造函数默认值时,该方法将添加到该类的伴随对象中。所以编译器会生成这个方法:

def <init>$default$1: Project.Config = Config() 
Run Code Online (Sandbox Code Playgroud)

它将被添加到您的Project对象中。

Scala 类型检查器生成一个Contexts. 每个上下文都有对其外部范围的上下文的引用。因此生成的方法获得一个上下文,并且该生成的方法的外部作用域是Project伴随对象。

当类型检查器尝试解析时,Config()它会遍历所有封闭的上下文并且无法找到Config(我不确定为什么,这可能是一个错误)。

Project._一旦它耗尽了上下文,它就会解析具有 import !的导入。类型检查器很高兴,因为它现在可以遍历导入并找到 apply 方法。

现在,当您将导入移动到下面时Project

object Project {
  case class Config()
}

import Project._

case class Project(config: Config = Config())
Run Code Online (Sandbox Code Playgroud)

在这种情况下,生成的方法可用的导入没有导入Project._(这也可能是一个错误),我假设是因为它位于生成的方法所在的对象定义下方。然后类型检查器会抛出错误,因为它找不到Config.

似乎发生的情况是,当类型检查器解析时,Config()它需要在伴生对象之上进行导入Project,因为它需要处理导入才能解析它,除非导入高于Project该导入,否则导入不在范围内。

对于那些希望进一步调试的人,请查看Contexts.lookupSymbol查找发生的位置