Skip to content

Opaque type's type parameter widened causing implicit lookup failure #12950

Closed
@erikerlandson

Description

@erikerlandson

Compiler version

3.0.0

Minimized code

package repro
object repro:
    object opq:
        opaque type Lift[T] = Int
        extension(v: Int)
            def lift[T]: Lift[T] = v
        extension[T](l: Lift[T])
            def value: Int = l

    export opq.Lift as Lift
    export opq.lift as lift

    final type Two

    extension[TL](l: Lift[TL])
        def repro[TR](using m: Mul[TL, TR]): Int = l.value + m.value

    abstract class Mul[TL, TR]:
        val value: Int

    transparent inline given mulGivenInt[TL <: Int & Singleton, TR <: Int & Singleton]: Mul[TL, TR] =
        val m: Int = scala.compiletime.constValue[TL] * scala.compiletime.constValue[TR]
        new Mul[TL, TR] { val value: Int = m }

    transparent inline given mulGivenTwo[TR <: Int & Singleton]: Mul[Two, TR] =
        val m: Int = 2 * scala.compiletime.constValue[TR]
        new Mul[Two, TR] { val value: Int = m }

Output

scala> import repro.repro.{*, given}

// this works, using a type 'Two' that is not an integer literal
scala> val x = 1.lift[Two]
val x: repro.repro.opq.Lift[repro.repro.Two] = 1

scala> x.repro[2]
val res0: Int = 5

// this will fail for some reason
scala> val y = 1.lift[2]                                                                                                                                                             
val y: repro.repro.opq.Lift[2] = 1
scala> y.repro[2]
1 |y.repro[2]
  |          ^
  |no implicit argument of type repro.repro.Mul[Int, (2 : Int)] was found for parameter m of method repro in object repro.
  |I found:
  |
  |    repro.repro.mulGivenInt[(Int & Singleton), (Int & Singleton)]
  |
  |But given instance mulGivenInt in object repro does not match type repro.repro.Mul[Int, (2 : Int)].

Expectation

In the second example val y = 1.lift[2] I would expect that the integer literal type parameter not be widened to Int in the call to y.repro[2] - it should succeed and return 5, the same as with x.repro[2]

Instead the TL type parameter is being widened to Int: repro.repro.Mul[Int, (2 : Int)]

It seems to be specifically related to using opaque type - a more simple repro I attempted worked correctly, when the opaque type was not involved.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions