diff --git a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala index 127300c6baa6..f21abf65b858 100644 --- a/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala +++ b/compiler/src/dotty/tools/dotc/transform/PCPCheckAndHeal.scala @@ -3,6 +3,7 @@ package transform import dotty.tools.dotc.ast.Trees._ import dotty.tools.dotc.ast.{TreeTypeMap, tpd, untpd} +import dotty.tools.dotc.core.Annotations.BodyAnnotation import dotty.tools.dotc.core.Constants._ import dotty.tools.dotc.core.Contexts._ import dotty.tools.dotc.core.Decorators._ @@ -23,6 +24,7 @@ import dotty.tools.dotc.typer.Inliner import scala.collection.mutable import dotty.tools.dotc.util.SourcePosition +import dotty.tools.dotc.util.Property import scala.annotation.constructorOnly @@ -33,20 +35,27 @@ import scala.annotation.constructorOnly class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(ictx) { import tpd._ + private val InAnnotation = Property.Key[Unit]() + override def transform(tree: Tree)(implicit ctx: Context): Tree = if (tree.source != ctx.source && tree.source.exists) transform(tree)(ctx.withSource(tree.source)) else tree match { case tree: DefDef if tree.symbol.is(Inline) && level > 0 => EmptyTree case tree: DefTree => - for (annot <- tree.symbol.annotations) - transform(annot.tree)(given ctx.withOwner(tree.symbol)) + lazy val annotCtx = ctx.fresh.setProperty(InAnnotation, true).withOwner(tree.symbol) + for (annot <- tree.symbol.annotations) annot match { + case annot: BodyAnnotation => annot // already checked in PrepareInlineable before the creation of the BodyAnnotation + case annot => transform(annot.tree)(given annotCtx) + } checkLevel(super.transform(tree)) case _ => checkLevel(super.transform(tree)) } /** Transform quoted trees while maintaining phase correctness */ override protected def transformQuotation(body: Tree, quote: Tree)(implicit ctx: Context): Tree = { + if (ctx.property(InAnnotation).isDefined) + ctx.error("Cannot have a quote in an annotation", quote.sourcePos) val body1 = transform(body)(quoteContext) super.transformQuotation(body1, quote) } diff --git a/tests/neg/i7121.scala b/tests/neg/i7121.scala new file mode 100644 index 000000000000..dc7dfcdb0f2f --- /dev/null +++ b/tests/neg/i7121.scala @@ -0,0 +1,13 @@ +import scala.quoted._ + +class annot1[T](x: Expr[T]) extends scala.annotation.Annotation +class annot2[T: Type](x: T) extends scala.annotation.Annotation + +class Test()(implicit qtx: QuoteContext) { + @annot1('{4}) // error + def foo(str: String) = () + + @annot2(4)(given '[Int]) // error + def foo2(str: String) = () + +}