Skip to content

Commit bc767cc

Browse files
committed
Require seeing ScalaSig before scanning for Scala pickling annotations
An alternative fix for #15166, which aligns with the behavior of the Scala 2 classfile parser. Before this commit, all classfiles, including those produced by the Java compiler and compilers of other JVM languages, were scanned for Scala pickling annotations. In certain situations (as in tests/pos/i15166), this is problematic, as the denotation of an annotation symbol defined as a Java inner class may be forced before the inner class table is populated and setClassInfo is called on the class root. We avoid this situation by only performing the pickling annotation scan for those classfiles having the `ScalaSig` attribute, i.e. those produced by the Scala 2 compiler. We also drop support for pickling TASTy using the classfile annotations `scala.annotation.internal.TASTYSignature` and `scala.annotation.internal.TASTYLongSignature`. These were never used by the compiler, there are no plans for future use, and preserving support would complicate this fix.
1 parent e4b1cfe commit bc767cc

File tree

4 files changed

+9
-15
lines changed

4 files changed

+9
-15
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,8 @@ class Definitions {
961961
@tu lazy val NativeAnnot: ClassSymbol = requiredClass("scala.native")
962962
@tu lazy val RepeatedAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Repeated")
963963
@tu lazy val SourceFileAnnot: ClassSymbol = requiredClass("scala.annotation.internal.SourceFile")
964+
@tu lazy val ScalaSignatureAnnot: ClassSymbol = requiredClass("scala.reflect.ScalaSignature")
965+
@tu lazy val ScalaLongSignatureAnnot: ClassSymbol = requiredClass("scala.reflect.ScalaLongSignature")
964966
@tu lazy val ScalaStrictFPAnnot: ClassSymbol = requiredClass("scala.annotation.strictfp")
965967
@tu lazy val ScalaStaticAnnot: ClassSymbol = requiredClass("scala.annotation.static")
966968
@tu lazy val SerialVersionUIDAnnot: ClassSymbol = requiredClass("scala.SerialVersionUID")

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

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,6 @@ object ClassfileParser {
5050
mapOver(tp)
5151
}
5252
}
53-
54-
private inline def sigOfClassName(n: String) = s"L$n;"
55-
val ScalaSignatureAnnot: String = sigOfClassName("scala.reflect.ScalaSignature")
56-
val ScalaLongSignatureAnnot: String = sigOfClassName("scala.reflect.ScalaLongSignature")
57-
val TASTYSignatureAnnot: String = sigOfClassName("scala.annotation.internal.TASTYSignature")
58-
val TASTYLongSignatureAnnot: String = sigOfClassName("scala.annotation.internal.TASTYLongSignature")
5953
}
6054

6155
class ClassfileParser(
@@ -876,7 +870,7 @@ class ClassfileParser(
876870

877871
/** Parse inner classes. Expects `in.bp` to point to the superclass entry.
878872
* Restores the old `bp`.
879-
* @return true iff classfile is from Scala, so no Java info needs to be read.
873+
* @return Some(unpickler) iff classfile is from Scala, so no Java info needs to be read.
880874
*/
881875
def unpickleOrParseInnerClasses()(using ctx: Context, in: DataReader): Option[Embedded] = {
882876
val oldbp = in.bp
@@ -1005,25 +999,21 @@ class ClassfileParser(
1005999
// attribute isn't, this classfile is a compilation artifact.
10061000
return Some(NoEmbedded)
10071001

1008-
if (scan(tpnme.RuntimeVisibleAnnotationATTR) || scan(tpnme.RuntimeInvisibleAnnotationATTR)) {
1002+
if (scan(tpnme.ScalaSignatureATTR) && scan(tpnme.RuntimeVisibleAnnotationATTR)) {
10091003
val attrLen = in.nextInt
10101004
val nAnnots = in.nextChar
10111005
var i = 0
10121006
while (i < nAnnots) {
1013-
val attrSig = pool.getExternalName(in.nextChar).value
1007+
val attrClass = pool.getType(in.nextChar).typeSymbol
10141008
val nArgs = in.nextChar
10151009
var j = 0
10161010
while (j < nArgs) {
10171011
val argName = pool.getName(in.nextChar)
10181012
if (argName.name == nme.bytes) {
1019-
if attrSig == ScalaSignatureAnnot then
1013+
if attrClass == defn.ScalaSignatureAnnot then
10201014
return unpickleScala(parseScalaSigBytes)
1021-
else if attrSig == ScalaLongSignatureAnnot then
1015+
else if attrClass == defn.ScalaLongSignatureAnnot then
10221016
return unpickleScala(parseScalaLongSigBytes)
1023-
else if attrSig == TASTYSignatureAnnot then
1024-
return unpickleTASTY(parseScalaSigBytes)
1025-
else if attrSig == TASTYLongSignatureAnnot then
1026-
return unpickleTASTY(parseScalaLongSigBytes)
10271017
}
10281018
parseAnnotArg(skip = true)
10291019
j += 1

library/src/scala/annotation/internal/TASTYLongSignature.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
@Retention(RetentionPolicy.RUNTIME)
99
@Target(ElementType.TYPE)
10+
@Deprecated
1011
public @interface TASTYLongSignature {
1112
public String[] bytes();
1213
}

library/src/scala/annotation/internal/TASTYSignature.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
@Retention(RetentionPolicy.RUNTIME)
99
@Target(ElementType.TYPE)
10+
@Deprecated
1011
public @interface TASTYSignature {
1112
public String bytes();
1213
}

0 commit comments

Comments
 (0)