All Downloads are FREE. Search and download functionalities are using the official Maven repository.

harness.deriving.IntersectionMirror.scala Maven / Gradle / Ivy

The newest version!
package harness.deriving

import scala.quoted.*

trait IntersectionMirror[A] {
  type ElementTypes <: Tuple
}
object IntersectionMirror {

  final class Impl[A, T <: Tuple] extends IntersectionMirror[A] {
    override type ElementTypes = T
  }

  transparent inline given derived[A]: IntersectionMirror[A] = ${ derivedImpl[A] }

  private def derivedImpl[A](using quotes: Quotes, tpe: Type[A]): Expr[IntersectionMirror[A]] = {
    import quotes.reflect.*

    type Elems <: Tuple

    @scala.annotation.nowarn
    def expandTypes(repr: TypeRepr): List[TypeRepr] =
      repr.dealias match {
        case AndType(left, right) => expandTypes(left) ::: expandTypes(right)
        case _                    => repr :: Nil
      }

    val tupleAppend = TypeRepr.of[? *: ?].asInstanceOf[AppliedType].tycon

    val expanded: List[TypeRepr] = expandTypes(TypeRepr.of[A])

    if (expanded.size < 2)
      report.errorAndAbort(s"Type ${TypeRepr.of[A].show} is not an intersection type")

    given Type[Elems] =
      expanded
        .foldRight(TypeRepr.of[EmptyTuple]) { case (t, acc) =>
          AppliedType(
            tupleAppend,
            List(t, acc),
          )
        }
        .asType
        .asInstanceOf[Type[Elems]]

    Apply(
      TypeApply(
        Select.unique(
          New(
            Applied(
              TypeTree.of[IntersectionMirror.Impl],
              List(
                TypeTree.of[A],
                TypeTree.of[Elems],
              ),
            ),
          ),
          "",
        ),
        List(
          TypeTree.of[A],
          TypeTree.of[Elems],
        ),
      ),
      Nil,
    ).asExprOf[IntersectionMirror[A]]
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy