diff options
author | Paul Phillips <paulp@improving.org> | 2012-08-02 10:07:19 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-08-11 20:27:46 -0700 |
commit | a55788e275faed91cb9223686a3aef6ee54213a8 (patch) | |
tree | 4ac92fc704d7e06edb38680114321309c84dbd5b /src/reflect/scala/reflect/internal/Symbols.scala | |
parent | 4459e5abb2b765cbdca34eb19c5d8b705203f771 (diff) | |
download | scala-a55788e275faed91cb9223686a3aef6ee54213a8.tar.gz scala-a55788e275faed91cb9223686a3aef6ee54213a8.tar.bz2 scala-a55788e275faed91cb9223686a3aef6ee54213a8.zip |
More resilience to missing classes.
The situation (I don't know how to make partest test this) is
package s
class A ; class S { def f(): A = ??? }
If one compiles this and removes A.class, should references to
class S cause the compiler to explode eagerly and fail to load S,
or explode lazily if and when it needs to know something about A?
This patch takes us from the former strategy to the latter.
Review by @xeno-by.
Diffstat (limited to 'src/reflect/scala/reflect/internal/Symbols.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 41 |
1 files changed, 41 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index 161d04b6ff..9311a74f18 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -392,6 +392,16 @@ trait Symbols extends api.Symbols { self: SymbolTable => case x: TermName => newErrorValue(x) } + /** Creates a placeholder symbol for when a name is encountered during + * unpickling for which there is no corresponding classfile. This defers + * failure to the point when that name is used for something, which is + * often to the point of never. + */ + def newStubSymbol(name: Name): Symbol = name match { + case n: TypeName => new StubClassSymbol(this, n) + case _ => new StubTermSymbol(this, name.toTermName) + } + @deprecated("Use the other signature", "2.10.0") def newClass(pos: Position, name: TypeName): Symbol = newClass(name, pos) @deprecated("Use the other signature", "2.10.0") @@ -2998,6 +3008,37 @@ trait Symbols extends api.Symbols { self: SymbolTable => || info.parents.exists(_.typeSymbol hasTransOwner sym) ) } + trait StubSymbol extends Symbol { + protected def stubWarning = { + val from = if (associatedFile == null) "" else s" - referenced from ${associatedFile.canonicalPath}" + s"$kindString $nameString$locationString$from (a classfile may be missing)" + } + private def fail[T](alt: T): T = { + // Avoid issuing lots of redundant errors + if (!hasFlag(IS_ERROR)) { + globalError(s"bad symbolic reference to " + stubWarning) + if (settings.debug.value) + (new Throwable).printStackTrace + + this setFlag IS_ERROR + } + alt + } + // This one doesn't call fail because SpecializeTypes winds up causing + // isMonomorphicType to be called, which calls this, which would fail us + // in all the scenarios we're trying to keep from failing. + override def originalInfo = NoType + override def associatedFile = owner.associatedFile + override def info = fail(NoType) + override def rawInfo = fail(NoType) + override def companionSymbol = fail(NoSymbol) + + locally { + debugwarn("creating stub symbol for " + stubWarning) + } + } + class StubClassSymbol(owner0: Symbol, name0: TypeName) extends ClassSymbol(owner0, owner0.pos, name0) with StubSymbol + class StubTermSymbol(owner0: Symbol, name0: TermName) extends TermSymbol(owner0, owner0.pos, name0) with StubSymbol trait FreeSymbol extends Symbol { def origin: String |