@@ -19,6 +19,10 @@ import scala.util.control.NonFatal
19
19
object ClassfileParser {
20
20
/** Marker trait for unpicklers that can be embedded in classfiles. */
21
21
trait Embedded
22
+
23
+ /** Indicate that there is nothing to unpickle and the corresponding symbols can
24
+ * be invalidated. */
25
+ object NoEmbedded extends Embedded
22
26
}
23
27
24
28
class ClassfileParser (
@@ -147,6 +151,15 @@ class ClassfileParser(
147
151
148
152
setClassInfo(classRoot, classInfo)
149
153
setClassInfo(moduleRoot, staticInfo)
154
+ } else if (result == Some (NoEmbedded )) {
155
+ for (sym <- List (moduleRoot.sourceModule.symbol, moduleRoot.symbol, classRoot.symbol)) {
156
+ classRoot.owner.asClass.delete(sym)
157
+ if (classRoot.owner == defn.ScalaShadowingPackageClass ) {
158
+ // Symbols in scalaShadowing are also added to scala
159
+ defn.ScalaPackageClass .delete(sym)
160
+ }
161
+ sym.markAbsent()
162
+ }
150
163
}
151
164
152
165
// eager load java enum definitions for exhaustivity check of pattern match
@@ -700,6 +713,10 @@ class ClassfileParser(
700
713
}
701
714
}
702
715
716
+ // Nothing$ and Null$ were incorrectly emitted with a Scala attribute
717
+ // instead of ScalaSignature before 2.13.0-M2, see https://github.com/scala/scala/pull/5952
718
+ private [this ] val scalaUnpickleWhitelist = List (tpnme.nothingClass, tpnme.nullClass)
719
+
703
720
/** Parse inner classes. Expects `in.bp` to point to the superclass entry.
704
721
* Restores the old `bp`.
705
722
* @return true iff classfile is from Scala, so no Java info needs to be read.
@@ -760,6 +777,18 @@ class ClassfileParser(
760
777
return unpickleTASTY(in.nextBytes(attrLen))
761
778
}
762
779
780
+ if (scan(tpnme.ScalaATTR ) && ! scalaUnpickleWhitelist.contains(classRoot.name)) {
781
+ // To understand the situation, it's helpful to know that:
782
+ // - Scalac emits the `ScalaSig` attribute for classfiles with pickled information
783
+ // and the `Scala` attribute for everything else.
784
+ // - Dotty emits the `TASTY` attribute for classfiles with pickled information
785
+ // and the `Scala` attribute for _every_ classfile.
786
+ //
787
+ // Therefore, if the `Scala` attribute is present but the `TASTY`
788
+ // attribute isn't, this classfile is a compilation artifact.
789
+ return Some (NoEmbedded )
790
+ }
791
+
763
792
if (scan(tpnme.RuntimeAnnotationATTR )) {
764
793
val attrLen = in.nextInt
765
794
val nAnnots = in.nextChar
0 commit comments