Skip to content

Commit 5c93bdb

Browse files
committed
Java annotations should not extend scala.annotation.{ClassfileAnnotation,Annotation}
This compiler fiction isn't necessary to handle them as annotations and could lead to runtime crashes when upcasting an annotation value.
1 parent 569b3e3 commit 5c93bdb

File tree

13 files changed

+22
-14
lines changed

13 files changed

+22
-14
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,8 +968,8 @@ class Definitions {
968968
@tu lazy val Caps_unsafeBoxFunArg: Symbol = CapsUnsafeModule.requiredMethod("unsafeBoxFunArg")
969969

970970
// Annotation base classes
971+
@tu lazy val JavaAnnotationClass: ClassSymbol = requiredClass("java.lang.annotation.Annotation")
971972
@tu lazy val AnnotationClass: ClassSymbol = requiredClass("scala.annotation.Annotation")
972-
@tu lazy val ClassfileAnnotationClass: ClassSymbol = requiredClass("scala.annotation.ClassfileAnnotation")
973973
@tu lazy val StaticAnnotationClass: ClassSymbol = requiredClass("scala.annotation.StaticAnnotation")
974974
@tu lazy val RefiningAnnotationClass: ClassSymbol = requiredClass("scala.annotation.RefiningAnnotation")
975975

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ object StdNames {
243243
final val ToString: N = "ToString"
244244
final val Xor: N = "^"
245245

246-
final val ClassfileAnnotation: N = "ClassfileAnnotation"
247246
final val ClassManifest: N = "ClassManifest"
248247
final val Enum: N = "Enum"
249248
final val Group: N = "Group"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -808,7 +808,7 @@ object SymDenotations {
808808

809809
/** Is this a Scala or Java annotation ? */
810810
def isAnnotation(using Context): Boolean =
811-
isClass && derivesFrom(defn.AnnotationClass)
811+
isClass && (derivesFrom(defn.AnnotationClass) || derivesFrom(defn.JavaAnnotationClass))
812812

813813
/** Is this symbol a class that extends `java.io.Serializable` ? */
814814
def isSerializable(using Context): Boolean =

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class ClassfileParser(
167167
val superType =
168168
if (isAnnotation) {
169169
in.nextChar
170-
defn.AnnotationClass.typeRef
170+
defn.ObjectType
171171
}
172172
else if (classRoot.symbol == defn.ComparableClass ||
173173
classRoot.symbol == defn.JavaCloneableClass ||
@@ -186,7 +186,6 @@ class ClassfileParser(
186186
// Consequently, no best implicit for the "Integral" evidence parameter of "range"
187187
// is found. Previously, this worked because of weak conformance, which has been dropped.
188188

189-
if (isAnnotation) ifaces = defn.ClassfileAnnotationClass.typeRef :: ifaces
190189
superType :: ifaces
191190
}
192191

compiler/src/dotty/tools/dotc/parsing/JavaParsers.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -858,10 +858,9 @@ object JavaParsers {
858858
}
859859
(statics.toList, members.toList)
860860
}
861-
def annotationParents: List[Select] = List(
862-
scalaAnnotationDot(tpnme.Annotation),
863-
Select(javaLangDot(nme.annotation), tpnme.Annotation),
864-
scalaAnnotationDot(tpnme.ClassfileAnnotation)
861+
def annotationParents: List[Tree] = List(
862+
javaLangObject(),
863+
Select(javaLangDot(nme.annotation), tpnme.Annotation)
865864
)
866865
def annotationDecl(start: Offset, mods: Modifiers): List[Tree] = {
867866
accept(AT)

compiler/src/dotty/tools/dotc/transform/RepeatableAnnotations.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Symbols.defn
1010
import Constants._
1111
import Types._
1212
import Decorators._
13+
import Flags._
1314

1415
import scala.collection.mutable
1516

@@ -33,7 +34,7 @@ class RepeatableAnnotations extends MiniPhase:
3334
val annsByType = stableGroupBy(annotations, _.symbol)
3435
annsByType.flatMap {
3536
case (_, a :: Nil) => a :: Nil
36-
case (sym, anns) if sym.derivesFrom(defn.ClassfileAnnotationClass) =>
37+
case (sym, anns) if sym.is(JavaDefined) =>
3738
sym.getAnnotation(defn.JavaRepeatableAnnot).flatMap(_.argumentConstant(0)) match
3839
case Some(Constant(containerTpe: Type)) =>
3940
val clashingAnns = annsByType.getOrElse(containerTpe.classSymbol, Nil)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ trait Applications extends Compatibility {
547547

548548
/** Is `sym` a constructor of a Java-defined annotation? */
549549
def isJavaAnnotConstr(sym: Symbol): Boolean =
550-
sym.is(JavaDefined) && sym.isConstructor && sym.owner.derivesFrom(defn.AnnotationClass)
550+
sym.is(JavaDefined) && sym.isConstructor && sym.owner.derivesFrom(defn.JavaAnnotationClass)
551551

552552
/** Match re-ordered arguments against formal parameters
553553
* @param n The position of the first parameter in formals in `methType`.

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1619,7 +1619,7 @@ class Namer { typer: Typer =>
16191619
typedAhead(tree, typer.typedExpr(_, pt))
16201620

16211621
def typedAheadAnnotation(tree: Tree)(using Context): tpd.Tree =
1622-
typedAheadExpr(tree, defn.AnnotationClass.typeRef)
1622+
typedAheadExpr(tree, defn.AnnotationClass.typeRef | defn.JavaAnnotationClass.typeRef)
16231623

16241624
def typedAheadAnnotationClass(tree: Tree)(using Context): Symbol = tree match {
16251625
case Apply(fn, _) => typedAheadAnnotationClass(fn)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2259,7 +2259,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
22592259
}
22602260

22612261
def typedAnnotation(annot: untpd.Tree)(using Context): Tree =
2262-
checkAnnotArgs(typed(annot, defn.AnnotationClass.typeRef))
2262+
checkAnnotArgs(typed(annot, defn.AnnotationClass.typeRef | defn.JavaAnnotationClass.typeRef))
22632263

22642264
def registerNowarn(tree: Tree, mdef: untpd.Tree)(using Context): Unit =
22652265
val annot = Annotations.Annotation(tree)
@@ -2669,7 +2669,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
26692669
end typedPackageDef
26702670

26712671
def typedAnnotated(tree: untpd.Annotated, pt: Type)(using Context): Tree = {
2672-
val annot1 = typedExpr(tree.annot, defn.AnnotationClass.typeRef)
2672+
val annot1 = typedExpr(tree.annot, defn.AnnotationClass.typeRef | defn.JavaAnnotationClass.typeRef)
26732673
val annotCls = Annotations.annotClass(annot1)
26742674
if annotCls == defn.NowarnAnnot then
26752675
registerNowarn(annot1, tree)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface Ann_1 {
2+
int value();
3+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def test(x: Ann_1) =
2+
val y: scala.annotation.Annotation = x // error

tests/neg/java-ann-extends/Ann.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public @interface Ann {
2+
int value();
3+
}

tests/neg/java-ann-extends/Test.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def test(x: Ann) =
2+
val y: scala.annotation.Annotation = x // error

0 commit comments

Comments
 (0)