@@ -914,7 +914,6 @@ object Checking {
914914 annot
915915 case _ => annot
916916 end checkNamedArgumentForJavaAnnotation
917-
918917}
919918
920919trait Checking {
@@ -1385,12 +1384,21 @@ trait Checking {
13851384 if ! Inlines .inInlineMethod && ! ctx.isInlineContext then
13861385 report.error(em " $what can only be used in an inline method " , pos)
13871386
1387+ def checkAnnot (tree : Tree )(using Context ): Tree =
1388+ tree match
1389+ case Ident (tpnme.BOUNDTYPE_ANNOT ) =>
1390+ // `FirstTransform.toTypeTree` creates `Annotated` nodes whose `annot` are
1391+ // `Ident`s, not annotation instances. See `tests/pos/annot-boundtype.scala`.
1392+ tree
1393+ case _ =>
1394+ checkAnnotArgs(checkAnnotClass(tree))
1395+
13881396 /** Check that the class corresponding to this tree is either a Scala or Java annotation.
13891397 *
13901398 * @return The original tree or an error tree in case `tree` isn't a valid
13911399 * annotation or already an error tree.
13921400 */
1393- def checkAnnotClass (tree : Tree )(using Context ): Tree =
1401+ private def checkAnnotClass (tree : Tree )(using Context ): Tree =
13941402 if tree.tpe.isError then
13951403 return tree
13961404 val cls = Annotations .annotClass(tree)
@@ -1402,8 +1410,8 @@ trait Checking {
14021410 errorTree(tree, em " $cls is not a valid Scala annotation: it does not extend `scala.annotation.Annotation` " )
14031411 else tree
14041412
1405- /** Check arguments of compiler-defined annotations */
1406- def checkAnnotArgs (tree : Tree )(using Context ): tree. type =
1413+ /** Check arguments of annotations */
1414+ private def checkAnnotArgs (tree : Tree )(using Context ): Tree =
14071415 val cls = Annotations .annotClass(tree)
14081416 tree match
14091417 case Apply (tycon, arg :: Nil ) if cls == defn.TargetNameAnnot =>
@@ -1414,8 +1422,61 @@ trait Checking {
14141422 case _ =>
14151423 report.error(em " @ ${cls.name} needs a string literal as argument " , arg.srcPos)
14161424 case _ =>
1425+ if cls.isRetainsLike then () // Do not check @retain annotations
1426+ else if cls == defn.ThrowsAnnot then
1427+ // Do not check @throws annotations.
1428+ // TODO(mbovel): in tests/run/t6380.scala, an annotation tree is
1429+ // `new throws[Exception](throws.<init>[Exception])`. What is this?
1430+ ()
1431+ else
1432+ tpd.allTermArguments(tree).foreach(checkAnnotArg)
14171433 tree
14181434
1435+ private def checkAnnotArg (tree : Tree )(using Context ): Unit =
1436+ def isTupleModule (sym : Symbol ): Boolean =
1437+ ctx.definitions.isTupleClass(sym.companionClass)
1438+
1439+ def isFunctionAllowed (t : Tree ): Boolean =
1440+ t match
1441+ case Select (qual, nme.apply) =>
1442+ qual.symbol == defn.ArrayModule
1443+ || qual.symbol == defn.ClassTagModule // class tags are used as arguments to Array.apply
1444+ || qual.symbol == defn.SymbolModule // used in Akka
1445+ || qual.symbol == defn.JSSymbolModule // used in Scala.js
1446+ || isTupleModule(qual.symbol)
1447+ case Select (New (clazz), nme.CONSTRUCTOR ) => clazz.symbol.isAnnotation
1448+ case Apply (fun, _) => isFunctionAllowed(fun)
1449+ case TypeApply (fun, _) => isFunctionAllowed(fun)
1450+ case _ => false
1451+
1452+ def valid (t : Tree ): Boolean =
1453+ t.tpe.isEffectivelySingleton
1454+ || (
1455+ t match
1456+ case Literal (_) => true
1457+ // `_` is used as placeholder for unspecified arguments of Java
1458+ // annotations. Example: tests/run/java-ann-super-class
1459+ case Ident (nme.WILDCARD ) => true
1460+ case Apply (fun, args) => isFunctionAllowed(fun) && args.forall(valid)
1461+ case TypeApply (fun, args) => isFunctionAllowed(fun)
1462+ // Support for `x.isInstanceOf[T]`. Probably not needed.
1463+ // case TypeApply(meth @ Select(arg, _), _) if meth.symbol == defn.Any_asInstanceOf => valid(arg)
1464+ case SeqLiteral (elems, _) => elems.forall(valid)
1465+ case Typed (expr, _) => valid(expr)
1466+ case NamedArg (_, arg) => valid(arg)
1467+ case Splice (_) => true
1468+ case Hole (_, _, _, _) => true
1469+ case _ => false
1470+ )
1471+
1472+ if ! valid(tree) then
1473+ report.error(
1474+ i """ Implementation restriction: not a valid annotation argument.
1475+ | Argument: $tree
1476+ | Type: ${tree.tpe}""" ,
1477+ tree.srcPos
1478+ )
1479+
14191480 /** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases
14201481 * 2. Check that parameterised `enum` cases do not extend java.lang.Enum.
14211482 * 3. Check that only a static `enum` base class can extend java.lang.Enum.
@@ -1663,7 +1724,7 @@ trait NoChecking extends ReChecking {
16631724 override def checkImplicitConversionDefOK (sym : Symbol )(using Context ): Unit = ()
16641725 override def checkImplicitConversionUseOK (tree : Tree , expected : Type )(using Context ): Unit = ()
16651726 override def checkFeasibleParent (tp : Type , pos : SrcPos , where : => String = " " )(using Context ): Type = tp
1666- override def checkAnnotArgs (tree : Tree )(using Context ): tree.type = tree
1727+ override def checkAnnot (tree : Tree )(using Context ): tree.type = tree
16671728 override def checkNoTargetNameConflict (stats : List [Tree ])(using Context ): Unit = ()
16681729 override def checkParentCall (call : Tree , caller : ClassSymbol )(using Context ): Unit = ()
16691730 override def checkSimpleKinded (tpt : Tree )(using Context ): Tree = tpt
0 commit comments