Skip to content

Code spliced for handling default parameters mentions companion object, potentially doesn't have to? #113

Description

@neko-kai

Derivation in this code:

final case class RandomPayload(field1: String, randomArray: Set[Int] = List.fill(10)(Random.nextInt(10)).toSet)

object RandomPayload extends WithCirce[RandomPayload]

Will produce the following error:

super constructor cannot be passed a self reference unless parameter is declared by-name
[error]   object RandomPayload extends WithCirce[RandomPayload]
[error]                                ^

Where WithCirce is defined as:

import io.circe.{Decoder, Encoder, derivation}

import scala.language.experimental.macros
import scala.reflect.macros.blackbox

/**
 * Provides circe codecs for case classes and sealed traits
 * {{{
 *   final case class Abc(a: String, b: String, c: String)
 *
 *   object Abc extends WithCirce[Abc]
 * }}}
 */
abstract class WithCirce[A](implicit encoder: DerivationDerivedEncoder[A], decoder: DerivationDerivedDecoder[A]) {
  implicit val enc: Encoder.AsObject[A] = encoder.value
  implicit val dec: Decoder[A] = decoder.value
}

final class MaterializeDerivationMacros(override val c: blackbox.Context) extends derivation.DerivationMacros(c) {
  import c.universe._

  def materializeEncoderImpl[A: c.WeakTypeTag]: c.Expr[DerivationDerivedEncoder[A]] =
    c.Expr[DerivationDerivedEncoder[A]] {
      q"{ ${symbolOf[DerivationDerivedEncoder.type].asClass.module}.apply(${materializeEncoder[A]}) }"
    }

  def materializeDecoderImpl[A: c.WeakTypeTag]: c.Expr[DerivationDerivedDecoder[A]] =
    c.Expr[DerivationDerivedDecoder[A]] {
      q"{ ${symbolOf[DerivationDerivedDecoder.type].asClass.module}.apply(${materializeDecoder[A]}) }"
    }
}

final case class DerivationDerivedEncoder[A](value: Encoder.AsObject[A])
object DerivationDerivedEncoder {
  implicit def materialize[A]: DerivationDerivedEncoder[A] = macro MaterializeDerivationMacros.materializeEncoderImpl[A]
}

final case class DerivationDerivedDecoder[A](value: Decoder[A])
object DerivationDerivedDecoder {
  implicit def materialize[A]: DerivationDerivedDecoder[A] = macro MaterializeDerivationMacros.materializeDecoderImpl[A]
}

If the default parameter is removed, the error disappears:

final case class RandomPayload(field1: String, randomArray: Set[Int])
object RandomPayload extends WithCirce[RandomPayload]

This didn't happen in older versions of circe-derivation and indicates that the code for default value management is splicing additional references to the companion object – which I'm not sure are necessary for the use case, although I may be wrong.

/cc @aparo

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions