Scala 3 macros: code splitting / lookup type/term by name

Viewed 38

Suppose that you have some typeclass and Scala 3 macros to derive it's instances. Macro code is large and bulky, so you decide to split project into two modules - runtime (typeclass itself) and macro code (which isn't required on runtime).

The problem: to write case class ... derives TypeClass you need to have macros defined in runtime module. Compiler will call TypeClass.derived[T], you can't override that. You need to delegate that derivation somehow, without statically linking to macro module.

Possible solution:

  1. Define (in macro module):

    object DerivationMacros { 
      inline def derive[T]: TypeClass[T] = /* impl */
    }
    
  2. Define (in runtime module):

    object TypeClass {
      def derived[T]: TypeClass[T] = #{ DerivationMacros.derive[T] }
    }
    
    trait TypeClass[T] { /* impl */ }
    

    With #{ .. } denoting imaginary construct that generates it's contents on runtime.

The problem 2: you can't produce ASTs with statically unknown types. At least I didn't found a method to lookup term/type by name. To make this #{ .. } construct work, you need to statically link runtime module to macro module, defeating whole benefit. You need a way to produce that code using manually crafted AST, so that direct dependencies will be avoided.

The question is: either how to do original code splitting task, or how to lookup terms by names?

0 Answers
Related