Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler crash for a package object containing a class and companion #5954

Closed
scabug opened this issue Jun 19, 2012 · 19 comments · Fixed by scala/scala#9661
Closed

Compiler crash for a package object containing a class and companion #5954

scabug opened this issue Jun 19, 2012 · 19 comments · Fixed by scala/scala#9661

Comments

@scabug
Copy link

scabug commented Jun 19, 2012

When I compile the following compilation unit, the compiler crashes upon the third compilation. I do not delete the generated class files between the compiler runs.

package p {
  package object base {
    case class B()
  }
}

The first compiler run is fine, the second generates a message regarding a suppressed failed assert, and on the third run the compiler crashes.

% scalac -version
Scala compiler version 2.9.2 -- Copyright 2002-2011, LAMP/EPFL

% rm -r p
% scalac Test.scala
% scalac Test.scala
Suppressing failed assert: java.lang.AssertionError: assertion failed: List(obje
ct package$B, object package$B)

% scalac Test.scala
Suppressing failed assert: java.lang.AssertionError: assertion failed: List(obje
ct package$B, object package$B)
error: java.lang.AssertionError: assertion failed: List(object package$B, object
 package$B)
        at scala.tools.nsc.symtab.Symbols$Symbol.suchThat(Symbols.scala:1055)
        at scala.tools.nsc.symtab.Symbols$Symbol.companionModule0(Symbols.scala:
1317)
        at scala.tools.nsc.symtab.Symbols$Symbol.companionSymbol(Symbols.scala:1
338)
        at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.scalaSignatureAd
dingMarker(GenJVM.scala:236)
        at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.genClass(GenJVM.
scala:350)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJ
VM.scala:86)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJ
VM.scala:86)
        at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(Has
hMap.scala:104)
        at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(Has
hMap.scala:104)
        at scala.collection.Iterator$class.foreach(Iterator.scala:772)
        at scala.collection.mutable.HashTable$$anon$1.foreach(HashTable.scala:15
7)
        at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala
:190)
        at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:45)
        at scala.collection.mutable.HashMap$$anon$2.foreach(HashMap.scala:104)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase.run(GenJVM.scala:86)
        at scala.tools.nsc.Global$Run.compileSources(Global.scala:953)
        at scala.tools.nsc.Global$Run.compile(Global.scala:1041)
        at scala.tools.nsc.Main$.process(Main.scala:106)
        at scala.tools.nsc.Main$.main(Main.scala:123)
        at scala.tools.nsc.Main.main(Main.scala)

Exception in thread "main" java.lang.AssertionError: assertion failed: List(obje
ct package$B, object package$B)
        at scala.tools.nsc.symtab.Symbols$Symbol.suchThat(Symbols.scala:1055)
        at scala.tools.nsc.symtab.Symbols$Symbol.companionModule0(Symbols.scala:
1317)
        at scala.tools.nsc.symtab.Symbols$Symbol.companionSymbol(Symbols.scala:1
338)
        at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.scalaSignatureAd
dingMarker(GenJVM.scala:236)
        at scala.tools.nsc.backend.jvm.GenJVM$BytecodeGenerator.genClass(GenJVM.
scala:350)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJ
VM.scala:86)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase$$anonfun$run$4.apply(GenJ
VM.scala:86)
        at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(Has
hMap.scala:104)
        at scala.collection.mutable.HashMap$$anon$2$$anonfun$foreach$3.apply(Has
hMap.scala:104)
        at scala.collection.Iterator$class.foreach(Iterator.scala:772)
        at scala.collection.mutable.HashTable$$anon$1.foreach(HashTable.scala:15
7)
        at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala
:190)
        at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:45)
        at scala.collection.mutable.HashMap$$anon$2.foreach(HashMap.scala:104)
        at scala.tools.nsc.backend.jvm.GenJVM$JvmPhase.run(GenJVM.scala:86)
        at scala.tools.nsc.Global$Run.compileSources(Global.scala:953)
        at scala.tools.nsc.Global$Run.compile(Global.scala:1041)
        at scala.tools.nsc.Main$.process(Main.scala:106)
        at scala.tools.nsc.Main$.main(Main.scala:123)
        at scala.tools.nsc.Main.main(Main.scala)
@scabug
Copy link
Author

scabug commented Jun 19, 2012

Imported From: https://issues.scala-lang.org/browse/SI-5954?orig=1
Reporter: @dgruntz
Affected Versions: 2.9.2, 2.10.0-M3, 2.10.0-M4
See #2130, #3437, #4695, #7195

@scabug
Copy link
Author

scabug commented Dec 10, 2012

@JamesIry said:
Under 2.10.0 RC3 the crash happens on the second compile but is otherwise identical to the bug reported here.

@scabug
Copy link
Author

scabug commented Dec 10, 2012

@retronym said:
(possibly) related: #4695

@scabug
Copy link
Author

scabug commented Dec 11, 2012

@JamesIry said:
Minimized the crasher a bit more.

@scabug
Copy link
Author

scabug commented Dec 11, 2012

@JamesIry said (edited on Dec 11, 2012 7:20:57 PM UTC):
Also looks related #5957

@scabug
Copy link
Author

scabug commented Jan 9, 2013

@JamesIry said:
Historical notes of things somewhat related #2130,#3437. At some point case classes in package objects did not work at all. So they got disabled. But now they work. So they've been reenabled. Except they don't work on the second compile because we're getting this duplicated symbol nonsense.

@scabug
Copy link
Author

scabug commented Jan 9, 2013

@JamesIry said (edited on Jan 9, 2013 10:32:35 PM UTC):
Here's the simplest reproducer

package object base {
  class B
  object B
}

@scabug
Copy link
Author

scabug commented Jan 10, 2013

@JamesIry said:
Some in progress notes. I've renamed class and object 'B' to 'buhB' to make it easier to do a search using contains. That's important because some names change along the way. All the following results come from the same run, which is important as ids aren't stable from one run to the next.

On the second and subsequent compiles, early in the process, we get symbol package$buhB from its class file. Here it has id 6946

*** package$buhB#6946
java.lang.Exception: Stack trace
  at java.lang.Thread.dumpStack(Thread.java:1273)
  at scala.reflect.internal.Symbols$Symbol.<init>(Symbols.scala:144)
  at scala.reflect.internal.Symbols$TermSymbol.<init>(Symbols.scala:2380)
  at scala.reflect.internal.Symbols$ModuleSymbol.<init>(Symbols.scala:2550)
  at scala.reflect.internal.Symbols$Symbol.createModuleSymbol(Symbols.scala:1089)
  at scala.reflect.internal.Symbols$Symbol.newTermSymbol(Symbols.scala:1106)
  at scala.reflect.internal.Symbols$Symbol.newModuleSymbol(Symbols.scala:252)
  at scala.reflect.internal.Symbols$Symbol.newModule(Symbols.scala:235)
  at scala.tools.nsc.symtab.SymbolLoaders.enterModule(SymbolLoaders.scala:47)
  at scala.tools.nsc.symtab.SymbolLoaders.enterClassAndModule(SymbolLoaders.scala:98)
  at scala.tools.nsc.symtab.SymbolLoaders.initializeFromClassPath(SymbolLoaders.scala:138)
  at scala.tools.nsc.symtab.SymbolLoaders$PackageLoader$$anonfun$doComplete$3.apply(SymbolLoaders.scala:231)
  at scala.tools.nsc.symtab.SymbolLoaders$PackageLoader$$anonfun$doComplete$3.apply(SymbolLoaders.scala:230)
  at scala.collection.TraversableLike$WithFilter$$anonfun$foreach$1.apply(TraversableLike.scala:772)
  at scala.collection.Iterator$class.foreach(Iterator.scala:727)
  at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
  at scala.collection.IterableLike$class.foreach(IterableLike.scala:72)
  at scala.collection.AbstractIterable.foreach(Iterable.scala:54)
  at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:771)
  at scala.tools.nsc.symtab.SymbolLoaders$PackageLoader.doComplete(SymbolLoaders.scala:230)
  at scala.tools.nsc.symtab.SymbolLoaders$SymbolLoader.complete(SymbolLoaders.scala:187)
  at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1224)
  at scala.reflect.internal.Types$TypeRef.decls(Types.scala:2406)
  at scala.tools.nsc.typechecker.Namers$Namer.enterPackage(Namers.scala:612)
  at scala.tools.nsc.typechecker.Namers$Namer.dispatch$1(Namers.scala:219)
  at scala.tools.nsc.typechecker.Namers$Namer.liftedTree1$1(Namers.scala:234)
  at scala.tools.nsc.typechecker.Namers$Namer.enterSym(Namers.scala:234)
  at scala.tools.nsc.typechecker.Analyzer$namerFactory$$anon$1.apply(Analyzer.scala:42)
  at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:463)
  at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:430)
  at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:430)
  at scala.collection.Iterator$class.foreach(Iterator.scala:727)
  at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
  at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:430)
  ...

Somewhat later we get symbol buhB from Namer, here with id 7260.

*** buhB#7260
java.lang.Exception: Stack trace
	at java.lang.Thread.dumpStack(Thread.java:1273)
	at scala.reflect.internal.Symbols$Symbol.<init>(Symbols.scala:144)
	at scala.reflect.internal.Symbols$TermSymbol.<init>(Symbols.scala:2380)
	at scala.reflect.internal.Symbols$ModuleSymbol.<init>(Symbols.scala:2550)
	at scala.reflect.internal.Symbols$Symbol.createModuleSymbol(Symbols.scala:1089)
	at scala.reflect.internal.Symbols$Symbol.newTermSymbol(Symbols.scala:1106)
	at scala.reflect.internal.Symbols$Symbol.newModuleSymbol(Symbols.scala:252)
	at scala.reflect.internal.Symbols$Symbol.newModule(Symbols.scala:235)
	at scala.tools.nsc.typechecker.Namers$Namer.createMemberSymbol(Namers.scala:289)
	at scala.tools.nsc.typechecker.Namers$Namer.assignSymbol(Namers.scala:249)
	at scala.tools.nsc.typechecker.Namers$Namer.assignAndEnterSymbol(Namers.scala:252)
	at scala.tools.nsc.typechecker.Namers$Namer.enterModuleSymbol(Namers.scala:411)
	at scala.tools.nsc.typechecker.Namers$Namer.enterModuleDef(Namers.scala:390)
	at scala.tools.nsc.typechecker.Namers$Namer.dispatch$1(Namers.scala:221)
	at scala.tools.nsc.typechecker.Namers$Namer.liftedTree1$1(Namers.scala:234)
	at scala.tools.nsc.typechecker.Namers$Namer.enterSym(Namers.scala:234)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$enterSyms$1.apply(Namers.scala:425)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$enterSyms$1.apply(Namers.scala:424)
	at scala.collection.LinearSeqOptimized$class.foldLeft(LinearSeqOptimized.scala:111)
	at scala.collection.immutable.List.foldLeft(List.scala:78)
	at scala.tools.nsc.typechecker.Namers$Namer.enterSyms(Namers.scala:424)
	at scala.tools.nsc.typechecker.Namers$Namer.templateSig(Namers.scala:860)
	at scala.tools.nsc.typechecker.Namers$Namer.getSig$1(Namers.scala:1298)
	at scala.tools.nsc.typechecker.Namers$Namer.typeSig(Namers.scala:1345)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply$mcV$sp(Namers.scala:707)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:706)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1$$anonfun$apply$1.apply(Namers.scala:706)
	at scala.tools.nsc.typechecker.Namers$Namer$LogTransitions.apply(Namers.scala:1374)
	at scala.tools.nsc.typechecker.Namers$Namer.scala$tools$nsc$typechecker$Namers$Namer$$logAndValidate(Namers.scala:1383)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:706)
	at scala.tools.nsc.typechecker.Namers$Namer$$anonfun$monoTypeCompleter$1.apply(Namers.scala:705)
	at scala.tools.nsc.typechecker.Namers$$anon$1.completeImpl(Namers.scala:1498)
	at scala.tools.nsc.typechecker.Namers$LockingTypeCompleter$class.complete(Namers.scala:1506)
	at scala.tools.nsc.typechecker.Namers$$anon$1.complete(Namers.scala:1496)
	at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1224)
	at scala.reflect.internal.SymbolTable.openPackageModule(SymbolTable.scala:244)
	at scala.tools.nsc.typechecker.Analyzer$packageObjects$$anon$2$$anon$4.traverse(Analyzer.scala:61)
	at scala.tools.nsc.typechecker.Analyzer$packageObjects$$anon$2$$anon$4.traverse(Analyzer.scala:57)
	at scala.reflect.api.Trees$Traverser$$anonfun$traverseTrees$1.apply(Trees.scala:2853)
	at scala.reflect.api.Trees$Traverser$$anonfun$traverseTrees$1.apply(Trees.scala:2853)
	at scala.collection.immutable.List.foreach(List.scala:309)
	at scala.reflect.api.Trees$Traverser.traverseTrees(Trees.scala:2853)
	at scala.reflect.internal.Trees$$anonfun$itraverse$1.apply$mcV$sp(Trees.scala:1095)
	at scala.reflect.api.Trees$Traverser.atOwner(Trees.scala:2873)
	at scala.reflect.internal.Trees$class.itraverse(Trees.scala:1094)
	at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:13)
	at scala.reflect.internal.SymbolTable.itraverse(SymbolTable.scala:13)
	at scala.reflect.api.Trees$Traverser.traverse(Trees.scala:2849)
	at scala.tools.nsc.typechecker.Analyzer$packageObjects$$anon$2$$anon$4.traverse(Analyzer.scala:64)
	at scala.tools.nsc.typechecker.Analyzer$packageObjects$$anon$2$$anon$4.traverse(Analyzer.scala:57)
	at scala.reflect.api.Trees$Traverser.apply(Trees.scala:2879)
	at scala.tools.nsc.typechecker.Analyzer$packageObjects$$anon$2.apply(Analyzer.scala:69)
	at scala.tools.nsc.Global$GlobalPhase.applyPhase(Global.scala:463)
	at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:430)
	at scala.tools.nsc.Global$GlobalPhase$$anonfun$run$1.apply(Global.scala:430)
	at scala.collection.Iterator$class.foreach(Iterator.scala:727)
	at scala.collection.AbstractIterator.foreach(Iterator.scala:1157)
	at scala.tools.nsc.Global$GlobalPhase.run(Global.scala:430)
        ...

Finally, during code gen we get our assert saying that symbols 6946 and 7260 are overloaded alternatives. Same name, same type, same owner.

assertion failed: Symbol is unexpectedly overloaded with alternatives 'object package$buhB#6946#MOD (object package$buhB#6946#MOD->package buhbase#29#PK->package <root>#2#PK)'and'object package$buhB#7260#MOD (object package$buhB#7260#MOD->package buhbase#29#PK->package <root>#2#PK)'.
	at scala.Predef$.assert(Predef.scala:179)
	at scala.reflect.internal.Symbols$Symbol.suchThat(Symbols.scala:1651)
	at scala.reflect.internal.Symbols$ClassSymbol.companionModule0(Symbols.scala:2937)
	at scala.reflect.internal.Symbols$ClassSymbol.companionModule(Symbols.scala:2940)
	at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genClass(GenASM.scala:1369)
	at scala.tools.nsc.backend.jvm.GenASM$AsmPhase.run(GenASM.scala:119)
        ...
}

So, Namer tried to look up buhB, didn't find it, created #7260. Later #7260 was renamed to package$buhB and by then the damage was done. I don't yet know where the name gets changed.

Some investigation I need to do: do all inner classes get loaded with mangled name symbols? Or is that something special about objects inside package objects? If the later, is that deliberate or a mistake? If the former, then shouldn't Namer be figuring out the mangling in order to do the lookup properly?

@scabug
Copy link
Author

scabug commented Jan 14, 2013

@adriaanm said (edited by @JamesIry on Jan 14, 2013 7:30:08 PM UTC):
scala/scala#1882 adds an implementation restriction preventing this problem from occurring, but the bug is being left open as the core problem isn't solved.

@scabug
Copy link
Author

scabug commented Jan 16, 2013

@JamesIry said:
Jason suggest this might be a related issue/fix #6976 scala/scala#1910. On the surface I don't think it is. With this issue we've got a problem with some names that start different (making lookup fail) and then at a later phase become the same. 6976 is our old friend lazy initialization.

@scabug
Copy link
Author

scabug commented Feb 4, 2013

@JamesIry said:
It turns out this works fine on second+ compile in sbt.

@scabug
Copy link
Author

scabug commented Feb 6, 2013

@JamesIry said:
The implementation restriction is being turned into a warning in scala/scala#2079

@scabug
Copy link
Author

scabug commented Feb 14, 2013

@JamesIry said:
Disabling the assert is not an option. With it disabled and separate compilation of a simple test driver you can end up with

how can getCommonSuperclass() do its job if different class symbols get the same bytecode-level internal name: Foo/package$Bar
	at scala.Predef$.assert(Predef.scala:179)
	at scala.tools.nsc.Global.assert(Global.scala:238)
	at scala.tools.nsc.backend.jvm.GenASM$JBuilder.javaName(GenASM.scala:547)
	at scala.tools.nsc.backend.jvm.GenASM$JPlainBuilder.genObjsInstr$1(GenASM.scala:2439)

Which is one of the things mentioned in the notes for #4695.

@scabug
Copy link
Author

scabug commented Feb 19, 2013

@adriaanm said:
I think Rex Kerr has a point when he says that we should be able to suppress warnings (especially new ones):

Note that the change in behavior in 2.10.1 to throw warnings for stuff like

maths/package.scala:1281: warning: class OutlierDist should be placed directly in
package maths instead of package object maths. Under some circumstances companion
objects and case classes in package objects can fail to recompile. See
https://issues.scala-lang.org/browse/SI-5954.

and also

mwt/MultiSensed.scala:143: warning: The outer reference in this type test cannot be
checked at run time. final case class NotValid(val i0: Int, val i1: Int) extends
Chunk {}

means that I can no longer run with -Xfatal-warnings, which was how I found all the
places I needed to import language.whatever; now any new instances will be lost in
the screensfull of warnings.

Incidentally, is there a way to make the latter warning go away? I don't want to
push the trait and case classes out of the enclosing class since they don't make
any logical sense elsewhere and they _are_ class-relative information (despite not
linking back to the superclass). But I would like to be able to declare that I
don't intend to check that aspect of the type at runtime; compile time is
sufficient. (I realize that I could just refer to the enclosing class, but I'd
rather avoid the extra field since there will be millions of these things.) If the
underlying bug for 5954 is fixed, I'd want to fix these also so I can
-Xfatal-warnings again.

@scabug
Copy link
Author

scabug commented Feb 20, 2013

@paulp said:
"I think Rex Kerr has a point when he says that we should be able to suppress warnings (especially new ones):"

This guy probably has a point as well.

#1781

@scabug
Copy link
Author

scabug commented Feb 28, 2013

@adriaanm said:
Scheduling for 2.10.1-RC3 because we should make the warning less intrusive in 2.10

@scabug
Copy link
Author

scabug commented Feb 28, 2013

@JamesIry said:
Paul and I have both spent some time working on this. It's extremely unlikely that the fix for this bug will be low-risk enough to be applicable to an RC. Plus, the bug has existed since 2.9 so it doesn't qualify as a 2.10.1 regression that could go into an RC.

I'm de-scheduling this one from RC3 and opening another ticket for suppressing the new warnings. If Paul (or whoever) discovers that the fix for this bug is low enough risk after all (and binary compatible) then we can schedule a back-port to 2.10.x and eliminate the warning entirely.

@scabug
Copy link
Author

scabug commented Sep 25, 2013

@retronym said:
Throw in implicit classes for a first-time crash:

package p1 {
  object `package` {
    implicit class Foo(a: Any)
    object Foo
  }
}
scalac-hash v2.11.0-M5 sandbox/test1.scala
[info] v2.11.0-M5 => /Users/jason/usr/scala-v2.11.0-M5-0-gd6fe890
sandbox/test1.scala:4: warning: object Foo should be placed directly in package p1 instead of package object p1. Under some circumstances companion objects and case classes in package objects can fail to recompile. See https://issues.scala-lang.org/browse/SI-5954.
    object Foo
           ^
sandbox/test1.scala:3: warning: class Foo should be placed directly in package p1 instead of package object p1. Under some circumstances companion objects and case classes in package objects can fail to recompile. See https://issues.scala-lang.org/browse/SI-5954.
    implicit class Foo(a: Any)
                   ^
error: java.lang.AssertionError: assertion failed: List(object package$Foo, object package$Foo)
	at scala.reflect.internal.Symbols$Symbol.suchThat(Symbols.scala:1790)
	at scala.reflect.internal.Symbols$ClassSymbol.companionModule0(Symbols.scala:3089)

@scabug
Copy link
Author

scabug commented Jan 20, 2014

@retronym said:
scala/scala#3389

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants