Skip to content

Commit ae6e7c6

Browse files
committed
Fix scala#2809: Invalidate and unlink symbols for artifact classfiles
This is similar to scala/scala#5952, we do not need to parse artifact classfiles (that is, classfiles produced by scalac or dotty that do not contain pickling information), so we discard them as soon as possible. This fixes various IDE crashes when trying to complete packages such as "scala."
1 parent 0fd21c8 commit ae6e7c6

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import scala.util.control.NonFatal
1919
object ClassfileParser {
2020
/** Marker trait for unpicklers that can be embedded in classfiles. */
2121
trait Embedded
22+
23+
/** Indicate that there is nothing to unpickle and the corresponding symbols can
24+
* be invalidated. */
25+
object NoEmbedded extends Embedded
2226
}
2327

2428
class ClassfileParser(
@@ -147,6 +151,17 @@ class ClassfileParser(
147151

148152
setClassInfo(classRoot, classInfo)
149153
setClassInfo(moduleRoot, staticInfo)
154+
} else if (result == Some(NoEmbedded)) {
155+
val scope = classRoot.owner.unforcedDecls.openForMutations
156+
157+
for (sym <- List(moduleRoot.sourceModule.symbol, moduleRoot.symbol, classRoot.symbol)) {
158+
scope.unlink(sym)
159+
if (classRoot.owner == defn.ScalaShadowingPackageClass) {
160+
// Symbols in scalaShadowing are also added to scala
161+
defn.ScalaPackageClass.unforcedDecls.openForMutations.unlink(sym)
162+
}
163+
sym.markAbsent()
164+
}
150165
}
151166

152167
// eager load java enum definitions for exhaustivity check of pattern match
@@ -692,6 +707,10 @@ class ClassfileParser(
692707
}
693708
}
694709

710+
// Nothing$ and Null$ were incorrectly emitted with a Scala attribute
711+
// instead of ScalaSignature before 2.13.0-M2, see https://github.com/scala/scala/pull/5952
712+
private[this] val scalaUnpickleWhitelist = List(tpnme.nothingClass, tpnme.nullClass)
713+
695714
/** Parse inner classes. Expects `in.bp` to point to the superclass entry.
696715
* Restores the old `bp`.
697716
* @return true iff classfile is from Scala, so no Java info needs to be read.
@@ -752,6 +771,12 @@ class ClassfileParser(
752771
return unpickleTASTY(in.nextBytes(attrLen))
753772
}
754773

774+
if (scan(tpnme.ScalaATTR) && !scalaUnpickleWhitelist.contains(classRoot.name)) {
775+
// If the Scala attribute is present but the TASTY attribute isn't, this
776+
// classfile is a compilation artifact.
777+
return Some(NoEmbedded)
778+
}
779+
755780
if (scan(tpnme.RuntimeAnnotationATTR)) {
756781
val attrLen = in.nextInt
757782
val nAnnots = in.nextChar

0 commit comments

Comments
 (0)