scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
231 stars 21 forks source link

Inner trait breaks implicit parameter (or some type inference problem with path-dependent type and singleton...) #7342

Open scabug opened 11 years ago

scabug commented 11 years ago
object Test {

  trait Foo

  trait TC[A]

  object TC {
    implicit def tc1[F <: Foo] = new TC[F] {}
    implicit def tc2[F1 <: Foo, F2 <: Foo] = new TC[(F1, F2)] {}
  }   

  object Bar {
    trait X
    val c = new Foo with X
    def bar[A](a: this.type => A)(implicit tc: TC[A]) = 1
  }

  Bar bar (_.c)

  Bar bar (b => (b.c, b.c))  // <- does not compile

  Bar bar (b => (b.c: Foo, b.c))
}

The next-to-last line does not compile due to implicit not being found. The last line compiles. It seems that the type of b.c is inferred to be Foo with b.X instead of Foo with Bar.X.

scabug commented 11 years ago

Imported From: https://issues.scala-lang.org/browse/SI-7342?orig=1 Reporter: Knut Arne Vedaa (kavedaa) Affected Versions: 2.10.1

scabug commented 8 years ago

@szeiger said: This looks like a problem with non-wildcard existentials. Simplified version without implicits:

trait Foo

trait TC[A]

class Bar {
  trait X
  val c = new Foo with X
}

object Test7342 {
  def tc2[F1 <: Foo, F2 <: Foo]: TC[(F1, F2)] = null

  def bar[A](a: Bar => A)(tc: TC[A]) = 1

  bar(b => (b.c, b.c))(tc2) // fails
  bar(b => (b.c: Foo, b.c))(tc2) // ok
}

A in bar is inferred from the first argument only, so it comes down to typechecking tc2 with the expected type. Minimized version:

trait TC[A] // works with +A

class Bar { trait X }

object Test7342 {
  def tc2[F1, F2]: TC[(F1, F2)] = null

  tc2: TC[(b.X forSome { val b: Bar }, b.X forSome { val b: Bar })] // ok
  tc2: TC[(b.X, b.X) forSome { val b: Bar }] // fails
}

IMHO this not a bug but a limitation of Scala's type system because there is no way to express a type application of tc2 with a common existential quantification over both type arguments.