Skip to content

Commit

Permalink
Better error for Java annotation nested in a Scala ConstantAnnotation
Browse files Browse the repository at this point in the history
Java supports nested annotations as constant annotation arguments, but
Scala's ConstantAnnotation doesn't. Better error message for this case.
  • Loading branch information
lrytz committed Dec 17, 2020
1 parent e346b8c commit a6bf012
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 36 deletions.
4 changes: 2 additions & 2 deletions src/compiler/scala/tools/nsc/typechecker/Typers.scala
Expand Up @@ -3858,7 +3858,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
* Convert an annotation constructor call into an AnnotationInfo.
*/
@nowarn("cat=lint-nonlocal-return")
def typedAnnotation(ann: Tree, annotee: Option[Tree], mode: Mode = EXPRmode): AnnotationInfo = context.withinAnnotation {
def typedAnnotation(ann: Tree, annotee: Option[Tree], mode: Mode = EXPRmode): AnnotationInfo = {
var hasError: Boolean = false
var unmappable: Boolean = false
val pending = ListBuffer[AbsTypeError]()
Expand Down Expand Up @@ -3921,7 +3921,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
// begin typedAnnotation
val treeInfo.Applied(fun0, _, argss) = ann
if (fun0.isErroneous) return finish(ErroneousAnnotation)
val typedFun = typed(fun0, mode.forFunMode)
val typedFun = context.withinAnnotation(typed(fun0, mode.forFunMode))
if (typedFun.isErroneous) return finish(ErroneousAnnotation)

val Select(New(annTpt), _) = typedFun: @unchecked
Expand Down
44 changes: 29 additions & 15 deletions test/files/neg/annots-constant-neg.check
Expand Up @@ -43,54 +43,68 @@ Test.scala:40: error: annotation argument cannot be null
Test.scala:43: error: annotation argument needs to be a constant; found: java.lang.Integer.TYPE
@JAnn(value = 0, b = java.lang.Integer.TYPE) def t16 = 0 // err
^
Test.scala:47: error: annotation argument needs to be a constant; found: Test.this.nonConst
Test.scala:48: error: nested classfile annotations must be defined in java; found: inline
@JAnn(value = 0, c = Array(new inline)) def t18 = 0 // err
^
Test.scala:52: error: annotation argument needs to be a constant; found: Test.this.nonConst
@Ann(nonConst) def u3 = 0 // err
^
Test.scala:49: error: not enough arguments for constructor Ann: (value: Int, a: String, b: Class[_], c: Array[Object]): Ann.
Test.scala:54: error: not enough arguments for constructor Ann: (value: Int, a: String, b: Class[_], c: Array[Object]): Ann.
Unspecified value parameter value.
@Ann() def u4 = 0 // err
^
Test.scala:56: error: annotation argument cannot be null
Test.scala:61: error: annotation argument cannot be null
@Ann(value = 0, a = null) def u10 = 0 // err
^
Test.scala:57: error: annotation argument needs to be a constant; found: Test.this.getClass()
Test.scala:62: error: annotation argument needs to be a constant; found: Test.this.getClass()
@Ann(value = 0, b = getClass) def u11 = 0 // err
^
Test.scala:58: error: Array constants have to be specified using the `Array(...)` factory method
Test.scala:63: error: Array constants have to be specified using the `Array(...)` factory method
@Ann(value = 0, c = new Array(1)) def u12 = 0 // err
^
Test.scala:61: error: annotation argument needs to be a constant; found: java.lang.Integer.TYPE
Test.scala:66: error: annotation argument needs to be a constant; found: java.lang.Integer.TYPE
@Ann(value = 0, b = java.lang.Integer.TYPE) def u16 = 0 // err
^
Test.scala:66: error: multiple constructors for Ann1 with alternatives:
Test.scala:69: error: Java annotation SuppressWarnings is abstract; cannot be instantiated
Error occurred in an application involving default arguments.
@Ann(value = 0, c = Array(new SuppressWarnings(value = Array("")))) def u17 = 0 // err
^
Test.scala:69: error: not found: value value
Error occurred in an application involving default arguments.
@Ann(value = 0, c = Array(new SuppressWarnings(value = Array("")))) def u17 = 0 // err
^
Test.scala:71: error: annotation argument needs to be a constant; found: new scala.inline()
@Ann(value = 0, c = Array(new inline)) def u18 = 0 // err
^
Test.scala:76: error: multiple constructors for Ann1 with alternatives:
(s: String)Ann1 <and>
(value: Int)Ann1
cannot be invoked with (x: String)
@Ann1(x = "") def v4 = 0 // err
^
Test.scala:68: error: Ann1 does not take parameters
Test.scala:78: error: Ann1 does not take parameters
@Ann1(0)(0) def v6 = 0 // err
^
Test.scala:69: error: not enough arguments for constructor Ann2: (x: Int)(y: Int): Ann2.
Test.scala:79: error: not enough arguments for constructor Ann2: (x: Int)(y: Int): Ann2.
Unspecified value parameter x.
@Ann2 def v7 = 0 // err
^
Test.scala:70: error: missing argument list for constructor Ann2 in class Ann2
Test.scala:80: error: missing argument list for constructor Ann2 in class Ann2
@Ann2(x = 0) def v8 = 0 // err
^
Test.scala:73: error: no arguments allowed for nullary constructor Ann3: (): Ann3
Test.scala:83: error: no arguments allowed for nullary constructor Ann3: (): Ann3
@Ann3(0) def v11 = 0 // err
^
Test.scala:74: error: not enough arguments for constructor Ann4: (x: Int, value: Int): Ann4.
Test.scala:84: error: not enough arguments for constructor Ann4: (x: Int, value: Int): Ann4.
Unspecified value parameter value.
@Ann4(0) def v12 = 0
^
Test.scala:80: error: no arguments allowed for nullary constructor Ann5: (): Ann5
Test.scala:90: error: no arguments allowed for nullary constructor Ann5: (): Ann5
@Ann5(0) def v18 = 0 // err
^
Test.scala:71: warning: Implementation limitation: multiple argument lists on annotations are
Test.scala:81: warning: Implementation limitation: multiple argument lists on annotations are
currently not supported; ignoring arguments List(0)
@Ann2(x = 0)(y = 0) def v9 = 0 // warn
^
1 warning
28 errors
32 errors
10 changes: 10 additions & 0 deletions test/files/neg/annots-constant-neg/Test.scala
Expand Up @@ -42,6 +42,11 @@ object Test {
@JAnn(value = 0, b = classOf[Int]) def t15 = 0
@JAnn(value = 0, b = java.lang.Integer.TYPE) def t16 = 0 // err

// nested annotation is ok
@JAnn(value = 0, c = Array(new SuppressWarnings(value = Array("")))) def t17 = 0
// but the nested annotation needs to be itself a Java annotation
@JAnn(value = 0, c = Array(new inline)) def t18 = 0 // err

@Ann(1) def u1 = 0
@Ann(const) def u2 = 0
@Ann(nonConst) def u3 = 0 // err
Expand All @@ -60,6 +65,11 @@ object Test {
@Ann(value = 0, b = classOf[Int]) def u15 = 0
@Ann(value = 0, b = java.lang.Integer.TYPE) def u16 = 0 // err

// nested annotations are only allowed for Java annotations, not for Scala ConstantAnnotations
@Ann(value = 0, c = Array(new SuppressWarnings(value = Array("")))) def u17 = 0 // err
// the outer and the nested annotation need to be Java annotations
@Ann(value = 0, c = Array(new inline)) def u18 = 0 // err

@Ann1() def v1 = 0
@Ann1(0) def v2 = 0
@Ann1(value = 0) def v3 = 0
Expand Down
7 changes: 0 additions & 7 deletions test/files/neg/nested-annotation.check

This file was deleted.

12 changes: 0 additions & 12 deletions test/files/neg/nested-annotation.scala

This file was deleted.

0 comments on commit a6bf012

Please sign in to comment.