@@ -916,7 +916,6 @@ object Checking {
916916 annot
917917 case _ => annot
918918 end checkNamedArgumentForJavaAnnotation
919-
920919}
921920
922921trait Checking {
@@ -1387,12 +1386,21 @@ trait Checking {
13871386 if ! Inlines .inInlineMethod && ! ctx.isInlineContext then
13881387 report.error(em " $what can only be used in an inline method " , pos)
13891388
1389+ def checkAnnot (tree : Tree )(using Context ): Tree =
1390+ tree match
1391+ case Ident (tpnme.BOUNDTYPE_ANNOT ) =>
1392+ // `FirstTransform.toTypeTree` creates `Annotated` nodes whose `annot` are
1393+ // `Ident`s, not annotation instances. See `tests/pos/annot-boundtype.scala`.
1394+ tree
1395+ case _ =>
1396+ checkAnnotArgs(checkAnnotClass(tree))
1397+
13901398 /** Check that the class corresponding to this tree is either a Scala or Java annotation.
13911399 *
13921400 * @return The original tree or an error tree in case `tree` isn't a valid
13931401 * annotation or already an error tree.
13941402 */
1395- def checkAnnotClass (tree : Tree )(using Context ): Tree =
1403+ private def checkAnnotClass (tree : Tree )(using Context ): Tree =
13961404 if tree.tpe.isError then
13971405 return tree
13981406 val cls = Annotations .annotClass(tree)
@@ -1404,8 +1412,8 @@ trait Checking {
14041412 errorTree(tree, em " $cls is not a valid Scala annotation: it does not extend `scala.annotation.Annotation` " )
14051413 else tree
14061414
1407- /** Check arguments of compiler-defined annotations */
1408- def checkAnnotArgs (tree : Tree )(using Context ): tree. type =
1415+ /** Check arguments of annotations */
1416+ private def checkAnnotArgs (tree : Tree )(using Context ): Tree =
14091417 val cls = Annotations .annotClass(tree)
14101418 tree match
14111419 case Apply (tycon, arg :: Nil ) if cls == defn.TargetNameAnnot =>
@@ -1416,8 +1424,40 @@ trait Checking {
14161424 case _ =>
14171425 report.error(em " @ ${cls.name} needs a string literal as argument " , arg.srcPos)
14181426 case _ =>
1427+ if cls.isRetainsLike then () // Do not check @retain annotations
1428+ else if cls == defn.ThrowsAnnot then
1429+ // Do not check @throws annotations.
1430+ // TODO(mbovel): in tests/run/t6380.scala, an annotation tree is
1431+ // `new throws[Exception](throws.<init>[Exception])`. What is this?
1432+ ()
1433+ else
1434+ tpd.allTermArguments(tree).foreach(checkAnnotArg)
14191435 tree
14201436
1437+ private def checkAnnotArg (tree : Tree )(using Context ): Unit =
1438+ def valid (t : Tree ): Boolean =
1439+ t match
1440+ case _ if t.tpe.isEffectivelySingleton => true
1441+ case Literal (_) => true
1442+ // `_` is used as placeholder for unspecified arguments of Java
1443+ // annotations. Example: tests/run/java-ann-super-class
1444+ case Ident (nme.WILDCARD ) => true
1445+ case Apply (fun, args) => valid(fun) && args.forall(valid)
1446+ case TypeApply (fun, args) => valid(fun)
1447+ case SeqLiteral (elems, _) => elems.forall(valid)
1448+ case Typed (expr, _) => valid(expr)
1449+ case NamedArg (_, arg) => valid(arg)
1450+ case Splice (_) => true
1451+ case Hole (_, _, _, _) => true
1452+ case _ => false
1453+ if ! valid(tree) then
1454+ report.error(
1455+ i """ Implementation restriction: not a valid annotation argument.
1456+ |Argument: $tree
1457+ |Type: ${tree.tpe}""" ,
1458+ tree.srcPos
1459+ )
1460+
14211461 /** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases
14221462 * 2. Check that parameterised `enum` cases do not extend java.lang.Enum.
14231463 * 3. Check that only a static `enum` base class can extend java.lang.Enum.
@@ -1665,7 +1705,7 @@ trait NoChecking extends ReChecking {
16651705 override def checkImplicitConversionDefOK (sym : Symbol )(using Context ): Unit = ()
16661706 override def checkImplicitConversionUseOK (tree : Tree , expected : Type )(using Context ): Unit = ()
16671707 override def checkFeasibleParent (tp : Type , pos : SrcPos , where : => String = " " )(using Context ): Type = tp
1668- override def checkAnnotArgs (tree : Tree )(using Context ): tree.type = tree
1708+ override def checkAnnot (tree : Tree )(using Context ): tree.type = tree
16691709 override def checkNoTargetNameConflict (stats : List [Tree ])(using Context ): Unit = ()
16701710 override def checkParentCall (call : Tree , caller : ClassSymbol )(using Context ): Unit = ()
16711711 override def checkSimpleKinded (tpt : Tree )(using Context ): Tree = tpt
0 commit comments