同じ名前のメソッドを持つクラスに対するimplicit defを2つ定義してimportした場合のコンパイルエラーがScala2.9と2.10で異なる件

同じ名前のimplicit defを2つ定義してimportした場合の挙動がScala2.9と2.10で異なる件 - xuwei-k's blog」みて思い出したので確認してみた。

Scala 2.9.1 + scalaz 6.0.3で下のようなコードを書いてコンパイルすると "reassignment to val" エラーになる。

import scalaz._; import Scalaz._

object IsWriterMAOrMAB {
    def main(args: Array[String]) {
        writer("foo", 1) >>= (n => writer("bar", n))
    }
}
[error] /tmp/ScalaSample/src/main/scala/IsWriterMAOrMAB.scala:5: reassignment to val
[error]         writer("foo", 1) >>= (n => writer("bar", n))
[error]                          ^
[error] one error found
[error] {file:/tmp/ScalaSample/}root/compile:compile: Compilation failed

implicit conversionsの適用時に曖昧でエラーが出た後、メソッド名が「=」で終わっているので代入演算子として再解釈しようとして"reassignment to val"というエラーになる模様。

scalazを使わず再現するコードを書くとこんな感じ。

object AmbiguousImplicitsSample {
  implicit def foo(n: Int) = new {
    def #=(m: Int) = m == n  
  }
  implicit def bar(n: Int) = new {
    def #=(m: Int) = m == n  
  }

  def main(args: Array[String]) {
    val i = 1
    println(i #= 1)
  }
}

メソッド内の処理の内容は特に関係ないです。
Scala 2.9.1でコンパイルすると……

[error] /tmp/ScalaSample/src/main/scala/AmbiguousImplicitsSample.scala:11: reassignment to val
[error]     println(i #= 1)
[error]               ^
[error] one error found
[error] (compile:compile) Compilation failed

メソッド名を「eq」や「=#=」などに変えると、ちゃんと「曖昧なのでimplicit conversionsを適用しませんでした」エラーになる。

[error] /tmp/ScalaSample/src/main/scala/AmbiguousImplicitsSample.scala:11: type mismatch;
[error]  found   : i.type (with underlying type Int)
[error]  required: ?{val =#=(x$1: ?>: Int(1) <: Any): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method foo in object AmbiguousImplicitsSample of type (n: Int)java.lang.Object{def =#=(m: Int): Boolean}
[error]  and method bar in object AmbiguousImplicitsSample of type (n: Int)java.lang.Object{def =#=(m: Int): Boolean}
[error]  are possible conversion functions from i.type to ?{val =#=(x$1: ?>: Int(1) <: Any): ?}
[error]     println(i =#= 1)
[error]             ^
[error] one error found
[error] (compile:compile) Compilation failed

一方Scala 2.10.1でコンパイルすると……

[error] /tmp/ScalaSample/src/main/scala/AmbiguousImplicitsSample.scala:11: type mismatch;
[error]  found   : i.type (with underlying type Int)
[error]  required: ?{def #=(x$1: ? >: Int(1)): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method foo in object AmbiguousImplicitsSample of type (n: Int)AnyRef{def #=(m: Int): Boolean}
[error]  and method bar in object AmbiguousImplicitsSample of type (n: Int)AnyRef{def #=(m: Int): Boolean}
[error]  are possible conversion functions from i.type to ?{def #=(x$1: ? >: Int(1)): ?}
[error]     println(i #= 1)
[error]             ^
[error] /tmp/ScalaSample/src/main/scala/AmbiguousImplicitsSample.scala:11: value #= is not a member of Int
[error]     println(i #= 1)
[error]               ^
[error] two errors found
[error] (compile:compile) Compilation failed

implicit conversionsの適用時に曖昧でエラーが出た後、「=」で終わるメソッド名でも、代入演算子として再解釈せずにエラーになりコンパイルが停止する模様。
これは多分改善されているのだと思う。まあどっちにしてもコンパイルエラーなので特に困ることはないと思うけど。