diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index 6bf6f3435..4978c257f 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -659,39 +659,26 @@ trait Definitions extends reflect.api.StandardDefinitions { } def packageExists(packageName: String): Boolean = getModuleIfDefined(packageName).isPackage + + private def getModuleOrClass(path: Name, len: Int): Symbol = { + val point = path lastPos('.', len - 1) + val owner = if (point > 0) getModuleOrClass(path.toTermName, point) else RootClass + val name = path subName (point + 1, len) + val sym = owner.info member name + val result = if (path.isTermName) sym.suchThat(_ hasFlag MODULE) else sym + if (result != NoSymbol) result + else { + if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug + missingHook(owner, name) orElse { + throw new MissingRequirementError((if (path.isTermName) "object " else "class ")+path) + } + } + } /** If you're looking for a class, pass a type name. * If a module, a term name. */ - private def getModuleOrClass(path: Name): Symbol = { - val module = path.isTermName - val fullname = path.toTermName - if (fullname == nme.NO_NAME) - return NoSymbol - - var sym: Symbol = RootClass - var i = 0 - var j = fullname.pos('.', i) - while (j < fullname.length) { -// val sym0 = sym //DEBUG - - sym = sym.info.member(fullname.subName(i, j)) - // if (sym == NoSymbol) - // println("no member "+fullname.subName(i, j)+" found in "+sym0+sym0.info.getClass+" "+sym0.info.typeSymbol.info.getClass) - i = j + 1 - j = fullname.pos('.', i) - } - val result = - if (module) sym.info.member(fullname.subName(i, j)).suchThat(_ hasFlag MODULE) - else sym.info.member(fullname.subName(i, j).toTypeName) - if (result == NoSymbol) { - // println("no member "+fullname.subName(i, j)+" found in "+sym+" "+module) - if (settings.debug.value) - { log(sym.info); log(sym.info.members) }//debug - throw new MissingRequirementError((if (module) "object " else "class ") + fullname) - } - result - } + private def getModuleOrClass(path: Name): Symbol = getModuleOrClass(path, path.length) private def newClass(owner: Symbol, name: TypeName, parents: List[Type]): Symbol = { val clazz = owner.newClass(NoPosition, name) @@ -840,7 +827,7 @@ trait Definitions extends reflect.api.StandardDefinitions { def init() { if (isInitialized) return - EmptyPackageClass setInfo ClassInfoType(Nil, new Scope, EmptyPackageClass) + EmptyPackageClass setInfo ClassInfoType(Nil, newPackageScope(EmptyPackageClass), EmptyPackageClass) EmptyPackage setInfo EmptyPackageClass.tpe RootClass.info.decls enter EmptyPackage @@ -937,5 +924,5 @@ trait Definitions extends reflect.api.StandardDefinitions { assert(Delegate_scalaCallers contains scalaCaller) Delegate_scalaCallerTargets += (scalaCaller -> methSym) } - } + } } diff --git a/src/compiler/scala/reflect/internal/FatalError.scala b/src/compiler/scala/reflect/internal/FatalError.scala index edbae1927..c84330848 100644 --- a/src/compiler/scala/reflect/internal/FatalError.scala +++ b/src/compiler/scala/reflect/internal/FatalError.scala @@ -3,4 +3,4 @@ * @author Martin Odersky */ package scala.reflect.internal -case class FatalError(msg: String) extends Throwable(msg) +case class FatalError(msg: String) extends Exception(msg) diff --git a/src/compiler/scala/reflect/internal/Names.scala b/src/compiler/scala/reflect/internal/Names.scala index 1ae5911c4..f70ab35bb 100644 --- a/src/compiler/scala/reflect/internal/Names.scala +++ b/src/compiler/scala/reflect/internal/Names.scala @@ -316,7 +316,7 @@ trait Names extends api.Names { def lastIndexOf(ch: Char) = toChars lastIndexOf ch - /** Return the subname with characters from start to end-1. */ + /** Return the subname with characters from from to to-1. */ def subName(from: Int, to: Int): Name /** Replace all occurrences of `from` by `to` in diff --git a/src/compiler/scala/reflect/internal/Scopes.scala b/src/compiler/scala/reflect/internal/Scopes.scala index e4ba3529b..27b67d51a 100644 --- a/src/compiler/scala/reflect/internal/Scopes.scala +++ b/src/compiler/scala/reflect/internal/Scopes.scala @@ -74,13 +74,10 @@ trait Scopes extends api.Scopes { self: SymbolTable => } /** Returns a new scope with the same content as this one. */ - def cloneScope: Scope = { - val clone = new Scope() - this.toList foreach (clone enter _) - clone - } - - def mkScope: Scope = new Scope() + def cloneScope: Scope = mkScope(this.toList) + + /** Returns a new scope of the same class as this one, with initial elements `decls` */ + def mkScope(decls: List[Symbol] = Nil): Scope = new Scope(decls) /** is the scope empty? */ override def isEmpty: Boolean = elems eq null @@ -302,7 +299,7 @@ trait Scopes extends api.Scopes { self: SymbolTable => override def foreach[U](p: Symbol => U): Unit = toList foreach p override def filter(p: Symbol => Boolean): Scope = - if (!(toList forall p)) new Scope(toList filter p) else this + if (!(toList forall p)) mkScope(toList filter p) else this override def mkString(start: String, sep: String, end: String) = toList.map(_.defString).mkString(start, sep, end) @@ -311,7 +308,11 @@ trait Scopes extends api.Scopes { self: SymbolTable => } + /** Create a new scope */ def newScope: Scope = new Scope + + /** Create new scope for the members of package `pkg` */ + def newPackageScope(pkgClass: Symbol): Scope = new Scope def newScopeWith(elems: Symbol*) = { val scope = newScope diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index 0e5ac3913..63a94a648 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -41,6 +41,12 @@ abstract class SymbolTable extends api.Universe /** Are we compiling for .NET? */ def forMSIL: Boolean = false + /** A last effort if symbol in a select . is not found. + * This is overridden by the reflection compiler to make up a package + * when it makes sense (i.e. is a package and is a term name). + */ + def missingHook(owner: Symbol, name: Name): Symbol = NoSymbol + /** A period is an ordinal number for a phase in a run. * Phases in later runs have higher periods than phases in earlier runs. * Later phases have higher periods than earlier phases in the same run. diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 333a97a29..82e42c112 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -1508,6 +1508,9 @@ trait Types extends api.Types { self: SymbolTable => def apply(parents: List[Type], decls: Scope, clazz: Symbol): RefinedType = new RefinedType0(parents, decls, clazz) } + + /** Overridden in reflection compiler */ + def validateClassInfo(tp: ClassInfoType) {} /** A class representing a class info */ @@ -1516,6 +1519,7 @@ trait Types extends api.Types { self: SymbolTable => override val decls: Scope, override val typeSymbol: Symbol) extends CompoundType { + validateClassInfo(this) /** refs indices */ private final val NonExpansive = 0 @@ -3405,7 +3409,7 @@ A type's typeSymbol should never be inspected directly. val elems = scope.toList val elems1 = mapOver(elems) if (elems1 eq elems) scope - else new Scope(elems1) + else scope.mkScope(elems1) } /** Map this function over given list of symbols */ @@ -5499,11 +5503,16 @@ A type's typeSymbol should never be inspected directly. private val lubResults = new mutable.HashMap[(Int, List[Type]), Type] private val glbResults = new mutable.HashMap[(Int, List[Type]), Type] - def lub(ts: List[Type]): Type = try { - lub(ts, lubDepth(ts)) - } finally { - lubResults.clear() - glbResults.clear() + def lub(ts: List[Type]): Type = ts match { + case List() => NothingClass.tpe + case List(t) => t + case _ => + try { + lub(ts, lubDepth(ts)) + } finally { + lubResults.clear() + glbResults.clear() + } } /** The least upper bound wrt <:< of a list of types */ @@ -5631,26 +5640,39 @@ A type's typeSymbol should never be inspected directly. private var globalGlbDepth = 0 private final val globalGlbLimit = 2 - def glb(ts: List[Type]): Type = try { - glb(ts, lubDepth(ts)) - } finally { - lubResults.clear() - glbResults.clear() + /** The greatest lower bound wrt <:< of a list of types */ + def glb(ts: List[Type]): Type = elimSuper(ts) match { + case List() => AnyClass.tpe + case List(t) => t + case ts0 => + try { + glbNorm(ts0, lubDepth(ts0)) + } finally { + lubResults.clear() + glbResults.clear() + } + } + + private def glb(ts: List[Type], depth: Int): Type = elimSuper(ts) match { + case List() => AnyClass.tpe + case List(t) => t + case ts0 => glbNorm(ts0, depth) } - /** The greatest lower bound wrt <:< of a list of types */ - private def glb(ts: List[Type], depth: Int): Type = { - def glb0(ts0: List[Type]): Type = elimSuper(ts0) match { + /** The greatest lower bound wrt <:< of a list of types, which have been normalized + * wrt elimSuper */ + private def glbNorm(ts: List[Type], depth: Int): Type = { + def glb0(ts0: List[Type]): Type = ts0 match { case List() => AnyClass.tpe case List(t) => t case ts @ PolyType(tparams, _) :: _ => val tparams1 = (tparams, matchingBounds(ts, tparams).transpose).zipped map ((tparam, bounds) => tparam.cloneSymbol.setInfo(lub(bounds, depth))) - PolyType(tparams1, glb0(matchingInstTypes(ts, tparams1))) + PolyType(tparams1, glbNorm(matchingInstTypes(ts, tparams1), depth)) case ts @ MethodType(params, _) :: rest => - MethodType(params, glb0(matchingRestypes(ts, params map (_.tpe)))) + MethodType(params, glbNorm(matchingRestypes(ts, params map (_.tpe)), depth)) case ts @ NullaryMethodType(_) :: rest => - NullaryMethodType(glb0(matchingRestypes(ts, Nil))) + NullaryMethodType(glbNorm(matchingRestypes(ts, Nil), depth)) case ts @ TypeBounds(_, _) :: rest => TypeBounds(lub(ts map (_.bounds.lo), depth), glb(ts map (_.bounds.hi), depth)) case ts => diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 9eee66d57..b52bc44a5 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -36,7 +36,9 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { try { new Scan(bytes, offset, classRoot, moduleRoot, filename).run() } catch { - case ex: IOException => + case ex: IOException => + throw ex + case ex: MissingRequirementError => throw ex case ex: Throwable => /*if (settings.debug.value)*/ ex.printStackTrace() @@ -815,14 +817,12 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { protected def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) - protected def errorMissingRequirement(msg: String): Nothing = - if (debug) errorBadSignature(msg) - else throw new IOException("class file needed by "+classRoot.name+" is missing.\n"+msg) - - protected def errorMissingRequirement(name: Name, owner: Symbol): Nothing = - errorMissingRequirement( - "reference " + (if (name.isTypeName) "type " else "value ") + - name.decode + " of " + owner.tpe.widen + " refers to nonexisting symbol.") + protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol = + missingHook(owner, name) orElse { + throw new MissingRequirementError( + "reference " + (if (name.isTypeName) "type " else "value ") + + name.decode + " of " + owner.tpe.widen) + } def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that. diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala index 0ba9f63de..078f4e31f 100644 --- a/src/compiler/scala/reflect/runtime/JavaToScala.scala +++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala @@ -16,6 +16,7 @@ import java.lang.reflect.{ WildcardType, AnnotatedElement } +import internal.MissingRequirementError import internal.pickling.ByteCodecs import internal.ClassfileConstants._ import internal.pickling.UnPickler @@ -41,6 +42,14 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => */ def unpickleClass(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = { def markAbsent(tpe: Type) = List(clazz, module, module.moduleClass) foreach (_ setInfo tpe) + def handleError(ex: Exception) = { + markAbsent(ErrorType) + if (settings.debug.value) ex.printStackTrace() + val msg = ex.getMessage() + throw new MissingRequirementError( + if (msg eq null) "reflection error while loading " + clazz.name + else "error while loading " + clazz.name + ", " + msg) + } try { println("unpickling " + clazz + " " + module) //debug markAbsent(NoType) @@ -69,13 +78,10 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => } } } catch { + case ex: MissingRequirementError => + handleError(ex) case ex: IOException => - markAbsent(ErrorType) - if (settings.debug.value) ex.printStackTrace() - val msg = ex.getMessage() - throw new IOException( - if (msg eq null) "reflection error while loading " + clazz.name - else "error while loading " + clazz.name + ", " + msg) + handleError(ex) } } @@ -133,9 +139,14 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => val tparams = jclazz.getTypeParameters.toList map createTypeParameter - val jsuperclazz = jclazz.getGenericSuperclass - val superclazz = if (jsuperclazz == null) AnyClass.tpe else typeToScala(jsuperclazz) - val parents = superclazz :: (jclazz.getGenericInterfaces.toList map typeToScala) + val parents = try { + parentsLevel += 1 + val jsuperclazz = jclazz.getGenericSuperclass + val superclazz = if (jsuperclazz == null) AnyClass.tpe else typeToScala(jsuperclazz) + superclazz :: (jclazz.getGenericInterfaces.toList map typeToScala) + } finally { + parentsLevel -= 1 + } clazz setInfo polyType(tparams, new ClassInfoType(parents, newScope, clazz)) module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass) module setInfo module.moduleClass.tpe @@ -143,16 +154,32 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => def enter(sym: Symbol) = (if (sym.isStatic) module.moduleClass else clazz).info.decls enter sym - for (jfield <- jclazz.getDeclaredFields) - enter(jfieldAsScala(jfield)) + pendingLoadActions = { () => - for (jmeth <- jclazz.getDeclaredMethods) - enter(jmethodAsScala(jmeth)) + for (jfield <- jclazz.getDeclaredFields) + enter(jfieldAsScala(jfield)) - for (jconstr <- jclazz.getConstructors) - enter(jconstrAsScala(jconstr)) + for (jmeth <- jclazz.getDeclaredMethods) + enter(jmethodAsScala(jmeth)) + + for (jconstr <- jclazz.getConstructors) + enter(jconstrAsScala(jconstr)) + + } :: pendingLoadActions + + if (parentsLevel == 0) { + while (!pendingLoadActions.isEmpty) { + val item = pendingLoadActions.head + pendingLoadActions = pendingLoadActions.tail + item() + } + } } } + + /** used to avoid cyclies */ + var parentsLevel = 0 + var pendingLoadActions: List[() => Unit] = Nil /** * If Java modifiers `mods` contain STATIC, return the module class @@ -252,13 +279,20 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => * The Scala package with given fully qualified name. Unlike `packageNameToScala`, * this one bypasses the cache. */ - private def makeScalaPackage(fullname: String): Symbol = { + def makeScalaPackage(fullname: String): Symbol = { println("make scala pkg "+fullname) val split = fullname lastIndexOf '.' val owner = if (split > 0) packageNameToScala(fullname take split) else RootClass assert(owner.isModuleClass, owner+" when making "+fullname) - val name = fullname drop (split + 1) - val pkg = owner.info decl newTermName(name) + val name = newTermName(fullname drop (split + 1)) + var pkg = owner.info decl name + if (pkg == NoSymbol) { + pkg = owner.newPackage(NoPosition, name) + pkg.moduleClass setInfo newPackageType(pkg.moduleClass) + pkg setInfo typeRef(pkg.owner.thisType, pkg.moduleClass, Nil) + owner.info.decls enter pkg + } else if (!pkg.isPackage) + throw new ReflectError(pkg+" is not a package") println(" = "+pkg+"/"+pkg.moduleClass) pkg.moduleClass } @@ -329,7 +363,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => val tparam = owner.newExistential(NoPosition, newTypeName("T$" + tparams.length)) .setInfo(TypeBounds( lub(jwild.getLowerBounds.toList map typeToScala), - glb(scala.tools.nsc.util.trace("glb args")(jwild.getUpperBounds.toList) map typeToScala map objToAny))) + glb(scala.tools.nsc.util.trace("glb args of "+owner)(jwild.getUpperBounds.toList) map typeToScala map objToAny))) tparams += tparam typeRef(NoPrefix, tparam, List()) case _ => @@ -428,4 +462,6 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable => copyAnnotations(meth, jconstr) meth } -} \ No newline at end of file +} + +class ReflectError(msg: String) extends java.lang.Error(msg) \ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala index 869e15e37..e4bbd5d2d 100644 --- a/src/compiler/scala/reflect/runtime/Loaders.scala +++ b/src/compiler/scala/reflect/runtime/Loaders.scala @@ -22,6 +22,7 @@ trait Loaders { self: SymbolTable => */ class TopClassCompleter(clazz: Symbol, module: Symbol) extends LazyType { def makePackage() { + println("wrong guess; making package "+clazz) val ptpe = newPackageType(module.moduleClass) for (sym <- List(clazz, module, module.moduleClass)) { sym setFlag Flags.PACKAGE @@ -80,7 +81,7 @@ trait Loaders { self: SymbolTable => * a TopClassCompleter type. When any of the two symbols is forced via info, * the TopClassCompleter will sort things out. */ - def newPackageType(pkg: Symbol) = new ClassInfoType(List(), new PackageScope(pkg), pkg) { + def newPackageType(pkgClass: Symbol) = new ClassInfoType(List(), new PackageScope(pkgClass), pkgClass) { /* override def decl(name: Name): Symbol = (decls lookup name) orElse { @@ -94,24 +95,31 @@ trait Loaders { self: SymbolTable => override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean) = member(name).filter (m => m.hasAllFlags(requiredFlags) && !m.hasFlag(excludedFlags)) */ - override def safeToString = pkg.toString + override def safeToString = pkgClass.toString } - class PackageScope(pkg: Symbol) extends Scope { + class PackageScope(pkgClass: Symbol) extends Scope { override def lookupEntry(name: Name): ScopeEntry = { val e = super.lookupEntry(name) if (e != null) e else try { - if (name.isTypeName) jClass.forName(pkg.fullName + "." + name) - val (clazz, module) = createClassModule(pkg, name.toTypeName, new TopClassCompleter(_, _)) - println("created "+module+"/"+module.moduleClass+" in "+pkg+", scope = "+(this map (_.name))) + jClass.forName(pkgClass.fullName + "." + name) + val (clazz, module) = createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _)) + println("created "+module+"/"+module.moduleClass+" in "+pkgClass+", scope = "+(this map (_.name))) lookupEntry(name) } catch { case ex: ClassNotFoundException => - println("not found: "+pkg.fullName + "." + name) + println("not found : "+pkgClass.fullName + "." + name) null } } + override def mkScope(decls: List[Symbol]) = { + val result = new PackageScope(pkgClass) + decls foreach (result enter) + result + } } + + override def newPackageScope(pkgClass: Symbol) = new PackageScope(pkgClass) } diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala index a1ace18c6..e01a7da6d 100644 --- a/src/compiler/scala/reflect/runtime/Mirror.scala +++ b/src/compiler/scala/reflect/runtime/Mirror.scala @@ -72,6 +72,7 @@ object Mirror extends Mirror /** test code; should go to tests once things settle down a bit * + */ object Test extends Mirror with App { val sym = classToScala(classOf[scala.collection.Iterable[_]]) println(sym) @@ -80,4 +81,3 @@ object Test extends Mirror with App { val ms = sym.info.members.toList map (_.initialize) println("members = "+(ms map (_.defString) mkString ("\n "))) } -*/ \ No newline at end of file diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala index 2f3e28c7b..a88465e93 100644 --- a/src/compiler/scala/reflect/runtime/SymbolTable.scala +++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala @@ -6,4 +6,21 @@ package runtime * It can be used either from the reflexive mirror itself (class Universe), or else from * a runtime compiler that uses reflection to get a class information (class scala.tools.nsc.ReflectGlobal) */ -trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders +trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava with Loaders { + + /** If `owner` is a package class and `name` is a term name, make a new package + * ., otherwise return NoSymbol + */ + override def missingHook(owner: Symbol, name: Name): Symbol = + if (name.isTermName && owner.hasPackageFlag) + makeScalaPackage(if (owner.isRoot) name.toString else owner.fullName+"."+name).sourceModule + else { + println(name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass) + super.missingHook(owner, name) + } + + /** Assert that packages have package scopes */ + override def validateClassInfo(tp: ClassInfoType) { + assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope]) + } +} diff --git a/src/compiler/scala/tools/nsc/CompilerCommand.scala b/src/compiler/scala/tools/nsc/CompilerCommand.scala index fe1e444e9..607fdd29b 100644 --- a/src/compiler/scala/tools/nsc/CompilerCommand.scala +++ b/src/compiler/scala/tools/nsc/CompilerCommand.scala @@ -5,7 +5,6 @@ package scala.tools.nsc -import java.io.IOException import scala.collection.mutable.ListBuffer import io.File diff --git a/src/compiler/scala/tools/nsc/MainGenericRunner.scala b/src/compiler/scala/tools/nsc/MainGenericRunner.scala index aa2ae50c4..5b17d3c59 100644 --- a/src/compiler/scala/tools/nsc/MainGenericRunner.scala +++ b/src/compiler/scala/tools/nsc/MainGenericRunner.scala @@ -5,7 +5,6 @@ package scala.tools.nsc -import java.io.IOException import java.net.URL import scala.tools.util.PathResolver diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index e5937925e..fbc1bc7cc 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -13,6 +13,7 @@ import scala.compat.Platform.currentTime import scala.tools.nsc.util.{ ClassPath } import classfile.ClassfileParser import reflect.internal.Flags._ +import reflect.internal.MissingRequirementError import util.Statistics._ import scala.tools.nsc.io.AbstractFile @@ -105,6 +106,14 @@ abstract class SymbolLoaders { }) } override def complete(root: Symbol) : Unit = { + def signalError(ex: Exception) { + ok = false + if (settings.debug.value) ex.printStackTrace() + val msg = ex.getMessage() + globalError( + if (msg eq null) "i/o error while loading " + root.name + else "error while loading " + root.name + ", " + msg); + } try { val start = currentTime val currentphase = phase @@ -116,12 +125,9 @@ abstract class SymbolLoaders { setSource(root.companionSymbol) // module -> class, class -> module } catch { case ex: IOException => - ok = false - if (settings.debug.value) ex.printStackTrace() - val msg = ex.getMessage() - globalError( - if (msg eq null) "i/o error while loading " + root.name - else "error while loading " + root.name + ", " + msg); + signalError(ex) + case ex: MissingRequirementError => + signalError(ex) } initRoot(root) if (!root.isPackageClass) initRoot(root.companionSymbol) diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index 5f047f527..34d18f770 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -64,7 +64,7 @@ abstract class Flatten extends InfoTransform { typeRef(sym.toplevelClass.owner.thisType, sym, Nil) case ClassInfoType(parents, decls, clazz) => var parents1 = parents - val decls1 = new Scope + val decls1 = decls.mkScope() if (clazz.isPackageClass) { atPhase(phase.next)(decls foreach (decls1 enter _)) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d424aef1b..1bf2099fc 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3668,9 +3668,12 @@ trait Typers extends Modes with Adaptations { if (name == nme.ERROR && forInteractive) return makeErrorTree - if (!qual.tpe.widen.isErroneous) + if (!qual.tpe.widen.isErroneous) { + val lastTry = missingHook(qual.tpe.typeSymbol, name) + if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt) notAMemberError(tree.pos, qual, name) - + } + if (forInteractive) makeErrorTree else setError(tree) } else { val tree1 = tree match { diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala index 59836fe95..a9a4a29cb 100644 --- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala +++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala @@ -7,7 +7,7 @@ package scala.tools package nsc package util -import java.io.{File, FileInputStream, PrintStream, IOException} +import java.io.{File, FileInputStream, PrintStream} import java.lang.Long.toHexString import java.lang.Float.intBitsToFloat import java.lang.Double.longBitsToDouble