summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala10
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala34
-rw-r--r--src/reflect/scala/reflect/internal/SymbolTable.scala4
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala41
-rw-r--r--src/reflect/scala/reflect/internal/pickling/UnPickler.scala8
-rw-r--r--test/files/neg/t5148.check5
6 files changed, 74 insertions, 28 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 2b0f082051..c60a3c941f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -220,11 +220,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
// not deprecated yet, but a method called "error" imported into
// nearly every trait really must go. For now using globalError.
- def error(msg: String) = globalError(msg)
- def globalError(msg: String) = reporter.error(NoPosition, msg)
- def inform(msg: String) = reporter.echo(msg)
- def warning(msg: String) =
- if (opt.fatalWarnings) globalError(msg)
+ def error(msg: String) = globalError(msg)
+ def inform(msg: String) = reporter.echo(msg)
+ override def globalError(msg: String) = reporter.error(NoPosition, msg)
+ override def warning(msg: String) =
+ if (settings.fatalWarnings.value) globalError(msg)
else reporter.warning(NoPosition, msg)
// Getting in front of Predef's asserts to supplement with more info.
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 10a946c318..005d26e119 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -452,7 +452,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def survivingParams(params: List[Symbol], env: TypeEnv) =
params filter {
p =>
- !p.isSpecialized ||
+ !p.isSpecialized ||
!env.contains(p) ||
!isPrimitiveValueType(env(p))
}
@@ -506,16 +506,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* was both already used for a map and mucho long. So "sClass" is the
* specialized subclass of "clazz" throughout this file.
*/
-
+
// SI-5545: Eliminate classes with the same name loaded from the bytecode already present - all we need to do is
// to force .info on them, as their lazy type will be evaluated and the symbols will be eliminated. Unfortunately
// evaluating the info after creating the specialized class will mess the specialized class signature, so we'd
- // better evaluate it before creating the new class symbol
+ // better evaluate it before creating the new class symbol
val clazzName = specializedName(clazz, env0).toTypeName
- val bytecodeClazz = clazz.owner.info.decl(clazzName)
+ val bytecodeClazz = clazz.owner.info.decl(clazzName)
// debuglog("Specializing " + clazz + ", but found " + bytecodeClazz + " already there")
bytecodeClazz.info
-
+
val sClass = clazz.owner.newClass(clazzName, clazz.pos, (clazz.flags | SPECIALIZED) & ~CASE)
def cloneInSpecializedClass(member: Symbol, flagFn: Long => Long, newName: Name = null) =
@@ -762,7 +762,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
val subclasses = specializations(clazz.info.typeParams) filter satisfiable
subclasses foreach {
env =>
@@ -1006,7 +1006,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Fails if such an environment cannot be found.
*
* If `strict` is true, a UnifyError is thrown if unification is impossible.
- *
+ *
* If `tparams` is true, then the methods tries to unify over type params in polytypes as well.
*/
private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean, tparams: Boolean = false): TypeEnv = (tp1, tp2) match {
@@ -1185,7 +1185,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
|| specializedTypeVars(t1).nonEmpty
|| specializedTypeVars(t2).nonEmpty)
}
-
+
env forall { case (tvar, tpe) =>
matches(tvar.info.bounds.lo, tpe) && matches(tpe, tvar.info.bounds.hi) || {
if (warnings)
@@ -1201,7 +1201,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
def satisfiabilityConstraints(env: TypeEnv): Option[TypeEnv] = {
val noconstraints = Some(emptyEnv)
def matches(tpe1: Type, tpe2: Type): Option[TypeEnv] = {
@@ -1232,7 +1232,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} with typechecker.Duplicators {
private val (castfrom, castto) = casts.unzip
private object CastMap extends SubstTypeMap(castfrom.toList, castto.toList)
-
+
class BodyDuplicator(_context: Context) extends super.BodyDuplicator(_context) {
override def castType(tree: Tree, pt: Type): Tree = {
// log(" expected type: " + pt)
@@ -1249,9 +1249,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
ntree
}
}
-
+
protected override def newBodyDuplicator(context: Context) = new BodyDuplicator(context)
-
+
}
/** A tree symbol substituter that substitutes on type skolems.
@@ -1359,7 +1359,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
def reportError[T](body: =>T)(handler: TypeError => T): T =
try body
catch {
@@ -1396,7 +1396,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
else None
} else None
}
-
+
curTree = tree
tree match {
case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) =>
@@ -1570,7 +1570,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
})
debuglog("created special overload tree " + t)
debuglog("created " + t)
- reportError {
+ reportError {
localTyper.typed(t)
} {
_ => super.transform(tree)
@@ -1629,9 +1629,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
super.transform(tree)
}
}
-
+
/** Duplicate the body of the given method `tree` to the new symbol `source`.
- *
+ *
* Knowing that the method can be invoked only in the `castmap` type environment,
* this method will insert casts for all the expressions of types mappend in the
* `castmap`.
diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala
index c564a93b62..761dcc0534 100644
--- a/src/reflect/scala/reflect/internal/SymbolTable.scala
+++ b/src/reflect/scala/reflect/internal/SymbolTable.scala
@@ -43,7 +43,9 @@ abstract class SymbolTable extends macros.Universe
lazy val treeBuild = gen
def log(msg: => AnyRef): Unit
- def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
+ def warning(msg: String): Unit = Console.err.println(msg)
+ def globalError(msg: String): Unit = abort(msg)
+ def abort(msg: String): Nothing = throw new FatalError(supplementErrorMessage(msg))
@deprecated("Give us a reason", "2.10.0")
def abort(): Nothing = abort("unknown error")
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 5b99e2fdf0..ac8b254f83 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -390,6 +390,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")
@@ -2996,6 +3006,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
diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
index 55746f414b..9234ccca7b 100644
--- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala
@@ -230,9 +230,11 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
fromName(nme.expandedName(name.toTermName, owner)) orElse {
// (3) Try as a nested object symbol.
nestedObjectSymbol orElse {
- // (4) Otherwise, fail.
- //System.err.println("missing "+name+" in "+owner+"/"+owner.id+" "+owner.info.decls)
- adjust(errorMissingRequirement(name, owner))
+ // (4) Call the mirror's "missing" hook.
+ adjust(mirrorThatLoaded(owner).missingHook(owner, name)) orElse {
+ // (5) Create a stub symbol to defer hard failure a little longer.
+ owner.newStubSymbol(name)
+ }
}
}
}
diff --git a/test/files/neg/t5148.check b/test/files/neg/t5148.check
index 96eb1fd364..6edfdf2b1e 100644
--- a/test/files/neg/t5148.check
+++ b/test/files/neg/t5148.check
@@ -1,2 +1,3 @@
-error: bad reference while unpickling Imports.class: term memberHandlers not found in scala.tools.nsc.interpreter.IMain
-one error found
+error: bad symbolic reference to value global in class IMain - referenced from t5148.scala (a classfile may be missing)
+error: bad symbolic reference to value memberHandlers in class IMain - referenced from t5148.scala (a classfile may be missing)
+two errors found