Open OndrejSpanel opened 2 years ago
Ok, thank you for this report, @OndrejSpanel.
Can you show the V3
type, so that we can maybe construct a failing test?
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.
Ok, thank you. I'll look at this ASAP.
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
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...
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.
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.
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:
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.