使用名为"clone"的隐式类方法编译错误

Bri*_*ent 3 scala scala-2.11

尝试使用名为的方法创建隐式类时,我收到意外的编译错误(在 2.11.8中)clone.

以下简化用法:

class Foo(val bar: String)

object Foo {
  implicit class Enrich(foo: Foo) {
    def clone(x: Int, y: Int): Int = x + y
  }
}

object Main extends App {
  val foo = new Foo("hello")
  println(foo.clone(1, 2))    // <- does not compile
}
Run Code Online (Sandbox Code Playgroud)

生成以下错误:

无法在Foo中访问类Object中的方法clone不允许受保护的方法clone,因为前缀类型Foo不符合访问发生的对象Main

但是,我可以手动应用隐式类,并成功编译:

println(Foo.Enrich(foo).clone(1, 2))    // <- OK
Run Code Online (Sandbox Code Playgroud)

如果我将方法重命名为其他东西(clone2例如),则代码按预期编译.

我假设这与魔法有关java.lang.Cloneable,但该方法并不期望参数.

那么这里发生了什么?

Yuv*_*kov 5

这与事实Object(或AnyRef在Scala中)拥有一个受保护的方法有关 clone(),该方法优先于重载决策Foo.

SI-6760部分谈到了这个问题,虽然clone有相同的签名,但在这种情况下它是不同的.

这感觉就像一个bug(现在开放为SI-10206).当我们使用-Ytyper-debug扩展typer树时,您可以看到它找到了合适的候选者def clone(int, int),但是在随后的后续搜索中失败了:

|-- foo.clone(1, 2) : pt=Unit EXPRmode (site: method main in Main)
|    |    |    |    |-- foo.clone BYVALmode-EXPRmode-FUNmode-POLYmode (silent: method main in Main)
|    |    |    |    |    |-- foo EXPRmode-POLYmode-QUALmode (silent: method main in Main)
|    |    |    |    |    |    \-> foo.type (with underlying type my.awesome.pkg.Foo)
|    |    |    |    |    [search #1] start `my.awesome.pkg.Foo`, searching for adaptation to pt=foo.type => ?{def clone: ?} (silent: method main in Main) implicits disabled
|    |    |    |    |    |-- my.awesome.pkg.Foo.Enrich TYPEmode (site: method Enrich in Foo)
|    |    |    |    |    |    \-> my.awesome.pkg.Foo.Enrich
|    |    |    |    |    |-- Foo TYPEmode (site: value foo in Foo)
|    |    |    |    |    |    \-> my.awesome.pkg.Foo
|    |    |    |    |    |-- Int TYPEmode (site: method clone in Enrich)
|    |    |    |    |    |    \-> Int
|    |    |    |    |    |-- Int TYPEmode (site: value x in Enrich)
|    |    |    |    |    |    \-> Int
|    |    |    |    |    |-- Int TYPEmode (site: value y in Enrich)
|    |    |    |    |    |    \-> Int
|    |    |    |    |    [search #1] considering pkg.this.Foo.Enrich
|    |    |    |    |    |-- pkg.this.Foo.Enrich BYVALmode-EXPRmode-FUNmode-POLYmode (silent: method main in Main) implicits disabled
|    |    |    |    |    |    \-> (foo: my.awesome.pkg.Foo)my.awesome.pkg.Foo.Enrich
|    |    |    |    |    [search #1] success inferred value of type foo.type => ?{def clone: ?} is SearchResult(pkg.this.Foo.Enrich, )
|    |    |    |    |    [search #2] start `my.awesome.pkg.Foo`, searching for adaptation to pt=(=> foo.type) => ?{def clone: ?} (silent: method main in Main) implicits disabled
|    |    |    |    |    \-> <error>
Main.scala:6: error: method clone in class Object cannot be accessed in my.awesome.pkg.Foo
 Access to protected method clone not permitted because
 prefix type my.awesome.pkg.Foo does not conform to
 object Main in package pkg where the access take place
    foo.clone(1, 2) // <- does not compile
Run Code Online (Sandbox Code Playgroud)

编辑

这确实在2.10.6下编译