From 5b63106448275d6cc4bb6822af33247c2521a63c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 14 Feb 2015 18:39:14 +0100 Subject: Make some tree fields lazy Lazy fields are - the rhs field of a ValDef or DefDef - the body field of a Template These can be instantiated with Lazy instances. The scheme is such that lazy fields are completely transparent for users of the Trees API. The only downside is that the parameter used to initialize a potentially lazy field has a weak type (now it's Any, with Dotty it would be a union type of the form `T | Lazy[T]`. Therefore, the parameter cannot be recovered through pattern matching. --- src/dotty/tools/dotc/ast/Desugar.scala | 8 +-- src/dotty/tools/dotc/ast/TreeInfo.scala | 11 ++-- src/dotty/tools/dotc/ast/TreeTypeMap.scala | 8 +-- src/dotty/tools/dotc/ast/Trees.scala | 73 ++++++++++++++++------ src/dotty/tools/dotc/ast/tpd.scala | 2 +- src/dotty/tools/dotc/ast/untpd.scala | 6 +- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 14 ++--- src/dotty/tools/dotc/transform/Constructors.scala | 8 +-- src/dotty/tools/dotc/transform/LazyVals.scala | 14 ++--- .../tools/dotc/transform/MacroTransform.scala | 4 +- src/dotty/tools/dotc/transform/RestoreScopes.scala | 4 +- .../tools/dotc/transform/SuperAccessors.scala | 4 +- src/dotty/tools/dotc/transform/TailRec.scala | 8 +-- src/dotty/tools/dotc/typer/Namer.scala | 8 +-- src/dotty/tools/dotc/typer/Typer.scala | 19 +++--- 15 files changed, 113 insertions(+), 78 deletions(-) (limited to 'src/dotty/tools') diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index cd198818a..60ca45f28 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -218,7 +218,7 @@ object desugar { /** The expansion of a class definition. See inline comments for what is involved */ def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = { - val TypeDef(name, impl @ Template(constr0, parents, self, body)) = cdef + val TypeDef(name, impl @ Template(constr0, parents, self, _)) = cdef val mods = cdef.mods val (constr1, defaultGetters) = defDef(constr0, isPrimaryConstructor = true) match { @@ -242,7 +242,7 @@ object desugar { val constr = cpy.DefDef(constr1)(tparams = constrTparams, vparamss = constrVparamss) // Add constructor type parameters to auxiliary constructors - val normalizedBody = body map { + val normalizedBody = impl.body map { case ddef: DefDef if ddef.name.isConstructorName => cpy.DefDef(ddef)(tparams = constrTparams) case stat => @@ -425,10 +425,10 @@ object desugar { val modul = ValDef(name, clsRef, New(clsRef, Nil)) .withMods(mods | ModuleCreationFlags) .withPos(mdef.pos) - val ValDef(selfName, selfTpt, selfRhs) = tmpl.self + val ValDef(selfName, selfTpt, _) = tmpl.self val selfMods = tmpl.self.mods if (!selfTpt.isEmpty) ctx.error("object definition may not have a self type", tmpl.self.pos) - val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(name)), selfRhs) + val clsSelf = ValDef(selfName, SingletonTypeTree(Ident(name)), tmpl.self.rhs) .withMods(selfMods) .withPos(tmpl.self.pos orElse tmpl.pos.startPos) val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body) diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index 3d633c58d..6ebf29ffa 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -28,8 +28,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => */ def isPureInterfaceMember(tree: Tree): Boolean = unsplice(tree) match { case EmptyTree | Import(_, _) | TypeDef(_, _) => true - case DefDef(_, _, _, _, rhs) => rhs.isEmpty - case ValDef(_, _, rhs) => rhs.isEmpty + case defn: ValOrDefDef => defn.rhs.isEmpty case _ => false } @@ -91,7 +90,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] => /** If tree is a closure, it's body, otherwise tree itself */ def closureBody(tree: tpd.Tree): tpd.Tree = tree match { - case Block(DefDef(nme.ANON_FUN, _, _, _, rhs) :: Nil, Closure(_, _, _)) => rhs + case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs case _ => tree } @@ -287,8 +286,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => | Import(_, _) | DefDef(_, _, _, _, _) => Pure - case vdef @ ValDef(_, _, rhs) => - if (vdef.mods is Mutable) Impure else exprPurity(rhs) + case vdef @ ValDef(_, _, _) => + if (vdef.mods is Mutable) Impure else exprPurity(vdef.rhs) case _ => Impure } @@ -478,7 +477,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] => if (stats exists (definedSym(_) == sym)) stats else Nil encl match { case Block(stats, _) => verify(stats) - case Template(_, _, _, stats) => verify(stats) + case encl: Template => verify(encl.body) case PackageDef(_, stats) => verify(stats) case _ => Nil } diff --git a/src/dotty/tools/dotc/ast/TreeTypeMap.scala b/src/dotty/tools/dotc/ast/TreeTypeMap.scala index 98027cd39..d2ec3ea10 100644 --- a/src/dotty/tools/dotc/ast/TreeTypeMap.scala +++ b/src/dotty/tools/dotc/ast/TreeTypeMap.scala @@ -78,22 +78,22 @@ final class TreeTypeMap( } override def transform(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = treeMap(tree) match { - case impl @ Template(constr, parents, self, body) => + case impl @ Template(constr, parents, self, _) => val tmap = withMappedSyms(localSyms(impl :: self :: Nil)) cpy.Template(impl)( constr = tmap.transformSub(constr), parents = parents mapconserve transform, self = tmap.transformSub(self), - body = body mapconserve tmap.transform + body = impl.body mapconserve tmap.transform ).withType(tmap.mapType(impl.tpe)) case tree1 => tree1.withType(mapType(tree1.tpe)) match { case id: Ident if tpd.needsSelect(id.tpe) => ref(id.tpe.asInstanceOf[TermRef]).withPos(id.pos) - case ddef @ DefDef(name, tparams, vparamss, tpt, rhs) => + case ddef @ DefDef(name, tparams, vparamss, tpt, _) => val (tmap1, tparams1) = transformDefs(ddef.tparams) val (tmap2, vparamss1) = tmap1.transformVParamss(vparamss) - cpy.DefDef(ddef)(name, tparams1, vparamss1, tmap2.transform(tpt), tmap2.transform(rhs)) + cpy.DefDef(ddef)(name, tparams1, vparamss1, tmap2.transform(tpt), tmap2.transform(ddef.rhs)) case blk @ Block(stats, expr) => val (tmap1, stats1) = transformDefs(stats) val expr1 = tmap1.transform(expr) diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index ff44a48c5..57cbb7f8f 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -334,9 +334,9 @@ object Trees { } /** A ValDef or DefDef tree */ - trait ValOrDefDef[-T >: Untyped] extends MemberDef[T] { + trait ValOrDefDef[-T >: Untyped] extends MemberDef[T] with WithLazyField[Tree[T]] { def tpt: Tree[T] - def rhs: Tree[T] + def rhs: Tree[T] = forceIfLazy } // ----------- Tree case classes ------------------------------------ @@ -619,17 +619,22 @@ object Trees { } /** mods val name: tpt = rhs */ - case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], rhs: Tree[T]) + case class ValDef[-T >: Untyped] private[ast] (name: TermName, tpt: Tree[T], private var preRhs: Any /*Tree[T] | Lazy[Tree[T]]*/) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = ValDef[T] assert(isEmpty || tpt != genericEmptyTree) + protected def maybeLazy = preRhs + protected def maybeLazy_=(x: Any) = preRhs = x } /** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */ - case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T]) + case class DefDef[-T >: Untyped] private[ast] (name: TermName, tparams: List[TypeDef[T]], + vparamss: List[List[ValDef[T]]], tpt: Tree[T], private var preRhs: Any /*Tree[T] | Lazy[Tree[T]]*/) extends ValOrDefDef[T] { type ThisTree[-T >: Untyped] = DefDef[T] assert(tpt != genericEmptyTree) + protected def maybeLazy = preRhs + protected def maybeLazy_=(x: Any) = preRhs = x } /** mods class name template or @@ -652,9 +657,12 @@ object Trees { } /** extends parents { self => body } */ - case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]) - extends DefTree[T] { + case class Template[-T >: Untyped] private[ast] (constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], private var preBody: Any /*List[Tree[T]] | Lazy[List[Tree]]]*/) + extends DefTree[T] with WithLazyField[List[Tree[T]]] { type ThisTree[-T >: Untyped] = Template[T] + protected def maybeLazy = preBody + protected def maybeLazy_=(x: Any) = preBody = x + def body: List[Tree[T]] = forceIfLazy } /** import expr.selectors @@ -746,6 +754,33 @@ object Trees { if (buf != null) buf.toList else trees } + // ----- Lazy trees and tree sequences + + /** A tree that can have a lazy field + * The field is represented by some private `var` which is + * proxied by the `maybeLazy` accessors. Forcing the field will + * set the `var` to the underlying value. + */ + trait WithLazyField[+T] { + protected def maybeLazy: Any + protected def maybeLazy_=(x: Any): Unit + def forceIfLazy: T = maybeLazy match { + case lzy: Lazy[T] => + val x = lzy.complete + maybeLazy = x + x + case x: T @ unchecked => x + } + } + + /** A base trait for lazy tree fields. + * These can be instantiated with Lazy instances which + * can delay tree construction until the field is first demanded. + */ + trait Lazy[T] { + def complete: T + } + // ----- Generic Tree Instances, inherited from `tpt` and `untpd`. abstract class Instance[T >: Untyped <: Type] extends DotClass { inst => @@ -1114,16 +1149,16 @@ object Trees { cpy.UnApply(tree)(transform(fun), transform(implicits), transform(patterns)) case EmptyValDef => tree - case tree @ ValDef(name, tpt, rhs) => + case tree @ ValDef(name, tpt, _) => val tpt1 = transform(tpt) - val rhs1 = transform(rhs) - cpy.ValDef(tree)(name, tpt1, rhs1) - case tree @ DefDef(name, tparams, vparamss, tpt, rhs) => - cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(rhs)) + val rhs1 = transform(tree.rhs) + cpy.ValDef(tree)(name, transform(tpt1), transform(rhs1)) + case tree @ DefDef(name, tparams, vparamss, tpt, _) => + cpy.DefDef(tree)(name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(tree.rhs)) case tree @ TypeDef(name, rhs) => cpy.TypeDef(tree)(name, transform(rhs), tree.tparams) - case Template(constr, parents, self, body) => - cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(body)) + case tree @ Template(constr, parents, self, _) => + cpy.Template(tree)(transformSub(constr), transform(parents), transformSub(self), transformStats(tree.body)) case Import(expr, selectors) => cpy.Import(tree)(transform(expr), selectors) case PackageDef(pid, stats) => @@ -1213,14 +1248,14 @@ object Trees { this(x, trees) case UnApply(fun, implicits, patterns) => this(this(this(x, fun), implicits), patterns) - case ValDef(name, tpt, rhs) => - this(this(x, tpt), rhs) - case DefDef(name, tparams, vparamss, tpt, rhs) => - this(this((this(x, tparams) /: vparamss)(apply), tpt), rhs) + case tree @ ValDef(name, tpt, _) => + this(this(x, tpt), tree.rhs) + case tree @ DefDef(name, tparams, vparamss, tpt, _) => + this(this((this(x, tparams) /: vparamss)(apply), tpt), tree.rhs) case TypeDef(name, rhs) => this(x, rhs) - case Template(constr, parents, self, body) => - this(this(this(this(x, constr), parents), self), body) + case tree @ Template(constr, parents, self, _) => + this(this(this(this(x, constr), parents), self), tree.body) case Import(expr, selectors) => this(x, expr) case PackageDef(pid, stats) => diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala index 52a617ea2..49358a1c0 100644 --- a/src/dotty/tools/dotc/ast/tpd.scala +++ b/src/dotty/tools/dotc/ast/tpd.scala @@ -161,7 +161,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo { def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree], proto: Type)(implicit ctx: Context): UnApply = ta.assignType(untpd.UnApply(fun, implicits, patterns), proto) - def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef = + def ValDef(sym: TermSymbol, rhs: Any /*Tree | Lazy[Tree]*/ = EmptyTree)(implicit ctx: Context): ValDef = ta.assignType(untpd.ValDef(sym.name, TypeTree(sym.info), rhs), sym) def SyntheticValDef(name: TermName, rhs: Tree)(implicit ctx: Context): ValDef = diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala index dfff17514..d7791bfa5 100644 --- a/src/dotty/tools/dotc/ast/untpd.scala +++ b/src/dotty/tools/dotc/ast/untpd.scala @@ -142,10 +142,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo { def Bind(name: Name, body: Tree): Bind = new Bind(name, body) def Alternative(trees: List[Tree]): Alternative = new Alternative(trees) def UnApply(fun: Tree, implicits: List[Tree], patterns: List[Tree]): UnApply = new UnApply(fun, implicits, patterns) - def ValDef(name: TermName, tpt: Tree, rhs: Tree): ValDef = new ValDef(name, tpt, rhs) - def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) + def ValDef(name: TermName, tpt: Tree, rhs: Any /*Tree | Lazy[Tree]*/): ValDef = new ValDef(name, tpt, rhs) + def DefDef(name: TermName, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Any /*Tree | Lazy[Tree]*/): DefDef = new DefDef(name, tparams, vparamss, tpt, rhs) def TypeDef(name: TypeName, rhs: Tree): TypeDef = new TypeDef(name, rhs) - def Template(constr: DefDef, parents: List[Tree], self: ValDef, body: List[Tree]): Template = new Template(constr, parents, self, body) + def Template(constr: DefDef, parents: List[Tree], self: ValDef, body:Any /* List[Tree] | lazy[List[Tree]]*/): Template = new Template(constr, parents, self, body) def Import(expr: Tree, selectors: List[untpd.Tree]): Import = new Import(expr, selectors) def PackageDef(pid: RefTree, stats: List[Tree]): PackageDef = new PackageDef(pid, stats) def Annotated(annot: Tree, arg: Tree): Annotated = new Annotated(annot, arg) diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 43dbef890..d6dfd7db0 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -312,17 +312,17 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { toTextLocal(extractor) ~ "(" ~ toTextGlobal(patterns, ", ") ~ ")" ~ ("(" ~ toTextGlobal(implicits, ", ") ~ ")" provided implicits.nonEmpty) - case tree @ ValDef(name, tpt, rhs) => + case tree @ ValDef(name, tpt, _) => dclTextOr { modText(tree.mods, if (tree.mods is Mutable) "var" else "val") ~~ nameIdText(tree) ~ optAscription(tpt) - } ~ optText(rhs)(" = " ~ _) - case tree @ DefDef(name, tparams, vparamss, tpt, rhs) => + } ~ optText(tree.rhs)(" = " ~ _) + case tree @ DefDef(name, tparams, vparamss, tpt, _) => atOwner(tree) { dclTextOr { val first = modText(tree.mods, "def") ~~ nameIdText(tree) ~ tparamsText(tparams) addVparamssText(first, vparamss) ~ optAscription(tpt) - } ~ optText(rhs)(" = " ~ _) + } ~ optText(tree.rhs)(" = " ~ _) } case tree @ TypeDef(name, rhs) => atOwner(tree) { @@ -341,9 +341,9 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { typeDefText(optText(rhs)(" = " ~ _)) } } - case Template(constr @ DefDef(_, tparams, vparamss, _, rhs), parents, self, stats) => + case impl @ Template(constr @ DefDef(_, tparams, vparamss, _, _), parents, self, _) => val tparamsTxt = tparamsText(tparams) - val primaryConstrs = if (rhs.isEmpty) Nil else constr :: Nil + val primaryConstrs = if (constr.rhs.isEmpty) Nil else constr :: Nil val prefix: Text = if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt else { @@ -356,7 +356,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val selfName = if (self.name == nme.WILDCARD) "this" else self.name.toString (selfName ~ optText(self.tpt)(": " ~ _) ~ " =>").close } provided !self.isEmpty - val bodyText = "{" ~~ selfText ~~ toTextGlobal(primaryConstrs ::: stats, "\n") ~ "}" + val bodyText = "{" ~~ selfText ~~ toTextGlobal(primaryConstrs ::: impl.body, "\n") ~ "}" prefix ~~ (" extends" provided ownerIsClass) ~~ parentsText ~~ bodyText case Import(expr, selectors) => def selectorText(sel: Tree): Text = sel match { diff --git a/src/dotty/tools/dotc/transform/Constructors.scala b/src/dotty/tools/dotc/transform/Constructors.scala index d68f20696..f61ee68b9 100644 --- a/src/dotty/tools/dotc/transform/Constructors.scala +++ b/src/dotty/tools/dotc/transform/Constructors.scala @@ -149,14 +149,14 @@ class Constructors extends MiniPhaseTransform with SymTransformer { thisTransfor def splitStats(stats: List[Tree]): Unit = stats match { case stat :: stats1 => stat match { - case stat @ ValDef(name, tpt, rhs) if !stat.symbol.is(Lazy) => + case stat @ ValDef(name, tpt, _) if !stat.symbol.is(Lazy) => val sym = stat.symbol if (isRetained(sym)) { - if (!rhs.isEmpty && !isWildcardArg(rhs)) - constrStats += Assign(ref(sym), intoConstr(rhs)).withPos(stat.pos) + if (!stat.rhs.isEmpty && !isWildcardArg(stat.rhs)) + constrStats += Assign(ref(sym), intoConstr(stat.rhs)).withPos(stat.pos) clsStats += cpy.ValDef(stat)(rhs = EmptyTree) } - else if (!rhs.isEmpty) { + else if (!stat.rhs.isEmpty) { sym.copySymDenotation( initFlags = sym.flags &~ Private, owner = constr.symbol).installAfter(thisTransform) diff --git a/src/dotty/tools/dotc/transform/LazyVals.scala b/src/dotty/tools/dotc/transform/LazyVals.scala index dde086089..87644d2f9 100644 --- a/src/dotty/tools/dotc/transform/LazyVals.scala +++ b/src/dotty/tools/dotc/transform/LazyVals.scala @@ -83,7 +83,8 @@ class LazyVals extends MiniPhaseTransform with SymTransformer { * dotty.runtime(eg dotty.runtime.LazyInt) */ def transformLocalValDef(x: ValDef)(implicit ctx: Context) = x match { - case x@ValDef(name, tpt, valueInitter) => + case ValDef(name, tpt, _) => + val valueInitter = x.rhs val holderName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL).toTermName val initName = ctx.freshName(name.toString + StdNames.nme.LAZY_LOCAL_INIT).toTermName val tpe = x.tpe.widen @@ -162,7 +163,7 @@ class LazyVals extends MiniPhaseTransform with SymTransformer { } def transformFieldValDefNonVolatile(x: ValDef)(implicit ctx: Context) = x match { - case x@ValDef(name, tpt, rhs) if (x.mods is Flags.Lazy) => + case ValDef(name, tpt, _) if (x.mods is Flags.Lazy) => val claz = x.symbol.owner.asClass val tpe = x.tpe.widen assert(!(x.mods is Flags.Mutable)) @@ -171,17 +172,16 @@ class LazyVals extends MiniPhaseTransform with SymTransformer { val containerTree = ValDef(containerSymbol, initValue(tpe)) if (x.tpe.isNotNull && tpe <:< defn.AnyRefType) { // can use 'null' value instead of flag - val slowPath = DefDef(x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, rhs)) + val slowPath = DefDef(x.symbol.asTerm, mkDefNonThreadSafeNonNullable(containerSymbol, x.rhs)) Thicket(List(containerTree, slowPath)) } else { val flagName = ctx.freshName(name.toString + StdNames.nme.BITMAP_PREFIX).toTermName val flagSymbol = ctx.newSymbol(x.symbol.owner, flagName, containerFlags, defn.BooleanType) val flag = ValDef(flagSymbol, Literal(Constants.Constant(false))) - val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), rhs)) + val slowPath = DefDef(x.symbol.asTerm, mkNonThreadSafeDef(ref(containerSymbol), ref(flagSymbol), x.rhs)) Thicket(List(containerTree, flag, slowPath)) } - } /** Create non-threadsafe lazy accessor equivalent to such code @@ -281,7 +281,7 @@ class LazyVals extends MiniPhaseTransform with SymTransformer { } def transformFieldValDefVolatile(x: ValDef)(implicit ctx: Context) = x match { - case x@ValDef(name, tpt, rhs) if (x.mods is Flags.Lazy) => + case ValDef(name, tpt, _) if (x.mods is Flags.Lazy) => assert(!(x.mods is Flags.Mutable)) val tpe = x.tpe.widen @@ -334,7 +334,7 @@ class LazyVals extends MiniPhaseTransform with SymTransformer { val state = Select(ref(helperModule), RLazyVals.Names.state.toTermName) val cas = Select(ref(helperModule), RLazyVals.Names.cas.toTermName) - val accessor = mkThreadSafeDef(x.symbol.asTerm, claz, ord, containerSymbol, rhs, tpe, offset, getFlag, state, cas, setFlag, wait) + val accessor = mkThreadSafeDef(x.symbol.asTerm, claz, ord, containerSymbol, x.rhs, tpe, offset, getFlag, state, cas, setFlag, wait) if(flag eq EmptyTree) Thicket(List(containerTree, accessor)) else Thicket(List(containerTree, flag, accessor)) diff --git a/src/dotty/tools/dotc/transform/MacroTransform.scala b/src/dotty/tools/dotc/transform/MacroTransform.scala index 3a8bcc920..0f57c3ff5 100644 --- a/src/dotty/tools/dotc/transform/MacroTransform.scala +++ b/src/dotty/tools/dotc/transform/MacroTransform.scala @@ -58,12 +58,12 @@ abstract class MacroTransform extends Phase { tree case _: PackageDef | _: MemberDef => super.transform(tree)(localCtx(tree)) - case Template(constr, parents, self, body) => + case impl @ Template(constr, parents, self, _) => cpy.Template(tree)( transformSub(constr), transform(parents)(ctx.superCallContext), transformSelf(self), - transformStats(body, tree.symbol)) + transformStats(impl.body, tree.symbol)) case _ => super.transform(tree) } diff --git a/src/dotty/tools/dotc/transform/RestoreScopes.scala b/src/dotty/tools/dotc/transform/RestoreScopes.scala index 5f2fd689d..8a6bb15ba 100644 --- a/src/dotty/tools/dotc/transform/RestoreScopes.scala +++ b/src/dotty/tools/dotc/transform/RestoreScopes.scala @@ -20,9 +20,9 @@ class RestoreScopes extends MiniPhaseTransform with IdentityDenotTransformer { t override def phaseName = "restoreScopes" override def transformTypeDef(tree: TypeDef)(implicit ctx: Context, info: TransformerInfo) = { - val TypeDef(_, Template(constr, _, _, body)) = tree + val TypeDef(_, impl: Template) = tree val restoredDecls = newScope - for (stat <- constr :: body) + for (stat <- impl.constr :: impl.body) if (stat.isInstanceOf[MemberDef] && stat.symbol.exists) restoredDecls.enter(stat.symbol) val cls = tree.symbol.asClass diff --git a/src/dotty/tools/dotc/transform/SuperAccessors.scala b/src/dotty/tools/dotc/transform/SuperAccessors.scala index 0d89e9d74..c4ff6e549 100644 --- a/src/dotty/tools/dotc/transform/SuperAccessors.scala +++ b/src/dotty/tools/dotc/transform/SuperAccessors.scala @@ -369,9 +369,9 @@ class SuperAccessors extends MacroTransform with IdentityDenotTransformer { this } transformSelect - case tree @ DefDef(_, _, _, _, rhs) => + case tree: DefDef => cpy.DefDef(tree)( - rhs = if (isMethodWithExtension(sym)) withInvalidOwner(transform(rhs)) else transform(rhs)) + rhs = if (isMethodWithExtension(sym)) withInvalidOwner(transform(tree.rhs)) else transform(tree.rhs)) case TypeApply(sel @ Select(qual, name), args) => mayNeedProtectedAccessor(sel, args, goToSuper = true) diff --git a/src/dotty/tools/dotc/transform/TailRec.scala b/src/dotty/tools/dotc/transform/TailRec.scala index b747636c7..2fd0c439c 100644 --- a/src/dotty/tools/dotc/transform/TailRec.scala +++ b/src/dotty/tools/dotc/transform/TailRec.scala @@ -83,8 +83,8 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete override def transformDefDef(tree: tpd.DefDef)(implicit ctx: Context, info: TransformerInfo): tpd.Tree = { val sym = tree.symbol tree match { - case dd@DefDef(name, tparams, vparamss0, tpt, rhs0) - if (sym.isEffectivelyFinal) && !((sym is Flags.Accessor) || (rhs0 eq EmptyTree) || (sym is Flags.Label)) => + case dd@DefDef(name, tparams, vparamss0, tpt, _) + if (sym.isEffectivelyFinal) && !((sym is Flags.Accessor) || (dd.rhs eq EmptyTree) || (sym is Flags.Label)) => val mandatory = sym.hasAnnotation(defn.TailrecAnnotationClass) atGroupEnd { implicit ctx: Context => @@ -104,7 +104,7 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete // now this speculatively transforms tree and throws away result in many cases val rhsSemiTransformed = { val transformer = new TailRecElimination(origMeth, owner, thisTpe, mandatory, label, abstractOverClass = defIsTopLevel) - val rhs = atGroupEnd(transformer.transform(rhs0)(_)) + val rhs = atGroupEnd(transformer.transform(dd.rhs)(_)) rewrote = transformer.rewrote rhs } @@ -117,7 +117,7 @@ class TailRec extends MiniPhaseTransform with DenotTransformer with FullParamete } else { if (mandatory) ctx.error("TailRec optimisation not applicable, method not tail recursive", dd.pos) - rhs0 + dd.rhs } }) } diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index c522a5998..4bf194f5e 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -436,9 +436,9 @@ class Namer { typer: Typer => protected implicit val ctx: Context = localContext(cls).setMode(ictx.mode &~ Mode.InSuperCall) - val TypeDef(name, impl @ Template(constr, parents, self, body)) = original + val TypeDef(name, impl @ Template(constr, parents, self, _)) = original - val (params, rest) = body span { + val (params, rest) = impl.body span { case td: TypeDef => td.mods is Param case td: ValDef => td.mods is ParamAccessor case _ => false @@ -496,9 +496,9 @@ class Namer { typer: Typer => index(rest)(inClassContext(selfInfo)) denot.info = ClassInfo(cls.owner.thisType, cls, parentRefs, decls, selfInfo) if (cls is Trait) { - if (body forall isNoInitMember) { + if (impl.body forall isNoInitMember) { cls.setFlag(NoInits) - if (body forall isPureInterfaceMember) + if (impl.body forall isPureInterfaceMember) cls.setFlag(PureInterface) } } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 974a42638..1e93f98f3 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -794,7 +794,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val tpt1 = if (tree.tpt.isEmpty) TypeTree(defn.ObjectType) else typedAheadType(tree.tpt) val refineClsDef = desugar.refinedTypeToClass(tpt1, tree.refinements) val refineCls = createSymbol(refineClsDef).asClass - val TypeDef(_, Template(_, _, _, refinements1)) = typed(refineClsDef) + val TypeDef(_, impl: Template) = typed(refineClsDef) + val refinements1 = impl.body val seen = mutable.Set[Symbol]() assert(tree.refinements.length == refinements1.length, s"${tree.refinements} != $refinements1") def addRefinement(parent: Type, refinement: Tree): Type = { @@ -866,24 +867,24 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } def typedValDef(vdef: untpd.ValDef, sym: Symbol)(implicit ctx: Context) = track("typedValDef") { - val ValDef(name, tpt, rhs) = vdef + val ValDef(name, tpt, _) = vdef addTypedModifiersAnnotations(vdef, sym) val tpt1 = typedType(tpt) - val rhs1 = rhs match { - case Ident(nme.WILDCARD) => rhs withType tpt1.tpe - case _ => typedExpr(rhs, tpt1.tpe) + val rhs1 = vdef.rhs match { + case rhs @ Ident(nme.WILDCARD) => rhs withType tpt1.tpe + case rhs => typedExpr(rhs, tpt1.tpe) } assignType(cpy.ValDef(vdef)(name, tpt1, rhs1), sym) } def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = track("typedDefDef") { - val DefDef(name, tparams, vparamss, tpt, rhs) = ddef + val DefDef(name, tparams, vparamss, tpt, _) = ddef addTypedModifiersAnnotations(ddef, sym) val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) val vparamss1 = vparamss nestedMapconserve (typed(_).asInstanceOf[ValDef]) if (sym is Implicit) checkImplicitParamsNotSingletons(vparamss1) val tpt1 = typedType(tpt) - val rhs1 = typedExpr(rhs, tpt1.tpe) + val rhs1 = typedExpr(ddef.rhs, tpt1.tpe) assignType(cpy.DefDef(ddef)(name, tparams1, vparamss1, tpt1, rhs1), sym) //todo: make sure dependent method types do not depend on implicits or by-name params } @@ -896,7 +897,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit } def typedClassDef(cdef: untpd.TypeDef, cls: ClassSymbol)(implicit ctx: Context) = track("typedClassDef") { - val TypeDef(name, impl @ Template(constr, parents, self, body)) = cdef + val TypeDef(name, impl @ Template(constr, parents, self, _)) = cdef val superCtx = ctx.superCallContext def typedParent(tree: untpd.Tree): Tree = if (tree.isType) typedType(tree)(superCtx) @@ -913,7 +914,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit val parents1 = ensureConstrCall(cls, parentsWithClass)(superCtx) val self1 = typed(self)(ctx.outer).asInstanceOf[ValDef] // outer context where class members are not visible val dummy = localDummy(cls, impl) - val body1 = typedStats(body, dummy)(inClassContext(self1.symbol)) + val body1 = typedStats(impl.body, dummy)(inClassContext(self1.symbol)) checkNoDoubleDefs(cls) val impl1 = cpy.Template(impl)(constr1, parents1, self1, body1) .withType(dummy.nonMemberTermRef) -- cgit v1.2.3