liufengyun / gestalt

gestalt : portable and solid macros for Scala
https://github.com/scalacenter/macros
31 stars 3 forks source link

support TypeTags #60

Open liufengyun opened 7 years ago

liufengyun commented 7 years ago

The Monadless library uses TypeTags:

trait Monadless[Monad[_]] {
  type M[T] = Monad[T]

  def lift[T](body: T)(implicit m: WeakTypeTag[Monad[_]]): Monad[T] = meta {  =>
    val tree = Transformer(toolbox)(body) // cannot access M, this.M doesn't help
    toolbox.traverse(tree) {
      case tree @ q"$pack.unlift[$t]($v)" =>
        toolbox.error("Unsupported unlift position", tree)
    }
    tree
  }
}

Following the extractor approach, TypeBags have to be platform-independent based on abstract types.

liufengyun commented 7 years ago

A simple solution to support TypeTags just for macros is as follows:

  1. implicit search of TypeTag arguments always succeed with dummy null
  2. macro transform don't change implicit parameter of type TypeTag to TermTree
  3. macro expansion creates an instance of TypeTag based on the type of the def macro and supplies to macro expansion.
xeno-by commented 7 years ago

In scala.reflect, typetags in macros are used for two task: 1) to obtain definition-site types instantiated with callsite knowledge, 2) to instantiate types via typeOf.

In the new macro system, both tasks are achieved by something else. 1) is covered by the fact that we can access types from the definition site inside meta blocks. 2) needs a different API (either termRef/typeRef/... or quasiquotes or something else like primitivizing typeOf).

Concretely, in this example, both M and Monad should be accessible inside the meta block by names M and Monad.

liufengyun commented 7 years ago

I've no idea how to make this work with separate compilation. It seems both M and Monad are inaccessible in the implementation method.

liufengyun commented 7 years ago

The following rule is disputable:

implicit search of TypeTag arguments always succeed with dummy null

It also makes writing macro helper non-standard: we cannot pass TypeTag as implicits!

liufengyun commented 7 years ago

A more correct approach is using the following rule:

liufengyun commented 7 years ago

The new rule is implemented in https://github.com/liufengyun/dotty/commit/5d7fa1f00ec47f77295c46ab44152fab5bc4a2f9, together with a small bug fix.

liufengyun commented 7 years ago

An even better rule is as follows:

This will reduce the unexpected behaviour to a minimum. For example, in a macro helper, programmers may accidentally forget to pass the implicit TypeTag around. In this case, an error message is more friendly than a run-time null pointer exception.