简体   繁体   中英

Scala macro annotation typecheck for implicit class fails

Macro sample code:

package macros
import scala.reflect.macros.whitebox.Context
import scala.language.experimental.macros
import scala.annotation.StaticAnnotation
class Ant extends StaticAnnotation {
    def macroTransform(annottees: Any*): Unit = macro Ant.impl
}
object Ant {
    def impl(c: Context)(annottees: c.Tree*): c.Tree = {
        import c.universe._
        c.internal.enclosingOwner.asType.toType // this line is Ok
        // ! Any commented line below causes the same compilation error
        // c.internal.enclosingOwner.asType.toType.decls
        // c.mirror.staticClass(c.internal.enclosingOwner.fullName + ".A".toString)
        // c.typecheck(annottees.head)
        q"""implicit class A(val v: Int) extends AnyVal { def ask() = println("ok") }"""
    }
}

Changing whitebox.Context to macros.Context or blackbox.Context does not help. Changing arguments withImplicitViewsDisabled=true, or withMacrosDisabled=true has no effect.

Exec sample code:

package test
import macros.Ant
object Test extends App {
    val a = new A(42)
    a.ask() // Output should be "ok" (not 42)
    // ! removing [implicit] lets code be compiled
    @Ant implicit class A(v: Int) { def ask() = println(v)}
}

So, removing line c.typecheck(annottees.head) and / or word implicit in line @Ant implicit class A(v: Int) lets code be compiled. Otherwise compilation crashes with error:

Error:scalac:
no progress in completing object Test: <?>
while compiling: D:\Projects\_Schemee\TestMacro1\src\test\Test.scala
during phase: globalPhase=typer, enteringPhase=namer
library version: version 2.11.6
compiler version: version 2.11.6
reconstructed args: -nobootcp -classpath ...
last tree to typer: Ident(v)
tree position: <unknown>
tree tpe: Int
symbol: value v
symbol definition: v: Int (a TermSymbol)
symbol package: test
symbol owners: value v -> method A -> object Test
call site: method A in object Test in package test
<Cannot read source file>

Compiled under latest IntelliJ. With and without Sbt.

The question is: how to use typecheck in macro annotation with implicit classes? (or am i missing something?)

EDITED:

Besides that that error is caused when trying to access enclosingOwner declarations or mirror class A "manually".

Github link

Issue link

It looks like an sbt bug or interaction with compiler behavior.

The original exception:

java.lang.NullPointerException
    at xsbt.Dependency$ExtractDependenciesByMemberRefTraverser$$anonfun$1.isDefinedAt(Dependency.scala:142)

That location:

      val typeSymbolCollector = new CollectTypeTraverser({
        case tpe if !tpe.typeSymbol.isPackage => tpe.typeSymbol
      })

The traverser has a comment suggesting similar issues:

/*
 * Some macros appear to contain themselves as original tree.
 * We must check that we don't inspect the same tree over and over.
 * See https://issues.scala-lang.org/browse/SI-8486
 *     https://github.com/sbt/sbt/issues/1237
 *     https://github.com/sbt/sbt/issues/1544
 */

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM