Skip to content

Commit d8cfc49

Browse files
mbovelKacperFKorban
andcommitted
Fix betasty unpickling error with invalid annotations
Throw away erroneous trees to avoid unpickling issues in best-effort mode. Co-Authored-By: Kacper Korban <[email protected]>
1 parent 3858eda commit d8cfc49

File tree

3 files changed

+38
-37
lines changed

3 files changed

+38
-37
lines changed

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1421,41 +1421,42 @@ trait Checking {
14211421
case Literal(_) => // ok
14221422
case _ =>
14231423
report.error(em"@${cls.name} needs a string literal as argument", arg.srcPos)
1424+
tree
14241425
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-
()
1426+
if cls.isRetainsLike then tree
14311427
else
1432-
tpd.allTermArguments(tree).foreach(checkAnnotArg)
1433-
tree
1434-
1435-
private def checkAnnotArg(tree: Tree)(using Context): Unit =
1436-
def valid(t: Tree): Boolean =
1437-
t match
1438-
case _ if t.tpe.isEffectivelySingleton => true
1439-
case Literal(_) => true
1440-
// `_` is used as placeholder for unspecified arguments of Java
1441-
// annotations. Example: tests/run/java-ann-super-class
1442-
case Ident(nme.WILDCARD) => true
1443-
case Apply(fun, args) => valid(fun) && args.forall(valid)
1444-
case TypeApply(fun, args) => valid(fun)
1445-
case SeqLiteral(elems, _) => elems.forall(valid)
1446-
case Typed(expr, _) => valid(expr)
1447-
case NamedArg(_, arg) => valid(arg)
1448-
case Splice(_) => true
1449-
case Hole(_, _, _, _) => true
1450-
case _ => false
1451-
if !valid(tree) then
1452-
report.error(
1453-
i"""Implementation restriction: not a valid annotation argument.
1454-
|Argument: $tree
1455-
|Type: ${tree.tpe}""",
1456-
tree.srcPos
1457-
)
1458-
1428+
tpd.allTermArguments(tree).foldLeft(tree: Tree)((acc: Tree, arg: Tree) =>
1429+
if validAnnotArg(arg) then acc
1430+
else errorTree(
1431+
EmptyTree,
1432+
em"""Implementation restriction: not a valid annotation argument.
1433+
|Argument: $arg
1434+
|Type: ${arg.tpe}""",
1435+
arg.srcPos
1436+
)
1437+
)
1438+
1439+
private def validAnnotArg(t: Tree)(using Context): Boolean =
1440+
t match
1441+
case _ if t.tpe.isEffectivelySingleton => true
1442+
case Literal(_) => true
1443+
// `Ident(nme.WILDCARD)` is used as placeholder for unspecified
1444+
// arguments of Java annotations. Example: tests/run/java-ann-super-class.
1445+
case Ident(nme.WILDCARD) => true
1446+
case Apply(fun, args) => validAnnotArg(fun) && args.forall(validAnnotArg)
1447+
case TypeApply(fun, args) => validAnnotArg(fun)
1448+
case SeqLiteral(elems, _) => elems.forall(validAnnotArg)
1449+
case Typed(expr, _) => validAnnotArg(expr)
1450+
// TODO(mbovel): should probably be handled by `tpd.allTermArguments` instead.
1451+
case NamedArg(_, arg) => validAnnotArg(arg)
1452+
// TODO(mbovel): we should probably not allow `Splice` and `Hole`.
1453+
// How to encode them as types?
1454+
// When removing those cases, tests/pos-macros/i7519b.scala and
1455+
// tests/pos-macros/i7052.scala fail.
1456+
case Splice(_) => true
1457+
case Hole(_, _, _, _) => true
1458+
case _ => false
1459+
14591460
/** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases
14601461
* 2. Check that parameterised `enum` cases do not extend java.lang.Enum.
14611462
* 3. Check that only a static `enum` base class can extend java.lang.Enum.

tests/neg/annot-invalid.check

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
| }
1818
| Type: Unit
1919
-- Error: tests/neg/annot-invalid.scala:6:21 ---------------------------------------------------------------------------
20-
6 | val x4: Int @annot((x: Int) => x) = 0 // error
20+
6 | val x3: Int @annot((x: Int) => x) = 0 // error
2121
| ^^^^^^^^^^^^^
2222
| Implementation restriction: not a valid annotation argument.
2323
| Argument: (x: Int) => x
@@ -41,7 +41,7 @@
4141
| }
4242
| Type: Unit
4343
-- Error: tests/neg/annot-invalid.scala:10:9 ---------------------------------------------------------------------------
44-
10 | @annot((x: Int) => x) val y4: Int = 0 // error
44+
10 | @annot((x: Int) => x) val y3: Int = 0 // error
4545
| ^^^^^^^^^^^^^
4646
| Implementation restriction: not a valid annotation argument.
4747
| Argument: (x: Int) => x

tests/neg/annot-invalid.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ class annot[T](arg: T) extends scala.annotation.Annotation
33
def main =
44
val x1: Int @annot(new Object {}) = 0 // error
55
val x2: Int @annot({val x = 1}) = 0 // error
6-
val x4: Int @annot((x: Int) => x) = 0 // error
6+
val x3: Int @annot((x: Int) => x) = 0 // error
77

88
@annot(new Object {}) val y1: Int = 0 // error
99
@annot({val x = 1}) val y2: Int = 0 // error
10-
@annot((x: Int) => x) val y4: Int = 0 // error
10+
@annot((x: Int) => x) val y3: Int = 0 // error
1111

1212
()

0 commit comments

Comments
 (0)