diff options
16 files changed, 644 insertions, 1133 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index 9ac1ce1b9c..ce3e7b1bb5 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -11,6 +11,7 @@ import java.lang.Float.floatToIntBits import java.lang.Double.doubleToLongBits import scala.io.Codec import scala.reflect.internal.pickling.{ PickleBuffer, PickleFormat } +import scala.reflect.internal.util.shortClassOfInstance import scala.collection.mutable.LinkedHashMap import PickleFormat._ import Flags._ @@ -80,7 +81,7 @@ abstract class Pickler extends SubComponent { private var entries = new Array[AnyRef](256) private var ep = 0 private val index = new LinkedHashMap[AnyRef, Int] - private lazy val nonClassRoot = findOrElse(root.ownersIterator)(!_.isClass)(NoSymbol) + private lazy val nonClassRoot = findSymbol(root.ownersIterator)(!_.isClass) private def isRootSym(sym: Symbol) = sym.name.toTermName == rootName && sym.owner == rootOwner @@ -106,13 +107,14 @@ abstract class Pickler extends SubComponent { * anyway? This is the case if symbol is a refinement class, * an existentially bound variable, or a higher-order type parameter. */ - private def isLocal(sym: Symbol): Boolean = - !sym.isPackageClass && sym != NoSymbol && - (isRootSym(sym) || - sym.isRefinementClass || - sym.isAbstractType && sym.hasFlag(EXISTENTIAL) || // existential param - sym.isParameter || - isLocal(sym.owner)) + private def isLocal(sym: Symbol): Boolean = (sym != NoSymbol) && !sym.isPackageClass && ( + isRootSym(sym) + || sym.isRefinementClass + || sym.isAbstractType && sym.hasFlag(EXISTENTIAL) // existential param + || sym.isParameter + || isLocal(sym.owner) + ) + private def isExternalSymbol(sym: Symbol): Boolean = (sym != NoSymbol) && !isLocal(sym) // Phase 1 methods: Populate entries/index ------------------------------------ @@ -135,13 +137,18 @@ abstract class Pickler extends SubComponent { true } + private def deskolemizeTypeSymbols(ref: AnyRef): AnyRef = ref match { + case sym: Symbol => deskolemize(sym) + case _ => ref + } + /** If the symbol is a type skolem, deskolemize and log it. * If we fail to deskolemize, in a method like * trait Trait[+A] { def f[CC[X]] : CC[A] } * the applied type CC[A] will hold a different CC symbol * than the type-constructor type-parameter CC. */ - private def deskolemize(sym: Symbol) = { + private def deskolemize(sym: Symbol): Symbol = { if (sym.isTypeSkolem) { val sym1 = sym.deSkolemize log({ @@ -169,7 +176,7 @@ abstract class Pickler extends SubComponent { putSymbol(sym.owner) putSymbol(sym.privateWithin) putType(sym.info) - if (sym.thisSym.tpeHK != sym.tpeHK) + if (sym.hasSelfType) putType(sym.typeOfThis) putSymbol(sym.alias) if (!sym.children.isEmpty) { @@ -202,252 +209,65 @@ abstract class Pickler extends SubComponent { case ThisType(sym) => putSymbol(sym) case SingleType(pre, sym) => - putType(pre); putSymbol(sym) + putType(pre) + putSymbol(sym) case SuperType(thistpe, supertpe) => putType(thistpe) putType(supertpe) case ConstantType(value) => putConstant(value) case TypeRef(pre, sym, args) => -// if (sym.isAbstractType && (sym hasFlag EXISTENTIAL)) -// if (!(boundSyms contains sym)) -// println("unbound existential: "+sym+sym.locationString) - putType(pre); putSymbol(sym); putTypes(args) + putType(pre) + putSymbol(sym) + putTypes(args) case TypeBounds(lo, hi) => - putType(lo); putType(hi) - case RefinedType(parents, decls) => - val rclazz = tp.typeSymbol - for (m <- decls.iterator) - if (m.owner != rclazz) abort("bad refinement member "+m+" of "+tp+", owner = "+m.owner) - putSymbol(rclazz); putTypes(parents); putSymbols(decls.toList) - case ClassInfoType(parents, decls, clazz) => - putSymbol(clazz); putTypes(parents); putSymbols(decls.toList) + putType(lo) + putType(hi) + case tp: CompoundType => + putSymbol(tp.typeSymbol) + putTypes(tp.parents) + putSymbols(tp.decls.toList) case MethodType(params, restpe) => - putType(restpe); putSymbols(params) + putType(restpe) + putSymbols(params) case NullaryMethodType(restpe) => putType(restpe) case PolyType(tparams, restpe) => - /* no longer needed since all params are now local - tparams foreach { tparam => - if (!isLocal(tparam)) locals += tparam // similar to existential types, these tparams are local - } - */ - putType(restpe); putSymbols(tparams) + putType(restpe) + putSymbols(tparams) case ExistentialType(tparams, restpe) => -// val savedBoundSyms = boundSyms // boundSyms are known to be local based on the EXISTENTIAL flag (see isLocal) -// boundSyms = tparams ::: boundSyms -// try { - putType(restpe) - // } finally { -// boundSyms = savedBoundSyms -// } + putType(restpe) putSymbols(tparams) - case AnnotatedType(annotations, underlying, selfsym) => + case AnnotatedType(_, underlying, selfsym) => putType(underlying) if (settings.selfInAnnots) putSymbol(selfsym) - putAnnotations(annotations filter (_.isStatic)) + tp.staticAnnotations foreach putAnnotation case _ => throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")") } } private def putTypes(tps: List[Type]) { tps foreach putType } - private def putTree(tree: Tree): Unit = if (putEntry(tree)) { - if (tree != EmptyTree) - putType(tree.tpe) - if (tree.hasSymbolField) - putSymbol(tree.symbol) - - tree match { - case EmptyTree => - - case tree@PackageDef(pid, stats) => - putTree(pid) - putTrees(stats) - - case ClassDef(mods, name, tparams, impl) => - putMods(mods) - putEntry(name) - putTree(impl) - putTrees(tparams) - - case ModuleDef(mods, name, impl) => - putMods(mods) - putEntry(name) - putTree(impl) - - case ValDef(mods, name, tpt, rhs) => - putMods(mods) - putEntry(name) - putTree(tpt) - putTree(rhs) - - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - putMods(mods) - putEntry(name) - putTrees(tparams) - putTreess(vparamss) - putTree(tpt) - putTree(rhs) - - case TypeDef(mods, name, tparams, rhs) => - putMods(mods) - putEntry(name) - putTree(rhs) - putTrees(tparams) - - case LabelDef(name, params, rhs) => - putEntry(name) - putTree(rhs) - putTrees(params) - - case Import(expr, selectors) => - putTree(expr) - for (ImportSelector(from, _, to, _) <- selectors) { - putEntry(from) - putEntry(to) - } -/* - case DocDef(comment, definition) => should not be needed - putConstant(Constant(comment)) - putTree(definition) -*/ - case Template(parents, self, body) => - putTrees(parents) - putTree(self) - putTrees(body) - - case Block(stats, expr) => - putTree(expr) - putTrees(stats) - - case CaseDef(pat, guard, body) => - putTree(pat) - putTree(guard) - putTree(body) - - case Alternative(trees) => - putTrees(trees) - - case Star(elem) => - putTree(elem) - - case Bind(name, body) => - putEntry(name) - putTree(body) - - case UnApply(fun: Tree, args) => - putTree(fun) - putTrees(args) - - case ArrayValue(elemtpt, trees) => - putTree(elemtpt) - putTrees(trees) - - - case Function(vparams, body) => - putTree(body) - putTrees(vparams) - - case Assign(lhs, rhs) => - putTree(lhs) - putTree(rhs) - - case If(cond, thenp, elsep) => - putTree(cond) - putTree(thenp) - putTree(elsep) - - case Match(selector, cases) => - putTree(selector) - putTrees(cases) - - case Return(expr) => - putTree(expr) - - case Try(block, catches, finalizer) => - putTree(block) - putTree(finalizer) - putTrees(catches) - - case Throw(expr) => - putTree(expr) - - case New(tpt) => - putTree(tpt) - - case Typed(expr, tpt) => - putTree(expr) - putTree(tpt) - - case TypeApply(fun, args) => - putTree(fun) - putTrees(args) - - case Apply(fun, args) => - putTree(fun) - putTrees(args) - - case ApplyDynamic(qual, args) => - putTree(qual) - putTrees(args) - - case Super(qual, mix) => - putTree(qual) - putEntry(mix:Name) - - case This(qual) => - putEntry(qual) - - case Select(qualifier, selector) => - putTree(qualifier) - putEntry(selector) - - case Ident(name) => - putEntry(name) - - case Literal(value) => - putEntry(value) - - case TypeTree() => - - case Annotated(annot, arg) => - putTree(annot) - putTree(arg) - - case SingletonTypeTree(ref) => - putTree(ref) - - case SelectFromTypeTree(qualifier, selector) => - putTree(qualifier) - putEntry(selector) - - case CompoundTypeTree(templ: Template) => - putTree(templ) - - case AppliedTypeTree(tpt, args) => - putTree(tpt) - putTrees(args) - - case TypeBoundsTree(lo, hi) => - putTree(lo) - putTree(hi) - - case ExistentialTypeTree(tpt, whereClauses) => - putTree(tpt) - putTrees(whereClauses) + private object putTreeTraverser extends Traverser { + // Only used when pickling trees, i.e. in an argument of some Annotation + // annotations in Modifiers are removed by the typechecker + override def traverseModifiers(mods: Modifiers): Unit = if (putEntry(mods)) putEntry(mods.privateWithin) + override def traverseName(name: Name): Unit = putEntry(name) + override def traverseConstant(const: Constant): Unit = putEntry(const) + override def traverse(tree: Tree): Unit = putTree(tree) + + def put(tree: Tree): Unit = { + if (tree.canHaveAttrs) + putType(tree.tpe) + if (tree.hasSymbolField) + putSymbol(tree.symbol) + + super.traverse(tree) } } - - private def putTrees(trees: List[Tree]) = trees foreach putTree - private def putTreess(treess: List[List[Tree]]) = treess foreach putTrees - - /** only used when pickling trees, i.e. in an - * argument of some Annotation */ - private def putMods(mods: Modifiers) = if (putEntry(mods)) { - // annotations in Modifiers are removed by the typechecker - val Modifiers(_, privateWithin, Nil) = mods - putEntry(privateWithin) + private def putTree(tree: Tree) { + if (putEntry(tree)) + putTreeTraverser put tree } /** Store a constant in map index, along with anything it references. @@ -461,7 +281,7 @@ abstract class Pickler extends SubComponent { } private def putChildren(sym: Symbol, children: List[Symbol]) { - assert(putEntry((sym, children))) + putEntry(sym -> children) children foreach putSymbol } @@ -469,14 +289,10 @@ abstract class Pickler extends SubComponent { private def putAnnotation(sym: Symbol, annot: AnnotationInfo) { // if an annotation with the same arguments is applied to the // same symbol multiple times, it's only pickled once. - if (putEntry((sym, annot))) + if (putEntry(sym -> annot)) putAnnotationBody(annot) } - /** used in AnnotatedType only, i.e. annotations on types */ - private def putAnnotations(annots: List[AnnotationInfo]) { - annots foreach putAnnotation - } private def putAnnotation(annot: AnnotationInfo) { if (putEntry(annot)) putAnnotationBody(annot) @@ -510,14 +326,11 @@ abstract class Pickler extends SubComponent { /** Write a reference to object, i.e., the object's number in the map index. */ - private def writeRef(ref0: AnyRef) { - val ref = ref0 match { - case sym: Symbol => deskolemize(sym) - case _ => ref0 - } - writeNat(index(ref)) + private def writeRef(ref: AnyRef) { + writeNat(index(deskolemizeTypeSymbols(ref))) } - private def writeRefs(refs: List[AnyRef]) { refs foreach writeRef } + private def writeRefs(refs: List[AnyRef]): Unit = refs foreach writeRef + private def writeRefsWithLength(refs: List[AnyRef]) { writeNat(refs.length) writeRefs(refs) @@ -567,446 +380,137 @@ abstract class Pickler extends SubComponent { } } - /** Write an entry */ - private def writeEntry(entry: AnyRef) { - def writeBody(entry: AnyRef): Int = entry match { - case name: Name => - writeName(name) - if (name.isTermName) TERMname else TYPEname - case NoSymbol => - NONEsym - case sym: Symbol if !isLocal(sym) => - val tag = - if (sym.isModuleClass) { - writeRef(sym.name.toTermName); EXTMODCLASSref - } else { - writeRef(sym.name); EXTref - } - if (!sym.owner.isRoot) writeRef(sym.owner) - tag - case sym: ClassSymbol => - writeSymInfo(sym) - if (sym.thisSym.tpe_* != sym.tpe_*) writeRef(sym.typeOfThis) - CLASSsym - case sym: TypeSymbol => - writeSymInfo(sym) - if (sym.isAbstractType) TYPEsym else ALIASsym - case sym: TermSymbol => - writeSymInfo(sym) - if (sym.alias != NoSymbol) writeRef(sym.alias) - if (sym.isModule) MODULEsym else VALsym - case NoType => - NOtpe - case NoPrefix => - NOPREFIXtpe - case ThisType(sym) => - writeRef(sym); THIStpe - case SingleType(pre, sym) => - writeRef(pre); writeRef(sym); SINGLEtpe - case SuperType(thistpe, supertpe) => - writeRef(thistpe); writeRef(supertpe); SUPERtpe - case ConstantType(value) => - writeRef(value); CONSTANTtpe - case TypeRef(pre, sym, args) => - writeRef(pre); writeRef(sym); writeRefs(args); TYPEREFtpe - case TypeBounds(lo, hi) => - writeRef(lo); writeRef(hi); TYPEBOUNDStpe - case tp @ RefinedType(parents, decls) => - writeRef(tp.typeSymbol); writeRefs(parents); REFINEDtpe - case ClassInfoType(parents, decls, clazz) => - writeRef(clazz); writeRefs(parents); CLASSINFOtpe - case mt @ MethodType(formals, restpe) => - writeRef(restpe); writeRefs(formals) ; METHODtpe - case mt @ NullaryMethodType(restpe) => - // reuse POLYtpe since those can never have an empty list of tparams. - // TODO: is there any way this can come back and bite us in the bottom? - // ugliness and thrift aside, this should make this somewhat more backward compatible - // (I'm not sure how old scalac's would deal with nested PolyTypes, as these used to be folded into one) - writeRef(restpe); writeRefs(Nil); POLYtpe - case PolyType(tparams, restpe) => // invar: tparams nonEmpty - writeRef(restpe); writeRefs(tparams); POLYtpe - case ExistentialType(tparams, restpe) => - writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe - case c @ Constant(_) => - if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0) - else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue) - else if (c.tag == FloatTag) writeLong(floatToIntBits(c.floatValue).toLong) - else if (c.tag == DoubleTag) writeLong(doubleToLongBits(c.doubleValue)) - else if (c.tag == StringTag) writeRef(newTermName(c.stringValue)) - else if (c.tag == ClazzTag) writeRef(c.typeValue) - else if (c.tag == EnumTag) writeRef(c.symbolValue) - LITERAL + c.tag // also treats UnitTag, NullTag; no value required - case AnnotatedType(annotations, tp, selfsym) => - annotations filter (_.isStatic) match { - case Nil => writeBody(tp) // write the underlying type if there are no annotations - case staticAnnots => - if (settings.selfInAnnots && selfsym != NoSymbol) - writeRef(selfsym) - writeRef(tp) - writeRefs(staticAnnots) - ANNOTATEDtpe - } - // annotations attached to a symbol (i.e. annots on terms) - case (target: Symbol, annot@AnnotationInfo(_, _, _)) => - writeRef(target) - writeAnnotation(annot) - SYMANNOT - - case ArrayAnnotArg(args) => - args foreach writeClassfileAnnotArg - ANNOTARGARRAY - - case (target: Symbol, children: List[_]) => - writeRef(target) - writeRefs(children.asInstanceOf[List[Symbol]]) - CHILDREN - - case EmptyTree => - writeNat(EMPTYtree) - TREE - - case tree@PackageDef(pid, stats) => - writeNat(PACKAGEtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(tree.mods) - writeRef(pid) - writeRefs(stats) - TREE - - case tree@ClassDef(mods, name, tparams, impl) => - writeNat(CLASStree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(mods) - writeRef(name) - writeRef(impl) - writeRefs(tparams) - TREE - - case tree@ModuleDef(mods, name, impl) => - writeNat(MODULEtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(mods) - writeRef(name) - writeRef(impl) - TREE - - case tree@ValDef(mods, name, tpt, rhs) => - writeNat(VALDEFtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(mods) - writeRef(name) - writeRef(tpt) - writeRef(rhs) - TREE - - case tree@DefDef(mods, name, tparams, vparamss, tpt, rhs) => - writeNat(DEFDEFtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(mods) - writeRef(name) - writeRefsWithLength(tparams) - writeNat(vparamss.length) - vparamss foreach writeRefsWithLength - writeRef(tpt) - writeRef(rhs) - TREE - - case tree@TypeDef(mods, name, tparams, rhs) => - writeNat(TYPEDEFtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(mods) - writeRef(name) - writeRef(rhs) - writeRefs(tparams) - TREE - - case tree@LabelDef(name, params, rhs) => - writeNat(LABELtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(name) - writeRef(rhs) - writeRefs(params) - TREE - - case tree@Import(expr, selectors) => - writeNat(IMPORTtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(expr) - for (ImportSelector(from, _, to, _) <- selectors) { - writeRef(from) - writeRef(to) - } - TREE - - case tree@DocDef(comment, definition) => - writeNat(DOCDEFtree) - writeRef(tree.tpe) - writeRef(Constant(comment)) - writeRef(definition) - TREE - - case tree@Template(parents, self, body) => - writeNat(TEMPLATEtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRefsWithLength(parents) - writeRef(self) - writeRefs(body) - TREE - - case tree@Block(stats, expr) => - writeNat(BLOCKtree) - writeRef(tree.tpe) - writeRef(expr) - writeRefs(stats) - TREE - - case tree@CaseDef(pat, guard, body) => - writeNat(CASEtree) - writeRef(tree.tpe) - writeRef(pat) - writeRef(guard) - writeRef(body) - TREE - - case tree@Alternative(trees) => - writeNat(ALTERNATIVEtree) - writeRef(tree.tpe) - writeRefs(trees) - TREE - - case tree@Star(elem) => - writeNat(STARtree) - writeRef(tree.tpe) - writeRef(elem) - TREE - - case tree@Bind(name, body) => - writeNat(BINDtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(name) - writeRef(body) - TREE - - case tree@UnApply(fun: Tree, args) => - writeNat(UNAPPLYtree) - writeRef(tree.tpe) - writeRef(fun) - writeRefs(args) - TREE - - case tree@ArrayValue(elemtpt, trees) => - writeNat(ARRAYVALUEtree) - writeRef(tree.tpe) - writeRef(elemtpt) - writeRefs(trees) - TREE - - case tree@Function(vparams, body) => - writeNat(FUNCTIONtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(body) - writeRefs(vparams) - TREE - - case tree@Assign(lhs, rhs) => - writeNat(ASSIGNtree) - writeRef(tree.tpe) - writeRef(lhs) - writeRef(rhs) - TREE - - case tree@If(cond, thenp, elsep) => - writeNat(IFtree) - writeRef(tree.tpe) - writeRef(cond) - writeRef(thenp) - writeRef(elsep) - TREE - - case tree@Match(selector, cases) => - writeNat(MATCHtree) - writeRef(tree.tpe) - writeRef(selector) - writeRefs(cases) - TREE - - case tree@Return(expr) => - writeNat(RETURNtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(expr) - TREE - - case tree@Try(block, catches, finalizer) => - writeNat(TREtree) - writeRef(tree.tpe) - writeRef(block) - writeRef(finalizer) - writeRefs(catches) - TREE - - case tree@Throw(expr) => - writeNat(THROWtree) - writeRef(tree.tpe) - writeRef(expr) - TREE - - case tree@New(tpt) => - writeNat(NEWtree) - writeRef(tree.tpe) - writeRef(tpt) - TREE - - case tree@Typed(expr, tpt) => - writeNat(TYPEDtree) - writeRef(tree.tpe) - writeRef(expr) - writeRef(tpt) - TREE - - case tree@TypeApply(fun, args) => - writeNat(TYPEAPPLYtree) - writeRef(tree.tpe) - writeRef(fun) - writeRefs(args) - TREE - - case tree@Apply(fun, args) => - writeNat(APPLYtree) - writeRef(tree.tpe) - writeRef(fun) - writeRefs(args) - TREE - - case tree@ApplyDynamic(qual, args) => - writeNat(APPLYDYNAMICtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(qual) - writeRefs(args) - TREE - - case tree@Super(qual, mix) => - writeNat(SUPERtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(qual) - writeRef(mix) - TREE - - case tree@This(qual) => - writeNat(THIStree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(qual) - TREE - - case tree@Select(qualifier, selector) => - writeNat(SELECTtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(qualifier) - writeRef(selector) - TREE - - case tree@Ident(name) => - writeNat(IDENTtree) - writeRef(tree.tpe) - writeRef(tree.symbol) - writeRef(name) - TREE - - case tree@Literal(value) => - writeNat(LITERALtree) - writeRef(tree.tpe) - writeRef(value) - TREE - - case tree@TypeTree() => - writeNat(TYPEtree) - writeRef(tree.tpe) - TREE - - case tree@Annotated(annot, arg) => - writeNat(ANNOTATEDtree) - writeRef(tree.tpe) - writeRef(annot) - writeRef(arg) - TREE - - case tree@SingletonTypeTree(ref) => - writeNat(SINGLETONTYPEtree) + private object writeTreeBodyTraverser extends Traverser { + private var refs = false + @inline private def asRefs[T](body: => T): T = { + val saved = refs + refs = true + try body finally refs = saved + } + override def traverseModifiers(mods: Modifiers): Unit = if (refs) writeRef(mods) else super.traverseModifiers(mods) + override def traverseName(name: Name): Unit = writeRef(name) + override def traverseConstant(const: Constant): Unit = writeRef(const) + override def traverseParams(params: List[Tree]): Unit = writeRefsWithLength(params) + override def traverseParamss(vparamss: List[List[Tree]]): Unit = { + writeNat(vparamss.length) + super.traverseParamss(vparamss) + } + override def traverse(tree: Tree): Unit = { + if (refs) + writeRef(tree) + else { writeRef(tree.tpe) - writeRef(ref) - TREE + if (tree.hasSymbolField) + writeRef(tree.symbol) - case tree@SelectFromTypeTree(qualifier, selector) => - writeNat(SELECTFROMTYPEtree) - writeRef(tree.tpe) - writeRef(qualifier) - writeRef(selector) - TREE + asRefs(super.traverse(tree)) + } + } + } - case tree@CompoundTypeTree(templ: Template) => - writeNat(COMPOUNDTYPEtree) - writeRef(tree.tpe) - writeRef(templ) - TREE + /** Write an entry */ + private def writeEntry(entry: AnyRef) { + def writeLocalSymbolBody(sym: Symbol) { + writeSymInfo(sym) + sym match { + case _: ClassSymbol if sym.hasSelfType => writeRef(sym.typeOfThis) + case _: TermSymbol if sym.alias.exists => writeRef(sym.alias) + case _ => + } + } + def writeExtSymbolBody(sym: Symbol) { + val name = if (sym.isModuleClass) sym.name.toTermName else sym.name + writeRef(name) + if (!sym.owner.isRoot) + writeRef(sym.owner) + } + def writeSymbolBody(sym: Symbol) { + if (sym ne NoSymbol) { + if (isLocal(sym)) + writeLocalSymbolBody(sym) + else + writeExtSymbolBody(sym) + } + } - case tree@AppliedTypeTree(tpt, args) => - writeNat(APPLIEDTYPEtree) - writeRef(tree.tpe) - writeRef(tpt) - writeRefs(args) - TREE + // NullaryMethodType reuses POLYtpe since those can never have an empty list of tparams. + // TODO: is there any way this can come back and bite us in the bottom? + // ugliness and thrift aside, this should make this somewhat more backward compatible + // (I'm not sure how old scalac's would deal with nested PolyTypes, as these used to be folded into one) + def writeTypeBody(tpe: Type): Unit = tpe match { + case NoType | NoPrefix => + case ThisType(sym) => writeRef(sym) + case SingleType(pre, sym) => writeRef(pre) ; writeRef(sym) + case SuperType(thistpe, supertpe) => writeRef(thistpe) ; writeRef(supertpe) + case ConstantType(value) => writeRef(value) + case TypeBounds(lo, hi) => writeRef(lo) ; writeRef(hi) + case TypeRef(pre, sym, args) => writeRef(pre) ; writeRef(sym); writeRefs(args) + case MethodType(formals, restpe) => writeRef(restpe) ; writeRefs(formals) + case NullaryMethodType(restpe) => writeRef(restpe); writeRefs(Nil) + case PolyType(tparams, restpe) => writeRef(restpe); writeRefs(tparams) + case ExistentialType(tparams, restpe) => writeRef(restpe); writeRefs(tparams) + case StaticallyAnnotatedType(annots, tp) => writeRef(tp) ; writeRefs(annots) + case AnnotatedType(_, tp, _) => writeTypeBody(tp) // write the underlying type if there are no static annotations + case CompoundType(parents, _, clazz) => writeRef(clazz); writeRefs(parents) + } - case tree@TypeBoundsTree(lo, hi) => - writeNat(TYPEBOUNDStree) - writeRef(tree.tpe) - writeRef(lo) - writeRef(hi) - TREE + def writeTreeBody(tree: Tree) { + writeNat(picklerSubTag(tree)) + if (!tree.isEmpty) + writeTreeBodyTraverser traverse tree + } - case tree@ExistentialTypeTree(tpt, whereClauses) => - writeNat(EXISTENTIALTYPEtree) - writeRef(tree.tpe) - writeRef(tpt) - writeRefs(whereClauses) - TREE + def writeConstant(c: Constant): Unit = c.tag match { + case BooleanTag => writeLong(if (c.booleanValue) 1 else 0) + case FloatTag => writeLong(floatToIntBits(c.floatValue).toLong) + case DoubleTag => writeLong(doubleToLongBits(c.doubleValue)) + case StringTag => writeRef(newTermName(c.stringValue)) + case ClazzTag => writeRef(c.typeValue) + case EnumTag => writeRef(c.symbolValue) + case tag => if (ByteTag <= tag && tag <= LongTag) writeLong(c.longValue) + } - case Modifiers(flags, privateWithin, _) => - val pflags = rawToPickledFlags(flags) - writeNat((pflags >> 32).toInt) - writeNat((pflags & 0xFFFFFFFF).toInt) - writeRef(privateWithin) - MODIFIERS + def writeModifiers(mods: Modifiers) { + val pflags = rawToPickledFlags(mods.flags) + writeNat((pflags >> 32).toInt) + writeNat((pflags & 0xFFFFFFFF).toInt) + writeRef(mods.privateWithin) + } - // annotations on types (not linked to a symbol) - case annot@AnnotationInfo(_, _, _) => - writeAnnotation(annot) - ANNOTINFO + def writeSymbolTuple(target: Symbol, other: Any) { + writeRef(target) + other match { + case annot: AnnotationInfo => writeAnnotation(annot) + case children: List[Symbol @unchecked] => writeRefs(children) + case _ => + } + } - case _ => - throw new FatalError("bad entry: " + entry + " " + entry.getClass) + def writeBody(entry: AnyRef): Unit = entry match { + case tree: Tree => writeTreeBody(tree) + case sym: Symbol => writeSymbolBody(sym) + case tpe: Type => writeTypeBody(tpe) + case name: Name => writeName(name) + case const: Constant => writeConstant(const) + case mods: Modifiers => writeModifiers(mods) + case annot: AnnotationInfo => writeAnnotation(annot) + case (target: Symbol, other) => writeSymbolTuple(target, other) + case ArrayAnnotArg(args) => args foreach writeClassfileAnnotArg + case _ => devWarning(s"Unexpected entry to pickler ${shortClassOfInstance(entry)} $entry") } // begin writeEntry - val startpos = writeIndex - // reserve some space so that the patchNat's most likely won't need to shift - writeByte(0); writeByte(0) - patchNat(startpos, writeBody(entry)) - patchNat(startpos + 1, writeIndex - (startpos + 2)) + // The picklerTag method can't determine if it's an external symbol reference + val tag = entry match { + case sym: Symbol if isExternalSymbol(sym) => if (sym.isModuleClass) EXTMODCLASSref else EXTref + case _ => picklerTag(entry) + } + writeNat(tag) + writeByte(0) // reserve a place to record the number of bytes written + val start = writeIndex + writeBody(entry) + val length = writeIndex - start + patchNat(start - 1, length) // patch bytes written over the placeholder } /** Write byte array */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 599969598e..e3d7bfd4f8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -425,11 +425,10 @@ trait Namers extends MethodSynthesis { sym } - /** Enter a module symbol. The tree parameter can be either - * a module definition or a class definition. + /** Enter a module symbol. */ def enterModuleSymbol(tree : ModuleDef): Symbol = { - var m: Symbol = context.scope lookupAll tree.name find (_.isModule) getOrElse NoSymbol + var m: Symbol = context.scope lookupModule tree.name val moduleFlags = tree.mods.flags | MODULE if (m.isModule && !m.isPackage && inCurrentScope(m) && (currentRun.canRedefine(m) || m.isSynthetic)) { updatePosFlags(m, tree.pos, moduleFlags) diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index 1b726c37b9..fd8f9bebba 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -283,6 +283,9 @@ abstract class TreeCheckers extends Analyzer { } private def traverseInternal(tree: Tree) { + if (!tree.canHaveAttrs) + return + checkSymbolRefsRespectScope(enclosingMemberDefs takeWhile (md => !md.symbol.hasPackageFlag), tree) checkReturnReferencesDirectlyEnclosingDef(tree) @@ -329,10 +332,9 @@ abstract class TreeCheckers extends Analyzer { return case _ => } - - if (tree.canHaveAttrs && tree.pos == NoPosition) + if (tree.pos == NoPosition) noPos(tree) - else if (tree.tpe == null && phase.id > currentRun.typerPhase.id) + else if (tree.tpe == null && isPastTyper) noType(tree) else if (tree.isDef) { checkSym(tree) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e93c0938e3..97e9d6ef52 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -13,7 +13,7 @@ package scala package tools.nsc package typechecker -import scala.collection.mutable +import scala.collection.{ mutable, immutable } import scala.reflect.internal.util.{ BatchSourceFile, Statistics, shortClassOfInstance } import mutable.ListBuffer import symtab.Flags._ @@ -3590,7 +3590,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper else { val annScope = annType.decls .filter(sym => sym.isMethod && !sym.isConstructor && sym.isJavaDefined) - val names = new scala.collection.mutable.HashSet[Symbol] + val names = mutable.Set[Symbol]() names ++= (if (isJava) annScope.iterator else typedFun.tpe.params.iterator) @@ -3603,7 +3603,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper val nvPairs = args map { case arg @ AssignOrNamedArg(Ident(name), rhs) => val sym = if (isJava) annScope.lookup(name) - else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol) + else findSymbol(typedFun.tpe.params)(_.name == name) if (sym == NoSymbol) { reportAnnotationError(UnknownAnnotationNameError(arg, name)) (nme.ERROR, None) @@ -3730,8 +3730,8 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper while (o != owner && o != NoSymbol && !o.hasPackageFlag) o = o.owner o == owner && !isVisibleParameter(sym) } - var localSyms = scala.collection.immutable.Set[Symbol]() - var boundSyms = scala.collection.immutable.Set[Symbol]() + var localSyms = immutable.Set[Symbol]() + var boundSyms = immutable.Set[Symbol]() def isLocal(sym: Symbol): Boolean = if (sym == NoSymbol || sym.isRefinementClass || sym.isLocalDummy) false else if (owner == NoSymbol) tree exists (defines(_, sym)) @@ -4311,7 +4311,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper NotAMemberError(tpt, TypeTree(tp), nme.CONSTRUCTOR) setError(tpt) } - else if (!( tp == sym.thisSym.tpe_* // when there's no explicit self type -- with (#3612) or without self variable + else if (!( tp == sym.typeOfThis // when there's no explicit self type -- with (#3612) or without self variable // sym.thisSym.tpe == tp.typeOfThis (except for objects) || narrowRhs(tp) <:< tp.typeOfThis || phase.erasedTypes diff --git a/src/reflect/scala/reflect/api/Trees.scala b/src/reflect/scala/reflect/api/Trees.scala index fa7d41f0fc..241747e6d8 100644 --- a/src/reflect/scala/reflect/api/Trees.scala +++ b/src/reflect/scala/reflect/api/Trees.scala @@ -2544,18 +2544,32 @@ trait Trees { self: Universe => class Traverser { protected[scala] var currentOwner: Symbol = rootMirror.RootClass + /** Traverse something which Trees contain, but which isn't a Tree itself. */ + def traverseName(name: Name): Unit = () + def traverseConstant(c: Constant): Unit = () + def traverseImportSelector(sel: ImportSelector): Unit = () + def traverseModifiers(mods: Modifiers): Unit = traverseAnnotations(mods.annotations) + /** Traverses a single tree. */ - def traverse(tree: Tree): Unit = itraverse(this, tree) + def traverse(tree: Tree): Unit = itraverse(this, tree) + def traversePattern(pat: Tree): Unit = traverse(pat) + def traverseGuard(guard: Tree): Unit = traverse(guard) + def traverseTypeAscription(tpt: Tree): Unit = traverse(tpt) + // Special handling of noSelfType necessary for backward compat: existing + // traversers break down when they see the unexpected tree. + def traverseSelfType(self: ValDef): Unit = if (self ne noSelfType) traverse(self) /** Traverses a list of trees. */ - def traverseTrees(trees: List[Tree]) { - trees foreach traverse - } + def traverseTrees(trees: List[Tree]): Unit = trees foreach traverse + def traverseTypeArgs(args: List[Tree]): Unit = traverseTrees(args) + def traverseParents(parents: List[Tree]): Unit = traverseTrees(parents) + def traverseCases(cases: List[CaseDef]): Unit = traverseTrees(cases) + def traverseAnnotations(annots: List[Tree]): Unit = traverseTrees(annots) /** Traverses a list of lists of trees. */ - def traverseTreess(treess: List[List[Tree]]) { - treess foreach traverseTrees - } + def traverseTreess(treess: List[List[Tree]]): Unit = treess foreach traverseTrees + def traverseParams(params: List[Tree]): Unit = traverseTrees(params) + def traverseParamss(vparamss: List[List[Tree]]): Unit = vparamss foreach traverseParams /** Traverses a list of trees with a given owner symbol. */ def traverseStats(stats: List[Tree], exprOwner: Symbol) { diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala index 215ab6abd6..f45fa40f89 100644 --- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala +++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala @@ -27,6 +27,8 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable => def filterAnnotations(p: AnnotationInfo => Boolean): Self // Retain only annotations meeting the condition. def withoutAnnotations: Self // Remove all annotations from this type. + def staticAnnotations = annotations filter (_.isStatic) + /** Symbols of any @throws annotations on this symbol. */ def throwsAnnotations(): List[Symbol] = annotations collect { diff --git a/src/reflect/scala/reflect/internal/Scopes.scala b/src/reflect/scala/reflect/internal/Scopes.scala index 485d4d5ddd..1060b3a99c 100644 --- a/src/reflect/scala/reflect/internal/Scopes.scala +++ b/src/reflect/scala/reflect/internal/Scopes.scala @@ -221,8 +221,8 @@ trait Scopes extends api.Scopes { self: SymbolTable => /** Lookup a module or a class, filtering out matching names in scope * which do not match that requirement. */ - def lookupModule(name: Name): Symbol = lookupAll(name.toTermName) find (_.isModule) getOrElse NoSymbol - def lookupClass(name: Name): Symbol = lookupAll(name.toTypeName) find (_.isClass) getOrElse NoSymbol + def lookupModule(name: Name): Symbol = findSymbol(lookupAll(name.toTermName))(_.isModule) + def lookupClass(name: Name): Symbol = findSymbol(lookupAll(name.toTypeName))(_.isClass) /** True if the name exists in this scope, false otherwise. */ def containsName(name: Name) = lookupEntry(name) != null diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index a6f9dfc164..98466ebb2b 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -41,6 +41,7 @@ abstract class SymbolTable extends macros.Universe with StdCreators with BuildUtils with PrivateWithin + with pickling.Translations { val gen = new TreeGen { val global: SymbolTable.this.type = SymbolTable.this } @@ -124,6 +125,10 @@ abstract class SymbolTable extends macros.Universe result } + @inline final def findSymbol(xs: TraversableOnce[Symbol])(p: Symbol => Boolean): Symbol = { + xs find p getOrElse NoSymbol + } + // For too long have we suffered in order to sort NAMES. // I'm pretty sure there's a reasonable default for that. // Notice challenge created by Ordering's invariance. diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index efdc8f7435..71de02ef9e 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -1859,6 +1859,8 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ def thisSym: Symbol = this + def hasSelfType = thisSym.tpeHK != this.tpeHK + /** The type of `this` in a class, or else the type of the symbol itself. */ def typeOfThis = thisSym.tpe_* diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 54a1913b96..9adddeed50 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -8,10 +8,12 @@ package reflect package internal import Flags._ -import scala.collection.mutable.{ListBuffer, LinkedHashSet} +import pickling.PickleFormat._ +import scala.collection.{ mutable, immutable } import util.Statistics -trait Trees extends api.Trees { self: SymbolTable => +trait Trees extends api.Trees { + self: SymbolTable => private[scala] var nodeCount = 0 @@ -160,7 +162,7 @@ trait Trees extends api.Trees { self: SymbolTable => override def freeTypes: List[FreeTypeSymbol] = freeSyms[FreeTypeSymbol](_.isFreeType, _.typeSymbol) private def freeSyms[S <: Symbol](isFree: Symbol => Boolean, symOfType: Type => Symbol): List[S] = { - val s = scala.collection.mutable.LinkedHashSet[S]() + val s = mutable.LinkedHashSet[S]() def addIfFree(sym: Symbol): Unit = if (sym != null && isFree(sym)) s += sym.asInstanceOf[S] for (t <- this) { addIfFree(t.symbol) @@ -1019,18 +1021,22 @@ trait Trees extends api.Trees { self: SymbolTable => } trait CannotHaveAttrs extends Tree { - override def canHaveAttrs = false - - private def requireLegal(value: Any, allowed: Any, what: String) = - require(value == allowed, s"can't set $what for $self to value other than $allowed") - super.setPos(NoPosition) + super.setType(NoType) + + override def canHaveAttrs = false override def setPos(pos: Position) = { requireLegal(pos, NoPosition, "pos"); this } override def pos_=(pos: Position) = setPos(pos) - - super.setType(NoType) override def setType(t: Type) = { requireLegal(t, NoType, "tpe"); this } override def tpe_=(t: Type) = setType(t) + + private def requireLegal(value: Any, allowed: Any, what: String) = ( + if (value != allowed) { + log(s"can't set $what for $self to value other than $allowed") + if (settings.debug && settings.developer) + (new Throwable).printStackTrace + } + ) } case object EmptyTree extends TermTree with CannotHaveAttrs { override def isEmpty = true; val asList = List(this) } @@ -1159,113 +1165,136 @@ trait Trees extends api.Trees { self: SymbolTable => override protected def itraverse(traverser: Traverser, tree: Tree): Unit = { import traverser._ - tree match { - case EmptyTree => - ; - case PackageDef(pid, stats) => - traverse(pid) - atOwner(mclass(tree.symbol)) { - traverseTrees(stats) - } - case ClassDef(mods, name, tparams, impl) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverse(impl) - } - case ModuleDef(mods, name, impl) => - atOwner(mclass(tree.symbol)) { - traverseTrees(mods.annotations); traverse(impl) - } - case ValDef(mods, name, tpt, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverse(tpt); traverse(rhs) - } - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverseTreess(vparamss); traverse(tpt); traverse(rhs) - } - case TypeDef(mods, name, tparams, rhs) => - atOwner(tree.symbol) { - traverseTrees(mods.annotations); traverseTrees(tparams); traverse(rhs) - } + + def traverseMemberDef(md: MemberDef, owner: Symbol): Unit = atOwner(owner) { + traverseModifiers(md.mods) + traverseName(md.name) + md match { + case ClassDef(_, _, tparams, impl) => traverseParams(tparams) ; traverse(impl) + case ModuleDef(_, _, impl) => traverse(impl) + case ValDef(_, _, tpt, rhs) => traverseTypeAscription(tpt) ; traverse(rhs) + case TypeDef(_, _, tparams, rhs) => traverseParams(tparams) ; traverse(rhs) + case DefDef(_, _, tparams, vparamss, tpt, rhs) => + traverseParams(tparams) + traverseParamss(vparamss) + traverseTypeAscription(tpt) + traverse(rhs) + } + } + def traverseComponents(): Unit = tree match { case LabelDef(name, params, rhs) => - traverseTrees(params); traverse(rhs) + traverseName(name) + traverseParams(params) + traverse(rhs) case Import(expr, selectors) => traverse(expr) + selectors foreach traverseImportSelector case Annotated(annot, arg) => - traverse(annot); traverse(arg) + traverse(annot) + traverse(arg) case Template(parents, self, body) => - traverseTrees(parents) - if (self ne noSelfType) traverse(self) + traverseParents(parents) + traverseSelfType(self) traverseStats(body, tree.symbol) case Block(stats, expr) => - traverseTrees(stats); traverse(expr) + traverseTrees(stats) + traverse(expr) case CaseDef(pat, guard, body) => - traverse(pat); traverse(guard); traverse(body) + traversePattern(pat) + traverseGuard(guard) + traverse(body) case Alternative(trees) => traverseTrees(trees) case Star(elem) => traverse(elem) case Bind(name, body) => + traverseName(name) traverse(body) case UnApply(fun, args) => - traverse(fun); traverseTrees(args) + traverse(fun) + traverseTrees(args) case ArrayValue(elemtpt, trees) => - traverse(elemtpt); traverseTrees(trees) - case Function(vparams, body) => - atOwner(tree.symbol) { - traverseTrees(vparams); traverse(body) - } + traverse(elemtpt) + traverseTrees(trees) case Assign(lhs, rhs) => - traverse(lhs); traverse(rhs) + traverse(lhs) + traverse(rhs) case AssignOrNamedArg(lhs, rhs) => - traverse(lhs); traverse(rhs) + traverse(lhs) + traverse(rhs) case If(cond, thenp, elsep) => - traverse(cond); traverse(thenp); traverse(elsep) + traverse(cond) + traverse(thenp) + traverse(elsep) case Match(selector, cases) => - traverse(selector); traverseTrees(cases) + traverse(selector) + traverseCases(cases) case Return(expr) => traverse(expr) case Try(block, catches, finalizer) => - traverse(block); traverseTrees(catches); traverse(finalizer) + traverse(block) + traverseCases(catches) + traverse(finalizer) case Throw(expr) => traverse(expr) case New(tpt) => traverse(tpt) case Typed(expr, tpt) => - traverse(expr); traverse(tpt) + traverse(expr) + traverseTypeAscription(tpt) case TypeApply(fun, args) => - traverse(fun); traverseTrees(args) + traverse(fun) + traverseTypeArgs(args) case Apply(fun, args) => - traverse(fun); traverseTrees(args) + traverse(fun) + traverseTrees(args) case ApplyDynamic(qual, args) => - traverse(qual); traverseTrees(args) - case Super(qual, _) => traverse(qual) - case This(_) => - ; + traverseTrees(args) + case Super(qual, mix) => + traverse(qual) + traverseName(mix) + case This(qual) => + traverseName(qual) case Select(qualifier, selector) => traverse(qualifier) - case Ident(_) => - ; + traverseName(selector) + case Ident(name) => + traverseName(name) case ReferenceToBoxed(idt) => traverse(idt) - case Literal(_) => - ; + case Literal(const) => + traverseConstant(const) case TypeTree() => ; case SingletonTypeTree(ref) => traverse(ref) case SelectFromTypeTree(qualifier, selector) => traverse(qualifier) + traverseName(selector) case CompoundTypeTree(templ) => traverse(templ) case AppliedTypeTree(tpt, args) => - traverse(tpt); traverseTrees(args) + traverse(tpt) + traverseTypeArgs(args) case TypeBoundsTree(lo, hi) => - traverse(lo); traverse(hi) + traverse(lo) + traverse(hi) case ExistentialTypeTree(tpt, whereClauses) => - traverse(tpt); traverseTrees(whereClauses) - case _ => xtraverse(traverser, tree) + traverse(tpt) + traverseTrees(whereClauses) + case _ => + xtraverse(traverser, tree) + } + + if (tree.canHaveAttrs) { + tree match { + case PackageDef(pid, stats) => traverse(pid) ; traverseStats(stats, mclass(tree.symbol)) + case md: ModuleDef => traverseMemberDef(md, mclass(tree.symbol)) + case md: MemberDef => traverseMemberDef(md, tree.symbol) + case Function(vparams, body) => atOwner(tree.symbol) { traverseParams(vparams) ; traverse(body) } + case _ => traverseComponents() + } } } @@ -1563,7 +1592,7 @@ trait Trees extends api.Trees { self: SymbolTable => } class FilterTreeTraverser(p: Tree => Boolean) extends Traverser { - val hits = new ListBuffer[Tree] + val hits = mutable.ListBuffer[Tree]() override def traverse(t: Tree) { if (p(t)) hits += t super.traverse(t) @@ -1571,7 +1600,7 @@ trait Trees extends api.Trees { self: SymbolTable => } class CollectTreeTraverser[T](pf: PartialFunction[Tree, T]) extends Traverser { - val results = new ListBuffer[T] + val results = mutable.ListBuffer[T]() override def traverse(t: Tree) { if (pf.isDefinedAt(t)) results += pf(t) super.traverse(t) diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 8f19e89dd4..9344212294 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -1483,6 +1483,14 @@ trait Types } } + object CompoundType { + def unapply(tp: Type): Option[(List[Type], Scope, Symbol)] = tp match { + case ClassInfoType(parents, decls, clazz) => Some((parents, decls, clazz)) + case RefinedType(parents, decls) => Some((parents, decls, tp.typeSymbol)) + case _ => None + } + } + /** A common base class for intersection types and class types */ abstract class CompoundType extends Type { @@ -3305,6 +3313,13 @@ trait Types object AnnotatedType extends AnnotatedTypeExtractor + object StaticallyAnnotatedType { + def unapply(tp: Type): Option[(List[AnnotationInfo], Type)] = tp.staticAnnotations match { + case Nil => None + case annots => Some((annots, tp.withoutAnnotations)) + } + } + /** A class representing types with a name. When an application uses * named arguments, the named argument types for calling isApplicable * are represented as NamedType. diff --git a/src/reflect/scala/reflect/internal/Variances.scala b/src/reflect/scala/reflect/internal/Variances.scala index bf00a7ac87..5280467055 100644 --- a/src/reflect/scala/reflect/internal/Variances.scala +++ b/src/reflect/scala/reflect/internal/Variances.scala @@ -142,7 +142,8 @@ trait Variances { // No variance check for object-private/protected methods/values. // Or constructors, or case class factory or extractor. def skip = ( - sym.hasLocalFlag + sym == NoSymbol + || sym.hasLocalFlag || sym.owner.isConstructor || sym.owner.isCaseApplyOrUnapply ) diff --git a/src/reflect/scala/reflect/internal/pickling/Translations.scala b/src/reflect/scala/reflect/internal/pickling/Translations.scala new file mode 100644 index 0000000000..e56cf796cb --- /dev/null +++ b/src/reflect/scala/reflect/internal/pickling/Translations.scala @@ -0,0 +1,128 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala +package reflect +package internal +package pickling + +import PickleFormat._ +import util.shortClassOfInstance + +trait Translations { + self: SymbolTable => + + def isTreeSymbolPickled(code: Int): Boolean = (code: @annotation.switch) match { + case PACKAGEtree | CLASStree | MODULEtree | VALDEFtree | DEFDEFtree | TYPEDEFtree | LABELtree => true + case IMPORTtree | TEMPLATEtree | BINDtree | FUNCTIONtree | RETURNtree => true + case APPLYDYNAMICtree | SUPERtree | THIStree | SELECTtree | IDENTtree => true + case _ => false + } + /** This method should be equivalent to tree.hasSymbolField, but that method + * doesn't do us any good when we're unpickling because we need to know based + * on the Int tag - the tree doesn't exist yet. Thus, this method is documentation only. + */ + def isTreeSymbolPickled(tree: Tree): Boolean = isTreeSymbolPickled(picklerSubTag(tree)) + + // The ad hoc pattern matching of tuples out of AnyRefs is a + // truly terrible idea. It reaches the height of its powers in + // combination with scala's insistence on helpfully tupling + // multiple arguments passed to a single-arg AnyRef. + def picklerTag(ref: AnyRef): Int = ref match { + case tp: Type => picklerTag(tp) + case sym: Symbol => picklerTag(sym) + case const: Constant => LITERAL + const.tag + case _: Tree => TREE // its sub tag more precisely identifies it + case _: TermName => TERMname + case _: TypeName => TYPEname + case _: ArrayAnnotArg => ANNOTARGARRAY // an array of annotation arguments + case _: AnnotationInfo => ANNOTINFO // annotations on types (not linked to a symbol) + case (_: Symbol, _: AnnotationInfo) => SYMANNOT // symbol annotations, i.e. on terms + case (_: Symbol, _: List[_]) => CHILDREN // the direct subclasses of a sealed symbol + case _: Modifiers => MODIFIERS + case _ => sys.error(s"unpicklable entry ${shortClassOfInstance(ref)} $ref") + } + + /** Local symbols only. The assessment of locality depends + * on convoluted conditions which depends in part on the root + * symbol being pickled, so it cannot be reproduced here. + * The pickler tags at stake are EXTMODCLASSref and EXTref. + * Those tags are never produced here - such symbols must be + * excluded prior to calling this method. + */ + def picklerTag(sym: Symbol): Int = sym match { + case NoSymbol => NONEsym + case _: ClassSymbol => CLASSsym + case _: TypeSymbol if sym.isAbstractType => TYPEsym + case _: TypeSymbol => ALIASsym + case _: TermSymbol if sym.isModule => MODULEsym + case _: TermSymbol => VALsym + } + + def picklerTag(tpe: Type): Int = tpe match { + case NoType => NOtpe + case NoPrefix => NOPREFIXtpe + case _: ThisType => THIStpe + case _: SingleType => SINGLEtpe + case _: SuperType => SUPERtpe + case _: ConstantType => CONSTANTtpe + case _: TypeBounds => TYPEBOUNDStpe + case _: TypeRef => TYPEREFtpe + case _: RefinedType => REFINEDtpe + case _: ClassInfoType => CLASSINFOtpe + case _: MethodType => METHODtpe + case _: PolyType => POLYtpe + case _: NullaryMethodType => POLYtpe // bad juju, distinct ints are not at a premium! + case _: ExistentialType => EXISTENTIALtpe + case _: AnnotatedType => ANNOTATEDtpe + } + + def picklerSubTag(tree: Tree): Int = tree match { + case EmptyTree => EMPTYtree + case _: PackageDef => PACKAGEtree + case _: ClassDef => CLASStree + case _: ModuleDef => MODULEtree + case _: ValDef => VALDEFtree + case _: DefDef => DEFDEFtree + case _: TypeDef => TYPEDEFtree + case _: LabelDef => LABELtree + case _: Import => IMPORTtree + // case _: DocDef => DOCDEFtree + case _: Template => TEMPLATEtree + case _: Block => BLOCKtree + case _: CaseDef => CASEtree + case _: Alternative => ALTERNATIVEtree + case _: Star => STARtree + case _: Bind => BINDtree + case _: UnApply => UNAPPLYtree + case _: ArrayValue => ARRAYVALUEtree + case _: Function => FUNCTIONtree + case _: Assign => ASSIGNtree + case _: If => IFtree + case _: Match => MATCHtree + case _: Return => RETURNtree + case _: Try => TREtree // TREtree? + case _: Throw => THROWtree + case _: New => NEWtree + case _: Typed => TYPEDtree + case _: TypeApply => TYPEAPPLYtree + case _: Apply => APPLYtree + case _: ApplyDynamic => APPLYDYNAMICtree + case _: Super => SUPERtree + case _: This => THIStree + case _: Select => SELECTtree + case _: Ident => IDENTtree + case _: Literal => LITERALtree + case _: TypeTree => TYPEtree + case _: Annotated => ANNOTATEDtree + case _: SingletonTypeTree => SINGLETONTYPEtree + case _: SelectFromTypeTree => SELECTFROMTYPEtree + case _: CompoundTypeTree => COMPOUNDTYPEtree + case _: AppliedTypeTree => APPLIEDTYPEtree + case _: TypeBoundsTree => TYPEBOUNDStree + case _: ExistentialTypeTree => EXISTENTIALTYPEtree + } +} + diff --git a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala index f42dbf56e1..c4f1f0cf96 100644 --- a/src/reflect/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/reflect/scala/reflect/internal/pickling/UnPickler.scala @@ -65,36 +65,38 @@ abstract class UnPickler { /** A map from symbols to their associated `decls` scopes */ private val symScopes = mutable.HashMap[Symbol, Scope]() + private def expect(expected: Int, msg: => String) { + val tag = readByte() + if (tag != expected) + errorBadSignature(s"$msg ($tag)") + } + //println("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug + @inline private def runAtIndex[T](i: Int)(body: => T): T = { + val saved = readIndex + readIndex = index(i) + try body finally readIndex = saved + } + // Laboriously unrolled for performance. def run() { var i = 0 while (i < index.length) { - if (entries(i) == null && isSymbolEntry(i)) { - val savedIndex = readIndex - readIndex = index(i) - entries(i) = readSymbol() - readIndex = savedIndex - } + if (entries(i) == null && isSymbolEntry(i)) + runAtIndex(i)(entries(i) = readSymbol()) + i += 1 } + // read children last, fix for #3951 i = 0 while (i < index.length) { if (entries(i) == null) { - if (isSymbolAnnotationEntry(i)) { - val savedIndex = readIndex - readIndex = index(i) - readSymbolAnnotation() - readIndex = savedIndex - } - else if (isChildrenEntry(i)) { - val savedIndex = readIndex - readIndex = index(i) - readChildren() - readIndex = savedIndex - } + if (isSymbolAnnotationEntry(i)) + runAtIndex(i)(readSymbolAnnotation()) + else if (isChildrenEntry(i)) + runAtIndex(i)(readChildren()) } i += 1 } @@ -145,6 +147,11 @@ abstract class UnPickler { tag == CHILDREN } + private def maybeReadSymbol(): Either[Int, Symbol] = readNat() match { + case index if isSymbolRef(index) => Right(at(index, readSymbol)) + case index => Left(index) + } + /** Does entry represent a refinement symbol? * pre: Entry is a class symbol */ @@ -256,14 +263,11 @@ abstract class UnPickler { val name = at(nameref, readName) val owner = readSymbolRef() val flags = pickledToRawFlags(readLongNat()) - var inforef = readNat() - val privateWithin = - if (!isSymbolRef(inforef)) NoSymbol - else { - val pw = at(inforef, readSymbol) - inforef = readNat() - pw - } + + val (privateWithin, inforef) = maybeReadSymbol() match { + case Left(index) => NoSymbol -> index + case Right(sym) => sym -> readNat() + } def isModuleFlag = (flags & MODULE) != 0L def isClassRoot = (name == classRoot.name) && (owner == classRoot.owner) @@ -305,7 +309,7 @@ abstract class UnPickler { sym case MODULEsym => - val clazz = at(inforef, () => readType()).typeSymbol // after the NMT_TRANSITION period, we can leave off the () => ... () + val clazz = at(inforef, () => readType()).typeSymbol // after NMT_TRANSITION, we can leave off the () => ... () if (isModuleRoot) moduleRoot setFlag pflags else owner.newLinkedModule(clazz, pflags) case VALsym => @@ -317,84 +321,48 @@ abstract class UnPickler { }) } - /** Read a type - * - * @param forceProperType is used to ease the transition to NullaryMethodTypes (commentmarker: NMT_TRANSITION) - * the flag say that a type of kind * is expected, so that PolyType(tps, restpe) can be disambiguated to PolyType(tps, NullaryMethodType(restpe)) - * (if restpe is not a ClassInfoType, a MethodType or a NullaryMethodType, which leaves TypeRef/SingletonType -- the latter would make the polytype a type constructor) - */ protected def readType(forceProperType: Boolean = false): Type = { val tag = readByte() val end = readEnd() + @inline def all[T](body: => T): List[T] = until(end, () => body) + + def readTypes() = all(readTypeRef) + def readSymbols() = all(readSymbolRef) + def readAnnots() = all(readAnnotationRef) + + // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType. + // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct + // alternative after parsing the arguments. + def MethodTypeRef(restpe: Type, params: List[Symbol]): Type = ( + if (restpe == NoType || (params contains NoSymbol)) NoType + else MethodType(params, restpe) + ) + def PolyOrNullaryType(restpe: Type, tparams: List[Symbol]): Type = tparams match { + case Nil => NullaryMethodType(restpe) + case _ => PolyType(tparams, restpe) + } + def CompoundType(clazz: Symbol, parents: List[Type]): Type = tag match { + case REFINEDtpe => RefinedType(parents, symScope(clazz), clazz) + case CLASSINFOtpe => ClassInfoType(parents, symScope(clazz), clazz) + } + + // We're stuck with the order types are pickled in, but with judicious use + // of named parameters we can recapture a declarative flavor in a few cases. + // But it's still a rat's nest of adhockery. (tag: @switch) match { - case NOtpe => - NoType - case NOPREFIXtpe => - NoPrefix - case THIStpe => - ThisType(readSymbolRef()) - case SINGLEtpe => - SingleType(readTypeRef(), readSymbolRef()) // !!! was singleType - case SUPERtpe => - val thistpe = readTypeRef() - val supertpe = readTypeRef() - SuperType(thistpe, supertpe) - case CONSTANTtpe => - ConstantType(readConstantRef()) - case TYPEREFtpe => - val pre = readTypeRef() - val sym = readSymbolRef() - val args = until(end, readTypeRef) - TypeRef(pre, sym, args) - case TYPEBOUNDStpe => - TypeBounds(readTypeRef(), readTypeRef()) - case REFINEDtpe => - val clazz = readSymbolRef() - RefinedType(until(end, readTypeRef), symScope(clazz), clazz) - case CLASSINFOtpe => - val clazz = readSymbolRef() - ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) - case METHODtpe | IMPLICITMETHODtpe => - val restpe = readTypeRef() - val params = until(end, readSymbolRef) - // if the method is overloaded, the params cannot be determined (see readSymbol) => return NoType. - // Only happen for trees, "case Apply" in readTree() takes care of selecting the correct - // alternative after parsing the arguments. - if (params.contains(NoSymbol) || restpe == NoType) NoType - else MethodType(params, restpe) - case POLYtpe => - val restpe = readTypeRef() - val typeParams = until(end, readSymbolRef) - if (typeParams.nonEmpty) { - // NMT_TRANSITION: old class files denoted a polymorphic nullary method as PolyType(tps, restpe), we now require PolyType(tps, NullaryMethodType(restpe)) - // when a type of kind * is expected (forceProperType is true), we know restpe should be wrapped in a NullaryMethodType (if it wasn't suitably wrapped yet) - def transitionNMT(restpe: Type) = { - val resTpeCls = restpe.getClass.toString // what's uglier than isInstanceOf? right! -- isInstanceOf does not work since the concrete types are defined in the compiler (not in scope here) - if(forceProperType /*&& pickleformat < 2.9 */ && !(resTpeCls.endsWith("MethodType"))) { assert(!resTpeCls.contains("ClassInfoType")) - NullaryMethodType(restpe) } - else restpe - } - PolyType(typeParams, transitionNMT(restpe)) - } - else - NullaryMethodType(restpe) - case EXISTENTIALtpe => - val restpe = readTypeRef() - newExistentialType(until(end, readSymbolRef), restpe) - - case ANNOTATEDtpe => - var typeRef = readNat() - val selfsym = if (isSymbolRef(typeRef)) { - val s = at(typeRef, readSymbol) - typeRef = readNat() - s - } else NoSymbol // selfsym can go. - val tp = at(typeRef, () => readType(forceProperType)) // NMT_TRANSITION - val annots = until(end, readAnnotationRef) - if (selfsym == NoSymbol) AnnotatedType(annots, tp, selfsym) - else tp - case _ => - noSuchTypeTag(tag, end) + case NOtpe => NoType + case NOPREFIXtpe => NoPrefix + case THIStpe => ThisType(readSymbolRef()) + case SINGLEtpe => SingleType(readTypeRef(), readSymbolRef()) + case SUPERtpe => SuperType(readTypeRef(), readTypeRef()) + case CONSTANTtpe => ConstantType(readConstantRef()) + case TYPEREFtpe => TypeRef(readTypeRef(), readSymbolRef(), readTypes()) + case TYPEBOUNDStpe => TypeBounds(readTypeRef(), readTypeRef()) + case REFINEDtpe | CLASSINFOtpe => CompoundType(readSymbolRef(), readTypes()) + case METHODtpe => MethodTypeRef(readTypeRef(), readSymbols()) + case POLYtpe => PolyOrNullaryType(readTypeRef(), readSymbols()) + case EXISTENTIALtpe => ExistentialType(underlying = readTypeRef(), quantified = readSymbols()) + case ANNOTATEDtpe => AnnotatedType(underlying = readTypeRef(), annotations = readAnnots(), selfsym = NoSymbol) } } @@ -483,9 +451,7 @@ abstract class UnPickler { * the symbol it requests. Called at top-level, for all * (symbol, annotInfo) entries. */ protected def readSymbolAnnotation() { - val tag = readByte() - if (tag != SYMANNOT) - errorBadSignature("symbol annotation expected ("+ tag +")") + expect(SYMANNOT, "symbol annotation expected") val end = readEnd() val target = readSymbolRef() target.addAnnotation(readAnnotationInfo(end)) @@ -501,260 +467,100 @@ abstract class UnPickler { readAnnotationInfo(end) } - /* Read an abstract syntax tree */ - protected def readTree(): Tree = { - val outerTag = readByte() - if (outerTag != TREE) - errorBadSignature("tree expected (" + outerTag + ")") - val end = readEnd() - val tag = readByte() - val tpe = if (tag == EMPTYtree) NoType else readTypeRef() - - // Set by the three functions to follow. If symbol is non-null - // after the new tree 't' has been created, t has its Symbol - // set to symbol; and it always has its Type set to tpe. - var symbol: Symbol = null - var mods: Modifiers = null - var name: Name = null - - /* Read a Symbol, Modifiers, and a Name */ - def setSymModsName() { - symbol = readSymbolRef() - mods = readModifiersRef() - name = readNameRef() + private def readNonEmptyTree(tag: Int, end: Int): Tree = { + @inline def all[T](body: => T): List[T] = until(end, () => body) + @inline def rep[T](body: => T): List[T] = times(readNat(), () => body) + + // !!! What is this doing here? + def fixApply(tree: Apply, tpe: Type): Apply = { + val Apply(fun, args) = tree + if (fun.symbol.isOverloaded) { + fun setType fun.symbol.info + inferMethodAlternative(fun, args map (_.tpe), tpe) + } + tree } - /* Read a Symbol and a Name */ - def setSymName() { - symbol = readSymbolRef() - name = readNameRef() + def ref() = readTreeRef() + def caseRef() = readCaseDefRef() + def modsRef() = readModifiersRef() + def implRef() = readTemplateRef() + def nameRef() = readNameRef() + def tparamRef() = readTypeDefRef() + def vparamRef() = readValDefRef() + def constRef() = readConstantRef() + def idRef() = readIdentRef() + def termNameRef() = readNameRef().toTermName + def typeNameRef() = readNameRef().toTypeName + def refTreeRef() = ref() match { + case t: RefTree => t + case t => errorBadSignature("RefTree expected, found " + t.shortClass) } - /* Read a Symbol */ - def setSym() { - symbol = readSymbolRef() + def selectorsRef() = all(ImportSelector(nameRef(), -1, nameRef(), -1)) + + /** A few of the most popular trees have been pulled to the top for + * switch efficiency purposes. + */ + def readTree(tpe: Type): Tree = (tag: @switch) match { + case IDENTtree => Ident(nameRef) + case SELECTtree => Select(ref, nameRef) + case APPLYtree => fixApply(Apply(ref, all(ref)), tpe) // !!! + case BINDtree => Bind(nameRef, ref) + case BLOCKtree => all(ref) match { case stats :+ expr => Block(stats, expr) } + case IFtree => If(ref, ref, ref) + case LITERALtree => Literal(constRef) + case TYPEAPPLYtree => TypeApply(ref, all(ref)) + case TYPEDtree => Typed(ref, ref) + case ALTERNATIVEtree => Alternative(all(ref)) + case ANNOTATEDtree => Annotated(ref, ref) + case APPLIEDTYPEtree => AppliedTypeTree(ref, all(ref)) + case APPLYDYNAMICtree => ApplyDynamic(ref, all(ref)) + case ARRAYVALUEtree => ArrayValue(ref, all(ref)) + case ASSIGNtree => Assign(ref, ref) + case CASEtree => CaseDef(ref, ref, ref) + case CLASStree => ClassDef(modsRef, typeNameRef, rep(tparamRef), implRef) + case COMPOUNDTYPEtree => CompoundTypeTree(implRef) + case DEFDEFtree => DefDef(modsRef, termNameRef, rep(tparamRef), rep(rep(vparamRef)), ref, ref) + case EXISTENTIALTYPEtree => ExistentialTypeTree(ref, all(ref)) + case FUNCTIONtree => Function(rep(vparamRef), ref) + case IMPORTtree => Import(ref, selectorsRef) + case LABELtree => LabelDef(termNameRef, rep(idRef), ref) + case MATCHtree => Match(ref, all(caseRef)) + case MODULEtree => ModuleDef(modsRef, termNameRef, implRef) + case NEWtree => New(ref) + case PACKAGEtree => PackageDef(refTreeRef, all(ref)) + case RETURNtree => Return(ref) + case SELECTFROMTYPEtree => SelectFromTypeTree(ref, typeNameRef) + case SINGLETONTYPEtree => SingletonTypeTree(ref) + case STARtree => Star(ref) + case SUPERtree => Super(ref, typeNameRef) + case TEMPLATEtree => Template(rep(ref), vparamRef, all(ref)) + case THIStree => This(typeNameRef) + case THROWtree => Throw(ref) + case TREtree => Try(ref, rep(caseRef), ref) + case TYPEBOUNDStree => TypeBoundsTree(ref, ref) + case TYPEDEFtree => TypeDef(modsRef, typeNameRef, rep(tparamRef), ref) + case TYPEtree => TypeTree() + case UNAPPLYtree => UnApply(ref, all(ref)) + case VALDEFtree => ValDef(modsRef, termNameRef, ref, ref) + case _ => noSuchTreeTag(tag, end) } - val t = tag match { - case EMPTYtree => - EmptyTree - - case PACKAGEtree => - setSym() - val pid = readTreeRef().asInstanceOf[RefTree] - val stats = until(end, readTreeRef) - PackageDef(pid, stats) - - case CLASStree => - setSymModsName() - val impl = readTemplateRef() - val tparams = until(end, readTypeDefRef) - ClassDef(mods, name.toTypeName, tparams, impl) - - case MODULEtree => - setSymModsName() - ModuleDef(mods, name.toTermName, readTemplateRef()) - - case VALDEFtree => - setSymModsName() - val tpt = readTreeRef() - val rhs = readTreeRef() - ValDef(mods, name.toTermName, tpt, rhs) - - case DEFDEFtree => - setSymModsName() - val tparams = times(readNat(), readTypeDefRef) - val vparamss = times(readNat(), () => times(readNat(), readValDefRef)) - val tpt = readTreeRef() - val rhs = readTreeRef() - DefDef(mods, name.toTermName, tparams, vparamss, tpt, rhs) - - case TYPEDEFtree => - setSymModsName() - val rhs = readTreeRef() - val tparams = until(end, readTypeDefRef) - TypeDef(mods, name.toTypeName, tparams, rhs) - - case LABELtree => - setSymName() - val rhs = readTreeRef() - val params = until(end, readIdentRef) - LabelDef(name.toTermName, params, rhs) - - case IMPORTtree => - setSym() - val expr = readTreeRef() - val selectors = until(end, () => { - val from = readNameRef() - val to = readNameRef() - ImportSelector(from, -1, to, -1) - }) - - Import(expr, selectors) - - case TEMPLATEtree => - setSym() - val parents = times(readNat(), readTreeRef) - val self = readValDefRef() - val body = until(end, readTreeRef) - - Template(parents, self, body) - - case BLOCKtree => - val expr = readTreeRef() - val stats = until(end, readTreeRef) - Block(stats, expr) - - case CASEtree => - val pat = readTreeRef() - val guard = readTreeRef() - val body = readTreeRef() - CaseDef(pat, guard, body) - - case ALTERNATIVEtree => - Alternative(until(end, readTreeRef)) - - case STARtree => - Star(readTreeRef()) - - case BINDtree => - setSymName() - Bind(name, readTreeRef()) - - case UNAPPLYtree => - val fun = readTreeRef() - val args = until(end, readTreeRef) - UnApply(fun, args) - - case ARRAYVALUEtree => - val elemtpt = readTreeRef() - val trees = until(end, readTreeRef) - ArrayValue(elemtpt, trees) - - case FUNCTIONtree => - setSym() - val body = readTreeRef() - val vparams = until(end, readValDefRef) - Function(vparams, body) - - case ASSIGNtree => - val lhs = readTreeRef() - val rhs = readTreeRef() - Assign(lhs, rhs) - - case IFtree => - val cond = readTreeRef() - val thenp = readTreeRef() - val elsep = readTreeRef() - If(cond, thenp, elsep) - - case MATCHtree => - val selector = readTreeRef() - val cases = until(end, readCaseDefRef) - Match(selector, cases) - - case RETURNtree => - setSym() - Return(readTreeRef()) - - case TREtree => - val block = readTreeRef() - val finalizer = readTreeRef() - val catches = until(end, readCaseDefRef) - Try(block, catches, finalizer) - - case THROWtree => - Throw(readTreeRef()) - - case NEWtree => - New(readTreeRef()) - - case TYPEDtree => - val expr = readTreeRef() - val tpt = readTreeRef() - Typed(expr, tpt) - - case TYPEAPPLYtree => - val fun = readTreeRef() - val args = until(end, readTreeRef) - TypeApply(fun, args) - - case APPLYtree => - val fun = readTreeRef() - val args = until(end, readTreeRef) - if (fun.symbol.isOverloaded) { - fun.setType(fun.symbol.info) - inferMethodAlternative(fun, args map (_.tpe), tpe) - } - Apply(fun, args) - - case APPLYDYNAMICtree => - setSym() - val qual = readTreeRef() - val args = until(end, readTreeRef) - ApplyDynamic(qual, args) - - case SUPERtree => - setSym() - val qual = readTreeRef() - val mix = readTypeNameRef() - Super(qual, mix) - - case THIStree => - setSym() - This(readTypeNameRef()) - - case SELECTtree => - setSym() - val qualifier = readTreeRef() - val selector = readNameRef() - Select(qualifier, selector) - - case IDENTtree => - setSymName() - Ident(name) - - case LITERALtree => - Literal(readConstantRef()) - - case TYPEtree => - TypeTree() - - case ANNOTATEDtree => - val annot = readTreeRef() - val arg = readTreeRef() - Annotated(annot, arg) - - case SINGLETONTYPEtree => - SingletonTypeTree(readTreeRef()) - - case SELECTFROMTYPEtree => - val qualifier = readTreeRef() - val selector = readTypeNameRef() - SelectFromTypeTree(qualifier, selector) - - case COMPOUNDTYPEtree => - CompoundTypeTree(readTemplateRef()) - - case APPLIEDTYPEtree => - val tpt = readTreeRef() - val args = until(end, readTreeRef) - AppliedTypeTree(tpt, args) - - case TYPEBOUNDStree => - val lo = readTreeRef() - val hi = readTreeRef() - TypeBoundsTree(lo, hi) - - case EXISTENTIALTYPEtree => - val tpt = readTreeRef() - val whereClauses = until(end, readTreeRef) - ExistentialTypeTree(tpt, whereClauses) + val tpe = readTypeRef() + val sym = if (isTreeSymbolPickled(tag)) readSymbolRef() else null + val result = readTree(tpe) - case _ => - noSuchTreeTag(tag, end) - } + if (sym ne null) result setSymbol sym + result setType tpe + } - if (symbol == null) t setType tpe - else t setSymbol symbol setType tpe + /* Read an abstract syntax tree */ + protected def readTree(): Tree = { + expect(TREE, "tree expected") + val end = readEnd() + readByte() match { + case EMPTYtree => EmptyTree + case tag => readNonEmptyTree(tag, end) + } } def noSuchTreeTag(tag: Int, end: Int) = diff --git a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala index e21e95903b..28afd18fe0 100644 --- a/src/reflect/scala/reflect/internal/settings/MutableSettings.scala +++ b/src/reflect/scala/reflect/internal/settings/MutableSettings.scala @@ -33,23 +33,26 @@ abstract class MutableSettings extends AbsSettings { } } - def overrideObjects: BooleanSetting - def printtypes: BooleanSetting + def Xexperimental: BooleanSetting + def XfullLubs: BooleanSetting + def XnoPatmatAnalysis: BooleanSetting + def Xprintpos: BooleanSetting + def Yposdebug: BooleanSetting + def Yrangepos: BooleanSetting + def Yshowsymkinds: BooleanSetting + def breakCycles: BooleanSetting def debug: BooleanSetting + def developer: BooleanSetting def explaintypes: BooleanSetting - def verbose: BooleanSetting + def overrideObjects: BooleanSetting + def printtypes: BooleanSetting def uniqid: BooleanSetting - def Yshowsymkinds: BooleanSetting - def Yposdebug: BooleanSetting - def Yrangepos: BooleanSetting - def Xprintpos: BooleanSetting + def verbose: BooleanSetting + def Yrecursion: IntSetting def maxClassfileName: IntSetting - def Xexperimental: BooleanSetting - def XnoPatmatAnalysis: BooleanSetting - def XfullLubs: BooleanSetting - def breakCycles: BooleanSetting } + object MutableSettings { import scala.language.implicitConversions /** Support the common use case, `if (settings.debug) println("Hello, martin.")` */ diff --git a/src/reflect/scala/reflect/runtime/Settings.scala b/src/reflect/scala/reflect/runtime/Settings.scala index d65e9329ed..11db83d7d5 100644 --- a/src/reflect/scala/reflect/runtime/Settings.scala +++ b/src/reflect/scala/reflect/runtime/Settings.scala @@ -34,16 +34,17 @@ private[reflect] class Settings extends MutableSettings { val XfullLubs = new BooleanSetting(false) val XnoPatmatAnalysis = new BooleanSetting(false) val Xprintpos = new BooleanSetting(false) - val Yshowsymkinds = new BooleanSetting(false) val Yposdebug = new BooleanSetting(false) val Yrangepos = new BooleanSetting(false) + val Yshowsymkinds = new BooleanSetting(false) + val breakCycles = new BooleanSetting(false) val debug = new BooleanSetting(false) + val developer = new BooleanSetting(false) val explaintypes = new BooleanSetting(false) val overrideObjects = new BooleanSetting(false) val printtypes = new BooleanSetting(false) val uniqid = new BooleanSetting(false) val verbose = new BooleanSetting(false) - val breakCycles = new BooleanSetting(false) val Yrecursion = new IntSetting(0) val maxClassfileName = new IntSetting(255) |