Skip to content

Commit c149aaf

Browse files
authored
Merge pull request #7495 from dotty-staging/java-annots-neg
Emit an error instead of crashing on incorrect Java annotation; support non-literal annot params with constant types
2 parents f44f09f + 5ba2e49 commit c149aaf

File tree

5 files changed

+37
-5
lines changed

5 files changed

+37
-5
lines changed

compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,11 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
240240
private def emitArgument(av: AnnotationVisitor,
241241
name: String,
242242
arg: Tree, bcodeStore: BCodeHelpers)(innerClasesStore: bcodeStore.BCInnerClassGen): Unit = {
243-
(normalizeArgument(arg): @unchecked) match {
243+
val narg = normalizeArgument(arg)
244+
// Transformation phases are not run on annotation trees, so we need to run
245+
// `constToLiteral` at this point.
246+
val t = constToLiteral(narg)(ctx.withPhase(ctx.erasurePhase))
247+
t match {
244248
case Literal(const @ Constant(_)) =>
245249
const.tag match {
246250
case BooleanTag | ByteTag | ShortTag | CharTag | IntTag | LongTag | FloatTag | DoubleTag => av.visit(name, const.value)
@@ -257,10 +261,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
257261
av.visit(name, t.args.head.tpe.classSymbol.denot.info.toTypeKind(bcodeStore)(innerClasesStore).toASMType)
258262
case Ident(nme.WILDCARD) =>
259263
// An underscore argument indicates that we want to use the default value for this parameter, so do not emit anything
260-
case t: tpd.RefTree =>
261-
assert(t.symbol.denot.owner.isAllOf(Flags.JavaEnumTrait),
262-
i"not an enum: $t / ${t.symbol} / ${t.symbol.denot.owner} / ${t.symbol.denot.owner.isTerm} / ${t.symbol.denot.owner.flagsString}")
263-
264+
case t: tpd.RefTree if t.symbol.denot.owner.isAllOf(Flags.JavaEnumTrait) =>
264265
val edesc = innerClasesStore.typeDescriptor(t.tpe.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the enumeration class.
265266
val evalue = t.symbol.name.mangledString // value the actual enumeration value.
266267
av.visitEnum(name, edesc, evalue)
@@ -306,6 +307,9 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
306307
val desc = innerClasesStore.typeDescriptor(typ.asInstanceOf[bcodeStore.int.Type]) // the class descriptor of the nested annotation class
307308
val nestedVisitor = av.visitAnnotation(name, desc)
308309
emitAssocs(nestedVisitor, assocs, bcodeStore)(innerClasesStore)
310+
311+
case t =>
312+
ctx.error(ex"Annotation argument is not a constant", t.sourcePos)
309313
}
310314
}
311315

tests/neg/java-annot/J.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import java.lang.annotation.*;
2+
3+
@Retention(RetentionPolicy.RUNTIME)
4+
public @interface J {
5+
String value();
6+
}

tests/neg/java-annot/S.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object C {
2+
val cs: String = "cs"
3+
}
4+
5+
object S {
6+
@J(C.cs) // error: Annotation argument is not a constant
7+
def f(): Int = 1
8+
}

tests/pos/java-annot/J.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import java.lang.annotation.*;
2+
3+
@Retention(RetentionPolicy.RUNTIME)
4+
public @interface J {
5+
String value();
6+
}

tests/pos/java-annot/S.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
object C {
2+
val cs: "cs" = "cs"
3+
}
4+
5+
object S {
6+
@J(C.cs) // OK: cs is a constant
7+
def f(): Int = 1
8+
}

0 commit comments

Comments
 (0)