diff options
4 files changed, 51 insertions, 25 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala index 61dce9efb..9197a2acc 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala @@ -18,6 +18,8 @@ object TastyBuffer { def relativeTo(base: Addr): Addr = this - base.index - AddrWidth } + + val NoAddr = Addr(-1) /** The maximal number of address bytes. * Since addresses are written as base-128 natural numbers, diff --git a/src/dotty/tools/dotc/core/pickling/TreePickler.scala b/src/dotty/tools/dotc/core/pickling/TreePickler.scala index 5f18a7552..dc98a58f3 100644 --- a/src/dotty/tools/dotc/core/pickling/TreePickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TreePickler.scala @@ -26,8 +26,14 @@ class TreePickler(pickler: TastyPickler) { op fillRef(lengthAddr, currentAddr, relative = true) } + + def preRegister(tree: Tree)(implicit ctx: Context): Unit = tree match { + case tree: MemberDef => + if (!symRefs.contains(tree.symbol)) symRefs(tree.symbol) = NoAddr + case _ => + } - def registerDef(sym: Symbol) = { + def registerDef(sym: Symbol): Unit = { symRefs(sym) = currentAddr forwardSymRefs.get(sym) match { case Some(refs) => @@ -44,14 +50,18 @@ class TreePickler(pickler: TastyPickler) { pickleName(TastyName.Signed(nameIndex(name), params.map(nameIndex), nameIndex(result))) } - private def pickleSym(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match { + private def pickleSymRef(sym: Symbol)(implicit ctx: Context) = symRefs.get(sym) match { case Some(label) => - writeRef(label) + if (label != NoAddr) writeRef(label) else pickleForwardSymRef(sym) case None => - val ref = reserveRef(relative = false) - assert(!sym.is(Flags.Package), sym) - //assert(!sym.is(Flags.Param) || sym.owner.isClass, sym.showLocated) // TODO enable - forwardSymRefs(sym) = ref :: forwardSymRefs.getOrElse(sym, Nil) + ctx.log(i"pickling reference to as yet undefined $sym in ${sym.owner}", sym.pos) + pickleForwardSymRef(sym) + } + + private def pickleForwardSymRef(sym: Symbol)(implicit ctx: Context) = { + val ref = reserveRef(relative = false) + assert(!sym.is(Flags.Package), sym) + forwardSymRefs(sym) = ref :: forwardSymRefs.getOrElse(sym, Nil) } def pickle(trees: List[Tree])(implicit ctx: Context) = { @@ -116,7 +126,7 @@ class TreePickler(pickler: TastyPickler) { throw ex } - def pickleNewType(tpe: Type, richTypes: Boolean): Unit = tpe match { + def pickleNewType(tpe: Type, richTypes: Boolean): Unit = try { tpe match { case ConstantType(value) => pickleConstant(value) case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) => @@ -130,7 +140,7 @@ class TreePickler(pickler: TastyPickler) { else if (tpe.prefix == NoPrefix) { def pickleRef() = { writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) - pickleSym(sym) + pickleSymRef(sym) } if (sym is Flags.BindDefinedType) { registerDef(sym) @@ -145,7 +155,7 @@ class TreePickler(pickler: TastyPickler) { } else { writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) - pickleSym(sym); pickleType(tpe.prefix) + pickleSymRef(sym); pickleType(tpe.prefix) } case tpe: TermRefWithSignature => writeByte(TERMREF) @@ -212,6 +222,10 @@ class TreePickler(pickler: TastyPickler) { writeByte(NOTYPE) // case NoPrefix => // not sure we need this! // writeByte(NOPREFIX) + }} catch { + case ex: AssertionError => + println(i"error while pickling type $tpe") + throw ex } def pickleMethodic(result: Type, names: List[Name], types: List[Type]) = @@ -296,6 +310,7 @@ class TreePickler(pickler: TastyPickler) { withLength { pickleTree(lhs); pickleTree(rhs) } case Block(stats, expr) => writeByte(BLOCK) + stats.foreach(preRegister) withLength { pickleTree(expr); stats.foreach(pickleTree) } case If(cond, thenp, elsep) => writeByte(IF) @@ -311,7 +326,7 @@ class TreePickler(pickler: TastyPickler) { withLength { pickleTree(pat); pickleTree(rhs); pickleTreeIfNonEmpty(guard) } case Return(expr, from) => writeByte(RETURN) - withLength { pickleSym(from.symbol); pickleTreeIfNonEmpty(expr) } + withLength { pickleSymRef(from.symbol); pickleTreeIfNonEmpty(expr) } case Try(block, cases, finalizer) => writeByte(TRY) withLength { pickleTree(block); cases.foreach(pickleTree); pickleTreeIfNonEmpty(finalizer) } @@ -344,14 +359,14 @@ class TreePickler(pickler: TastyPickler) { case tree: ValDef => pickleDef(VALDEF, tree.symbol, tree.tpt, tree.rhs) case tree: DefDef => - def pickleParams = { - tree.tparams.foreach(pickleParam) + def pickleAllParams = { + pickleParams(tree.tparams) for (vparams <- tree.vparamss) { writeByte(PARAMS) - withLength { vparams.foreach(pickleParam) } + withLength { pickleParams(vparams) } } } - pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleParams) + pickleDef(DEFDEF, tree.symbol, tree.tpt, tree.rhs, pickleAllParams) case tree: TypeDef => pickleDef(TYPEDEF, tree.symbol, tree.rhs) case tree: Template => @@ -363,7 +378,7 @@ class TreePickler(pickler: TastyPickler) { case _ => false } withLength { - params.foreach(pickleParam) + pickleParams(params) tree.parents.foreach(pickleTree) val cinfo @ ClassInfo(_, _, _, _, selfInfo) = tree.symbol.owner.info if ((selfInfo ne NoType) || !tree.self.isEmpty) { @@ -373,8 +388,7 @@ class TreePickler(pickler: TastyPickler) { pickleType(cinfo.selfType) } } - pickleTree(tree.constr) - rest.foreach(pickleTree) + pickleStats(tree.constr :: rest) } case Import(expr, selectors) => writeByte(IMPORT) @@ -391,7 +405,7 @@ class TreePickler(pickler: TastyPickler) { } case PackageDef(pid, stats) => writeByte(PACKAGE) - withLength { pickleType(pid.tpe); stats.foreach(pickleTree) } + withLength { pickleType(pid.tpe); pickleStats(stats) } case EmptyTree => writeByte(EMPTYTREE) }} @@ -401,8 +415,8 @@ class TreePickler(pickler: TastyPickler) { throw ex } - def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ()) = { + assert(symRefs(sym) == NoAddr) registerDef(sym) writeByte(tag) withLength { @@ -421,6 +435,16 @@ class TreePickler(pickler: TastyPickler) { case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt) case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs) } + + def pickleParams(trees: List[Tree]): Unit = { + trees.foreach(preRegister) + trees.foreach(pickleParam) + } + + def pickleStats(stats: List[Tree]) = { + stats.foreach(preRegister) + stats.foreach(pickleTree) + } def pickleModifiers(sym: Symbol): Unit = { import Flags._ diff --git a/src/dotty/tools/dotc/reporting/Reporter.scala b/src/dotty/tools/dotc/reporting/Reporter.scala index 5bb660cdb..223fc33d5 100644 --- a/src/dotty/tools/dotc/reporting/Reporter.scala +++ b/src/dotty/tools/dotc/reporting/Reporter.scala @@ -109,9 +109,9 @@ trait Reporting { this: Context => * See [[config.CompilerCommand#explainAdvanced]] for the exact meaning of * "contains" here. */ - def log(msg: => String): Unit = + def log(msg: => String, pos: SourcePosition = NoSourcePosition): Unit = if (this.settings.log.value.containsPhase(phase)) - echo(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg") + echo(s"[log ${ctx.phasesStack.reverse.mkString(" -> ")}] $msg", pos) def debuglog(msg: => String): Unit = if (ctx.debug) log(msg) diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala index fd50df6ba..7bc41321c 100644 --- a/src/dotty/tools/dotc/transform/Pickler.scala +++ b/src/dotty/tools/dotc/transform/Pickler.scala @@ -6,7 +6,7 @@ import TreeTransforms._ import Contexts.Context import Decorators._ import pickling._ -import config.Printers +import config.Printers.{noPrinter, pickling} import java.io.PrintStream import Periods._ @@ -25,7 +25,7 @@ class Pickler extends MiniPhaseTransform { thisTransform => override def transformUnit(tree: Tree)(implicit ctx: Context, info: TransformerInfo): Tree = { if (!ctx.compilationUnit.isJava) { val pickler = new TastyPickler - println(i"unpickling in run ${ctx.runId}") + pickling.println(i"unpickling in run ${ctx.runId}") val previous = if (ctx.settings.YtestPickler.value) tree.show else "" val treePkl = new TreePickler(pickler) @@ -40,7 +40,7 @@ class Pickler extends MiniPhaseTransform { thisTransform => case (row, i) => s"${i}0: ${row.mkString(" ")}" } // println(i"rawBytes = \n$rawBytes%\n%") // DEBUG - if (Printers.pickling ne Printers.noPrinter) new TastyPrinter(bytes).printContents() + if (pickling ne noPrinter) new TastyPrinter(bytes).printContents() if (ctx.settings.YtestPickler.value) unpickle(bytes, previous)(ctx.fresh.setPeriod(Period(ctx.runId + 1, FirstPhaseId))) |