Skip to content

Commit 3be56dd

Browse files
committed
SI-8502 create PackageClass instead of Class symbol stubs for pkgs
scala#4111 creates a stub type symbol for missing packages, deferring (or avoiding) a crash if a package is missing. The symbol created was a ClassSymbol, which could lead to an assertion failure in flattten: case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) => assert(args.isEmpty && sym.enclosingTopLevelClass != NoSymbol, sym.ownerChain) `pre` is the stub ClassSymbol, so `isFlattenablePrefix` is true (but it should be false). The assertion then fails because the enclosing class of a top-level class defined in a missing package is NoSymbol. This failed only with GenBCode, which traverses more of the symbol graph while building ClassBTypes: it looks collects the nested classes of `Outer` into a `NestedInfo`.
1 parent f2e055f commit 3be56dd

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/reflect/scala/reflect/internal/Symbols.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,8 +495,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
495495
* failure to the point when that name is used for something, which is
496496
* often to the point of never.
497497
*/
498-
def newStubSymbol(name: Name, missingMessage: String): Symbol = name match {
499-
case n: TypeName => new StubClassSymbol(this, n, missingMessage)
498+
def newStubSymbol(name: Name, missingMessage: String, isPackage: Boolean = false): Symbol = name match {
499+
case n: TypeName => if (isPackage) new StubPackageClassSymbol(this, n, missingMessage) else new StubClassSymbol(this, n, missingMessage)
500500
case _ => new StubTermSymbol(this, name.toTermName, missingMessage)
501501
}
502502

@@ -3469,6 +3469,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
34693469
override def companionSymbol = fail(NoSymbol)
34703470
}
34713471
class StubClassSymbol(owner0: Symbol, name0: TypeName, val missingMessage: String) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol
3472+
class StubPackageClassSymbol(owner0: Symbol, name0: TypeName, val missingMessage: String) extends PackageClassSymbol(owner0, owner0.pos, name0) with StubSymbol
34723473
class StubTermSymbol(owner0: Symbol, name0: TermName, val missingMessage: String) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol
34733474

34743475
trait FreeSymbol extends Symbol {

src/reflect/scala/reflect/internal/pickling/UnPickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ abstract class UnPickler {
398398
val sym = readSymbolRef() match {
399399
case stub: StubSymbol if !stub.isClass =>
400400
// SI-8502 This allows us to create a stub for a unpickled reference to `missingPackage.Foo`.
401-
stub.owner.newStubSymbol(stub.name.toTypeName, stub.missingMessage)
401+
stub.owner.newStubSymbol(stub.name.toTypeName, stub.missingMessage, isPackage = true)
402402
case sym => sym
403403
}
404404
ThisType(sym)

test/files/run/t8502b.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import scala.tools.partest._
2+
import java.io.File
3+
4+
// used to crash with an assertion failure in flatten because the type symbol created for the missing
5+
// package was a ClassSymbol, not a PackageClassSymbol
6+
// - isFlattenablePrefix(vanishingPackage) was true (wrongly)
7+
// - therefore flatten tried to flatten the class defined in the package, but the class is
8+
// top-level, vanishingClass.enclosingTopLevelClass is NoSymbol
9+
object Test extends StoreReporterDirectTest {
10+
def code = ???
11+
12+
def compileCode(code: String) = {
13+
val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator")
14+
compileString(newCompiler("-cp", classpath, "-d", testOutput.path))(code)
15+
}
16+
17+
def show(): Unit = {
18+
compileCode("""
19+
class Outer {
20+
class Nested extends vanishing.Vanishing
21+
}
22+
23+
package vanishing {
24+
class Vanishing
25+
}
26+
""")
27+
assert(filteredInfos.isEmpty, filteredInfos)
28+
deletePackage("vanishing")
29+
compileCode("""
30+
class Test {
31+
def f(o: Outer): Outer = o
32+
}
33+
""")
34+
assert(storeReporter.infos.isEmpty, storeReporter.infos.mkString("\n")) // Included a MissingRequirementError before.
35+
}
36+
37+
def deletePackage(name: String) {
38+
val directory = new File(testOutput.path, name)
39+
for (f <- directory.listFiles()) {
40+
assert(f.getName.endsWith(".class"))
41+
assert(f.delete())
42+
}
43+
assert(directory.listFiles().isEmpty)
44+
assert(directory.delete())
45+
}
46+
}

0 commit comments

Comments
 (0)