Skip to content

Commit

Permalink
Discard the full annotation tree if a sub-tree is invalid
Browse files Browse the repository at this point in the history
  • Loading branch information
mbovel committed Nov 23, 2024
1 parent 040ec39 commit dd3b668
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 42 deletions.
74 changes: 36 additions & 38 deletions compiler/src/dotty/tools/dotc/typer/Checking.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions tests/neg/annot-invalid.check
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit dd3b668

Please sign in to comment.