bug icon indicating copy to clipboard operation
bug copied to clipboard

Implicit resolution bug in scalac (working in dotty)

Open virusdave opened this issue 8 years ago • 5 comments

I didn't get an answer on the scala list, and don't see this particular case already on the bug tracker. Then again, i don't really understand why this isn't working, so i may have missed it.

Repro example showing the failure:

trait ShapeLevel
trait FlatShapeLevel extends ShapeLevel
trait ColumnsShapeLevel extends FlatShapeLevel

abstract class Shape[Level <: ShapeLevel, -Mixed_, Unpacked_, Packed_]
object Shape extends TupleShapeImplicits { }
trait TupleShapeImplicits {
  implicit final def tuple2Shape[Level <: ShapeLevel, M1,M2, U1,U2, P1,P2](
      implicit u1: Shape[_ <: Level, M1, U1, P1], 
               u2: Shape[_ <: Level, M2, U2, P2]): 
    Shape[Level, (M1,M2), (U1,U2), (P1,P2)] = ???
}

class Query[A, B] {
  def map[C, D](f: (A) => C)(implicit shape: Shape[_ <: FlatShapeLevel, C, D, _]) = ???
}


// This works, but is too restrictive on the `Level` of the implicit shape
def pairItGood[A, B](q: Query[A, B])(implicit shape: Shape[FlatShapeLevel, A, B, _]) =
  q.map(x => (x, x))

// This works, since i've given it the 'hint' to use the `tuple2Shape` (no-longer-)implicit def
def pairItHint[A, B](q: Query[A, B])(implicit shape: Shape[_ <: FlatShapeLevel, A, B, _]) = {
  implicit val hint = Shape.tuple2Shape(shape, shape)
  q.map(x => (x, x))
}

// This fails.  Why can't we find `tuple2Shape` in this case?  FAILS IN SCALAC, WORKS IN DOTTY!
def pairItBad[A, B](q: Query[A, B])(implicit shape: Shape[_ <: FlatShapeLevel, A, B, _]) =
  q.map(x => (x, x))

Scalac: https://scastie.scala-lang.org/2hFKFaBtSoiJuBDgt26vwA Dotty: https://scastie.scala-lang.org/TgdSZ64xS8e7Ta8HjzZyig

Scala-users thread: https://users.scala-lang.org/t/implicit-resolution-quirk/528/4

virusdave avatar Jul 20 '17 17:07 virusdave

Any thoughts on this?

virusdave avatar Aug 08 '17 19:08 virusdave

There are a lot of existential types in this example that make me feel uneasy (there's even a warning about them). Which naturally leads to the following definition that does work:

def pairItBad[L <: FlatShapeLevel, A, B, C](q: Query[A, B])(implicit shape: Shape[L, A, B, C]) =
    q.map(x => (x, x))

Note: Dotty doesn't have existential types (only wildcards).

joroKr21 avatar Jan 18 '18 00:01 joroKr21

@joroKr21 Has this issue between existential types and implicit search been reported in scala/bug before?

jvican avatar Feb 19 '18 10:02 jvican

I don't know. There are many issues about existential types. It's probably not so much the implicit search being involved, but rather type inference messing up with skolems and type variables.

joroKr21 avatar Feb 19 '18 14:02 joroKr21

Actually in this example implicit search does matter, because internally it uses an existential abstraction to find implicit candidates.

joroKr21 avatar Feb 19 '18 14:02 joroKr21