scala3 icon indicating copy to clipboard operation
scala3 copied to clipboard

Refinements lost in inferred type

Open wz7982 opened this issue 1 year ago • 2 comments

Compiler version

3.4.0

Minimized code

import scala.deriving.Mirror

case class A(x: Int, y: String)

trait SomeTrait[T]

object SomeTrait:
    given [T]: SomeTrait[T] with {}

def f1[T](using p: Mirror.ProductOf[T]): Tuple.Elem[p.MirroredElemTypes, 0] = ???

def f2[T, R](f: T => R)(using SomeTrait[R]) = ???

// Scala3.3 is fine, 3.4 has compilation errors, p MirroredElemTypes type is missing and has been changed to Nothing
val x = f2(_ => f1[A])

Output

-- [E172] Type Error: ----------------------------------------------------------
13 |val x = f2(_ => f1[A])
   |                      ^
   |            No given instance of type SomeTrait[
   |              <error Match type reduction failed since selector Nothing
   |            matches none of the cases
   |
   |                case x *: xs => (0 : Int) match {
   |              case (0 : Int) => x
   |              case scala.compiletime.ops.int.S[n1] => Tuple.Elem[xs, n1]
   |            }>
   |              ] was found for parameter x$2 of method f2
1 error found

Expectation

The code is working properly

wz7982 avatar Feb 21 '24 05:02 wz7982

changing some definitions around, it seems like the refinements to the mirror are not being kept:

scala> case class A(x: Int, y: String)
     |
     | trait SomeTrait[T]
     |
     | object SomeTrait:
     |     given [T]: SomeTrait[T] with {}
     |
     | def f1[T](using p: Mirror.ProductOf[T]): p.type = p
     |
     | def f2[T, R](f: T => R)(using SomeTrait[R]): R = ???
     |
     | def x = f2(_ => f1[A])
// defined case class A
// defined trait SomeTrait
// defined object SomeTrait
def f1[T](using p: scala.deriving.Mirror.ProductOf[T]): p.type
def f2[T, R](f: T => R)(using x$2: SomeTrait[R]): R
def x: scala.deriving.Mirror.ProductOf[A]

bishabosha avatar Feb 21 '24 09:02 bishabosha

more verbosely:

scala -S 3 -Xprint:typer
Welcome to Scala 3.4.0 (21.0.1, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.

scala> import scala.deriving.Mirror
     |
     | case class A(x: Int, y: String)
     |
     | trait SomeTrait[T]
     |
     | object SomeTrait:
     |     given [T]: SomeTrait[T] with {}
     |
     | def f1[T](using p: Mirror.ProductOf[T]): p.type = p
     |
     | def f2[T, R](f: T => R)(using SomeTrait[R]): R = ???
     |
     | def x = f2(_ => f1[A])
[[syntax trees at end of                     typer]] // rs$line$1
package <empty> {
  final lazy module val rs$line$1: rs$line$1 = new rs$line$1()
  final module class rs$line$1() extends Object() { this: rs$line$1.type =>
    import scala.deriving.Mirror
    case class A(x: Int, y: String) extends Object(), _root_.scala.Product,
      _root_.scala.Serializable {
      val x: Int
      val y: String
      def copy(x: Int, y: String): A = new A(x, y)
      def copy$default$1: Int @uncheckedVariance = A.this.x
      def copy$default$2: String @uncheckedVariance = A.this.y
      def _1: Int = this.x
      def _2: String = this.y
    }
    final lazy module val A: A = new A()
    final module class A() extends AnyRef() { this: A.type =>
      def apply(x: Int, y: String): A = new A(x, y)
      def unapply(x$1: A): A = x$1
      override def toString: String = "A"
    }
    trait SomeTrait[T >: Nothing <: Any]() extends Object {
      T
    }
    final lazy module val SomeTrait: SomeTrait = new SomeTrait()
    final module class SomeTrait() extends Object() { this: SomeTrait.type =>
      given class given_SomeTrait_T[T >: Nothing <: Any]() extends Object(),
        SomeTrait[given_SomeTrait_T.this.T] {
        T
      }
      final given def given_SomeTrait_T[T >: Nothing <: Any]:
        SomeTrait.given_SomeTrait_T[T] = new SomeTrait.given_SomeTrait_T[T]()
    }
    def f1[T >: Nothing <: Any](using p: scala.deriving.Mirror.ProductOf[T]):
      p.type = p
    def f2[T >: Nothing <: Any, R >: Nothing <: Any](f: T => R)(using
      x$2: SomeTrait[R]): R = ???
    def x: scala.deriving.Mirror.ProductOf[A] =
      f2[Any, scala.deriving.Mirror.ProductOf[A]](
        {
          def $anonfun(_$1: Any): scala.deriving.Mirror.ProductOf[A] =
            f1[A](
              A.$asInstanceOf[

                  scala.deriving.Mirror.Product{
                    type MirroredMonoType = A; type MirroredType = A;
                      type MirroredLabel = ("A" : String);
                      type MirroredElemTypes = (Int, String);
                      type MirroredElemLabels = (("x" : String), ("y" : String))
                    }

              ]
            )
          closure($anonfun)
        }
      )(
        SomeTrait.given_SomeTrait_T[

            scala.deriving.Mirror.Product{
              type MirroredType = A; type MirroredMonoType = A;
                type MirroredElemTypes <: Tuple
            }

        ]
      )
  }
}

// defined case class A
// defined trait SomeTrait
// defined object SomeTrait
def f1[T](using p: scala.deriving.Mirror.ProductOf[T]): p.type
def f2[T, R](f: T => R)(using x$2: SomeTrait[R]): R
def x: scala.deriving.Mirror.ProductOf[A]

bishabosha avatar Feb 21 '24 09:02 bishabosha