From 4a984f82d5bfca05123c53bd385d0299818f8a75 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Wed, 22 Feb 2012 22:46:32 -0800 Subject: Methods to derive new DefDefs. I guess I'd seen DefDef(mods, name, tparams, vparamss, tpt, rhs) one too many times and went a little crazy. What do you prefer: - val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1 - treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs)) + deriveDefDef(tree1)(transform) Me too. --- .../scala/tools/nsc/transform/AddInterfaces.scala | 6 +-- .../scala/tools/nsc/transform/CleanUp.scala | 7 ++- .../scala/tools/nsc/transform/Constructors.scala | 11 ++--- .../scala/tools/nsc/transform/Erasure.scala | 4 +- .../scala/tools/nsc/transform/ExplicitOuter.scala | 4 +- .../scala/tools/nsc/transform/LambdaLift.scala | 9 ++-- .../scala/tools/nsc/transform/LazyVals.scala | 5 +-- src/compiler/scala/tools/nsc/transform/Mixin.scala | 51 +++++++++++----------- .../tools/nsc/transform/SpecializeTypes.scala | 43 +++++++----------- .../scala/tools/nsc/transform/TailCalls.scala | 13 +++--- .../scala/tools/nsc/transform/UnCurry.scala | 34 ++++++++------- .../scala/tools/nsc/typechecker/RefChecks.scala | 9 ++-- src/library/scala/reflect/api/Trees.scala | 29 +++++++++++- 13 files changed, 116 insertions(+), 109 deletions(-) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index b4ec8a23ce..d5a413337b 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -319,10 +319,8 @@ abstract class AddInterfaces extends InfoTransform { case ClassDef(mods, name, tparams, impl) if (sym.needsImplClass) => implClass(sym).initialize // to force lateDEFERRED flags treeCopy.ClassDef(tree, mods | INTERFACE, name, tparams, ifaceTemplate(impl)) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) - if (sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass) => - treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, - addMixinConstructorCalls(rhs, sym.owner)) // (3) + case DefDef(_,_,_,_,_,_) if sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass => + deriveDefDef(tree)(addMixinConstructorCalls(_, sym.owner)) // (3) case Template(parents, self, body) => val parents1 = sym.owner.info.parents map (t => TypeTree(t) setPos tree.pos) treeCopy.Template(tree, parents1, emptyValDef, body) diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 50e6139e65..4521ce9982 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -669,9 +669,9 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val newCtor = findStaticCtor(template) match { // in case there already were static ctors - augment existing ones // currently, however, static ctors aren't being generated anywhere else - case Some(ctor @ DefDef(mods, name, tparams, vparamss, tpt, rhs)) => + case Some(ctor @ DefDef(_,_,_,_,_,_)) => // modify existing static ctor - val newBlock = rhs match { + deriveDefDef(ctor) { case block @ Block(stats, expr) => // need to add inits to existing block treeCopy.Block(block, newStaticInits.toList ::: stats, expr) @@ -679,11 +679,10 @@ abstract class CleanUp extends Transform with ast.TreeDSL { // need to create a new block with inits and the old term treeCopy.Block(term, newStaticInits.toList, term) } - treeCopy.DefDef(ctor, mods, name, tparams, vparamss, tpt, newBlock) case None => // create new static ctor val staticCtorSym = currentClass.newStaticConstructor(template.pos) - val rhs = Block(newStaticInits.toList, Literal(Constant())) + val rhs = Block(newStaticInits.toList, Literal(Constant(()))) localTyper.typedPos(template.pos)(DefDef(staticCtorSym, rhs)) } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index 4370714fa5..c638d25114 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -164,14 +164,12 @@ abstract class Constructors extends Transform with ast.TreeDSL { // Triage all template definitions to go into defBuf/auxConstructorBuf, constrStatBuf, or constrPrefixBuf. for (stat <- stats) stat match { - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + case DefDef(_,_,_,_,_,rhs) => // methods with constant result type get literals as their body // all methods except the primary constructor go into template stat.symbol.tpe match { case MethodType(List(), tp @ ConstantType(c)) => - defBuf += treeCopy.DefDef( - stat, mods, name, tparams, vparamss, tpt, - Literal(c) setPos rhs.pos setType tp) + defBuf += deriveDefDef(stat)(Literal(c) setPos _.pos setType tp) case _ => if (stat.symbol.isPrimaryConstructor) () else if (stat.symbol.isConstructor) auxConstructorBuf += stat @@ -547,13 +545,12 @@ abstract class Constructors extends Transform with ast.TreeDSL { } // Assemble final constructor - defBuf += treeCopy.DefDef( - constr, constr.mods, constr.name, constr.tparams, constr.vparamss, constr.tpt, + defBuf += deriveDefDef(constr)(_ => treeCopy.Block( constrBody, paramInits ::: constrPrefixBuf.toList ::: uptoSuperStats ::: guardSpecializedInitializer(remainingConstrStats), - constrBody.expr)); + constrBody.expr)) // Followed by any auxiliary constructors defBuf ++= auxConstructorBuf diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index 5f84d765b9..c1ddd21e9d 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -849,8 +849,8 @@ abstract class Erasure extends AddInterfaces case ClassDef(mods, name, tparams, impl) => debuglog("defs of " + tree.symbol + " = " + tree.symbol.info.decls) treeCopy.ClassDef(tree, mods, name, List(), impl) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - treeCopy.DefDef(tree, mods, name, List(), vparamss, tpt, rhs) + case DefDef(_,_,_,_,_,_) => + copyDefDef(tree)(tparams = Nil) case TypeDef(_, _, _, _) => EmptyTree case Apply(instanceOf @ TypeApply(fun @ Select(qual, name), args @ List(arg)), List()) // !!! todo: simplify by having GenericArray also extract trees diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index 252b3ccffc..bc35084a4c 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -471,7 +471,7 @@ abstract class ExplicitOuter extends InfoTransform treeCopy.Template(tree, parents, self, if (newDefs.isEmpty) decls else decls ::: newDefs.toList) ) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + case DefDef(_, _, _, vparamss, _, rhs) => if (sym.isClassConstructor) { rhs match { case Literal(_) => @@ -484,7 +484,7 @@ abstract class ExplicitOuter extends InfoTransform sym.newValueParameter(nme.OUTER, sym.pos) setInfo outerField(clazz).info ((ValDef(outerParam) setType NoType) :: vparamss.head) :: vparamss.tail } else vparamss - super.transform(treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs)) + super.transform(copyDefDef(tree)(vparamss = vparamss1)) } } else super.transform(tree) diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 5c015944c8..99cc7393aa 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -320,11 +320,12 @@ abstract class LambdaLift extends InfoTransform { case Some(ps) => val freeParams = ps map (p => ValDef(p) setPos tree.pos setType NoType) tree match { - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => + case DefDef(_, _, _, vparams :: _, _, _) => val addParams = cloneSymbols(ps).map(_.setFlag(PARAM)) sym.updateInfo( lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType))) - treeCopy.DefDef(tree, mods, name, tparams, List(vparamss.head ++ freeParams), tpt, rhs) + + copyDefDef(tree)(vparamss = List(vparams ++ freeParams)) case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) => // Disabled attempt to to add getters to freeParams // this does not work yet. Problem is that local symbols need local names @@ -489,8 +490,8 @@ abstract class LambdaLift extends InfoTransform { stat, mods, name, tparams, treeCopy.Template(impl, parents, self, body ::: lifted)) liftedDefs -= stat.symbol result - case DefDef(mods, name, tp, vp, tpt, Block(Nil, expr)) if !stat.symbol.isConstructor => - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, expr) + case DefDef(_, _, _, _, _, Block(Nil, expr)) if !stat.symbol.isConstructor => + deriveDefDef(stat)(_ => expr) case _ => stat } diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 18ab2e9326..38dfcd4307 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -68,7 +68,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD curTree = tree tree match { - case DefDef(mods, name, tparams, vparams, tpt, rhs) => atOwner(tree.symbol) { + case DefDef(_, _, _, _, _, rhs) => atOwner(tree.symbol) { val res = if (!sym.owner.isClass && sym.isLazy) { val enclosingClassOrDummyOrMethod = { val enclMethod = sym.enclMethod @@ -90,8 +90,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD } else super.transform(rhs) - treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, - if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res) + deriveDefDef(tree)(_ => if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res) } case Template(parents, self, body) => atOwner(currentOwner) { diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index b3b7596f9a..0ee2f1cd5a 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -523,17 +523,17 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { addLateInterfaceMembers(currentOwner) tree - case DefDef(mods, name, tparams, List(vparams), tpt, rhs) => + case DefDef(_, _, _, vparams :: Nil, _, _) => if (currentOwner.isImplClass) { if (isImplementedStatically(sym)) { sym setFlag notOVERRIDE self = sym.newValueParameter(nme.SELF, sym.pos) setInfo toInterface(currentOwner.typeOfThis) val selfdef = ValDef(self) setType NoType - treeCopy.DefDef(tree, mods, name, tparams, List(selfdef :: vparams), tpt, rhs) - } else { - EmptyTree - } - } else { + copyDefDef(tree)(vparamss = List(selfdef :: vparams)) + } + else EmptyTree + } + else { if (currentOwner.isTrait && sym.isSetter && !atPhase(currentRun.picklerPhase)(sym.isDeferred)) { sym.addAnnotation(TraitSetterAnnotationClass) } @@ -699,15 +699,17 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * This rhs is typed and then mixin transformed. */ def completeSuperAccessor(stat: Tree) = stat match { - case DefDef(mods, name, tparams, List(vparams), tpt, EmptyTree) if stat.symbol.isSuperAccessor => + case DefDef(_, _, _, vparams :: Nil, _, EmptyTree) if stat.symbol.isSuperAccessor => val rhs0 = (Super(clazz, tpnme.EMPTY) DOT stat.symbol.alias)(vparams map (v => Ident(v.symbol)): _*) val rhs1 = localTyped(stat.pos, rhs0, stat.symbol.tpe.resultType) - val rhs2 = atPhase(currentRun.mixinPhase)(transform(rhs1)) - debuglog("complete super acc " + stat.symbol.fullLocationString + - " " + rhs1 + " " + stat.symbol.alias.fullLocationString + - "/" + stat.symbol.alias.owner.hasFlag(lateINTERFACE))//debug - treeCopy.DefDef(stat, mods, name, tparams, List(vparams), tpt, rhs2) + debuglog( + "complete super acc " + stat.symbol.fullLocationString + + " " + rhs1 + " " + stat.symbol.alias.fullLocationString + + "/" + stat.symbol.alias.owner.hasFlag(lateINTERFACE) + )//debug + + deriveDefDef(stat)(_ => atPhase(currentRun.mixinPhase)(transform(rhs1))) case _ => stat } @@ -883,14 +885,13 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ def addCheckedGetters(clazz: Symbol, stats: List[Tree]): List[Tree] = { def dd(stat: DefDef) = { - val DefDef(mods, name, tp, vp, tpt, rhs) = stat - val sym = stat.symbol - def isUnit = sym.tpe.resultType.typeSymbol == UnitClass - def isEmpty = rhs == EmptyTree + val sym = stat.symbol + def isUnit = sym.tpe.resultType.typeSymbol == UnitClass + def isEmpty = stat.rhs == EmptyTree if (sym.isLazy && !isEmpty && !clazz.isImplClass) { assert(fieldOffset contains sym, sym) - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, + deriveDefDef(stat)(rhs => if (isUnit) mkLazyDef(clazz, sym, List(rhs), UNIT, fieldOffset(sym)) else { @@ -901,7 +902,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } else if (needsInitFlag(sym) && !isEmpty && !clazz.hasFlag(IMPLCLASS | TRAIT)) { assert(fieldOffset contains sym, sym) - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, + deriveDefDef(stat)(rhs => (mkCheckedAccessor(clazz, _: Tree, fieldOffset(sym), stat.pos, sym))( if (sym.tpe.resultType.typeSymbol == UnitClass) UNIT else rhs @@ -909,26 +910,24 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { ) } else if (sym.isConstructor) { - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, addInitBits(clazz, rhs)) + deriveDefDef(stat)(addInitBits(clazz, _)) } else if (settings.checkInit.value && !clazz.isTrait && sym.isSetter) { val getter = sym.getter(clazz) if (needsInitFlag(getter) && fieldOffset.isDefinedAt(getter)) - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, - Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter))), UNIT) - ) + deriveDefDef(stat)(rhs => Block(List(rhs, localTyper.typed(mkSetFlag(clazz, fieldOffset(getter), getter))), UNIT)) else stat } else if (sym.isModule && (!clazz.isTrait || clazz.isImplClass) && !sym.isBridge) { - treeCopy.DefDef(stat, mods, name, tp, vp, tpt, - typedPos(stat.pos) { + deriveDefDef(stat)(rhs => + typedPos(stat.pos)( mkInnerClassAccessorDoubleChecked( // Martin to Hubert: I think this can be replaced by selfRef(tree.pos) // @PP: It does not seem so, it crashes for me trying to bootstrap. - if (clazz.isImplClass) gen.mkAttributedIdent(vp.head.head.symbol) else gen.mkAttributedThis(clazz), + if (clazz.isImplClass) gen.mkAttributedIdent(stat.vparamss.head.head.symbol) else gen.mkAttributedThis(clazz), rhs ) - } + ) ) } else stat diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 2282d04cd5..1e1c9efebb 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1232,7 +1232,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { */ class CollectMethodBodies extends Traverser { override def traverse(tree: Tree) = tree match { - case DefDef(mods, name, tparams, vparams :: Nil, tpt, rhs) => + case DefDef(_, _, _, vparams :: Nil, _, rhs) => if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) { debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs)) body(tree.symbol) = rhs @@ -1402,7 +1402,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { self, atOwner(currentOwner)(transformTrees(body ::: specMembers))) - case ddef @ DefDef(mods, name, tparams, vparamss, tpt, rhs) if info.isDefinedAt(symbol) => + case ddef @ DefDef(_, _, _, vparamss, _, _) if info.isDefinedAt(symbol) => // log("--> method: " + ddef + " in " + ddef.symbol.owner + ", " + info(symbol)) if (symbol.isConstructor) { @@ -1410,36 +1410,29 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val superRef: Tree = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) forwardCtorCall(tree.pos, superRef, vparamss, symbol.owner) } - if (symbol.isPrimaryConstructor) localTyper typed { - atPos(symbol.pos)(treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, Block(List(t), Literal(Constant())))) - } else { - // duplicate the original constructor + if (symbol.isPrimaryConstructor) + localTyper.typedPos(symbol.pos)(deriveDefDef(tree)(_ => Block(List(t), Literal(Constant())))) + else // duplicate the original constructor duplicateBody(ddef, info(symbol).target) - } - } else info(symbol) match { - + } + else info(symbol) match { case Implementation(target) => assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName) // we have an rhs, specialize it val tree1 = duplicateBody(ddef, target) debuglog("implementation: " + tree1) - val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1 - treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs)) + deriveDefDef(tree1)(transform) case NormalizedMember(target) => log("Normalized member: " + symbol + ", target: " + target) if (target.isDeferred || conflicting(typeEnv(symbol))) { - treeCopy.DefDef( - tree, mods, name, tparams, vparamss, tpt, - localTyper typed gen.mkSysErrorCall("boom! you stepped on a bug. This method should never be called.") - ) + deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called.")) } else { // we have an rhs, specialize it val tree1 = duplicateBody(ddef, target) debuglog("implementation: " + tree1) - val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1 - treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs)) + deriveDefDef(tree1)(transform) } case SpecialOverride(target) => @@ -1450,9 +1443,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val tree1 = addBody(ddef, target) (new ChangeOwnerTraverser(target, tree1.symbol))(tree1.rhs) debuglog("changed owners, now: " + tree1) - val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1 - treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs)) - + deriveDefDef(tree1)(transform) case SpecialOverload(original, env) => debuglog("completing specialized " + symbol.fullName + " calling " + original) @@ -1474,7 +1465,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { log("forward: " + fwd + ", " + ddef) val rhs1 = forwardCall(tree.pos, gen.mkAttributedRef(symbol.owner.thisType, fwd.target), vparamss) log("-->d completed forwarder to specialized overload: " + fwd.target + ": " + rhs1) - localTyper.typed(treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1)) + localTyper.typed(deriveDefDef(tree)(_ => rhs1)) case SpecializedAccessor(target) => val rhs1 = if (symbol.isGetter) @@ -1482,13 +1473,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else Assign(gen.mkAttributedRef(target), Ident(vparamss.head.head.symbol)) log("specialized accessor: " + target + " -> " + rhs1) - localTyper.typed(treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1)) + localTyper.typed(deriveDefDef(tree)(_ => rhs1)) case Abstract(targ) => log("abstract: " + targ) - val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree - val t = treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs) - localTyper.typed(t) + localTyper.typed(deriveDefDef(tree)(rhs => rhs)) } case ValDef(mods, name, tpt, rhs) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor => @@ -1555,7 +1544,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def addBody(tree: DefDef, source: Symbol): DefDef = { val symbol = tree.symbol debuglog("specializing body of" + symbol.defString) - val DefDef(mods, name, tparams, vparams :: Nil, tpt, _) = tree + val DefDef(_, _, tparams, vparams :: Nil, tpt, _) = tree // val (_, origtparams) = splitParams(source.typeParams) val env = typeEnv(symbol) val boundTvars = env.keySet @@ -1584,7 +1573,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val newBody = symSubstituter(body(source).duplicate) tpt.tpe = tpt.tpe.substSym(oldtparams, newtparams) - treeCopy.DefDef(tree, mods, name, tparams, List(newSyms map ValDef), tpt, newBody) + copyDefDef(tree)(vparamss = List(newSyms map ValDef), rhs = newBody) } /** Create trees for specialized members of 'sClass', based on the diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 1655ad09c4..93fcd27191 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -223,13 +223,12 @@ abstract class TailCalls extends Transform { } tree match { - case dd @ DefDef(mods, name, tparams, vparams, tpt, rhs) => + case dd @ DefDef(_, _, _, vparamss0, _, rhs0) => val newCtx = new Context(dd) + debuglog("Considering " + dd.name + " for tailcalls") + val newRHS = transform(rhs0, newCtx) - debuglog("Considering " + name + " for tailcalls") - val newRHS = transform(rhs, newCtx) - - treeCopy.DefDef(tree, mods, name, tparams, vparams, tpt, { + deriveDefDef(tree)(rhs => if (newCtx.isTransformed) { /** We have rewritten the tree, but there may be nested recursive calls remaining. * If @tailrec is given we need to fail those now. @@ -241,7 +240,7 @@ abstract class TailCalls extends Transform { } } val newThis = newCtx.newThis(tree.pos) - val vpSyms = vparams.flatten map (_.symbol) + val vpSyms = vparamss0.flatten map (_.symbol) typedPos(tree.pos)(Block( List(ValDef(newThis, This(currentClass))), @@ -254,7 +253,7 @@ abstract class TailCalls extends Transform { newRHS } - }) + ) case Block(stats, expr) => treeCopy.Block(tree, diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 6a7fcc98c3..4b587a3f41 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -458,9 +458,8 @@ abstract class UnCurry extends InfoTransform */ private def replaceElidableTree(tree: Tree): Tree = { tree match { - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - val newRhs = Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe - treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, newRhs) setSymbol tree.symbol setType tree.tpe + case DefDef(_,_,_,_,_,_) => + deriveDefDef(tree)(rhs => Block(Nil, gen.mkZero(rhs.tpe)) setType rhs.tpe) setSymbol tree.symbol setType tree.tpe case _ => gen.mkZero(tree.tpe) setType tree.tpe } @@ -628,14 +627,16 @@ abstract class UnCurry extends InfoTransform } else super.transform(tree).asInstanceOf[Template] newMembers.clear tmpl - case dd @ DefDef(mods, name, tparams, vparamss, tpt, rhs) => - val rhs1 = nonLocalReturnKeys.get(tree.symbol) match { - case None => rhs - case Some(k) => atPos(rhs.pos)(nonLocalReturnTry(rhs, k, tree.symbol)) - } - val flatdd = treeCopy.DefDef(tree, mods, name, tparams, List(vparamss.flatten), tpt, rhs1) - if (dd.symbol hasAnnotation VarargsClass) addJavaVarargsForwarders(dd, flatdd, tree) - flatdd + case dd @ DefDef(_, _, _, vparamss0, _, rhs0) => + val flatdd = copyDefDef(dd)( + vparamss = List(vparamss0.flatten), + rhs = nonLocalReturnKeys get dd.symbol match { + case Some(k) => atPos(rhs0.pos)(nonLocalReturnTry(rhs0, k, dd.symbol)) + case None => rhs0 + } + ) + addJavaVarargsForwarders(dd, flatdd) + case Try(body, catches, finalizer) => if (opt.virtPatmat) { if(catches exists (cd => !treeInfo.isCatchCase(cd))) debugwarn("VPM BUG! illegal try/catch "+ catches); tree } else if (catches forall treeInfo.isCatchCase) tree @@ -698,9 +699,9 @@ abstract class UnCurry extends InfoTransform * It looks for the method in the `repeatedParams` map, and generates a Java-style * varargs forwarder. It then adds the forwarder to the `newMembers` sequence. */ - private def addJavaVarargsForwarders(dd: DefDef, flatdd: DefDef, tree: Tree): Unit = { - if (!repeatedParams.contains(dd.symbol)) - return + private def addJavaVarargsForwarders(dd: DefDef, flatdd: DefDef): DefDef = { + if (!dd.symbol.hasAnnotation(VarargsClass) || !repeatedParams.contains(dd.symbol)) + return flatdd def toSeqType(tp: Type): Type = { val arg = elementType(ArrayClass, tp) @@ -721,7 +722,7 @@ abstract class UnCurry extends InfoTransform val reps = repeatedParams(dd.symbol) val rpsymbols = reps.map(_.symbol).toSet - val theTyper = typer.atOwner(tree, currentClass) + val theTyper = typer.atOwner(dd, currentClass) val flatparams = flatdd.vparamss.head // create the type @@ -773,10 +774,11 @@ abstract class UnCurry extends InfoTransform case None => // enter symbol into scope currentClass.info.decls enter forwsym - // add the method to `newMembers` newMembers += forwtree } + + flatdd } } } diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 92e9f54190..89617e6f2c 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1528,12 +1528,9 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R // inside annotations. applyRefchecksToAnnotations(tree) var result: Tree = tree match { - case DefDef(mods, name, tparams, vparams, tpt, EmptyTree) if tree.symbol.hasAnnotation(NativeAttr) => - tree.symbol.resetFlag(DEFERRED) - transform(treeCopy.DefDef( - tree, mods, name, tparams, vparams, tpt, - typed(gen.mkSysErrorCall("native method stub")) - )) + case DefDef(_, _, _, _, _, EmptyTree) if sym hasAnnotation NativeAttr => + sym resetFlag DEFERRED + transform(deriveDefDef(tree)(_ => typed(gen.mkSysErrorCall("native method stub")))) case ValDef(_, _, _, _) | DefDef(_, _, _, _, _, _) => checkDeprecatedOvers(tree) diff --git a/src/library/scala/reflect/api/Trees.scala b/src/library/scala/reflect/api/Trees.scala index 1472866460..9d96f30afb 100644 --- a/src/library/scala/reflect/api/Trees.scala +++ b/src/library/scala/reflect/api/Trees.scala @@ -13,7 +13,7 @@ trait Trees { self: Universe => private[scala] var nodeCount = 0 - type Modifiers <: AbsModifiers + type Modifiers >: Null <: AbsModifiers abstract class AbsModifiers { def modifiers: Set[Modifier] @@ -660,6 +660,33 @@ trait Trees { self: Universe => val treeCopy = newLazyTreeCopier + def copyDefDef(tree: Tree)( + mods: Modifiers = null, + name: Name = null, + tparams: List[TypeDef] = null, + vparamss: List[List[ValDef]] = null, + tpt: Tree = null, + rhs: Tree = null + ): DefDef = tree match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(tree, + if (mods eq null) mods0 else mods, + if (name eq null) name0 else name, + if (tparams eq null) tparams0 else tparams, + if (vparamss eq null) vparamss0 else vparamss, + if (tpt eq null) tpt0 else tpt, + if (rhs eq null) rhs0 else rhs + ) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + def deriveDefDef(ddef: Tree)(applyToRhs: Tree => Tree): DefDef = ddef match { + case DefDef(mods0, name0, tparams0, vparamss0, tpt0, rhs0) => + treeCopy.DefDef(ddef, mods0, name0, tparams0, vparamss0, tpt0, applyToRhs(rhs0)) + case t => + sys.error("Not a DefDef: " + t + "/" + t.getClass) + } + class Traverser { protected var currentOwner: Symbol = definitions.RootClass -- cgit v1.2.3