summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@gmail.com>2016-10-26 17:21:02 +0200
committerLukas Rytz <lukas.rytz@gmail.com>2016-10-27 10:42:00 +0200
commit5751763261312bfadabb91b15b3ed826648023af (patch)
tree4191dce74832537fb22c17d295f800c5809d6d2b /src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
parent762bcdcd7fcdf75d7645b4d8a3d14a2d60ed1fd0 (diff)
downloadscala-5751763261312bfadabb91b15b3ed826648023af.tar.gz
scala-5751763261312bfadabb91b15b3ed826648023af.tar.bz2
scala-5751763261312bfadabb91b15b3ed826648023af.zip
Classfile parser and unpickler require class and module symbol arguments
In SymbolLoaders, when seeing a classfile `Foo.class`, we always (unconditionally) create 3 symbols: a class, a module and a module class. Some symbols get invalidated later (`.exists`). Until now, the classfile parser (and unpickler) received the "root" symbol as argument, which is the symbol whose type is being completed. This is either the class symbol or the module symbol. The classfile parser would then try to lookup the other symbol through `root.companionClass` or `root.companionModule`. Howver, this lookup can fail. One example is scala-dev#248: when a type alias (in a package object) shadows a class symbol, `companionClass` will fail. The implementations of the classfile parser / unpickler assume that both the `clazz` and the `staticModule` symbols are available. This change makes sure that they are always passed in explicitly. Before this patch, in the example of scala-dev#248, the `classRoot` of the unpickler was NoSymbol. This caused a bug when unpickling the module class symbol, causing a second module class symbol to be created mistakingly. The next commit cleans up this logic, more details there. This second symbol would then cause the crash in the backend because it doesn't have an `associatedFile`, therefore `isCoDefinedWith` would spuriously return `true`.
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala21
1 files changed, 9 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index e69c9f816a..6d5b697925 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -132,17 +132,12 @@ abstract class ClassfileParser {
finally loaders.parentsLevel -= 1
}
- def parse(file: AbstractFile, root: Symbol): Unit = {
- debuglog("[class] >> " + root.fullName)
-
+ def parse(file: AbstractFile, clazz: Symbol, module: Symbol): Unit = {
this.file = file
- pushBusy(root) {
+ pushBusy(clazz) {
this.in = new AbstractFileReader(file)
- this.clazz = if (root.isModule) root.companionClass else root
- // WARNING! do no use clazz.companionModule to find staticModule.
- // In a situation where root can be defined, but its companionClass not,
- // this would give incorrect results (see SI-5031 in separate compilation scenario)
- this.staticModule = if (root.isModule) root else root.companionModule
+ this.clazz = clazz
+ this.staticModule = module
this.isScala = false
parseHeader()
@@ -1020,7 +1015,6 @@ abstract class ClassfileParser {
def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile) {
def jflags = entry.jflags
- val completer = new loaders.ClassfileLoader(file)
val name = entry.originalName
val sflags = jflags.toScalaFlags
val owner = ownerForFlags(jflags)
@@ -1031,8 +1025,11 @@ abstract class ClassfileParser {
val (innerClass, innerModule) = if (file == NoAbstractFile) {
(newStub(name.toTypeName), newStub(name.toTermName))
} else {
- val cls = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer
- val mod = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer
+ val cls = owner.newClass(name.toTypeName, NoPosition, sflags)
+ val mod = owner.newModule(name.toTermName, NoPosition, sflags)
+ val completer = new loaders.ClassfileLoader(file, cls, mod)
+ cls setInfo completer
+ mod setInfo completer
mod.moduleClass setInfo loaders.moduleClassLoader
List(cls, mod.moduleClass) foreach (_.associatedFile = file)
(cls, mod)