Skip to content

Commit 872459d

Browse files
committed
Allow New, Select, Block, ValDef, DefDef, Closure and EmptyTree
And use a TreeMap for the annotation check
1 parent d9ba132 commit 872459d

File tree

15 files changed

+129
-107
lines changed

15 files changed

+129
-107
lines changed

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,6 @@ class Definitions {
499499

500500
@tu lazy val DummyImplicitClass: ClassSymbol = requiredClass("scala.DummyImplicit")
501501

502-
@tu lazy val SymbolModule: Symbol = requiredModule("scala.Symbol")
503-
@tu lazy val JSSymbolModule: Symbol = requiredModule("scala.scalajs.js.Symbol")
504-
505502
@tu lazy val ScalaRuntimeModule: Symbol = requiredModule("scala.runtime.ScalaRunTime")
506503
def runtimeMethodRef(name: PreName): TermRef = ScalaRuntimeModule.requiredMethodRef(name)
507504
def ScalaRuntime_drop: Symbol = runtimeMethodRef(nme.drop).symbol

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

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,12 +1388,12 @@ trait Checking {
13881388

13891389
def checkAnnot(tree: Tree)(using Context): Tree =
13901390
tree match
1391-
case Ident(tpnme.BOUNDTYPE_ANNOT) =>
1391+
case Ident(tpnme.BOUNDTYPE_ANNOT) =>
13921392
// `FirstTransform.toTypeTree` creates `Annotated` nodes whose `annot` are
13931393
// `Ident`s, not annotation instances. See `tests/pos/annot-boundtype.scala`.
13941394
tree
1395-
case _ =>
1396-
checkAnnotArgs(checkAnnotClass(tree))
1395+
case _ =>
1396+
checkAnnotTree(checkAnnotClass(tree))
13971397

13981398
/** Check that the class corresponding to this tree is either a Scala or Java annotation.
13991399
*
@@ -1413,7 +1413,7 @@ trait Checking {
14131413
else tree
14141414

14151415
/** Check arguments of annotations */
1416-
private def checkAnnotArgs(tree: Tree)(using Context): Tree =
1416+
private def checkAnnotTree(tree: Tree)(using Context): Tree =
14171417
val cls = Annotations.annotClass(tree)
14181418
tree match
14191419
case Apply(tycon, arg :: Nil) if cls == defn.TargetNameAnnot =>
@@ -1424,40 +1424,43 @@ trait Checking {
14241424
case _ =>
14251425
report.error(em"@${cls.name} needs a string literal as argument", arg.srcPos)
14261426
tree
1427+
case _ if cls.isRetainsLike =>
1428+
tree
14271429
case _ =>
1428-
if cls.isRetainsLike then tree
1429-
else
1430-
tpd.allTermArguments(tree).foldLeft(tree: Tree)((acc: Tree, arg: Tree) =>
1431-
if validAnnotArg(arg) then acc
1432-
else errorTree(
1430+
checkAnnotTreeMap.transform(tree)
1431+
1432+
private def checkAnnotTreeMap(using Context) =
1433+
new TreeMap:
1434+
override def transform(tree: Tree)(using Context): Tree =
1435+
tree match
1436+
case _ if tree.isType =>
1437+
super.transform(tree)
1438+
case _: ( Literal
1439+
| Ident
1440+
| New
1441+
| Select
1442+
| Apply
1443+
| TypeApply
1444+
| SeqLiteral
1445+
| Typed
1446+
| Block
1447+
| ValDef
1448+
| DefDef
1449+
| Closure
1450+
| NamedArg
1451+
| EmptyTree.type
1452+
| Splice
1453+
| Hole) =>
1454+
super.transform(tree)
1455+
case _ =>
1456+
errorTree(
14331457
EmptyTree,
1434-
em"""Implementation restriction: not a valid annotation argument.
1435-
|Argument: $arg
1436-
|Type: ${arg.tpe}""",
1437-
arg.srcPos
1458+
em"""Implementation restriction: this tree cannot be used in an annotation.
1459+
|Tree: ${tree}
1460+
|Type: ${tree.tpe}""",
1461+
tree.srcPos
14381462
)
1439-
)
1440-
1441-
private def validAnnotArg(t: Tree)(using Context): Boolean =
1442-
t match
1443-
case _ if t.tpe.isEffectivelySingleton => true
1444-
case Literal(_) => true
1445-
// `Ident(nme.WILDCARD)` is used as placeholder for unspecified
1446-
// arguments of Java annotations. Example: tests/run/java-ann-super-class.
1447-
case Ident(nme.WILDCARD) => true
1448-
case Apply(fun, args) => validAnnotArg(fun) && args.forall(validAnnotArg)
1449-
case TypeApply(fun, args) => validAnnotArg(fun)
1450-
case SeqLiteral(elems, _) => elems.forall(validAnnotArg)
1451-
case Typed(expr, _) => validAnnotArg(expr)
1452-
// TODO(mbovel): should probably be handled by `tpd.allTermArguments` instead.
1453-
case NamedArg(_, arg) => validAnnotArg(arg)
1454-
// TODO(mbovel): do we really want to allow `Splice` and `Hole`?
1455-
// When removing those cases, tests/pos-macros/i7519b.scala and
1456-
// tests/pos-macros/i7052.scala fail.
1457-
case Splice(_) => true
1458-
case Hole(_, _, _, _) => true
1459-
case _ => false
1460-
1463+
14611464
/** 1. Check that all case classes that extend `scala.reflect.Enum` are `enum` cases
14621465
* 2. Check that parameterised `enum` cases do not extend java.lang.Enum.
14631466
* 3. Check that only a static `enum` base class can extend java.lang.Enum.

tests/neg/annot-invalid.check

Lines changed: 20 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,24 @@
11
-- Error: tests/neg/annot-invalid.scala:4:21 ---------------------------------------------------------------------------
22
4 | val x1: Int @annot(new Object {}) = 0 // error
33
| ^^^^^^^^^^^^^
4-
| Implementation restriction: not a valid annotation argument.
5-
| Argument: {
6-
| final class $anon() extends Object() {}
7-
| new $anon():Object
8-
| }
9-
| Type: Object
10-
-- Error: tests/neg/annot-invalid.scala:5:21 ---------------------------------------------------------------------------
11-
5 | val x2: Int @annot({val x = 1}) = 0 // error
12-
| ^^^^^^^^^^^
13-
| Implementation restriction: not a valid annotation argument.
14-
| Argument: {
15-
| val x: Int = 1
16-
| ()
17-
| }
18-
| Type: Unit
19-
-- Error: tests/neg/annot-invalid.scala:6:21 ---------------------------------------------------------------------------
20-
6 | val x3: Int @annot((x: Int) => x) = 0 // error
21-
| ^^^^^^^^^^^^^
22-
| Implementation restriction: not a valid annotation argument.
23-
| Argument: (x: Int) => x
24-
| Type: Int => Int
25-
-- Error: tests/neg/annot-invalid.scala:8:9 ----------------------------------------------------------------------------
26-
8 | @annot(new Object {}) val y1: Int = 0 // error
4+
| Implementation restriction: this tree cannot be used in an annotation.
5+
| Tree: final class $anon() extends Object() {}
6+
| Type: Object {...}
7+
-- Error: tests/neg/annot-invalid.scala:5:28 ---------------------------------------------------------------------------
8+
5 | val x2: Int @annot({class C}) = 0 // error
9+
| ^^^^^^^
10+
| Implementation restriction: this tree cannot be used in an annotation.
11+
| Tree: class C() extends Object() {}
12+
| Type: C
13+
-- Error: tests/neg/annot-invalid.scala:7:9 ----------------------------------------------------------------------------
14+
7 | @annot(new Object {}) val y1: Int = 0 // error
2715
| ^^^^^^^^^^^^^
28-
| Implementation restriction: not a valid annotation argument.
29-
| Argument: {
30-
| final class $anon() extends Object() {}
31-
| new $anon():Object
32-
| }
33-
| Type: Object
34-
-- Error: tests/neg/annot-invalid.scala:9:9 ----------------------------------------------------------------------------
35-
9 | @annot({val x = 1}) val y2: Int = 0 // error
36-
| ^^^^^^^^^^^
37-
| Implementation restriction: not a valid annotation argument.
38-
| Argument: {
39-
| val x: Int = 1
40-
| ()
41-
| }
42-
| Type: Unit
43-
-- Error: tests/neg/annot-invalid.scala:10:9 ---------------------------------------------------------------------------
44-
10 | @annot((x: Int) => x) val y3: Int = 0 // error
45-
| ^^^^^^^^^^^^^
46-
| Implementation restriction: not a valid annotation argument.
47-
| Argument: (x: Int) => x
48-
| Type: Int => Int
16+
| Implementation restriction: this tree cannot be used in an annotation.
17+
| Tree: final class $anon() extends Object() {}
18+
| Type: Object {...}
19+
-- Error: tests/neg/annot-invalid.scala:8:16 ---------------------------------------------------------------------------
20+
8 | @annot({class C}) val y2: Int = 0 // error
21+
| ^^^^^^^
22+
| Implementation restriction: this tree cannot be used in an annotation.
23+
| Tree: class C() extends Object() {}
24+
| Type: C

tests/neg/annot-invalid.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ class annot[T](arg: T) extends scala.annotation.Annotation
22

33
def main =
44
val x1: Int @annot(new Object {}) = 0 // error
5-
val x2: Int @annot({val x = 1}) = 0 // error
6-
val x3: Int @annot((x: Int) => x) = 0 // error
5+
val x2: Int @annot({class C}) = 0 // error
76

87
@annot(new Object {}) val y1: Int = 0 // error
9-
@annot({val x = 1}) val y2: Int = 0 // error
10-
@annot((x: Int) => x) val y3: Int = 0 // error
8+
@annot({class C}) val y2: Int = 0 // error
119

1210
()

tests/neg/i15054.scala

Lines changed: 0 additions & 15 deletions
This file was deleted.

tests/neg/i7740a.scala

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/neg/i7740b.scala

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/pos/annot-17939b.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import scala.annotation.Annotation
2+
class myRefined(f: ? => Boolean) extends Annotation
3+
4+
def test(axes: Int) = true
5+
6+
trait Tensor:
7+
def mean(axes: Int): Int @myRefined(_ => test(axes))
8+
9+
class TensorImpl() extends Tensor:
10+
def mean(axes: Int) = ???

tests/pos/annot-boundtype.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,3 @@ def f2(t: Tuple) =
1313
t match
1414
case _: (t *: ts) => ()
1515
case _ => ()
16-

tests/pos/annot-valid.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ def main =
44
val n: Int = 0
55
def f(x: Any): Unit = ()
66

7+
object O:
8+
def g(x: Any): Unit = ()
9+
710
val x1: Int @annot(42) = 0
811
val x2: Int @annot("hello") = 0
912
val x3: Int @annot(classOf[Int]) = 0
@@ -18,7 +21,12 @@ def main =
1821
val x12: Int @annot(f(2)) = 0
1922
val x13: Int @annot(throw new Error()) = 0
2023
val x14: Int @annot(42: Double) = 0
21-
24+
val x15: Int @annot(O.g(2)) = 0
25+
val x16: Int @annot({val y: Int = 2}) = 0
26+
val x17: Int @annot({def f = 2}) = 0
27+
val x18: Int @annot((x: Int) => x) = 0
28+
val x19: Int @annot(O.g) = 0
29+
2230
@annot(42) val y1: Int = 0
2331
@annot("hello") val y2: Int = 0
2432
@annot(classOf[Int]) val y3: Int = 0
@@ -33,5 +41,10 @@ def main =
3341
@annot(f(2)) val y12: Int = 0
3442
@annot(throw new Error()) val y13: Int = 0
3543
@annot(42: Double) val y14: Int = 0
44+
@annot(O.g(2)) val y15: Int = 0
45+
@annot({val y: Int = 2}) val y16: Int = 0
46+
@annot({def f = 2}) val y17: Int = 0
47+
@annot((x: Int) => x) val y18: Int = 0
48+
@annot(O.g) val y19: Int = 0
3649

3750
()

0 commit comments

Comments
 (0)