scala / bug

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

Can't find implicit delegating to another implicit via path-dependent type #12767

Open DmytroMitin opened 1 year ago

DmytroMitin commented 1 year ago

Reproduction steps

Scala version: 2.13.10

The code snippets 1-5 compile

  1. type parameter + type parameter
    
    trait TC1[T, S]
    object TC1 {
    implicit def mkTC1[T, S](implicit tc2: TC2[T, S]): TC1[T, S] = null
    }

trait TC2[T, S] object TC2 { implicit def mkTC2[T]: TC2[T, Int] = null }

implicitly[TC1[Boolean, Int]] // compiles

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw

2. type member + type parameter
```scala
trait TC1[T] {
  type S
}
object TC1 {
  type Aux[T, S0] = TC1[T] { type S = S0}
  implicit def mkTC1[T, S](implicit tc2: TC2[T, S]): TC1.Aux[T, S] = null 
}

trait TC2[T, S]
object TC2 {
  implicit def mkTC2[T]: TC2[T, Int] = null
}

implicitly[TC1.Aux[Boolean, Int]] // compiles

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw/1

  1. type member + type member + extra type parameter
    
    trait TC1[T] {
    type S
    }
    object TC1 {
    type Aux[T, S0] = TC1[T] { type S = S0}
    implicit def mkTC1[T, S](implicit tc2: TC2.Aux[T, S]): TC1.Aux[T, S] = null 
    }

trait TC2[T] { type S } object TC2 { type Aux[T, S0] = TC2[T] {type S = S0} implicit def mkTC2[T]: Aux[T, Int] = null }

implicitly[TC1.Aux[Boolean, Int]] // compiles

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw/2

4. type member + type member + path-dependent type
```scala
trait TC1[T] {
  type S
}
object TC1 {
  type Aux[T, S0] = TC1[T] { type S = S0}
  implicit def mkTC1[T](implicit tc2: TC2[T]): TC1.Aux[T, tc2.S] = null 
}

trait TC2[T] {
  type S
}
object TC2 {
  type Aux[T, S0] = TC2[T] {type S = S0}
  implicit def mkTC2[T]: Aux[T, Int] = null
}

implicitly[TC1.Aux[Boolean, Int]] // compiles

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw/3

  1. type parameter + type member + extra type parameter
    
    trait TC1[T, S]
    object TC1 {
    implicit def mkTC1[T, S](implicit tc2: TC2.Aux[T, S]): TC1[T, S] = null 
    }

trait TC2[T] { type S } object TC2 { type Aux[T, S0] = TC2[T] {type S = S0} implicit def mkTC2[T]: Aux[T, Int] = null }

implicitly[TC1[Boolean, Int]] // compiles

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw/4

But the following doesn't compile

6. type parameter + type member + path-dependent type
```scala
trait TC1[T, S]
object TC1 {
  implicit def mkTC1[T](implicit tc2: TC2[T]): TC1[T, tc2.S] = null 
}

trait TC2[T] {
  type S
}
object TC2 {
  type Aux[T, S0] = TC2[T] {type S = S0}
  implicit def mkTC2[T]: Aux[T, Int] = null
}

implicitly[TC1[Boolean, Int]] // doesn't compile

https://scastie.scala-lang.org/DmytroMitin/3Zni7OdnTRiafKeFLV4hIw/5

Problem

The code snippet no. 6 should compile too.

Or is it intended difference between type parameters and type members? (Functional dependencies?)

In Scala 3 all snippets compile including 6

  1. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw
  2. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw/1
  3. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw/2
  4. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw/3
  5. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw/4
  6. https://scastie.scala-lang.org/DmytroMitin/SK3wpTDTQa6qFmIGbaPSLw/5

Possibly related to https://github.com/lampepfl/dotty/issues/17212