@@ -1392,12 +1392,21 @@ trait Checking {
13921392 if ! Inlines .inInlineMethod && ! ctx.isInlineContext then
13931393 report.error(em " $what can only be used in an inline method " , pos)
13941394
1395+ def checkAnnot (tree : Tree )(using Context ): Tree =
1396+ tree match
1397+ case Ident (tpnme.BOUNDTYPE_ANNOT ) =>
1398+ // `FirstTransform.toTypeTree` creates `Annotated` nodes whose `annot` are
1399+ // `Ident`s, not annotation instances. See `tests/pos/annot-boundtype.scala`.
1400+ tree
1401+ case _ =>
1402+ checkAnnotTree(checkAnnotClass(tree))
1403+
13951404 /** Check that the class corresponding to this tree is either a Scala or Java annotation.
13961405 *
13971406 * @return The original tree or an error tree in case `tree` isn't a valid
13981407 * annotation or already an error tree.
13991408 */
1400- def checkAnnotClass (tree : Tree )(using Context ): Tree =
1409+ private def checkAnnotClass (tree : Tree )(using Context ): Tree =
14011410 if tree.tpe.isError then
14021411 return tree
14031412 val cls = Annotations .annotClass(tree)
@@ -1409,8 +1418,8 @@ trait Checking {
14091418 errorTree(tree, em " $cls is not a valid Scala annotation: it does not extend `scala.annotation.Annotation` " )
14101419 else tree
14111420
1412- /** Check arguments of compiler-defined annotations */
1413- def checkAnnotArgs (tree : Tree )(using Context ): tree. type =
1421+ /** Check arguments of annotations */
1422+ private def checkAnnotTree (tree : Tree )(using Context ): Tree =
14141423 val cls = Annotations .annotClass(tree)
14151424 tree match
14161425 case Apply (tycon, arg :: Nil ) if cls == defn.TargetNameAnnot =>
@@ -1424,8 +1433,57 @@ trait Checking {
14241433 arg.tpe.widenTermRefExpr.normalized match
14251434 case _ : ConstantType => ()
14261435 case _ => report.error(em " @ ${cls.name} requires constant expressions as a parameter " , arg.srcPos)
1427- case _ =>
1428- tree
1436+ case _ => ()
1437+
1438+ findInvalidAnnotSubTree(tree) match
1439+ case None => tree
1440+ case Some (invalidSubTree) =>
1441+ errorTree(
1442+ EmptyTree ,
1443+ em """ Expression cannot be used inside an annotation argument.
1444+ |Tree: ${invalidSubTree}
1445+ |Type: ${invalidSubTree.tpe}""" ,
1446+ invalidSubTree.srcPos
1447+ )
1448+
1449+ private def findInvalidAnnotSubTree (tree : Tree )(using Context ): Option [Tree ] =
1450+ type ValidAnnotTree =
1451+ Ident
1452+ | Select
1453+ | This
1454+ | Super
1455+ | Apply
1456+ | TypeApply
1457+ | Literal
1458+ | New
1459+ | Typed
1460+ | NamedArg
1461+ | Assign
1462+ | Block
1463+ | SeqLiteral
1464+ | Inlined
1465+ | Hole
1466+ | Annotated
1467+ | EmptyTree .type
1468+
1469+ val accumulator = new TreeAccumulator [Option [Tree ]]:
1470+ override def apply (acc : Option [Tree ], tree : Tree )(using Context ): Option [Tree ] =
1471+ if acc.isDefined then
1472+ acc
1473+ else
1474+ tree match
1475+ case tree if tree.isType => foldOver(acc, tree)
1476+ case closureDef(meth) =>
1477+ val paramsRes =
1478+ meth.paramss.foldLeft(acc): (acc : Option [Tree ], params : List [ValDef ] | List [TypeDef ]) =>
1479+ params.foldLeft(acc): (acc : Option [Tree ], param : ValDef | TypeDef ) =>
1480+ foldOver(acc, param)
1481+ foldOver(paramsRes, meth.rhs)
1482+ case tree : ValidAnnotTree => foldOver(acc, tree)
1483+ case _ => Some (tree)
1484+
1485+ accumulator(None , tree)
1486+
14291487
14301488 /** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases
14311489 * 2. Check that parameterised `enum` cases do not extend java.lang.Enum.
@@ -1674,7 +1732,7 @@ trait NoChecking extends ReChecking {
16741732 override def checkImplicitConversionDefOK (sym : Symbol )(using Context ): Unit = ()
16751733 override def checkImplicitConversionUseOK (tree : Tree , expected : Type )(using Context ): Unit = ()
16761734 override def checkFeasibleParent (tp : Type , pos : SrcPos , where : => String = " " )(using Context ): Type = tp
1677- override def checkAnnotArgs (tree : Tree )(using Context ): tree.type = tree
1735+ override def checkAnnot (tree : Tree )(using Context ): tree.type = tree
16781736 override def checkNoTargetNameConflict (stats : List [Tree ])(using Context ): Unit = ()
16791737 override def checkParentCall (call : Tree , caller : ClassSymbol )(using Context ): Unit = ()
16801738 override def checkSimpleKinded (tpt : Tree )(using Context ): Tree = tpt
0 commit comments