Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

derivation: capturing mirror and nested compile-time summoning leads to ClassCastException at runtime #11542

Closed
jodersky opened this issue Feb 26, 2021 · 2 comments · Fixed by #12062

Comments

@jodersky
Copy link
Contributor

Compiler version

3.0.0-RC1

Minimized code

object demo {

  trait Reader[A]

  given Reader[Int] with {}

  inline def summonReader[T <: Tuple]: List[Reader[_]] = inline compiletime.erasedValue[T] match {
    case _: EmptyTuple => Nil
    case _: (t *: ts) => compiletime.summonInline[Reader[t]] :: summonReader[ts]
  }

  class CombinedReader[A](
    m: deriving.Mirror.ProductOf[A],
    childReaders: List[Reader[_]]
  ) extends Reader[A]

  inline given [A <: Tuple](using m: deriving.Mirror.ProductOf[A]): Reader[A] = {
    new CombinedReader(m, summonReader[m.MirroredElemTypes])
  }

}

@main def run() = {
  // OK
  //summon[demo.Reader[(Int, Int, Int)]]

  // Exception in thread "main" java.lang.ClassCastException: class main$package$$anon$2 cannot be cast to class scala.deriving.Mirror$Product (main$package$$anon$2 and scala.deriving.Mirror$Product are in unnamed module of loader 'app')
  //      at main$package$.run(main.scala:25)
  //      at run.main(main.scala:23)
  summon[demo.Reader[(Int, (Int, Int))]]
}

Output

The program compiles, but encounters a ClassCastException at runtime, as shown in the comment above.

Expectation

There should be no exception.

Notes

The class cast exception only happens if the mirror is captured and there is a nested summoning. If, for example, CombinedReader would not use take m or childReader arguments, the program works as expected.

@nicolasstucki
Copy link
Contributor

Minimized

type Foo = Tuple2[Int, Int]
// case class Foo(x: Int, y: Int) // works
class Reader(m: deriving.Mirror.ProductOf[Foo])
given reader1(using m: deriving.Mirror.ProductOf[Foo]): Reader = new Reader(m)
inline def summonReader(): Reader = compiletime.summonInline[Reader]
@main def run() = summonReader()

@odersky
Copy link
Contributor

odersky commented Apr 3, 2021

It works if summonReader is made transparent.

odersky added a commit to dotty-staging/dotty that referenced this issue Apr 12, 2021
Mirror support runs in PostTyper to add new members to mirrors generated
during Typer. But some anonymous mirrors are generated during inlining.
We need to add the missing methods for them as well.

Fixes scala#11542
Fixes scala#11961
Fixes scala#12052
odersky added a commit to dotty-staging/dotty that referenced this issue Apr 13, 2021
Mirror support runs in PostTyper to add new members to mirrors generated
during Typer. But some anonymous mirrors are generated during inlining.
We need to add the missing methods for them as well.

Fixes scala#11542
Fixes scala#11961
Fixes scala#12052
michelou pushed a commit to michelou/dotty that referenced this issue Apr 14, 2021
Mirror support runs in PostTyper to add new members to mirrors generated
during Typer. But some anonymous mirrors are generated during inlining.
We need to add the missing methods for them as well.

Fixes scala#11542
Fixes scala#11961
Fixes scala#12052
@Kordyjan Kordyjan added this to the 3.0.1 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants