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

Exception when compiling with Scala 3 #585

Open
OndrejSpanel opened this issue Aug 31, 2022 · 7 comments
Open

Exception when compiling with Scala 3 #585

OndrejSpanel opened this issue Aug 31, 2022 · 7 comments

Comments

@OndrejSpanel
Copy link
Contributor

I have a quite large closed source project which I am gradually migrating to Scala 3. I get exception when compiling with Scala 3 with some of my decoders. The exception is:

Exception occurred while executing macro expansion.
java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$This cannot be cast to class dotty.tools.dotc.ast.Trees$RefTree (dotty.tools.dotc.ast.Trees$This and dotty.tools.dotc.ast.Trees$RefTree are in unnamed module of loader java.net.URLClassLoader @4c15b562)


    implicit val decoder: Decoder[V3] = deriveDecoder

I might be able to create a short repro later, but I am not sure if / when, as Scala 3 is not a priority task for me yet.

@sirthias
Copy link
Owner

Ok, thank you for this report, @OndrejSpanel.
Can you show the V3 type, so that we can maybe construct a failing test?

@OndrejSpanel
Copy link
Contributor Author

OndrejSpanel commented Aug 31, 2022

Sure. Actually it is quite simple:

  object V3 {
    implicit val encoder: Encoder[V3] = deriveEncoder
    implicit val decoder: Decoder[V3] = deriveDecoder
  }
  case class V3(x: Double, y: Double, z: Double)

Perhaps you may be interested in what follows, which is:

  implicit val vector3fEncoder: Encoder[Vector3f] = V3.encoder.contramap(v => V3(v.x, v.y, v.z))
  implicit val vector3fDecoder: Decoder[Vector3f] = V3.decoder.map(v => Vector3f(v.x, v.y, v.z))

Vector3f is an external class defined in a Scala library I have no control over.

All of this is defined inside of a trait, which is then derived to create an object used to access the types.

@sirthias
Copy link
Owner

Ok, thank you.
I'll look at this ASAP.

@OndrejSpanel
Copy link
Contributor Author

defined inside of a trait

This seems to be causing the issue. A small repro is:

import io.bullet.borer._
import io.bullet.borer.derivation.MapBasedCodecs._

trait Types {
  object V3 {
    implicit val encoder: Encoder[V3] = deriveEncoder
    implicit val decoder: Decoder[V3] = deriveDecoder
  }
  case class V3(x: Double, y: Double, z: Double)
}

See also https://scastie.scala-lang.org/SWN4jtpOQf6LxwTuAmZf9g

Exception occurred while executing macro expansion.
java.lang.ClassCastException: class dotty.tools.dotc.ast.Trees$This cannot be cast to class dotty.tools.dotc.ast.Trees$RefTree

@sirthias
Copy link
Owner

sirthias commented Sep 1, 2022

Ah, ok, thank you.
Constructs such as these often create problems, because of the extra references to the outer context object that case class (and the V3 objects) carry.
I'll look into it...

@OndrejSpanel
Copy link
Contributor Author

While it would be probably good to have it fixed, knowing the cause (outer class reference) is enough for me to restructure the code so that it no longer shows the issue.

@sirthias
Copy link
Owner

sirthias commented Dec 9, 2022

Just looked at this a bit.
It looks like a compiler problem since borer derivation doesn't manually manipulate trees anywhere.
Although admittedly a bit complex, the macros stay completely within the "safe space" of quotations and splices.

One thing I noticed: When you move the derivations out of the V3 object underneath the Types trait things compile normally. It looks like this object creates some trouble somewhere.

However, if I move the derivation code out of the trait completely like this:

    trait Types {
      case class V3(x: Double, y: Double, z: Double)
    }
    object Types extends Types

    implicit val encoder: Encoder[Types.V3] = MapBasedCodecs.deriveEncoder
    implicit val decoder: Decoder[Types.V3] = MapBasedCodecs.deriveDecoder

I get another problem:

Exception occurred while executing macro expansion.
java.lang.Exception: Expr cast exception: Types.this.V3.apply(x, `x₂`, `x₃`)
of type: Types.this.V3
did not conform to type: Types.V3

So, wrapper traits definitely cause pain at this point, which is why it's probably better to avoid them altogether.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants