Search code examples
scalascala-macrosscala-3

Building Dynamic Expressions with Scala3 macro


In Scala2's macro, you could dynamically construct expressions by using Context.parse and so on.

  def generateExpr[T: c.WeakTypeTag](target: C#Symbol): C#Expr[T] = {
    if (target.isModule) {
      c.Expr[T](c.parse(target.fullName))
    } else {
      c.Expr[T] {
        c.parse(
          s"""new ${target.fullName}(${
            val a = target.asClass.primaryConstructor.asMethod
            val b = a.paramLists
            target.asClass.primaryConstructor.asMethod.paramLists
              .collect {
                case curry if !curry.exists(_.isImplicit) =>
                  curry.map { param => s"inject[${param.typeSignature.toString}]" }.mkString(",")
              }
              .mkString(")(")
          }) with MixIn"""
        )
      }
    }
  }

Even if the pre-composition syntax literal refers to a symbol that is not in the current classpath, the compilation will succeed if it can be resolved in the module that calls macro.

However, there is no such feature in the released Scala3.

My goal is to use

  1. to refer to a symbol that is not in the classpath of a module using macro.
  2. I want to use new $T(???) with Trait from the type information.

Are these no longer feasible?

=====

https://github.com/lampepfl/dotty/discussions/12590

As mentioned in this issue, the deployment of variable length parameters to Trees is also unknown. These will be relevant as dynamic AST construction.


Solution

  • Those are use cases that we explicitly did not want to support since they cause language fragmentation, with many possible dialects supported by macros. I am sure there are good use cases for this, but overall I believe allowing this would be detrimental to the language ecosystem as a whole.

    https://contributors.scala-lang.org/t/compatibility-required-for-migration-from-scala2-macro/5100/2?u=giiita