From dd3b668b8b9065fc9dd23f0c9df0631b6fd43d64 Mon Sep 17 00:00:00 2001 From: Matt Bovel Date: Sat, 23 Nov 2024 19:55:45 +0100 Subject: [PATCH] Discard the full annotation tree if a sub-tree is invalid --- .../src/dotty/tools/dotc/typer/Checking.scala | 74 +++++++++---------- tests/neg/annot-invalid.check | 8 +- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/typer/Checking.scala b/compiler/src/dotty/tools/dotc/typer/Checking.scala index 85ed864715e6..a6cd5f46eea7 100644 --- a/compiler/src/dotty/tools/dotc/typer/Checking.scala +++ b/compiler/src/dotty/tools/dotc/typer/Checking.scala @@ -1425,48 +1425,46 @@ trait Checking { report.error(em"@${cls.name} needs a string literal as argument", arg.srcPos) tree case _ => - checkAnnotTreeMap.transform(tree) - - private def checkAnnotTreeMap(using Context) = - new TreeMap: - override def transform(tree: Tree)(using Context): Tree = - tree match - case _ if tree.isType => - super.transform(tree) - case _: ( EmptyTree.type - | Ident - | Select - | This - | Super - | Apply - | TypeApply - | Literal - | New - | Typed - | NamedArg - | Assign - | Block - | If - | Closure - | Return - | SeqLiteral - | Inlined - | Quote - | Splice - | Hole - | ValDef - | DefDef - | Annotated) => - super.transform(tree) - case _ => + tree.find(!isValidAnnotSubtree(_)) match + case None => tree + case Some(invalidSubTree) => errorTree( EmptyTree, - em"""Implementation restriction: this tree cannot be used in an annotation. - |Tree: ${tree} - |Type: ${tree.tpe}""", - tree.srcPos + em"""Implementation restriction: expression cannot be used inside an annotation argument. + |Tree: ${invalidSubTree} + |Type: ${invalidSubTree.tpe}""", + invalidSubTree.srcPos ) + /** Returns `true` if this tree can appear inside an annotation argument. */ + private def isValidAnnotSubtree(subTree: Tree) = + subTree.isType || subTree.isInstanceOf[ + EmptyTree.type + | Ident + | Select + | This + | Super + | Apply + | TypeApply + | Literal + | New + | Typed + | NamedArg + | Assign + | Block + | If + | Closure + | Return + | SeqLiteral + | Inlined + | Quote + | Splice + | Hole + | ValDef + | DefDef + | Annotated + ] + /** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases * 2. Check that parameterised `enum` cases do not extend java.lang.Enum. * 3. Check that only a static `enum` base class can extend java.lang.Enum. diff --git a/tests/neg/annot-invalid.check b/tests/neg/annot-invalid.check index 09a29f1be6cb..8305f47a8c58 100644 --- a/tests/neg/annot-invalid.check +++ b/tests/neg/annot-invalid.check @@ -1,24 +1,24 @@ -- Error: tests/neg/annot-invalid.scala:4:21 --------------------------------------------------------------------------- 4 | val x1: Int @annot(new Object {}) = 0 // error | ^^^^^^^^^^^^^ - | Implementation restriction: this tree cannot be used in an annotation. + | Implementation restriction: expression cannot be used inside an annotation argument. | Tree: final class $anon() extends Object() {} | Type: Object {...} -- Error: tests/neg/annot-invalid.scala:5:28 --------------------------------------------------------------------------- 5 | val x2: Int @annot({class C}) = 0 // error | ^^^^^^^ - | Implementation restriction: this tree cannot be used in an annotation. + | Implementation restriction: expression cannot be used inside an annotation argument. | Tree: class C() extends Object() {} | Type: C -- Error: tests/neg/annot-invalid.scala:7:9 ---------------------------------------------------------------------------- 7 | @annot(new Object {}) val y1: Int = 0 // error | ^^^^^^^^^^^^^ - | Implementation restriction: this tree cannot be used in an annotation. + | Implementation restriction: expression cannot be used inside an annotation argument. | Tree: final class $anon() extends Object() {} | Type: Object {...} -- Error: tests/neg/annot-invalid.scala:8:16 --------------------------------------------------------------------------- 8 | @annot({class C}) val y2: Int = 0 // error | ^^^^^^^ - | Implementation restriction: this tree cannot be used in an annotation. + | Implementation restriction: expression cannot be used inside an annotation argument. | Tree: class C() extends Object() {} | Type: C