/* NSC -- new Scala compiler * Copyright 2005-2009 LAMP/EPFL * @author Martin Odersky */ // $Id: UnPickler.scala 18463 2009-08-11 07:22:25Z odersky $ package scala.tools.nsc package symtab package classfile import java.io.IOException import java.lang.{Float, Double} import scala.tools.nsc.util.{Position, NoPosition} import scala.io.UTF8Codec import Flags._ import PickleFormat._ import collection.mutable.{HashMap, ListBuffer} /** This abstract class implements .. * * @author Martin Odersky * @version 1.0 */ abstract class UnPickler { val global: Global import global._ /** Unpickle symbol table information descending from a class and/or module root * from an array of bytes. * @param bytes bytearray from which we unpickle * @param offset offset from which unpickling starts * @param classroot the top-level class which is unpickled, or NoSymbol if unapplicable * @param moduleroot the top-level module which is unpickled, or NoSymbol if unapplicable * @param filename filename associated with bytearray, only used for error messages */ def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) { try { val p = if (currentRun.isDefined && currentRun.picklerPhase != NoPhase && phase.id > currentRun.picklerPhase.id) currentRun.picklerPhase else phase atPhase(p) { new UnPickle(bytes, offset, classRoot, moduleRoot, filename) } } catch { case ex: IOException => throw ex case ex: Throwable => /*if (settings.debug.value)*/ ex.printStackTrace() throw new RuntimeException("error reading Scala signature of "+filename+": "+ex.getMessage()) } } private class UnPickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) extends PickleBuffer(bytes, offset, -1) { if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot) checkVersion(filename) /** A map from entry numbers to array offsets */ private val index = createIndex /** A map from entry numbers to symbols, types, or annotations */ private val entries = new Array[AnyRef](index.length) /** A map from symbols to their associated `decls' scopes */ private val symScopes = new HashMap[Symbol, Scope] for (i <- 0 until index.length) { if (isSymbolEntry(i)) at(i, readSymbol) else if (isSymbolAnnotationEntry(i)) at(i, {() => readSymbolAnnotation(); null}) else if (isChildrenEntry(i)) at(i, {() => readChildren(); null}) } if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug private def checkVersion(filename: String) { val major = readNat() val minor = readNat() if (major != MajorVersion || minor > MinorVersion) throw new IOException("Scala signature " + classRoot.name + " has wrong version\n expected: " + MajorVersion + "." + MinorVersion + "\n found: " + major + "." + minor + " in "+filename) } /** The `decls' scope associated with given symbol */ private def symScope(sym: Symbol, isTemp : Boolean) = symScopes.get(sym) match { case None => val s = if (isTemp) newTempScope else if (sym.isClass || sym.isModuleClass || sym.isModule) newClassScope(sym); else newScope symScopes(sym) = s; s case Some(s) => s } private def symScope(sym : Symbol) : Scope = symScope(sym, false) /** Does entry represent an (internal) symbol */ private def isSymbolEntry(i: Int): Boolean = { val tag = bytes(index(i)) (firstSymTag <= tag && tag <= lastSymTag && (tag != CLASSsym || !isRefinementSymbolEntry(i))) } /** Does entry represent an (internal or external) symbol */ private def isSymbolRef(i: Int): Boolean = { val tag = bytes(index(i)) (firstSymTag <= tag && tag <= lastExtSymTag) } /** Does entry represent a name? */ private def isNameEntry(i: Int): Boolean = { val tag = bytes(index(i)) tag == TERMname || tag == TYPEname } /** Does entry represent a symbol annotation? */ private def isSymbolAnnotationEntry(i: Int): Boolean = { val tag = bytes(index(i)) tag == SYMANNOT } /** Does the entry represent children of a symbol? */ private def isChildrenEntry(i: Int): Boolean = { val tag = bytes(index(i)) tag == CHILDREN } /** Does entry represent a refinement symbol? * pre: Entry is a class symbol */ private def isRefinementSymbolEntry(i: Int): Boolean = { val savedIndex = readIndex readIndex = index(i) val tag = readByte() if (tag != CLASSsym) assert(false) readNat(); // read length val result = readNameRef() == nme.REFINE_CLASS_NAME.toTypeName readIndex = savedIndex result } /** If entry at <code>i</code> is undefined, define it by performing * operation <code>op</code> with <code>readIndex at start of i'th * entry. Restore <code>readIndex</code> afterwards. */ private def at[T <: AnyRef](i: Int, op: () => T): T = { var r = entries(i) if (r eq null) { val savedIndex = readIndex readIndex = index(i) r = op() assert(entries(i) eq null, entries(i)) entries(i) = r readIndex = savedIndex } r.asInstanceOf[T] } /** Read a name */ private def readName(): Name = { val tag = readByte() val len = readNat() tag match { case TERMname => newTermName(bytes, readIndex, len) case TYPEname => newTypeName(bytes, readIndex, len) case _ => errorBadSignature("bad name tag: " + tag) } } /** Read a symbol */ private def readSymbol(): Symbol = { val tag = readByte() val end = readNat() + readIndex var sym: Symbol = NoSymbol tag match { case EXTref | EXTMODCLASSref => val name = readNameRef() val owner = if (readIndex == end) definitions.RootClass else readSymbolRef() def fromName(name: Name) = if (name.toTermName == nme.ROOT) definitions.RootClass else if (name == nme.ROOTPKG) definitions.RootPackage else if (tag == EXTref) owner.info.decl(name) else owner.info.decl(name).moduleClass sym = fromName(name) // If sym not found try with expanded name. // This can happen if references to private symbols are // read from outside; for instance when checking the children of a class // (see t1722) if (sym == NoSymbol) { sym = fromName(owner.expandedName(name)) } // If the owner is overloaded (i.e. a method), it's not possible to select the // right member => return NoSymbol. This can only happen when unpickling a tree. // the "case Apply" in readTree() takes care of selecting the correct alternative // after parsing the arguments. if (sym == NoSymbol && !owner.hasFlag(OVERLOADED)) { errorBadSignature( "reference " + (if (name.isTypeName) "type " else "value ") + name.decode + " of " + owner + " refers to nonexisting symbol.") } case NONEsym => sym = NoSymbol case _ => // symbols that were pickled with Pickler.writeSymInfo var defaultGetter: Symbol = NoSymbol var nameref = readNat() if (tag == VALsym && isSymbolRef(nameref)) { defaultGetter = at(nameref, readSymbol) nameref = readNat() } val name = at(nameref, readName) val owner = readSymbolRef() val flags = pickledToRawFlags(readLongNat()) var privateWithin: Symbol = NoSymbol var inforef = readNat() if (isSymbolRef(inforef)) { privateWithin = at(inforef, readSymbol) inforef = readNat() } tag match { case TYPEsym => sym = owner.newAbstractType(NoPosition, name) case ALIASsym => sym = owner.newAliasType(NoPosition, name) case CLASSsym => sym = if (name == classRoot.name && owner == classRoot.owner) (if ((flags & MODULE) != 0) moduleRoot.moduleClass else classRoot) else if ((flags & MODULE) != 0) owner.newModuleClass(NoPosition, name) else owner.newClass(NoPosition, name) if (readIndex != end) sym.typeOfThis = new LazyTypeRef(readNat()) case MODULEsym => val clazz = at(inforef, readType).typeSymbol sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot else { assert(clazz.isInstanceOf[ModuleClassSymbol], clazz) val mclazz = clazz.asInstanceOf[ModuleClassSymbol] val m = owner.newModule(NoPosition, name, mclazz) mclazz.setSourceModule(m) m } case VALsym => sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot.resetFlag(MODULE) else owner.newValue(NoPosition, name) sym.defaultGetter = defaultGetter case _ => errorBadSignature("bad symbol tag: " + tag) } sym.setFlag(flags.toLong & PickledFlags) sym.privateWithin = privateWithin if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR), sym) if (sym hasFlag SUPERACCESSOR) assert(readIndex != end) sym.setInfo( if (readIndex != end) new LazyTypeRefAndAlias(inforef, readNat()) else new LazyTypeRef(inforef)) if (sym.owner.isClass && sym != classRoot && sym != moduleRoot && !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter && !sym.isExistential) symScope(sym.owner) enter sym } sym } /** Read a type */ private def readType(): Type = { val tag = readByte() val end = readNat() + readIndex tag match { case NOtpe => NoType case NOPREFIXtpe => NoPrefix case THIStpe => mkThisType(readSymbolRef()) case SINGLEtpe => singleType(readTypeRef(), readSymbolRef()) case SUPERtpe => val thistpe = readTypeRef() val supertpe = readTypeRef() SuperType(thistpe, supertpe) case CONSTANTtpe => mkConstantType(readConstantRef()) case TYPEREFtpe => val pre = readTypeRef() val sym = readSymbolRef() var args = until(end, readTypeRef) rawTypeRef(pre, sym, args) case TYPEBOUNDStpe => mkTypeBounds(readTypeRef(), readTypeRef()) case REFINEDtpe => val clazz = readSymbolRef() /* val ps = until(end, readTypeRef) val dcls = symScope(clazz) new RefinedType(ps, dcls) { override def symbol = clazz } */ new RefinedType(until(end, readTypeRef), symScope(clazz, true)) { override def typeSymbol = clazz } case CLASSINFOtpe => val clazz = readSymbolRef() ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) case METHODtpe => 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 IMPLICITMETHODtpe => val restpe = readTypeRef() val params = until(end, readSymbolRef) ImplicitMethodType(params, restpe) case POLYtpe => val restpe = readTypeRef() val typeParams = until(end, readSymbolRef) // see comment above in "case METHODtpe" if (typeParams.contains(NoSymbol) || restpe == NoType) NoType else PolyType(typeParams, restpe) case EXISTENTIALtpe => val restpe = readTypeRef() ExistentialType(until(end, readSymbolRef), restpe) case ANNOTATEDtpe => var typeRef = readNat() val selfsym = if (isSymbolRef(typeRef)) { val s = at(typeRef, readSymbol) typeRef = readNat() s } else NoSymbol val tp = at(typeRef, readType) val annots = until(end, readAnnotationRef) if (settings.selfInAnnots.value || (selfsym == NoSymbol)) AnnotatedType(annots, tp, selfsym) else tp // drop annotations with a self symbol unless // -Yself-in-annots is on case DEBRUIJNINDEXtpe => DeBruijnIndex(readNat(), readNat()) case _ => errorBadSignature("bad type tag: " + tag) } } /** Read a constant */ private def readConstant(): Constant = { val tag = readByte() val len = readNat() tag match { case LITERALunit => Constant(()) case LITERALboolean => Constant(if (readLong(len) == 0) false else true) case LITERALbyte => Constant(readLong(len).asInstanceOf[Byte]) case LITERALshort => Constant(readLong(len).asInstanceOf[Short]) case LITERALchar => Constant(readLong(len).asInstanceOf[Char]) case LITERALint => Constant(readLong(len).asInstanceOf[Int]) case LITERALlong => Constant(readLong(len)) case LITERALfloat => Constant(Float.intBitsToFloat(readLong(len).asInstanceOf[Int])) case LITERALdouble => Constant(Double.longBitsToDouble(readLong(len))) case LITERALstring => Constant(readNameRef().toString()) case LITERALnull => Constant(null) case LITERALclass => Constant(readTypeRef()) case LITERALenum => Constant(readSymbolRef()) case _ => errorBadSignature("bad constant tag: " + tag) } } /** Read children and store them into the corresponding symbol. */ private def readChildren() { val tag = readByte() assert(tag == CHILDREN) val end = readNat() + readIndex val target = readSymbolRef() while (readIndex != end) target addChild readSymbolRef() } /** Read an annotation argument, which is pickled either * as a Constant or a Tree. */ private def readAnnotArg(): Tree = { if (peekByte() == TREE) { readTree() } else { val const = readConstant() Literal(const).setType(const.tpe) } } /** Read a ClassfileAnnotArg (argument to a classfile annotation) */ private def readClassfileAnnotArg(): ClassfileAnnotArg = { val b = peekByte() if (peekByte() == ANNOTINFO) { NestedAnnotArg(readAnnotation()) } else if (peekByte() == ANNOTARGARRAY) { readByte() val end = readNat() + readIndex ArrayAnnotArg(until(end, readClassfileAnnotArgRef).toArray) } else { LiteralAnnotArg(readConstant()) } } /** Read an AnnotationInfo. Not to be called directly, use * readAnnotation or readSymbolAnnotation */ private def readAnnotationInfo(end: Int): AnnotationInfo = { val atp = readTypeRef() val args = new ListBuffer[Tree] val assocs = new ListBuffer[(Name, ClassfileAnnotArg)] while (readIndex != end) { val argref = readNat() if (isNameEntry(argref)) assocs += ((at(argref, readName), readClassfileAnnotArgRef)) else args += at(argref, readAnnotArg) } AnnotationInfo(atp, args.toList, assocs.toList) } /** Read an annotation and as a side effect store it into * the symbol it requests. Called at top-level, for all * (symbol, annotInfo) entries. */ private def readSymbolAnnotation() { val tag = readByte() if (tag != SYMANNOT) errorBadSignature("symbol annotation expected ("+ tag +")") val end = readNat() + readIndex val target = readSymbolRef() target.addAnnotation(readAnnotationInfo(end)) } /** Read an annotation and return it. Used when unpickling * an ANNOTATED(WSELF)tpe or a NestedAnnotArg */ private def readAnnotation(): AnnotationInfo = { val tag = readByte() if (tag != ANNOTINFO) errorBadSignature("annotation expected (" + tag + ")") val end = readNat() + readIndex readAnnotationInfo(end) } /* Read an abstract syntax tree */ private def readTree(): Tree = { val outerTag = readByte() if (outerTag != TREE) errorBadSignature("tree expected (" + outerTag + ")") val end = readNat() + readIndex val tag = readByte() val tpe = if (tag != EMPTYtree) readTypeRef() else NoType tag match { case EMPTYtree => EmptyTree case PACKAGEtree => val symbol = readSymbolRef() val pid = readTreeRef().asInstanceOf[RefTree] val stats = until(end, readTreeRef) PackageDef(pid, stats) setType tpe case CLASStree => val symbol = readSymbolRef() val mods = readModifiersRef() val name = readNameRef() val impl = readTemplateRef() val tparams = until(end, readTypeDefRef) (ClassDef(mods, name, tparams, impl). setSymbol(symbol). setType(tpe)) case MODULEtree => val symbol = readSymbolRef() val mods = readModifiersRef() val name = readNameRef() val impl = readTemplateRef() (ModuleDef(mods, name, impl). setSymbol(symbol). setType(tpe)) case VALDEFtree => val symbol = readSymbolRef() val mods = readModifiersRef() val name = readNameRef() val tpt = readTreeRef() val rhs = readTreeRef() (ValDef(mods, name, tpt, rhs). setSymbol(symbol). setType(tpe)) case DEFDEFtree => val symbol = readSymbolRef() val mods = readModifiersRef() val name = readNameRef() val numTparams = readNat() val tparams = times(numTparams, readTypeDefRef) val numVparamss = readNat val vparamss = times(numVparamss, () => { val len = readNat() times(len, readValDefRef)}) val tpt = readTreeRef() val rhs = readTreeRef() (DefDef(mods, name, tparams, vparamss, tpt, rhs). setSymbol(symbol). setType(tpe)) case TYPEDEFtree => val symbol = readSymbolRef() val mods = readModifiersRef() val name = readNameRef() val rhs = readTreeRef() val tparams = until(end, readTypeDefRef) (TypeDef(mods, name, tparams, rhs). setSymbol(symbol). setType(tpe)) case LABELtree => val symbol = readSymbolRef() val name = readNameRef() val rhs = readTreeRef() val params = until(end, readIdentRef) (LabelDef(name, params, rhs). setSymbol(symbol). setType(tpe)) case IMPORTtree => val symbol = readSymbolRef() val expr = readTreeRef() val selectors = until(end, () => { val from = readNameRef() val to = readNameRef() (from, to) }) (Import(expr, selectors). setSymbol(symbol). setType(tpe)) case DOCDEFtree => val comment = readConstantRef match { case Constant(com: String) => com case other => errorBadSignature("Document comment not a string (" + other + ")") } val definition = readTreeRef() (DocDef(comment, definition).setType(tpe)) case TEMPLATEtree => val symbol = readSymbolRef() val numParents = readNat() val parents = times(numParents, readTreeRef) val self = readValDefRef() val body = until(end, readTreeRef) (Template(parents, self, body). setSymbol(symbol). setType(tpe)) case BLOCKtree => val expr = readTreeRef() val stats = until(end, readTreeRef) Block(stats, expr).setType(tpe) case CASEtree => val pat = readTreeRef() val guard = readTreeRef() val body = readTreeRef() CaseDef(pat, guard, body).setType(tpe) case SEQUENCEtree => val trees = until(end, readTreeRef) Sequence(trees).setType(tpe) case ALTERNATIVEtree => val trees = until(end, readTreeRef) Alternative(trees).setType(tpe) case STARtree => val elem = readTreeRef() Star(elem).setType(tpe) case BINDtree => val symbol = readSymbolRef() val name = readNameRef() val body = readTreeRef() (Bind(name, body). setSymbol(symbol). setType(tpe)) case UNAPPLYtree => val fun = readTreeRef() val args = until(end, readTreeRef) (UnApply(fun: Tree, args).setType(tpe)) case ARRAYVALUEtree => val elemtpt = readTreeRef() val trees = until(end, readTreeRef) (ArrayValue(elemtpt, trees).setType(tpe)) case FUNCTIONtree => val symbol = readSymbolRef() val body = readTreeRef() val vparams = until(end, readValDefRef) (Function(vparams, body). setSymbol(symbol). setType(tpe)) case ASSIGNtree => val lhs = readTreeRef() val rhs = readTreeRef() Assign(lhs, rhs).setType(tpe) case IFtree => val cond = readTreeRef() val thenp = readTreeRef() val elsep = readTreeRef() If(cond, thenp, elsep).setType(tpe) case MATCHtree => val selector = readTreeRef() val cases = until(end, readCaseDefRef) Match(selector, cases).setType(tpe) case RETURNtree => val symbol = readSymbolRef() val expr = readTreeRef() (Return(expr). setSymbol(symbol). setType(tpe)) case TREtree => val block = readTreeRef() val finalizer = readTreeRef() val catches = until(end, readCaseDefRef) Try(block, catches, finalizer).setType(tpe) case THROWtree => val expr = readTreeRef() Throw(expr).setType(tpe) case NEWtree => val tpt = readTreeRef() New(tpt).setType(tpe) case TYPEDtree => val expr = readTreeRef() val tpt = readTreeRef() Typed(expr, tpt).setType(tpe) case TYPEAPPLYtree => val fun = readTreeRef() val args = until(end, readTreeRef) TypeApply(fun, args).setType(tpe) case APPLYtree => val fun = readTreeRef() val args = until(end, readTreeRef) if (fun.symbol hasFlag OVERLOADED) { fun.setType(fun.symbol.info) typer.infer.inferMethodAlternative(fun, Nil, args map (_.tpe), tpe) } Apply(fun, args).setType(tpe) case APPLYDYNAMICtree => val symbol = readSymbolRef() val qual = readTreeRef() val args = until(end, readTreeRef) ApplyDynamic(qual, args).setSymbol(symbol).setType(tpe) case SUPERtree => val symbol = readSymbolRef() val qual = readNameRef() val mix = readNameRef() Super(qual, mix).setSymbol(symbol).setType(tpe) case THIStree => val symbol = readSymbolRef() val qual = readNameRef() This(qual).setSymbol(symbol).setType(tpe) case SELECTtree => val symbol = readSymbolRef() val qualifier = readTreeRef() val selector = readNameRef() Select(qualifier, selector).setSymbol(symbol).setType(tpe) case IDENTtree => val symbol = readSymbolRef() val name = readNameRef() Ident(name).setSymbol(symbol).setType(tpe) case LITERALtree => val value = readConstantRef() Literal(value).setType(tpe) case TYPEtree => TypeTree().setType(tpe) case ANNOTATEDtree => val annot = readTreeRef() val arg = readTreeRef() Annotated(annot, arg).setType(tpe) case SINGLETONTYPEtree => val ref = readTreeRef() SingletonTypeTree(ref).setType(tpe) case SELECTFROMTYPEtree => val qualifier = readTreeRef() val selector = readNameRef() SelectFromTypeTree(qualifier, selector).setType(tpe) case COMPOUNDTYPEtree => val templ = readTemplateRef() CompoundTypeTree(templ: Template).setType(tpe) case APPLIEDTYPEtree => val tpt = readTreeRef() val args = until(end, readTreeRef) AppliedTypeTree(tpt, args).setType(tpe) case TYPEBOUNDStree => val lo = readTreeRef() val hi = readTreeRef() TypeBoundsTree(lo, hi).setType(tpe) case EXISTENTIALTYPEtree => val tpt = readTreeRef() val whereClauses = until(end, readTreeRef) ExistentialTypeTree(tpt, whereClauses).setType(tpe) case _ => errorBadSignature("unknown tree type (" + tag + ")") } } def readModifiers(): Modifiers = { val tag = readNat() if (tag != MODIFIERS) errorBadSignature("expected a modifiers tag (" + tag + ")") val end = readNat() + readIndex val pflagsHi = readNat() val pflagsLo = readNat() val pflags = (pflagsHi.toLong << 32) + pflagsLo val flags = pickledToRawFlags(pflags) val privateWithin = readNameRef() Modifiers(flags, privateWithin, Nil) } /* Read a reference to a pickled item */ private def readNameRef(): Name = at(readNat(), readName) private def readSymbolRef(): Symbol = at(readNat(), readSymbol) private def readTypeRef(): Type = at(readNat(), readType) private def readConstantRef(): Constant = at(readNat(), readConstant) private def readAnnotArgRef(): Tree = at(readNat(), readAnnotArg) private def readClassfileAnnotArgRef(): ClassfileAnnotArg = at(readNat(), readClassfileAnnotArg) private def readAnnotationRef(): AnnotationInfo = at(readNat(), readAnnotation) private def readModifiersRef(): Modifiers = at(readNat(), readModifiers) private def readTreeRef(): Tree = at(readNat(), readTree) private def readTemplateRef(): Template = readTreeRef() match { case templ:Template => templ case other => errorBadSignature("expected a template (" + other + ")") } private def readCaseDefRef(): CaseDef = readTreeRef() match { case tree:CaseDef => tree case other => errorBadSignature("expected a case def (" + other + ")") } private def readValDefRef(): ValDef = readTreeRef() match { case tree:ValDef => tree case other => errorBadSignature("expected a ValDef (" + other + ")") } private def readIdentRef(): Ident = readTreeRef() match { case tree:Ident => tree case other => errorBadSignature("expected an Ident (" + other + ")") } private def readTypeDefRef(): TypeDef = readTreeRef() match { case tree:TypeDef => tree case other => errorBadSignature("expected an TypeDef (" + other + ")") } private def errorBadSignature(msg: String) = throw new RuntimeException("malformed Scala signature of " + classRoot.name + " at " + readIndex + "; " + msg) private class LazyTypeRef(i: Int) extends LazyType { private val definedAtRunId = currentRunId private val p = phase // In IDE, captures class files dependencies so they can be reloaded when their dependencies change. private val ideHook = unpickleIDEHook override def complete(sym: Symbol) : Unit = { val tp = ideHook(at(i, readType)) if (p != phase) atPhase(p) (sym setInfo tp) else sym setInfo tp if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp)) } override def load(sym: Symbol) { complete(sym) } } private class LazyTypeRefAndAlias(i: Int, j: Int) extends LazyTypeRef(i) { override def complete(sym: Symbol) { super.complete(sym) var alias = at(j, readSymbol) if (alias hasFlag OVERLOADED) { atPhase(currentRun.picklerPhase) { alias = alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)) } } sym.asInstanceOf[TermSymbol].setAlias(alias) } } } }