From dd0e68e422d1c793ce5656795fd621f9b576fc24 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 2 Dec 2017 11:43:18 +0100 Subject: [PATCH 1/7] Fix #3608: Treat outer selections as separate Tasty tree Tasty needs to know about outer selections as separate trees. So instead of exposing a name for outer selects we expose a tree format. This allows us to store the type of tree selection in the tree, which got lost before. Also: Change format of NAMEDarg to no longer require a length. --- .../src/dotty/tools/dotc/core/NameTags.scala | 4 +++ .../tools/dotc/core/tasty/TastyFormat.scala | 30 +++++++++---------- .../dotc/core/tasty/TastyUnpickler.scala | 2 +- .../tools/dotc/core/tasty/TreePickler.scala | 22 ++++++++++---- .../tools/dotc/core/tasty/TreeUnpickler.scala | 7 +++-- tests/pickling/i3608.scala | 10 +++++++ 6 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 tests/pickling/i3608.scala diff --git a/compiler/src/dotty/tools/dotc/core/NameTags.scala b/compiler/src/dotty/tools/dotc/core/NameTags.scala index 3afe715147b4..11c890823100 100644 --- a/compiler/src/dotty/tools/dotc/core/NameTags.scala +++ b/compiler/src/dotty/tools/dotc/core/NameTags.scala @@ -11,6 +11,10 @@ object NameTags extends TastyFormat.NameTags { final val TRAITSETTER = 6 // A Scala-2 trait setter, generated by AugmentScala2Traits + final val OUTERSELECT = 13 // A name `_outer`, used by the inliner to indicate an + // outer accessor that will be filled in by ExplicitOuter. + // indicates the number of hops needed to select the outer field. + final val INITIALIZER = 24 // A mixin initializer method final val AVOIDCLASH = 25 // Adds a suffix to avoid a name clash; diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala index f2c8db08e2f4..82824495513d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala @@ -37,12 +37,11 @@ Macro-format: UNIQUE Length separator_NameRef uniqid_Nat underlying_NameRef? DEFAULTGETTER Length underlying_NameRef index_Nat VARIANT Length underlying_NameRef variance_Nat // 0: Contravariant, 1: Covariant - OUTERSELECT Length underlying_NameRef nhops_Nat SUPERACCESSOR Length underlying_NameRef PROTECTEDACCESSOR Length underlying_NameRef PROTECTEDSETTER Length underlying_NameRef - INITIALIZER Length underlying_NameRef + OBJECTCLASS Length underlying_NameRef SIGNED Length original_NameRef resultSig_NameRef paramSig_NameRef* @@ -81,9 +80,9 @@ Standard-Section: "ASTs" TopLevelStat* SELECT possiblySigned_NameRef qual_Term QUALTHIS typeIdent_Tree NEW cls_Type + NAMEDARG paramName_NameRef arg_Term SUPER Length this_Term mixinTypeIdent_Tree? TYPED Length expr_Term ascription_Type - NAMEDARG Length paramName_NameRef arg_Term ASSIGN Length lhs_Term rhs_Term BLOCK Length expr_Term Stat* INLINED Length call_Term expr_Term Stat* @@ -93,6 +92,7 @@ Standard-Section: "ASTs" TopLevelStat* TRY Length expr_Term CaseDef* finalizer_Term? RETURN Length meth_ASTRef expr_Term? REPEATED Length elem_Type elem_Term* + SELECTouter Length levels_Nat qual_Term underlying_Type BIND Length boundName_NameRef patType_Type pat_Term ALTERNATIVE Length alt_Term* UNAPPLY Length fun_Term ImplicitArg* pat_Type pat_Term* @@ -248,10 +248,6 @@ object TastyFormat { final val VARIANT = 12 // A name `+` o `-` indicating // a co- or contra-variant parameter of a type lambda. - final val OUTERSELECT = 13 // A name `_outer`, used by the inliner to indicate an - // outer accessor that will be filled in by ExplicitOuter. - // indicates the number of hops needed to select the outer field. - final val SUPERACCESSOR = 20 // The name of a super accessor `super$name` created by SuperAccesors. final val PROTECTEDACCESSOR = 21 // The name of a protected accessor `protected$` created by SuperAccesors. @@ -336,6 +332,7 @@ object TastyFormat { final val RECtype = 90 final val TYPEALIAS = 91 final val SINGLETONtpt = 92 + final val NAMEDARG = 93 // Cat. 4: tag Nat AST @@ -362,15 +359,15 @@ object TastyFormat { final val APPLY = 136 final val TYPEAPPLY = 137 final val TYPED = 138 - final val NAMEDARG = 139 - final val ASSIGN = 140 - final val BLOCK = 141 - final val IF = 142 - final val LAMBDA = 143 - final val MATCH = 144 - final val RETURN = 145 - final val TRY = 146 - final val INLINED = 147 + final val ASSIGN = 139 + final val BLOCK = 140 + final val IF = 141 + final val LAMBDA = 142 + final val MATCH = 143 + final val RETURN = 144 + final val TRY = 145 + final val INLINED = 146 + final val SELECTouter = 147 final val REPEATED = 148 final val BIND = 149 final val ALTERNATIVE = 150 @@ -536,6 +533,7 @@ object TastyFormat { case MATCH => "MATCH" case RETURN => "RETURN" case INLINED => "INLINED" + case SELECTouter => "SELECTouter" case TRY => "TRY" case REPEATED => "REPEATED" case BIND => "BIND" diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala index 87b074054ce7..f3ae3292776f 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -58,7 +58,7 @@ class TastyUnpickler(reader: TastyReader) { val originals = until(end)(readName()) val original = if (originals.isEmpty) EmptyTermName else originals.head uniqueNameKindOfSeparator(separator)(original, num) - case DEFAULTGETTER | VARIANT | OUTERSELECT => + case DEFAULTGETTER | VARIANT => numberedNameKindOfTag(tag)(readName(), readNat()) case SIGNED => val original = readName() diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 6986392c8e35..37e82f8fdf37 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -342,10 +342,21 @@ class TreePickler(pickler: TastyPickler) { pickleTree(qual.withType(tref)) } case Select(qual, name) => - writeByte(if (name.isTypeName) SELECTtpt else SELECT) - val sig = tree.tpe.signature - pickleNameAndSig(name, sig) - pickleTree(qual) + name match { + case OuterSelectName(_, levels) => + writeByte(SELECTouter) + withLength { + writeNat(levels) + pickleTree(qual) + val SkolemType(tp) = tree.tpe + pickleType(tp) + } + case _ => + writeByte(if (name.isTypeName) SELECTtpt else SELECT) + val sig = tree.tpe.signature + pickleNameAndSig(name, sig) + pickleTree(qual) + } case Apply(fun, args) => writeByte(APPLY) withLength { @@ -382,7 +393,8 @@ class TreePickler(pickler: TastyPickler) { withLength { pickleTree(expr); pickleTpt(tpt) } case NamedArg(name, arg) => writeByte(NAMEDARG) - withLength { pickleName(name); pickleTree(arg) } + pickleName(name) + pickleTree(arg) case Assign(lhs, rhs) => writeByte(ASSIGN) withLength { pickleTree(lhs); pickleTree(rhs) } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 41a98c8edae9..c1a06769a7c4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -913,6 +913,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi SingletonTypeTree(readTerm()) case BYNAMEtpt => ByNameTypeTree(readTpt()) + case NAMEDARG => + NamedArg(readName(), readTerm()) case _ => readPathTerm() } @@ -960,8 +962,6 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case expr => expr } Typed(expr1, tpt) - case NAMEDARG => - NamedArg(readName(), readTerm()) case ASSIGN => Assign(readTerm(), readTerm()) case BLOCK => @@ -983,6 +983,9 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi Return(expr, Ident(from.termRef)) case TRY => Try(readTerm(), readCases(end), ifBefore(end)(readTerm(), EmptyTree)) + case SELECTouter => + val levels = readNat() + readTerm().outerSelect(levels, SkolemType(readType())) case REPEATED => val elemtpt = readTpt() SeqLiteral(until(end)(readTerm()), elemtpt) diff --git a/tests/pickling/i3608.scala b/tests/pickling/i3608.scala new file mode 100644 index 000000000000..2751d5d017dd --- /dev/null +++ b/tests/pickling/i3608.scala @@ -0,0 +1,10 @@ +class A { + class Foo { + inline def inlineMeth: Unit = new Bar + } + class Bar +} + +class B extends A { + (new Foo).inlineMeth +} From 800e0aa61d0afce76a2683e1b5c6173146815310 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 2 Dec 2017 19:43:21 +0100 Subject: [PATCH 2/7] Fix #3597 - Don't check inline for params after pickling There was a discrepancy in that value parameters had a Deferred flag set before pickling but not after unpickling. This triggered a check that the (missing) rhs of an inline parameter was a constant. This commit changes the condition of the test to also exclude parameters. It also aligns frontend and unpickler in that the frontend will no longer mark term parameters as Deferred. --- compiler/src/dotty/tools/dotc/ast/TreeInfo.scala | 2 +- compiler/src/dotty/tools/dotc/core/Flags.scala | 2 +- compiler/src/dotty/tools/dotc/typer/Typer.scala | 2 +- tests/pos-from-tasty/i3597.scala | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 tests/pos-from-tasty/i3597.scala diff --git a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala index 77e38410990f..d44fb91aad63 100644 --- a/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/compiler/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -264,7 +264,7 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped] */ def lacksDefinition(mdef: MemberDef)(implicit ctx: Context) = mdef match { case mdef: ValOrDefDef => - mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor) + mdef.unforcedRhs == EmptyTree && !mdef.name.isConstructorName && !mdef.mods.is(TermParamOrAccessor) case mdef: TypeDef => def isBounds(rhs: Tree): Boolean = rhs match { case _: TypeBoundsTree => true diff --git a/compiler/src/dotty/tools/dotc/core/Flags.scala b/compiler/src/dotty/tools/dotc/core/Flags.scala index 66f17a3c7f85..60438a125334 100644 --- a/compiler/src/dotty/tools/dotc/core/Flags.scala +++ b/compiler/src/dotty/tools/dotc/core/Flags.scala @@ -575,7 +575,7 @@ object Flags { final val SyntheticOrPrivate = Synthetic | Private /** A deferred member or a parameter accessor (these don't have right hand sides) */ - final val DeferredOrParamAccessor = Deferred | ParamAccessor + final val DeferredOrParamOrAccessor = Deferred | Param | ParamAccessor /** value that's final or inline */ final val FinalOrInline = Final | Inline diff --git a/compiler/src/dotty/tools/dotc/typer/Typer.scala b/compiler/src/dotty/tools/dotc/typer/Typer.scala index 1519780ea8be..fcfdce97cc97 100644 --- a/compiler/src/dotty/tools/dotc/typer/Typer.scala +++ b/compiler/src/dotty/tools/dotc/typer/Typer.scala @@ -1300,7 +1300,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit case rhs => typedExpr(rhs, tpt1.tpe) } val vdef1 = assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) - if (sym.is(Inline, butNot = DeferredOrParamAccessor)) + if (sym.is(Inline, butNot = DeferredOrParamOrAccessor)) checkInlineConformant(rhs1, em"right-hand side of inline $sym") patchIfLazy(vdef1) patchFinalVals(vdef1) diff --git a/tests/pos-from-tasty/i3597.scala b/tests/pos-from-tasty/i3597.scala new file mode 100644 index 000000000000..04e33975ea2c --- /dev/null +++ b/tests/pos-from-tasty/i3597.scala @@ -0,0 +1,3 @@ +object Test { + def bar(inline n: Int) = n +} From c27e96c1cc5c82fc22473f83324ffba04bae1200 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Dec 2017 15:06:31 +0100 Subject: [PATCH 3/7] Fix condition in expandPrivate Previous condition did not take into account private static members. Their "enclosing class" is the enclosing package, but we really want to count them as static members of their lexical enclosing class here. --- compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala | 2 +- tests/run/i3006b.check | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala index 34bc6c6e2694..e5ee8556ec88 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExpandPrivate.scala @@ -74,7 +74,7 @@ class ExpandPrivate extends MiniPhase with IdentityDenotTransformer { thisPhase private def ensurePrivateAccessible(d: SymDenotation)(implicit ctx: Context) = if (isVCPrivateParamAccessor(d)) d.ensureNotPrivate.installAfter(thisPhase) - else if (d.is(PrivateTerm) && !d.owner.is(Package) && d.owner != ctx.owner.enclosingClass) { + else if (d.is(PrivateTerm) && !d.owner.is(Package) && d.owner != ctx.owner.lexicallyEnclosingClass) { // Paths `p1` and `p2` are similar if they have a common suffix that follows // possibly different directory paths. That is, their common suffix extends // in both cases either to the start of the path or to a file separator character. diff --git a/tests/run/i3006b.check b/tests/run/i3006b.check index b62605500d51..3698829ef115 100644 --- a/tests/run/i3006b.check +++ b/tests/run/i3006b.check @@ -1,3 +1,3 @@ -Foo$$_$bar$1 -Foo$$_$bar$2 -Bar$$_$bar$1 +bar$1 +bar$2 +bar$1 From 81116ea37533a86508c7f559d704f8200d0c4c29 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Dec 2017 15:07:09 +0100 Subject: [PATCH 4/7] Fix #3596: Handle supercall arguments in unpickler --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 27 +++++++++++-------- tests/pos-from-tasty/i3596.scala | 2 ++ 2 files changed, 18 insertions(+), 11 deletions(-) create mode 100644 tests/pos-from-tasty/i3596.scala diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index c1a06769a7c4..7b3c4edbfae2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -55,6 +55,9 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi */ private[this] var seenRoots: Set[Symbol] = Set() + /** A map from unpickled class symbols to their local dummies */ + private[this] val localDummies = new mutable.HashMap[ClassSymbol, Symbol] + /** The root owner tree. See `OwnerTree` class definition. Set by `enterTopLevel`. */ private[this] var ownerTree: OwnerTree = _ @@ -424,7 +427,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createMemberSymbol() case TEMPLATE => - val localDummy = ctx.newLocalDummy(ctx.owner) + val localDummy = localDummies(ctx.owner.asClass) registerSym(currentAddr, localDummy) localDummy case tag => @@ -478,6 +481,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi ctx.enter(sym) registerSym(start, sym) if (isClass) { + localDummies(sym.asClass) = ctx.newLocalDummy(sym) sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) } @@ -745,14 +749,15 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi else NoType cls.info = new TempClassInfo(cls.owner.thisType, cls, cls.unforcedDecls, assumedSelfType) val localDummy = symbolAtCurrent() + val parentCtx = ctx.withOwner(localDummy) assert(readByte() == TEMPLATE) val end = readEnd() val tparams = readIndexedParams[TypeDef](TYPEPARAM) val vparams = readIndexedParams[ValDef](PARAM) val parents = collectWhile(nextByte != SELFDEF && nextByte != DEFDEF) { nextByte match { - case APPLY | TYPEAPPLY => readTerm() - case _ => readTpt() + case APPLY | TYPEAPPLY => readTerm()(parentCtx) + case _ => readTpt()(parentCtx) } } val parentTypes = parents.map(_.tpe.dealias) @@ -766,13 +771,14 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi if (self.isEmpty) NoType else self.tpt.tpe) cls.setNoInitsFlags(fork.indexStats(end)) val constr = readIndexedDef().asInstanceOf[DefDef] + val mappedParents = parents.map(_.changeOwner(localDummy, constr.symbol)) val lazyStats = readLater(end, rdr => implicit ctx => { val stats = rdr.readIndexedStats(localDummy, end) tparams ++ vparams ++ stats }) setPos(start, - untpd.Template(constr, parents, self, lazyStats) + untpd.Template(constr, mappedParents, self, lazyStats) .withType(localDummy.termRef)) } @@ -922,15 +928,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi def readLengthTerm(): Tree = { val end = readEnd() - def localNonClassCtx = { - val ctx1 = ctx.fresh.setNewScope - if (ctx.owner.isClass) ctx1.setOwner(ctx1.newLocalDummy(ctx.owner)) else ctx1 - } - def readBlock(mkTree: (List[Tree], Tree) => Tree): Tree = { val exprReader = fork skipTree() - val localCtx = localNonClassCtx + val localCtx = ctx.fresh.setNewScope val stats = readStats(ctx.owner, end)(localCtx) val expr = exprReader.readTerm()(localCtx) mkTree(stats, expr) @@ -1030,7 +1031,11 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case ANNOTATEDtpt => Annotated(readTpt(), readTerm()) case LAMBDAtpt => - val localCtx = localNonClassCtx + var localCtx = ctx.fresh.setNewScope + ctx.owner match { + case cls: ClassSymbol => localCtx = localCtx.setOwner(localDummies(cls)) + case _ => + } val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) val body = readTpt()(localCtx) LambdaTypeTree(tparams, body) diff --git a/tests/pos-from-tasty/i3596.scala b/tests/pos-from-tasty/i3596.scala new file mode 100644 index 000000000000..6f122631779f --- /dev/null +++ b/tests/pos-from-tasty/i3596.scala @@ -0,0 +1,2 @@ +class Bar(ctor : Int => Int) +class Foo extends Bar(x => x) From d0a8606b77fcdb41d9b6c7158d37855d4d525cce Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Dec 2017 15:50:53 +0100 Subject: [PATCH 5/7] When unpickling, enter only class members into enclosing scope. --- compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 7b3c4edbfae2..6ae3d96f6eb7 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -478,7 +478,10 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord) } sym.annotations = annots - ctx.enter(sym) + ctx.owner match { + case cls: ClassSymbol => cls.enter(sym) + case _ => + } registerSym(start, sym) if (isClass) { localDummies(sym.asClass) = ctx.newLocalDummy(sym) From 3f291da1b7ffc7aa7df56134ec909e4de94ac6d7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Dec 2017 17:28:18 +0100 Subject: [PATCH 6/7] Clean up treatment of local contexts in unpickler --- .../tools/dotc/core/tasty/TreeUnpickler.scala | 35 +++++++------------ 1 file changed, 13 insertions(+), 22 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6ae3d96f6eb7..04c0a06bdba4 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -386,10 +386,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi private def noRhs(end: Addr): Boolean = currentAddr == end || isModifierTag(nextByte) - private def localContext(owner: Symbol)(implicit ctx: Context) = { - val lctx = ctx.fresh.setOwner(owner) - if (owner.isClass) lctx.setScope(owner.unforcedDecls) else lctx.setNewScope - } + private def localContext(owner: Symbol)(implicit ctx: Context) = + ctx.fresh.setOwner(owner) private def normalizeFlags(tag: Int, givenFlags: FlagSet, name: Name, isAbsType: Boolean, rhsIsEmpty: Boolean)(implicit ctx: Context): FlagSet = { val lacksDefinition = @@ -646,19 +644,18 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } } + val localCtx = localContext(sym) + def readRhs(implicit ctx: Context) = if (noRhs(end)) EmptyTree else readLater(end, rdr => ctx => rdr.readTerm()(ctx)) - def localCtx = localContext(sym) - def ValDef(tpt: Tree) = ta.assignType(untpd.ValDef(sym.name.asTermName, tpt, readRhs(localCtx)), sym) def DefDef(tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree) = ta.assignType( - untpd.DefDef( - sym.name.asTermName, tparams, vparamss, tpt, readRhs(localCtx)), + untpd.DefDef(sym.name.asTermName, tparams, vparamss, tpt, readRhs(localCtx)), sym) def TypeDef(rhs: Tree) = @@ -672,7 +669,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case DEFDEF => val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) val vparamss = readParamss(localCtx) - val tpt = readTpt() + val tpt = readTpt()(localCtx) val typeParams = tparams.map(_.symbol) val valueParamss = ctx.normalizeIfConstructor( vparamss.nestedMap(_.symbol), name == nme.CONSTRUCTOR) @@ -685,7 +682,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } DefDef(tparams, vparamss, tpt) case VALDEF => - val tpt = readTpt() + val tpt = readTpt()(localCtx) sym.info = tpt.tpe ValDef(tpt) case TYPEDEF | TYPEPARAM => @@ -704,7 +701,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } TypeDef(readTemplate(localCtx)) } else { - val rhs = readTpt() + val rhs = readTpt()(localCtx) sym.info = NoCompleter sym.info = rhs.tpe match { case _: TypeBounds | _: ClassInfo => checkNonCyclic(sym, rhs.tpe, reportErrors = false) @@ -713,7 +710,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi TypeDef(rhs) } case PARAM => - val tpt = readTpt() + val tpt = readTpt()(localCtx) if (noRhs(end)) { sym.info = tpt.tpe ValDef(tpt) @@ -934,9 +931,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi def readBlock(mkTree: (List[Tree], Tree) => Tree): Tree = { val exprReader = fork skipTree() - val localCtx = ctx.fresh.setNewScope - val stats = readStats(ctx.owner, end)(localCtx) - val expr = exprReader.readTerm()(localCtx) + val stats = readStats(ctx.owner, end) + val expr = exprReader.readTerm() mkTree(stats, expr) } @@ -1034,13 +1030,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case ANNOTATEDtpt => Annotated(readTpt(), readTerm()) case LAMBDAtpt => - var localCtx = ctx.fresh.setNewScope - ctx.owner match { - case cls: ClassSymbol => localCtx = localCtx.setOwner(localDummies(cls)) - case _ => - } - val tparams = readParams[TypeDef](TYPEPARAM)(localCtx) - val body = readTpt()(localCtx) + val tparams = readParams[TypeDef](TYPEPARAM) + val body = readTpt() LambdaTypeTree(tparams, body) case TYPEBOUNDStpt => TypeBoundsTree(readTpt(), readTpt()) From 2fa395b5704a6c71fc95665e403a94a0ecbd2047 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 3 Dec 2017 18:59:08 +0100 Subject: [PATCH 7/7] Drop localDummies again With the cleaned-up local scope handling we don't need them anymore. --- .../src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 04c0a06bdba4..8052deda72e5 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -55,9 +55,6 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi */ private[this] var seenRoots: Set[Symbol] = Set() - /** A map from unpickled class symbols to their local dummies */ - private[this] val localDummies = new mutable.HashMap[ClassSymbol, Symbol] - /** The root owner tree. See `OwnerTree` class definition. Set by `enterTopLevel`. */ private[this] var ownerTree: OwnerTree = _ @@ -425,7 +422,7 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi case VALDEF | DEFDEF | TYPEDEF | TYPEPARAM | PARAM => createMemberSymbol() case TEMPLATE => - val localDummy = localDummies(ctx.owner.asClass) + val localDummy = ctx.newLocalDummy(ctx.owner) registerSym(currentAddr, localDummy) localDummy case tag => @@ -482,7 +479,6 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi } registerSym(start, sym) if (isClass) { - localDummies(sym.asClass) = ctx.newLocalDummy(sym) sym.completer.withDecls(newScope) forkAt(templateStart).indexTemplateParams()(localContext(sym)) }