Macro & dotty: extract type in pattern match using quotes

I have the following code using pattern matching on Expr[...]:

  private def validateTransformations[T: Type](transformations: Seq[Expr[Transformer[_]]])(using Quotes): Seq[Either[String, MacroTransformer]] =
    transformations.map {
      case '{
        type u <: T
        Visit[`u`](
          $enter: `u` => VisitorCommand,
          $leave: `u` => VisitorCommand)
        } => Right(MacroVisit(u, enter, leave))
      case _ => Left("does not know")
    }

when Visit is defined as follow:

sealed trait Transformer[T]

case class Visit[T](
    enter: T => VisitorCommand,
    leave: T => VisitorCommand)
    extends Transformer[T]

The goal of this code is to parse the transformations given as arguments to the macro to save them on the following representation:

  sealed trait MacroTransformer
  case class MacroVisit[T](typ: Type[T], enter: Expr[T => VisitorCommand], leave: Expr[T => VisitorCommand]) extends MacroTransformer

The code is visible on macro-visit/VisitMacro.scala at scala_3 · sangria-graphql/macro-visit · GitHub

Extracting the $enter and $leave functions work.
But extracting the type 'u' does not. I’ve tried different syntaxes, like type $u <: T instead of type u <: T but scalac refuses this syntax:

[error] -- Error: /Users/yannsimon/projects/sangria/macro-visit/src/main/scala-3/sangria/visitor/VisitMacro.scala:101:13
[error] 101 |        type $u <: T
[error]     |        ^^^^^^^^^^^^
[error]     |Quoted pattern variable names starting with $ are not suported anymore.
[error]     |Use lower cases type pattern name instead.

I don’t know how pattern match & extract the type at the same time. Has someone an idea?

1 Like

Hi, all you need to do is call scala.quoted.Type.of[u] to get a quoted Type value from a type in scope

so assuming you have imported scala.quoted.Type (as shown by the context bound) you can do the following:

 private def validateTransformations[T: Type](transformations: Seq[Expr[Transformer[_]]])(using Quotes): Seq[Either[String, MacroTransformer]] =
    transformations.map {
      case '{
        type u <: T
        Visit[`u`](
          $enter: `u` => VisitorCommand,
          $leave: `u` => VisitorCommand)
-        } => Right(MacroVisit(u, enter, leave))
+        } => Right(MacroVisit(Type.of[u], enter, leave))
      case _ => Left("does not know")
    }
1 Like

Thanks a lot, it’s working!