Skip to content

Compiler crash when using macro annotation with local class: "asTerm called on not-a-Term val <none>" #22908

@tschuchortdev

Description

@tschuchortdev

Compiler crashes when running a macro annotation on a local class. The same macro annotation works correctly with top-level classes.

Compiler version

3.6.2

Minimized code

import scala.annotation.{MacroAnnotation, experimental} import scala.quoted.{Expr, Quotes, Type} @experimental class backedByLazyVal extends MacroAnnotation { override def transform(using q: Quotes)(definition: q.reflect.Definition, companion: Option[q.reflect.Definition]): List[q.reflect.Definition] = { import q.reflect.{*, given} val defdef: DefDef = definition.asInstanceOf[DefDef] val lazyValSym = Symbol.newVal(parent = Symbol.spliceOwner, Symbol.freshName(defdef.name + "_lazyval"), defdef.returnTpt.tpe, Flags.Lazy | Flags.Private, privateWithin = Symbol.noSymbol) val lazyValDef = ValDef(lazyValSym, rhs = defdef.rhs.map(_.changeOwner(lazyValSym))) val redirectedDefDef = DefDef.copy(defdef)( name = defdef.name, paramss = defdef.paramss, tpt = defdef.tpt, rhs = Some( // This seems to be the problem Ref(lazyValSym).changeOwner(defdef.symbol)) ) List(lazyValDef, redirectedDefDef) } }

This test works:

import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers var executedCount = 0 class MacroTestClass { @backedByLazyVal def foo: Int = { println("executed") executedCount += 1 1234 } } class LazyValMacroTest extends AnyFlatSpec with Matchers { "LazyValMacro" should "run body only once" in { val c = new MacroTestClass assert(c.foo == 1234) assert(executedCount == 1) assert(c.foo == 1234) assert(executedCount == 1) } }

This test crashes the compiler:

import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers class LazyValMacroTest extends AnyFlatSpec with Matchers { "LazyValMacro" should "run body only once" in { var executedCount = 0 class MacroTestClass { @backedByLazyVal def foo: Int = { println("executed") executedCount += 1 1234 } } val c = new MacroTestClass assert(c.foo == 1234) assert(executedCount == 1) assert(c.foo == 1234) assert(executedCount == 1) } }

Output

[error] java.lang.AssertionError: assertion failed: asTerm called on not-a-Term val <none> [error] scala.runtime.Scala3RunTime$.assertFailed(Scala3RunTime.scala:8) [error] dotty.tools.dotc.core.Symbols$Symbol.asTerm(Symbols.scala:186) [error] dotty.tools.dotc.transform.ParamForwarding.transformIfParamAlias(ParamForwarding.scala:43) [error] dotty.tools.dotc.transform.ParamForwarding.transformValDef(ParamForwarding.scala:66) [error] dotty.tools.dotc.transform.MegaPhase.goValDef(MegaPhase.scala:1026) [error] dotty.tools.dotc.transform.MegaPhase.goValDef(MegaPhase.scala:1027) [error] dotty.tools.dotc.transform.MegaPhase.goValDef(MegaPhase.scala:1027) [error] dotty.tools.dotc.transform.MegaPhase.goValDef(MegaPhase.scala:1027) [error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:257) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452) [error] dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:376) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454) [error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:272) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452) [error] dotty.tools.dotc.transform.MegaPhase.loop$2(MegaPhase.scala:471) [error] dotty.tools.dotc.transform.MegaPhase.transformBlock(MegaPhase.scala:476) [error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:315) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454) [error] dotty.tools.dotc.transform.MegaPhase.mapDefDef$1(MegaPhase.scala:265) [error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:268) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452) [error] dotty.tools.dotc.transform.MegaPhase.loop$3(MegaPhase.scala:486) [error] dotty.tools.dotc.transform.MegaPhase.transformTrees(MegaPhase.scala:486) [error] dotty.tools.dotc.transform.MegaPhase.transformSpecificTrees(MegaPhase.scala:489) [error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:410) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454) [error] dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:376) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454) [error] dotty.tools.dotc.transform.MegaPhase.transformNamed$1(MegaPhase.scala:272) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:452) [error] dotty.tools.dotc.transform.MegaPhase.loop$1(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.transformStats(MegaPhase.scala:465) [error] dotty.tools.dotc.transform.MegaPhase.mapPackage$1(MegaPhase.scala:396) [error] dotty.tools.dotc.transform.MegaPhase.transformUnnamed$1(MegaPhase.scala:399) [error] dotty.tools.dotc.transform.MegaPhase.transformTree(MegaPhase.scala:454) [error] dotty.tools.dotc.transform.MegaPhase.transformUnit(MegaPhase.scala:481) [error] dotty.tools.dotc.transform.MegaPhase.run(MegaPhase.scala:493) [error] dotty.tools.dotc.core.Phases$Phase.runOn$$anonfun$1(Phases.scala:380) [error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15) [error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10) [error] scala.collection.immutable.List.foreach(List.scala:334) [error] dotty.tools.dotc.core.Phases$Phase.runOn(Phases.scala:373) [error] dotty.tools.dotc.Run.runPhases$1$$anonfun$1(Run.scala:343) [error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:15) [error] scala.runtime.function.JProcedure1.apply(JProcedure1.java:10) [error] scala.collection.ArrayOps$.foreach$extension(ArrayOps.scala:1323) [error] dotty.tools.dotc.Run.runPhases$1(Run.scala:336) [error] dotty.tools.dotc.Run.compileUnits$$anonfun$1(Run.scala:384) [error] dotty.tools.dotc.Run.compileUnits$$anonfun$adapted$1(Run.scala:396) [error] dotty.tools.dotc.util.Stats$.maybeMonitored(Stats.scala:69) [error] dotty.tools.dotc.Run.compileUnits(Run.scala:396) [error] dotty.tools.dotc.Run.compileSources(Run.scala:282) [error] dotty.tools.dotc.Run.compile(Run.scala:267) [error] dotty.tools.dotc.Driver.doCompile(Driver.scala:37) [error] dotty.tools.xsbt.CompilerBridgeDriver.run(CompilerBridgeDriver.java:141) [error] dotty.tools.xsbt.CompilerBridge.run(CompilerBridge.java:22) [error] sbt.internal.inc.AnalyzingCompiler.compile(AnalyzingCompiler.scala:91) [error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$7(MixedAnalyzingCompiler.scala:196) [error] scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:23) [error] sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:252) [error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4(MixedAnalyzingCompiler.scala:186) [error] sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compile$4$adapted(MixedAnalyzingCompiler.scala:166) [error] sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:241) [error] sbt.internal.inc.MixedAnalyzingCompiler.compileScala$1(MixedAnalyzingCompiler.scala:166) [error] sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:204) [error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:542) [error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:542) [error] sbt.internal.inc.Incremental$.$anonfun$apply$3(Incremental.scala:178) [error] sbt.internal.inc.Incremental$.$anonfun$apply$3$adapted(Incremental.scala:176) [error] sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:454) [error] sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:117) [error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56) [error] sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52) [error] sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:265) [error] sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:409) [error] sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:496) [error] sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:396) [error] sbt.internal.inc.Incremental$.apply(Incremental.scala:204) [error] sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:542) [error] sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:496) [error] sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332) [error] sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:433) [error] sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137) [error] sbt.Defaults$.compileIncrementalTaskImpl(Defaults.scala:2419) [error] sbt.Defaults$.$anonfun$compileIncrementalTask$2(Defaults.scala:2369) [error] sbt.internal.server.BspCompileTask$.$anonfun$compute$1(BspCompileTask.scala:41) [error] sbt.internal.io.Retry$.apply(Retry.scala:47) [error] sbt.internal.io.Retry$.apply(Retry.scala:29) [error] sbt.internal.io.Retry$.apply(Retry.scala:24) [error] sbt.internal.server.BspCompileTask$.compute(BspCompileTask.scala:41) [error] sbt.Defaults$.$anonfun$compileIncrementalTask$1(Defaults.scala:2367) [error] scala.Function1.$anonfun$compose$1(Function1.scala:49) [error] sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:63) [error] sbt.std.Transform$$anon$4.work(Transform.scala:69) [error] sbt.Execute.$anonfun$submit$2(Execute.scala:283) [error] sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:24) [error] sbt.Execute.work(Execute.scala:292) [error] sbt.Execute.$anonfun$submit$1(Execute.scala:283) [error] sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:265) [error] sbt.CompletionService$$anon$2.call(CompletionService.scala:65) [error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) [error] java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:572) [error] java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) [error] java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) [error] java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) 

Expectation

Macro annotation should work correctly even for local classes.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions