diff options
Diffstat (limited to 'src/compiler')
56 files changed, 557 insertions, 454 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala index ce5bb3d1c4..7ed3e977db 100644 --- a/src/compiler/scala/reflect/internal/Definitions.scala +++ b/src/compiler/scala/reflect/internal/Definitions.scala @@ -814,6 +814,9 @@ trait Definitions extends reflect.api.StandardDefinitions { try getModule(fullname.toTermName) catch { case _: MissingRequirementError => NoSymbol } + def termMember(owner: Symbol, name: String): Symbol = owner.info.member(newTermName(name)) + def typeMember(owner: Symbol, name: String): Symbol = owner.info.member(newTypeName(name)) + def getMember(owner: Symbol, name: Name): Symbol = { if (owner == NoSymbol) NoSymbol else owner.info.nonPrivateMember(name) match { diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala index c4ee7254dc..e43a0906a8 100644 --- a/src/compiler/scala/reflect/internal/NameManglers.scala +++ b/src/compiler/scala/reflect/internal/NameManglers.scala @@ -92,6 +92,7 @@ trait NameManglers { def isLocalName(name: Name) = name endsWith LOCAL_SUFFIX_STRING def isLoopHeaderLabel(name: Name) = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX) def isProtectedAccessorName(name: Name) = name startsWith PROTECTED_PREFIX + def isSuperAccessorName(name: Name) = name startsWith SUPER_PREFIX_STRING def isReplWrapperName(name: Name) = name containsName INTERPRETER_IMPORT_WRAPPER def isSetterName(name: Name) = name endsWith SETTER_SUFFIX def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING) diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala index a78e0cc939..3c181e39c6 100644 --- a/src/compiler/scala/reflect/internal/StdNames.scala +++ b/src/compiler/scala/reflect/internal/StdNames.scala @@ -94,6 +94,7 @@ trait StdNames extends NameManglers { self: SymbolTable => val EMPTY: NameType = "" val ANON_FUN_NAME: NameType = "$anonfun" + val ANON_CLASS_NAME: NameType = "$anon" val EMPTY_PACKAGE_NAME: NameType = "<empty>" val IMPORT: NameType = "<import>" val MODULE_VAR_SUFFIX: NameType = "$module" @@ -442,7 +443,6 @@ trait StdNames extends NameManglers { self: SymbolTable => protected implicit def createNameType(name: String): TypeName = newTypeNameCached(name) val REFINE_CLASS_NAME: NameType = "<refinement>" - val ANON_CLASS_NAME: NameType = "$anon" } /** For fully qualified type names. diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala index b3c62bffbf..4bcf522a8f 100644 --- a/src/compiler/scala/reflect/internal/SymbolTable.scala +++ b/src/compiler/scala/reflect/internal/SymbolTable.scala @@ -78,16 +78,18 @@ abstract class SymbolTable extends api.Universe type RunId = Int final val NoRunId = 0 + private var phStack: List[Phase] = Nil private var ph: Phase = NoPhase private var per = NoPeriod + final def atPhaseStack: List[Phase] = phStack final def phase: Phase = ph final def phase_=(p: Phase) { //System.out.println("setting phase to " + p) - assert((p ne null) && p != NoPhase) + assert((p ne null) && p != NoPhase, p) ph = p - per = (currentRunId << 8) + p.id + per = period(currentRunId, p.id) } /** The current compiler run identifier. */ @@ -112,14 +114,18 @@ abstract class SymbolTable extends api.Universe final def phaseOf(period: Period): Phase = phaseWithId(phaseId(period)) final def period(rid: RunId, pid: Phase#Id): Period = - (currentRunId << 8) + pid + (rid << 8) + pid /** Perform given operation at given phase. */ @inline final def atPhase[T](ph: Phase)(op: => T): T = { val current = phase phase = ph + phStack ::= ph try op - finally phase = current + finally { + phase = current + phStack = phStack.tail + } } /** Since when it is to be "at" a phase is inherently ambiguous, * a couple unambiguously named methods. diff --git a/src/compiler/scala/reflect/internal/Trees.scala b/src/compiler/scala/reflect/internal/Trees.scala index b6b7e3cbda..610c6dc493 100644 --- a/src/compiler/scala/reflect/internal/Trees.scala +++ b/src/compiler/scala/reflect/internal/Trees.scala @@ -272,7 +272,18 @@ trait Trees extends api.Trees { self: SymbolTable => override def traverse(t: Tree) { if (t != EmptyTree && t.pos == NoPosition) { t.setPos(pos) - super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? + super.traverse(t) // TODO: bug? shouldn't the traverse be outside of the if? + // @PP: it's pruning whenever it encounters a node with a + // position, which I interpret to mean that (in the author's + // mind at least) either the children of a positioned node will + // already be positioned, or the children of a positioned node + // do not merit positioning. + // + // Whatever the author's rationale, it does seem like a bad idea + // to press on through a positioned node to find unpositioned + // children beneath it and then to assign whatever happens to + // be in `pos` to such nodes. There are supposed to be some + // position invariants which I can't imagine surviving that. } } } diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index 04efe04636..fd75e42b61 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -3903,7 +3903,6 @@ trait Types extends api.Types { self: SymbolTable => */ def rawToExistential = new TypeMap { private var expanded = immutable.Set[Symbol]() - private var generated = immutable.Set[Type]() def apply(tp: Type): Type = tp match { case TypeRef(pre, sym, List()) if isRawIfWithoutArgs(sym) => if (expanded contains sym) AnyRefClass.tpe @@ -3914,10 +3913,6 @@ trait Types extends api.Types { self: SymbolTable => } finally { expanded -= sym } - case ExistentialType(_, _) if !(generated contains tp) => // to avoid infinite expansions. todo: not sure whether this is needed - val result = mapOver(tp) - generated += result - result case _ => mapOver(tp) } @@ -4319,83 +4314,83 @@ trait Types extends api.Types { self: SymbolTable => else mapOver(tp) } - class InstantiateDependentMap(params: List[Symbol], actuals: List[Type]) extends TypeMap with KeepOnlyTypeConstraints { - private val actualsIndexed = actuals.toIndexedSeq + class InstantiateDependentMap(params: List[Symbol], actuals0: List[Type]) extends TypeMap with KeepOnlyTypeConstraints { + private val actuals = actuals0.toIndexedSeq + private val existentials = new Array[Symbol](actuals.size) + def existentialsNeeded: List[Symbol] = existentials.filter(_ ne null).toList - object ParamWithActual { - def unapply(sym: Symbol): Option[Type] = { - val pid = params indexOf sym - if(pid != -1) Some(actualsIndexed(pid)) else None - } + private object StableArg { + def unapply(param: Symbol) = Arg unapply param map actuals filter (tp => + tp.isStable && (tp.typeSymbol != NothingClass) + ) + } + private object Arg { + def unapply(param: Symbol) = Some(params indexOf param) filter (_ >= 0) } - def apply(tp: Type): Type = - mapOver(tp) match { - case SingleType(NoPrefix, ParamWithActual(arg)) if arg.isStable => arg // unsound to replace args by unstable actual #3873 - // (soundly) expand type alias selections on implicit arguments, see depmet_implicit_oopsla* test cases -- typically, `param.isImplicit` - case tp1@TypeRef(SingleType(NoPrefix, ParamWithActual(arg)), sym, targs) => - val res = typeRef(arg, sym, targs) - if(res.typeSymbolDirect isAliasType) res.dealias - else tp1 - case tp1 => tp1 // don't return the original `tp`, which may be different from `tp1`, due to dropping annotations - } - - def existentialsNeeded: List[Symbol] = existSyms.filter(_ ne null).toList - - private val existSyms: Array[Symbol] = new Array(actualsIndexed.size) - private def haveExistential(i: Int) = {assert((i >= 0) && (i <= actualsIndexed.size)); existSyms(i) ne null} + def apply(tp: Type): Type = mapOver(tp) match { + // unsound to replace args by unstable actual #3873 + case SingleType(NoPrefix, StableArg(arg)) => arg + // (soundly) expand type alias selections on implicit arguments, + // see depmet_implicit_oopsla* test cases -- typically, `param.isImplicit` + case tp1 @ TypeRef(SingleType(NoPrefix, Arg(pid)), sym, targs) => + val arg = actuals(pid) + val res = typeRef(arg, sym, targs) + if (res.typeSymbolDirect.isAliasType) res.dealias else tp1 + // don't return the original `tp`, which may be different from `tp1`, + // due to dropping annotations + case tp1 => tp1 + } /* Return the type symbol for referencing a parameter inside the existential quantifier. * (Only needed if the actual is unstable.) */ - def existSymFor(actualIdx: Int) = - if (haveExistential(actualIdx)) existSyms(actualIdx) - else { - val oldSym = params(actualIdx) - val symowner = oldSym.owner - val bound = singletonBounds(actualsIndexed(actualIdx)) - - val sym = symowner.newExistential(newTypeName(oldSym.name + ".type"), oldSym.pos) - sym.setInfo(bound) - sym.setFlag(oldSym.flags) - - existSyms(actualIdx) = sym - sym + private def existentialFor(pid: Int) = { + if (existentials(pid) eq null) { + val param = params(pid) + existentials(pid) = ( + param.owner.newExistential(newTypeName(param.name + ".type"), param.pos, param.flags) + setInfo singletonBounds(actuals(pid)) + ) } + existentials(pid) + } //AM propagate more info to annotations -- this seems a bit ad-hoc... (based on code by spoon) override def mapOver(arg: Tree, giveup: ()=>Nothing): Tree = { + // TODO: this should be simplified; in the stable case, one can + // probably just use an Ident to the tree.symbol. + // + // @PP: That leads to failure here, where stuff no longer has type + // 'String @Annot("stuff")' but 'String @Annot(x)'. + // + // def m(x: String): String @Annot(x) = x + // val stuff = m("stuff") + // + // (TODO cont.) Why an existential in the non-stable case? + // + // @PP: In the following: + // + // def m = { val x = "three" ; val y: String @Annot(x) = x; y } + // + // m is typed as 'String @Annot(x) forSome { val x: String }'. + // + // Both examples are from run/constrained-types.scala. object treeTrans extends Transformer { - override def transform(tree: Tree): Tree = { - tree match { - case RefParamAt(pid) => - // TODO: this should be simplified; in the stable case, one can probably - // just use an Ident to the tree.symbol. Why an existential in the non-stable case? - val actual = actualsIndexed(pid) - if (actual.isStable && actual.typeSymbol != NothingClass) { - gen.mkAttributedQualifier(actualsIndexed(pid), tree.symbol) - } else { - val sym = existSymFor(pid) - (Ident(sym.name) - copyAttrs tree - setType typeRef(NoPrefix, sym, Nil)) - } - case _ => super.transform(tree) - } - } - object RefParamAt { - def unapply(tree: Tree): Option[Int] = tree match { - case Ident(_) => Some(params indexOf tree.symbol) filterNot (_ == -1) - case _ => None - } + override def transform(tree: Tree): Tree = tree.symbol match { + case StableArg(actual) => + gen.mkAttributedQualifier(actual, tree.symbol) + case Arg(pid) => + val sym = existentialFor(pid) + Ident(sym) copyAttrs tree setType typeRef(NoPrefix, sym, Nil) + case _ => + super.transform(tree) } } - - treeTrans.transform(arg) + treeTrans transform arg } } - object StripAnnotationsMap extends TypeMap { def apply(tp: Type): Type = tp match { case AnnotatedType(_, atp, _) => diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index b21b33e138..9f93108420 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -862,13 +862,12 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { override def complete(sym: Symbol) = try { super.complete(sym) var alias = at(j, readSymbol) - if (alias.isOverloaded) { - atPhase(picklerPhase) { - alias = alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)) - } - } + if (alias.isOverloaded) + alias = atPhase(picklerPhase)((alias suchThat (alt => sym.tpe =:= sym.owner.thisType.memberType(alt)))) + sym.asInstanceOf[TermSymbol].setAlias(alias) - } catch { + } + catch { case e: MissingRequirementError => throw toTypeError(e) } } diff --git a/src/compiler/scala/reflect/internal/util/Collections.scala b/src/compiler/scala/reflect/internal/util/Collections.scala index 94672097c4..e3fb1a9cad 100644 --- a/src/compiler/scala/reflect/internal/util/Collections.scala +++ b/src/compiler/scala/reflect/internal/util/Collections.scala @@ -65,6 +65,16 @@ trait Collections { lb.toList } + final def foreachWithIndex[A, B](xs: List[A])(f: (A, Int) => Unit) { + var index = 0 + var ys = xs + while (!ys.isEmpty) { + f(ys.head, index) + ys = ys.tail + index += 1 + } + } + final def mapWithIndex[A, B](xs: List[A])(f: (A, Int) => B): List[B] = { val lb = new ListBuffer[B] var index = 0 diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index 4493188b31..ff8d86873c 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -193,10 +193,6 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb if (settings.debug.value) body } - @inline final override def debuglog(msg: => String) { - if (settings.debug.value && (settings.log containsPhase globalPhase)) - inform("[log " + phase + "] " + msg) - } // Warnings issued only under -Ydebug. For messages which should reach // developer ears, but are not adequately actionable by users. @inline final override def debugwarn(msg: => String) { @@ -213,10 +209,28 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb def informTime(msg: String, start: Long) = informProgress(elapsedMessage(msg, start)) def logError(msg: String, t: Throwable): Unit = () + + private def atPhaseStackMessage = atPhaseStack match { + case Nil => "" + case ps => ps.reverseMap("->" + _).mkString("(", " ", ")") + } + private def shouldLogAtThisPhase = ( + (settings.log.isSetByUser) + && ((settings.log containsPhase globalPhase) || (settings.log containsPhase phase)) + ) + + def logAfterEveryPhase[T](msg: String)(op: => T) { + log("Running operation '%s' after every phase.\n".format(msg) + describeAfterEveryPhase(op)) + } // Over 200 closure objects are eliminated by inlining this. @inline final def log(msg: => AnyRef): Unit = - if (settings.log containsPhase globalPhase) - inform("[log " + phase + "] " + msg) + if (shouldLogAtThisPhase) + inform("[log %s%s] %s".format(globalPhase, atPhaseStackMessage, msg)) + + @inline final override def debuglog(msg: => String) { + if (settings.debug.value) + log(msg) + } def logThrowable(t: Throwable): Unit = globalError(throwableAsString(t)) def throwableAsString(t: Throwable): String = @@ -754,6 +768,51 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb line1 :: line2 :: descs mkString } + /** Returns List of (phase, value) pairs, including only those + * where the value compares unequal to the previous phase's value. + */ + def afterEachPhase[T](op: => T): List[(Phase, T)] = { + phaseDescriptors.map(_.ownPhase).foldLeft(List[(Phase, T)]()) { (res, ph) => + val value = afterPhase(ph)(op) + if (res.nonEmpty && res.head._2 == value) res + else ((ph, value)) :: res + } reverse + } + + /** Returns List of ChangeAfterPhase objects, encapsulating those + * phase transitions where the result of the operation gave a different + * list than it had when run during the previous phase. + */ + def changesAfterEachPhase[T](op: => List[T]): List[ChangeAfterPhase[T]] = { + val ops = ((NoPhase, Nil)) :: afterEachPhase(op) + + ops sliding 2 map { + case (_, before) :: (ph, after) :: Nil => + val lost = before filterNot (after contains _) + val gained = after filterNot (before contains _) + ChangeAfterPhase(ph, lost, gained) + case _ => ??? + } toList + } + private def numberedPhase(ph: Phase) = "%2d/%s".format(ph.id, ph.name) + + case class ChangeAfterPhase[+T](ph: Phase, lost: List[T], gained: List[T]) { + private def mkStr(what: String, xs: List[_]) = ( + if (xs.isEmpty) "" + else xs.mkString(what + " after " + numberedPhase(ph) + " {\n ", "\n ", "\n}\n") + ) + override def toString = mkStr("Lost", lost) + mkStr("Gained", gained) + } + + def describeAfterEachPhase[T](op: => T): List[String] = + afterEachPhase(op) map { case (ph, t) => "[after %-15s] %s".format(numberedPhase(ph), t) } + + def describeAfterEveryPhase[T](op: => T): String = + describeAfterEachPhase(op) map (" " + _ + "\n") mkString + + def printAfterEachPhase[T](op: => T): Unit = + describeAfterEachPhase(op) foreach (m => println(" " + m)) + // ----------- Runs --------------------------------------- private var curRun: Run = null @@ -808,9 +867,27 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb def currentUnit: CompilationUnit = if (currentRun eq null) NoCompilationUnit else currentRun.currentUnit def currentSource: SourceFile = if (currentUnit.exists) currentUnit.source else lastSeenSourceFile + // TODO - trim these to the absolute minimum. + @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op) + @inline final def afterExplicitOuter[T](op: => T): T = afterPhase(currentRun.explicitouterPhase)(op) + @inline final def afterFlatten[T](op: => T): T = afterPhase(currentRun.flattenPhase)(op) + @inline final def afterIcode[T](op: => T): T = afterPhase(currentRun.icodePhase)(op) + @inline final def afterMixin[T](op: => T): T = afterPhase(currentRun.mixinPhase)(op) + @inline final def afterPickler[T](op: => T): T = afterPhase(currentRun.picklerPhase)(op) + @inline final def afterRefchecks[T](op: => T): T = afterPhase(currentRun.refchecksPhase)(op) + @inline final def afterSpecialize[T](op: => T): T = afterPhase(currentRun.specializePhase)(op) @inline final def afterTyper[T](op: => T): T = afterPhase(currentRun.typerPhase)(op) + @inline final def afterUncurry[T](op: => T): T = afterPhase(currentRun.uncurryPhase)(op) @inline final def beforeErasure[T](op: => T): T = beforePhase(currentRun.erasurePhase)(op) - @inline final def afterErasure[T](op: => T): T = afterPhase(currentRun.erasurePhase)(op) + @inline final def beforeExplicitOuter[T](op: => T): T = beforePhase(currentRun.explicitouterPhase)(op) + @inline final def beforeFlatten[T](op: => T): T = beforePhase(currentRun.flattenPhase)(op) + @inline final def beforeIcode[T](op: => T): T = beforePhase(currentRun.icodePhase)(op) + @inline final def beforeMixin[T](op: => T): T = beforePhase(currentRun.mixinPhase)(op) + @inline final def beforePickler[T](op: => T): T = beforePhase(currentRun.picklerPhase)(op) + @inline final def beforeRefchecks[T](op: => T): T = beforePhase(currentRun.refchecksPhase)(op) + @inline final def beforeSpecialize[T](op: => T): T = beforePhase(currentRun.specializePhase)(op) + @inline final def beforeTyper[T](op: => T): T = beforePhase(currentRun.typerPhase)(op) + @inline final def beforeUncurry[T](op: => T): T = beforePhase(currentRun.uncurryPhase)(op) /** Don't want to introduce new errors trying to report errors, * so swallow exceptions. @@ -1027,9 +1104,11 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb val refchecksPhase = phaseNamed("refchecks") val uncurryPhase = phaseNamed("uncurry") // tailcalls, specialize + val specializePhase = phaseNamed("specialize") val explicitouterPhase = phaseNamed("explicitouter") val erasurePhase = phaseNamed("erasure") // lazyvals, lambdalift, constructors + val lambdaLiftPhase = phaseNamed("lambdalift") val flattenPhase = phaseNamed("flatten") val mixinPhase = phaseNamed("mixin") val cleanupPhase = phaseNamed("cleanup") diff --git a/src/compiler/scala/tools/nsc/SubComponent.scala b/src/compiler/scala/tools/nsc/SubComponent.scala index cd9fef117f..7e832a56b0 100644 --- a/src/compiler/scala/tools/nsc/SubComponent.scala +++ b/src/compiler/scala/tools/nsc/SubComponent.scala @@ -46,6 +46,9 @@ abstract class SubComponent { private var ownPhaseCache: WeakReference[Phase] = new WeakReference(null) private var ownPhaseRunId = global.NoRunId + + @inline final def atOwnPhase[T](op: => T) = global.atPhase(ownPhase)(op) + @inline final def afterOwnPhase[T](op: => T) = global.afterPhase(ownPhase)(op) /** The phase corresponding to this subcomponent in the current compiler run */ def ownPhase: Phase = { diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 855b55bb5e..ad87889145 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -79,16 +79,16 @@ trait Trees extends reflect.internal.Trees { self: Global => val (edefs, rest) = body span treeInfo.isEarlyDef val (evdefs, etdefs) = edefs partition treeInfo.isEarlyValDef val gvdefs = evdefs map { - case vdef @ ValDef(mods, name, tpt, rhs) => - treeCopy.ValDef( - vdef.duplicate, mods, name, - atPos(focusPos(vdef.pos)) { TypeTree() setOriginal tpt setPos focusPos(tpt.pos) }, // atPos in case - EmptyTree) - } - val lvdefs = evdefs map { - case vdef @ ValDef(mods, name, tpt, rhs) => - treeCopy.ValDef(vdef, Modifiers(PRESUPER), name, tpt, rhs) + case vdef @ ValDef(_, _, tpt, _) => copyValDef(vdef)( + // !!! I know "atPos in case" wasn't intentionally planted to + // add an air of mystery to this file, but it is the sort of + // comment which only its author could love. + tpt = atPos(focusPos(vdef.pos))(TypeTree() setOriginal tpt setPos focusPos(tpt.pos)), // atPos in case + rhs = EmptyTree + ) } + val lvdefs = evdefs collect { case vdef: ValDef => copyValDef(vdef)(mods = Modifiers(PRESUPER)) } + val constrs = { if (constrMods hasFlag TRAIT) { if (body forall treeInfo.isInterfaceMember) List() @@ -108,13 +108,11 @@ trait Trees extends reflect.internal.Trees { self: Global => DefDef(constrMods, nme.CONSTRUCTOR, List(), vparamss1, TypeTree(), Block(lvdefs ::: List(superCall), Literal(Constant()))))) } } - // println("typed template, gvdefs = "+gvdefs+", parents = "+parents+", constrs = "+constrs) constrs foreach (ensureNonOverlapping(_, parents ::: gvdefs)) - // vparamss2 are used as field definitions for the class. remove defaults - val vparamss2 = vparamss map (vps => vps map { vd => - treeCopy.ValDef(vd, vd.mods &~ DEFAULTPARAM, vd.name, vd.tpt, EmptyTree) - }) - Template(parents, self, gvdefs ::: vparamss2.flatten ::: constrs ::: etdefs ::: rest) + // Field definitions for the class - remove defaults. + val fieldDefs = vparamss.flatten map (vd => copyValDef(vd)(mods = vd.mods &~ DEFAULTPARAM, rhs = EmptyTree)) + + Template(parents, self, gvdefs ::: fieldDefs ::: constrs ::: etdefs ::: rest) } /** Construct class definition with given class symbol, value parameters, diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index e3a59058a3..8e445a62db 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -1423,15 +1423,14 @@ self => def implicitClosure(start: Int, location: Int): Tree = { val param0 = convertToParam { atPos(in.offset) { - var paramexpr: Tree = Ident(ident()) - if (in.token == COLON) { - in.nextToken() - paramexpr = Typed(paramexpr, typeOrInfixType(location)) + Ident(ident()) match { + case expr if in.token == COLON => + in.nextToken() ; Typed(expr, typeOrInfixType(location)) + case expr => expr } - paramexpr } } - val param = treeCopy.ValDef(param0, param0.mods | Flags.IMPLICIT, param0.name, param0.tpt, param0.rhs) + val param = copyValDef(param0)(mods = param0.mods | Flags.IMPLICIT) atPos(start, in.offset) { accept(ARROW) Function(List(param), if (location != InBlock) expr() else block()) @@ -2689,8 +2688,8 @@ self => val (self, body) = templateBody(true) if (in.token == WITH && self.isEmpty) { val earlyDefs: List[Tree] = body flatMap { - case vdef @ ValDef(mods, name, tpt, rhs) if !mods.isDeferred => - List(treeCopy.ValDef(vdef, mods | Flags.PRESUPER, name, tpt, rhs)) + case vdef @ ValDef(mods, _, _, _) if !mods.isDeferred => + List(copyValDef(vdef)(mods = mods | Flags.PRESUPER)) case tdef @ TypeDef(mods, name, tparams, rhs) => List(treeCopy.TypeDef(tdef, mods | Flags.PRESUPER, name, tparams, rhs)) case stat if !stat.isEmpty => diff --git a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala index 05571b2424..aab944f65a 100644 --- a/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala +++ b/src/compiler/scala/tools/nsc/backend/ScalaPrimitives.scala @@ -565,7 +565,7 @@ abstract class ScalaPrimitives { import definitions._ val code = getPrimitive(fun) - def elementType = atPhase(currentRun.typerPhase) { + def elementType = beforeTyper { val arrayParent = tpe :: tpe.parents collectFirst { case TypeRef(_, ArrayClass, elem :: Nil) => elem } diff --git a/src/compiler/scala/tools/nsc/backend/icode/Members.scala b/src/compiler/scala/tools/nsc/backend/icode/Members.scala index 298c9171a1..44a58e75b4 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/Members.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/Members.scala @@ -212,6 +212,12 @@ trait Members { def isStatic: Boolean = symbol.isStaticMember override def toString() = symbol.fullName + + def matchesSignature(other: IMethod) = { + (symbol.name == other.symbol.name) && + (params corresponds other.params)(_.kind == _.kind) && + (returnType == other.returnType) + } import opcodes._ def checkLocals(): Unit = { diff --git a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala index a485272ca6..5eef02f2cb 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/TypeKinds.scala @@ -145,7 +145,7 @@ trait TypeKinds { self: ICodes => * Here we make the adjustment by rewinding to a pre-erasure state and * sifting through the parents for a class type. */ - def lub0(tk1: TypeKind, tk2: TypeKind): Type = atPhase(currentRun.uncurryPhase) { + def lub0(tk1: TypeKind, tk2: TypeKind): Type = beforeUncurry { import definitions._ val tp = global.lub(List(tk1.toType, tk2.toType)) val (front, rest) = tp.parents span (_.typeSymbol.hasTraitFlag) diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala index c06bd2e097..69de0dfa90 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/ReachingDefinitions.scala @@ -105,11 +105,9 @@ abstract class ReachingDefinitions { def genAndKill(b: BasicBlock): (ListSet[Definition], ListSet[Local]) = { var genSet = ListSet[Definition]() var killSet = ListSet[Local]() - for ((i, idx) <- b.toList.zipWithIndex) i match { - case STORE_LOCAL(local) => - killSet = killSet + local - genSet = updateReachingDefinition(b, idx, genSet) - case _ => () + for ((STORE_LOCAL(local), idx) <- b.toList.zipWithIndex) { + killSet = killSet + local + genSet = updateReachingDefinition(b, idx, genSet) } (genSet, killSet) } diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala index 865bacffaa..32177c309a 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BytecodeWriters.scala @@ -23,9 +23,7 @@ trait BytecodeWriters { import global._ private def outputDirectory(sym: Symbol): AbstractFile = ( - settings.outputDirs.outputDirFor { - atPhase(currentRun.flattenPhase.prev)(sym.sourceFile) - } + settings.outputDirs.outputDirFor(beforeFlatten(sym.sourceFile)) ) private def getFile(base: AbstractFile, cls: JClass, suffix: String): AbstractFile = { var dir = base diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala index 8238705cc3..a838c7d54d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala @@ -37,11 +37,9 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with /** Create a new phase */ override def newPhase(p: Phase): Phase = new JvmPhase(p) - private def outputDirectory(sym: Symbol): AbstractFile = ( - settings.outputDirs.outputDirFor { - atPhase(currentRun.flattenPhase.prev)(sym.sourceFile) - } - ) + private def outputDirectory(sym: Symbol): AbstractFile = + settings.outputDirs outputDirFor beforeFlatten(sym.sourceFile) + private def getFile(base: AbstractFile, cls: JClass, suffix: String): AbstractFile = { var dir = base val pathParts = cls.getName().split("[./]").toList @@ -87,7 +85,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // succeed or warn that it isn't. hasApproximate && { // Before erasure so we can identify generic mains. - atPhase(currentRun.erasurePhase) { + beforeErasure { val companion = sym.linkedClassOfClass val companionMain = companion.tpe.member(nme.main) @@ -161,7 +159,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } val codeGenerator = new BytecodeGenerator(bytecodeWriter) - log("Created new bytecode generator for " + classes.size + " classes.") + debuglog("Created new bytecode generator for " + classes.size + " classes.") sortedClasses foreach { c => try codeGenerator.genClass(c) @@ -212,7 +210,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with final val ExcludedForwarderFlags = { import Flags._ - ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | BridgeAndPrivateFlags ) + // Should include DEFERRED but this breaks findMember. + ( CASE | SPECIALIZED | LIFTED | PROTECTED | STATIC | EXPANDEDNAME | BridgeAndPrivateFlags ) } // Additional interface parents based on annotations and other cues @@ -272,7 +271,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with * of inner class all until root class. */ def collectInnerClass(s: Symbol): Unit = { - // TODO: something atPhase(currentRun.flattenPhase.prev) which accounts for + // TODO: some beforeFlatten { ... } which accounts for // being nested in parameterized classes (if we're going to selectively flatten.) val x = innerClassSymbolFor(s) val isInner = x.isClass && !x.rawowner.isPackageClass @@ -393,7 +392,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with // it must be a top level class (name contains no $s) def isCandidateForForwarders(sym: Symbol): Boolean = - atPhase(currentRun.picklerPhase.next) { + afterPickler { !(sym.name.toString contains '$') && sym.hasModuleFlag && !sym.isImplClass && !sym.isNestedClass } @@ -433,7 +432,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with private def addEnclosingMethodAttribute(jclass: JClass, clazz: Symbol) { val sym = clazz.originalEnclosingMethod if (sym.isMethod) { - log("enclosing method for %s is %s (in %s)".format(clazz, sym, sym.enclClass)) + debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, sym.enclClass)) jclass addAttribute fjbgContext.JEnclosingMethodAttribute( jclass, javaName(sym.enclClass), @@ -449,7 +448,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with enclClass, clazz) ) else { - log("enclosing method for %s is %s (in %s)".format(clazz, sym, enclClass)) + debuglog("enclosing method for %s is %s (in %s)".format(clazz, sym, enclClass)) jclass addAttribute fjbgContext.JEnclosingMethodAttribute( jclass, javaName(enclClass), @@ -681,7 +680,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with ) def addGenericSignature(jmember: JMember, sym: Symbol, owner: Symbol) { if (needsGenericSignature(sym)) { - val memberTpe = atPhase(currentRun.erasurePhase)(owner.thisType.memberInfo(sym)) + val memberTpe = beforeErasure(owner.thisType.memberInfo(sym)) // println("addGenericSignature sym: " + sym.fullName + " : " + memberTpe + " sym.info: " + sym.info) // println("addGenericSignature: "+ (sym.ownerChain map (x => (x.name, x.isImplClass)))) erasure.javaSig(sym, memberTpe) foreach { sig => @@ -700,7 +699,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with return } if ((settings.check.value contains "genjvm")) { - val normalizedTpe = atPhase(currentRun.erasurePhase)(erasure.prepareSigMap(memberTpe)) + val normalizedTpe = beforeErasure(erasure.prepareSigMap(memberTpe)) val bytecodeTpe = owner.thisType.memberInfo(sym) if (!sym.isType && !sym.isConstructor && !(erasure.erasure(sym, normalizedTpe) =:= bytecodeTpe)) { clasz.cunit.warning(sym.pos, @@ -716,9 +715,8 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } val index = jmember.getConstantPool.addUtf8(sig).toShort if (opt.verboseDebug) - atPhase(currentRun.erasurePhase) { - println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index) - } + beforeErasure(println("add generic sig "+sym+":"+sym.info+" ==> "+sig+" @ "+index)) + val buf = ByteBuffer.allocate(2) buf putShort index addAttribute(jmember, tpnme.SignatureATTR, buf) @@ -793,14 +791,14 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with innerSym.rawname + innerSym.moduleSuffix // add inner classes which might not have been referenced yet - atPhase(currentRun.erasurePhase.next) { + afterErasure { for (sym <- List(clasz.symbol, clasz.symbol.linkedClassOfClass); m <- sym.info.decls.map(innerClassSymbolFor) if m.isClass) innerClassBuffer += m } val allInners = innerClassBuffer.toList if (allInners.nonEmpty) { - log(clasz.symbol.fullName('.') + " contains " + allInners.size + " inner classes.") + debuglog(clasz.symbol.fullName('.') + " contains " + allInners.size + " inner classes.") val innerClassesAttr = jclass.getInnerClasses() // sort them so inner classes succeed their enclosing class // to satisfy the Eclipse Java compiler @@ -1228,7 +1226,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with val jtype = javaType(method).asInstanceOf[JMethodType] def emit(invoke: String) { - log("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype)) + debuglog("%s %s %s.%s:%s".format(invoke, receiver.accessString, jowner, jname, jtype)) invoke match { case "invokeinterface" => jcode.emitINVOKEINTERFACE(jowner, jname, jtype) case "invokevirtual" => jcode.emitINVOKEVIRTUAL(jowner, jname, jtype) @@ -1928,9 +1926,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with } def isTopLevelModule(sym: Symbol): Boolean = - atPhase (currentRun.picklerPhase.next) { - sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass - } + afterPickler { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } def isStaticModule(sym: Symbol): Boolean = { sym.isModuleClass && !sym.isImplClass && !sym.isLifted diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala index d2e54ff3f1..2fb615f893 100644 --- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala +++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala @@ -1125,7 +1125,7 @@ abstract class GenMSIL extends SubComponent { } // method: implicit view(FunctionX[PType0, PType1, ...,PTypeN, ResType]):DelegateType - val (isDelegateView, paramType, resType) = atPhase(currentRun.typerPhase) { + val (isDelegateView, paramType, resType) = beforeTyper { msym.tpe match { case MethodType(params, resultType) if (params.length == 1 && msym.name == nme.view_) => @@ -1954,7 +1954,7 @@ abstract class GenMSIL extends SubComponent { } // createClassMembers0 private def isTopLevelModule(sym: Symbol): Boolean = - atPhase (currentRun.refchecksPhase) { + beforeRefchecks { sym.isModuleClass && !sym.isImplClass && !sym.isNestedClass } diff --git a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala index 5fc7329955..95c371fa8b 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/DeadCodeElimination.scala @@ -225,9 +225,9 @@ abstract class DeadCodeElimination extends SubComponent { m foreachBlock { bb => assert(bb.closed, "Open block in computeCompensations") - for ((i, idx) <- bb.toList.zipWithIndex) { + foreachWithIndex(bb.toList) { (i, idx) => if (!useful(bb)(idx)) { - for ((consumedType, depth) <- i.consumedTypes.reverse.zipWithIndex) { + foreachWithIndex(i.consumedTypes.reverse) { (consumedType, depth) => log("Finding definitions of: " + i + "\n\t" + consumedType + " at depth: " + depth) val defs = rdef.findDefs(bb, idx, 1, depth) for (d <- defs) { diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index a3a19868e0..d017cf94b3 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -466,8 +466,10 @@ abstract class Inliners extends SubComponent { } } - private def isHigherOrderMethod(sym: Symbol) = - sym.isMethod && atPhase(currentRun.erasurePhase.prev)(sym.info.paramTypes exists isFunctionType) + private def isHigherOrderMethod(sym: Symbol) = ( + sym.isMethod + && beforeExplicitOuter(sym.info.paramTypes exists isFunctionType) // was "at erasurePhase.prev" + ) /** Should method 'sym' being called in 'receiver' be loaded from disk? */ def shouldLoadImplFor(sym: Symbol, receiver: Symbol): Boolean = { diff --git a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala index bd890b7194..395757237b 100644 --- a/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala +++ b/src/compiler/scala/tools/nsc/dependencies/DependencyAnalysis.scala @@ -145,10 +145,8 @@ trait DependencyAnalysis extends SubComponent with Files { val name = d.toString d.symbol match { case s : ModuleClassSymbol => - val isTopLevelModule = - atPhase (currentRun.picklerPhase.next) { - !s.isImplClass && !s.isNestedClass - } + val isTopLevelModule = afterPickler { !s.isImplClass && !s.isNestedClass } + if (isTopLevelModule && (s.companionModule != NoSymbol)) { dependencies.emits(source, nameToFile(unit.source.file, name)) } @@ -182,16 +180,18 @@ trait DependencyAnalysis extends SubComponent with Files { || (tree.symbol.sourceFile.path != file.path)) && (!tree.symbol.isClassConstructor)) { updateReferences(tree.symbol.fullName) - atPhase(currentRun.uncurryPhase.prev) { - checkType(tree.symbol.tpe) - } + // was "at uncurryPhase.prev", which is actually non-deterministic + // because the continuations plugin may or may not supply uncurry's + // immediately preceding phase. + beforeRefchecks(checkType(tree.symbol.tpe)) } tree match { case cdef: ClassDef if !cdef.symbol.hasPackageFlag && !cdef.symbol.isAnonymousFunction => if (cdef.symbol != NoSymbol) buf += cdef.symbol - atPhase(currentRun.erasurePhase.prev) { + // was "at erasurePhase.prev" + beforeExplicitOuter { for (s <- cdef.symbol.info.decls) s match { case ts: TypeSymbol if !ts.isClass => @@ -202,9 +202,8 @@ trait DependencyAnalysis extends SubComponent with Files { super.traverse(tree) case ddef: DefDef => - atPhase(currentRun.typerPhase.prev) { - checkType(ddef.symbol.tpe) - } + // was "at typer.prev" + beforeTyper { checkType(ddef.symbol.tpe) } super.traverse(tree) case a @ Select(q, n) if ((a.symbol != NoSymbol) && (q.symbol != null)) => // #2556 if (!a.symbol.isConstructor && diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 477cec8c8e..0f28407f5a 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -1052,6 +1052,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") def newTyperRun() { currentTyperRun = new TyperRun + perRunCaches.clearAll() } class TyperResult(val tree: Tree) extends ControlThrowable diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala index 0539c885c2..bad181eb76 100644 --- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala +++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala @@ -48,7 +48,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana protected def newCompiler(settings: Settings) = new BuilderGlobal(settings) val compiler = newCompiler(settings) - import compiler.{Symbol, Type, atPhase, currentRun} + import compiler.{ Symbol, Type, beforeErasure } import compiler.dependencyAnalysis.Inherited private case class SymWithHistory(sym: Symbol, befErasure: Type) @@ -160,10 +160,8 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana isCorrespondingSym(s.sym, sym)) match { case Some(SymWithHistory(oldSym, info)) => val changes = changeSet(oldSym.info, sym) - val changesErasure = - atPhase(currentRun.erasurePhase.prev) { - changeSet(info, sym) - } + val changesErasure = beforeErasure(changeSet(info, sym)) + changesOf(oldSym) = (changes ++ changesErasure).distinct case _ => // a new top level definition @@ -333,11 +331,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana for (src <- files; localDefs = compiler.dependencyAnalysis.definitions(src)) { definitions(src) = (localDefs map (s => { this.classes += s.fullName -> src - SymWithHistory( - s.cloneSymbol, - atPhase(currentRun.erasurePhase.prev) { - s.info.cloneInfo(s) - }) + SymWithHistory(s.cloneSymbol, beforeErasure(s.info.cloneInfo(s))) })) } this.references = compiler.dependencyAnalysis.references diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index 7c71438b98..16085c07d6 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -324,7 +324,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) private def implicitsCommand(line: String): Result = { val intp = ILoop.this.intp import intp._ - import global.Symbol + import global.{ Symbol, afterTyper } def p(x: Any) = intp.reporter.printMessage("" + x) @@ -348,7 +348,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // This groups the members by where the symbol is defined val byOwner = syms groupBy (_.owner) - val sortedOwners = byOwner.toList sortBy { case (owner, _) => intp.afterTyper(source.info.baseClasses indexOf owner) } + val sortedOwners = byOwner.toList sortBy { case (owner, _) => afterTyper(source.info.baseClasses indexOf owner) } sortedOwners foreach { case (owner, members) => @@ -440,7 +440,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) else { val tp = intp.typeOfExpression(line, false) if (tp == NoType) "" // the error message was already printed - else intp.afterTyper(tp.toString) + else intp.global.afterTyper(tp.toString) } } private def warningsCommand(): Result = { diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index de408f083f..9a12bc1471 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -230,9 +230,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } with MemberHandlers import memberHandlers._ - def atPickler[T](op: => T): T = atPhase(currentRun.picklerPhase)(op) - def afterTyper[T](op: => T): T = atPhase(currentRun.typerPhase.next)(op) - /** Temporarily be quiet */ def beQuietDuring[T](body: => T): T = { val saved = printResults @@ -787,10 +784,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } def compile(source: String): Boolean = compileAndSaveRun("<console>", source) - def lineAfterTyper[T](op: => T): T = { - assert(lastRun != null, "Internal error: trying to use atPhase, but Run is null." + this) - atPhase(lastRun.typerPhase.next)(op) - } /** The innermost object inside the wrapper, found by * following accessPath into the outer one. @@ -799,7 +792,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends val readRoot = getRequiredModule(readPath) // the outermost wrapper (accessPath split '.').foldLeft(readRoot) { (sym, name) => if (name == "") sym else - lineAfterTyper(sym.info member newTermName(name)) + afterTyper(sym.info member newTermName(name)) } } /** We get a bunch of repeated warnings for reasons I haven't @@ -842,7 +835,6 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends // private class Request(val line: String, val trees: List[Tree]) { val lineRep = new ReadEvalPrint() - import lineRep.lineAfterTyper private var _originalLine: String = null def withOriginalLine(s: String): this.type = { _originalLine = s ; this } @@ -961,7 +953,7 @@ class IMain(initialSettings: Settings, protected val out: JPrintWriter) extends } lazy val resultSymbol = lineRep.resolvePathToSymbol(accessPath) - def applyToResultMember[T](name: Name, f: Symbol => T) = lineAfterTyper(f(resultSymbol.info.nonPrivateDecl(name))) + def applyToResultMember[T](name: Name, f: Symbol => T) = afterTyper(f(resultSymbol.info.nonPrivateDecl(name))) /* typeOf lookup with encoding */ def lookupTypeOf(name: Name) = typeOf.getOrElse(name, typeOf(global.encode(name.toString))) diff --git a/src/compiler/scala/tools/nsc/interpreter/Imports.scala b/src/compiler/scala/tools/nsc/interpreter/Imports.scala index d34ca8bbca..073501912a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Imports.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Imports.scala @@ -191,5 +191,5 @@ trait Imports { prevRequestList flatMap (req => req.handlers map (req -> _)) private def membersAtPickler(sym: Symbol): List[Symbol] = - atPickler(sym.info.nonPrivateMembers) + beforePickler(sym.info.nonPrivateMembers) }
\ No newline at end of file diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala index d96e8b07fc..0e2c34efbf 100644 --- a/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala +++ b/src/compiler/scala/tools/nsc/interpreter/JLineCompletion.scala @@ -18,7 +18,7 @@ class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput import global._ import definitions.{ PredefModule, RootClass, AnyClass, AnyRefClass, ScalaPackage, JavaLangPackage, getModuleIfDefined } type ExecResult = Any - import intp.{ debugging, afterTyper } + import intp.{ debugging } // verbosity goes up with consecutive tabs private var verbosity: Int = 0 diff --git a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala index 48a5fa9e34..7e032753f2 100644 --- a/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/compiler/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -13,7 +13,7 @@ import scala.reflect.internal.Chars trait MemberHandlers { val intp: IMain - import intp.{ Request, global, naming, atPickler } + import intp.{ Request, global, naming } import global._ import naming._ @@ -200,10 +200,10 @@ trait MemberHandlers { def importedSymbols = individualSymbols ++ wildcardSymbols lazy val individualSymbols: List[Symbol] = - atPickler(individualNames map (targetType nonPrivateMember _)) + beforePickler(individualNames map (targetType nonPrivateMember _)) lazy val wildcardSymbols: List[Symbol] = - if (importsWildcard) atPickler(targetType.nonPrivateMembers) + if (importsWildcard) beforePickler(targetType.nonPrivateMembers) else Nil /** Complete list of names imported by a wildcard */ diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala index 835fbb5638..ef84876b94 100644 --- a/src/compiler/scala/tools/nsc/interpreter/Power.scala +++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala @@ -15,6 +15,31 @@ import scala.io.Codec import java.net.{ URL, MalformedURLException } import io.{ Path } +/** Collecting some power mode examples. + +scala> trait F[@specialized(Int) T] { def f: T = ??? } +defined trait F + +scala> trait G[@specialized(Long, Int) T] extends F[T] { override def f: T = super.f } +defined trait G + +scala> changesAfterEachPhase(intp("G").info.members filter (_.name.toString contains "super")) > +Gained after 1/parser { + method super$f +} + +Gained after 12/specialize { + method super$f$mcJ$sp + method super$f$mcI$sp +} + +Lost after 18/flatten { + method super$f$mcJ$sp + method super$f$mcI$sp + method super$f +} +*/ + /** A class for methods to be injected into the intp in power mode. */ class Power[ReplValsImpl <: ReplVals : Manifest](val intp: IMain, replVals: ReplValsImpl) { diff --git a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala index 6e5dec4205..b20017c1d3 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ReplVals.scala @@ -62,10 +62,12 @@ object ReplVals { class AppliedTypeFromManifests(sym: Symbol) { def apply[M](implicit m1: Manifest[M]): Type = - appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x).asInstanceOf[Type])) + if (sym eq NoSymbol) NoType + else appliedType(sym.typeConstructor, List(m1) map (x => manifestToType(x).asInstanceOf[Type])) def apply[M1, M2](implicit m1: Manifest[M1], m2: Manifest[M2]): Type = - appliedType(sym.typeConstructor, List(m1, m2) map (x => manifestToType(x).asInstanceOf[Type])) + if (sym eq NoSymbol) NoType + else appliedType(sym.typeConstructor, List(m1, m2) map (x => manifestToType(x).asInstanceOf[Type])) } (sym: Symbol) => new AppliedTypeFromManifests(sym) diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index 3490c1f5a8..4d94ed68fc 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -653,15 +653,12 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { // leaves auxiliary constructors unable to access members of the companion object // as unqualified identifiers. def addCompanionObject(statics: List[Tree], cdef: ClassDef): List[Tree] = { - def implWithImport(importStmt: Tree) = { - import cdef.impl._ - treeCopy.Template(cdef.impl, parents, self, importStmt :: body) - } + def implWithImport(importStmt: Tree) = deriveTemplate(cdef.impl)(importStmt :: _) // if there are no statics we can use the original cdef, but we always // create the companion so import A._ is not an error (see ticket #1700) val cdefNew = if (statics.isEmpty) cdef - else treeCopy.ClassDef(cdef, cdef.mods, cdef.name, cdef.tparams, implWithImport(importCompanionObject(cdef))) + else deriveClassDef(cdef)(_ => implWithImport(importCompanionObject(cdef))) List(makeCompanionObject(cdefNew, statics), cdefNew) } diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index f99d1399c0..e7959f36b2 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -533,7 +533,7 @@ class MutableSettings(val errorFn: String => Unit) Some(rest) } override def tryToSetColon(args: List[String]) = tryToSet(args) - override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(" +").toList) + override def tryToSetFromPropertyValue(s: String) = tryToSet(s.trim.split(',').toList) def unparse: List[String] = value map { name + ":" + _ } withHelpSyntax(name + ":<" + arg + ">") diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index a8083d7a2d..a7ddfae819 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -424,19 +424,21 @@ abstract class ClassfileParser { def forceMangledName(name: Name, module: Boolean): Symbol = { val parts = name.decode.toString.split(Array('.', '$')) var sym: Symbol = definitions.RootClass - atPhase(currentRun.flattenPhase.prev) { + + // was "at flatten.prev" + beforeFlatten { for (part0 <- parts; if !(part0 == ""); part = newTermName(part0)) { - val sym1 = atPhase(currentRun.icodePhase) { + val sym1 = beforeIcode { sym.linkedClassOfClass.info sym.info.decl(part.encode) }//.suchThat(module == _.isModule) - if (sym1 == NoSymbol) - sym = sym.info.decl(part.encode.toTypeName) - else - sym = sym1 + + sym = ( + if (sym1 ne NoSymbol) sym1 + else sym.info.decl(part.encode.toTypeName) + ) } } -// println("found: " + sym) sym } @@ -1205,7 +1207,7 @@ abstract class ClassfileParser { // if loading during initialization of `definitions` typerPhase is not yet set. // in that case we simply load the member at the current phase if (currentRun.typerPhase != null) - atPhase(currentRun.typerPhase)(getMember(sym, innerName.toTypeName)) + beforeTyper(getMember(sym, innerName.toTypeName)) else getMember(sym, innerName.toTypeName) diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index 7d42dabc08..68af518d3a 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -179,7 +179,7 @@ abstract class ICodeReader extends ClassfileParser { } else { forceMangledName(name, false) - atPhase(currentRun.flattenPhase.next)(definitions.getClass(name)) + afterFlatten(definitions.getClass(name.toTypeName)) } if (sym.isModule) sym.moduleClass diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index d5a413337b..1abaf1c1d6 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -82,7 +82,9 @@ abstract class AddInterfaces extends InfoTransform { implClassMap.getOrElse(iface, { atPhase(implClassPhase) { - log("%s.implClass == %s".format(iface, iface.implClass)) + if (iface.implClass ne NoSymbol) + log("%s.implClass == %s".format(iface, iface.implClass)) + val implName = nme.implClassName(iface.name) var impl = if (iface.owner.isClass) iface.owner.info.decl(implName) else NoSymbol @@ -193,7 +195,7 @@ abstract class AddInterfaces extends InfoTransform { case PolyType(_, restpe) => implType(restpe) } - sym setInfo implType(atPhase(currentRun.erasurePhase)(iface.info)) + sym setInfo implType(beforeErasure(iface.info)) } override def load(clazz: Symbol) { complete(clazz) } @@ -316,9 +318,9 @@ abstract class AddInterfaces extends InfoTransform { override def transform(tree: Tree): Tree = { val sym = tree.symbol val tree1 = tree match { - case ClassDef(mods, name, tparams, impl) if (sym.needsImplClass) => + case ClassDef(mods, _, _, impl) if sym.needsImplClass => implClass(sym).initialize // to force lateDEFERRED flags - treeCopy.ClassDef(tree, mods | INTERFACE, name, tparams, ifaceTemplate(impl)) + copyClassDef(tree)(mods = mods | INTERFACE, impl = ifaceTemplate(impl)) case DefDef(_,_,_,_,_,_) if sym.isClassConstructor && sym.isPrimaryConstructor && sym.owner != ArrayClass => deriveDefDef(tree)(addMixinConstructorCalls(_, sym.owner)) // (3) case Template(parents, self, body) => @@ -337,7 +339,7 @@ abstract class AddInterfaces extends InfoTransform { val mix1 = mix if (mix == tpnme.EMPTY) mix else { - val ps = atPhase(currentRun.erasurePhase) { + val ps = beforeErasure { sym.info.parents dropWhile (p => p.symbol.name != mix) } assert(!ps.isEmpty, tree); diff --git a/src/compiler/scala/tools/nsc/transform/CleanUp.scala b/src/compiler/scala/tools/nsc/transform/CleanUp.scala index 4521ce9982..2c024fe6fa 100644 --- a/src/compiler/scala/tools/nsc/transform/CleanUp.scala +++ b/src/compiler/scala/tools/nsc/transform/CleanUp.scala @@ -47,7 +47,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { val Template(parents, self, body) = tree clearStatics() val newBody = transformTrees(body) - val templ = treeCopy.Template(tree, parents, self, transformTrees(newStaticMembers.toList) ::: newBody) + val templ = deriveTemplate(tree)(_ => transformTrees(newStaticMembers.toList) ::: newBody) try addStaticInits(templ) // postprocess to include static ctors finally clearStatics() } @@ -686,7 +686,7 @@ abstract class CleanUp extends Transform with ast.TreeDSL { localTyper.typedPos(template.pos)(DefDef(staticCtorSym, rhs)) } - treeCopy.Template(template, template.parents, template.self, newCtor :: template.body) + deriveTemplate(template)(newCtor :: _) } } diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala index c638d25114..804c15a350 100644 --- a/src/compiler/scala/tools/nsc/transform/Constructors.scala +++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala @@ -175,7 +175,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { else if (stat.symbol.isConstructor) auxConstructorBuf += stat else defBuf += stat } - case ValDef(mods, name, tpt, rhs) => + case ValDef(_, _, _, rhs) => // val defs with constant right-hand sides are eliminated. // for all other val defs, an empty valdef goes into the template and // the initializer goes as an assignment into the constructor @@ -188,7 +188,7 @@ abstract class Constructors extends Transform with ast.TreeDSL { (if (canBeMoved(stat)) constrPrefixBuf else constrStatBuf) += mkAssign( stat.symbol, rhs1) } - defBuf += treeCopy.ValDef(stat, mods, name, tpt, EmptyTree) + defBuf += deriveValDef(stat)(_ => EmptyTree) } case ClassDef(_, _, _, _) => // classes are treated recursively, and left in the template @@ -226,11 +226,11 @@ abstract class Constructors extends Transform with ast.TreeDSL { tree match { case DefDef(_, _, _, _, _, body) if (tree.symbol.isOuterAccessor && tree.symbol.owner == clazz && clazz.isEffectivelyFinal) => - log("outerAccessors += " + tree.symbol.fullName) + debuglog("outerAccessors += " + tree.symbol.fullName) outerAccessors ::= ((tree.symbol, body)) case Select(_, _) => if (!mustbeKept(tree.symbol)) { - log("accessedSyms += " + tree.symbol.fullName) + debuglog("accessedSyms += " + tree.symbol.fullName) accessedSyms addEntry tree.symbol } super.traverse(tree) @@ -560,14 +560,13 @@ abstract class Constructors extends Transform with ast.TreeDSL { clazz.info.decls unlink sym // Eliminate all field definitions that can be dropped from template - treeCopy.Template(impl, impl.parents, impl.self, - defBuf.toList filter (stat => mustbeKept(stat.symbol))) + deriveTemplate(impl)(_ => defBuf.toList filter (stat => mustbeKept(stat.symbol))) } // transformClassTemplate override def transform(tree: Tree): Tree = tree match { - case ClassDef(mods, name, tparams, impl) if !tree.symbol.isInterface && !isValueClass(tree.symbol) => - treeCopy.ClassDef(tree, mods, name, tparams, transformClassTemplate(impl)) + case ClassDef(_,_,_,_) if !tree.symbol.isInterface && !isValueClass(tree.symbol) => + deriveClassDef(tree)(transformClassTemplate) case _ => super.transform(tree) } diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index c1ddd21e9d..2412c90962 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -223,7 +223,7 @@ abstract class Erasure extends AddInterfaces /** The Java signature of type 'info', for symbol sym. The symbol is used to give the right return * type for constructors. */ - def javaSig(sym0: Symbol, info: Type): Option[String] = atPhase(currentRun.erasurePhase) { + def javaSig(sym0: Symbol, info: Type): Option[String] = beforeErasure { val isTraitSignature = sym0.enclClass.isTrait def superSig(parents: List[Type]) = traceSig("superSig", parents) { @@ -257,7 +257,7 @@ abstract class Erasure extends AddInterfaces // Anything which could conceivably be a module (i.e. isn't known to be // a type parameter or similar) must go through here or the signature is // likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$. - def fullNameInSig(sym: Symbol) = "L" + atPhase(currentRun.icodePhase)(sym.javaBinaryName) + def fullNameInSig(sym: Symbol) = "L" + beforeIcode(sym.javaBinaryName) def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = { val tp = tp0.dealias @@ -421,9 +421,9 @@ abstract class Erasure extends AddInterfaces /** Box `tree` of unboxed type */ private def box(tree: Tree): Tree = tree match { - case LabelDef(name, params, rhs) => - val rhs1 = box(rhs) - treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe + case LabelDef(_, _, _) => + val ldef = deriveLabelDef(tree)(box) + ldef setType ldef.rhs.tpe case _ => typedPos(tree.pos)(tree.tpe.typeSymbol match { case UnitClass => @@ -440,7 +440,7 @@ abstract class Erasure extends AddInterfaces * fields (see TupleX). (ID) */ case Apply(boxFun, List(arg)) if isUnbox(tree.symbol) && safeToRemoveUnbox(arg.tpe.typeSymbol) => - log("boxing an unbox: " + tree + " and replying with " + arg) + log("boxing an unbox: " + tree + "/" + tree.symbol + " and replying with " + arg + " of type " + arg.tpe) arg case _ => (REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe @@ -460,9 +460,9 @@ abstract class Erasure extends AddInterfaces println("unbox shorten: "+tree) // this never seems to kick in during build and test; therefore disabled. adaptToType(unboxed, pt) */ - case LabelDef(name, params, rhs) => - val rhs1 = unbox(rhs, pt) - treeCopy.LabelDef(tree, name, params, rhs1) setType rhs1.tpe + case LabelDef(_, _, _) => + val ldef = deriveLabelDef(tree)(unbox(_, pt)) + ldef setType ldef.rhs.tpe case _ => typedPos(tree.pos)(pt.typeSymbol match { case UnitClass => @@ -604,8 +604,8 @@ abstract class Erasure extends AddInterfaces throw ex } def adaptCase(cdef: CaseDef): CaseDef = { - val body1 = adaptToType(cdef.body, tree1.tpe) - treeCopy.CaseDef(cdef, cdef.pat, cdef.guard, body1) setType body1.tpe + val newCdef = deriveCaseDef(cdef)(adaptToType(_, tree1.tpe)) + newCdef setType newCdef.body.tpe } def adaptBranch(branch: Tree): Tree = if (branch == EmptyTree) branch else adaptToType(branch, tree1.tpe); @@ -648,21 +648,20 @@ abstract class Erasure extends AddInterfaces private def checkNoDoubleDefs(root: Symbol) { def doubleDefError(sym1: Symbol, sym2: Symbol) { // the .toString must also be computed at the earlier phase - def atRefc[T](op: => T) = atPhase[T](currentRun.refchecksPhase.next)(op) - val tpe1 = atRefc(root.thisType.memberType(sym1)) - val tpe2 = atRefc(root.thisType.memberType(sym2)) + val tpe1 = afterRefchecks(root.thisType.memberType(sym1)) + val tpe2 = afterRefchecks(root.thisType.memberType(sym2)) if (!tpe1.isErroneous && !tpe2.isErroneous) unit.error( if (sym1.owner == root) sym1.pos else root.pos, (if (sym1.owner == sym2.owner) "double definition:\n" else if (sym1.owner == root) "name clash between defined and inherited member:\n" else "name clash between inherited members:\n") + - sym1 + ":" + atRefc(tpe1.toString) + + sym1 + ":" + afterRefchecks(tpe1.toString) + (if (sym1.owner == root) "" else sym1.locationString) + " and\n" + - sym2 + ":" + atRefc(tpe2.toString) + + sym2 + ":" + afterRefchecks(tpe2.toString) + (if (sym2.owner == root) " at line " + (sym2.pos).line else sym2.locationString) + "\nhave same type" + - (if (atRefc(tpe1 =:= tpe2)) "" else " after erasure: " + atPhase(phase.next)(sym1.tpe))) + (if (afterRefchecks(tpe1 =:= tpe2)) "" else " after erasure: " + afterErasure(sym1.tpe))) sym1.setInfo(ErrorType) } @@ -672,7 +671,7 @@ abstract class Erasure extends AddInterfaces if (e.sym.isTerm) { var e1 = decls.lookupNextEntry(e) while (e1 ne null) { - if (atPhase(phase.next)(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) + if (afterErasure(e1.sym.info =:= e.sym.info)) doubleDefError(e.sym, e1.sym) e1 = decls.lookupNextEntry(e1) } } @@ -686,10 +685,10 @@ abstract class Erasure extends AddInterfaces || !sym.hasTypeAt(currentRun.refchecksPhase.id)) override def matches(sym1: Symbol, sym2: Symbol): Boolean = - atPhase(phase.next)(sym1.tpe =:= sym2.tpe) + afterErasure(sym1.tpe =:= sym2.tpe) } while (opc.hasNext) { - if (!atPhase(currentRun.refchecksPhase.next)( + if (!afterRefchecks( root.thisType.memberType(opc.overriding) matches root.thisType.memberType(opc.overridden))) { debuglog("" + opc.overriding.locationString + " " + @@ -708,8 +707,8 @@ abstract class Erasure extends AddInterfaces for (member <- root.info.nonPrivateMember(other.name).alternatives) { if (member != other && !(member hasFlag BRIDGE) && - atPhase(phase.next)(member.tpe =:= other.tpe) && - !atPhase(refchecksPhase.next)( + afterErasure(member.tpe =:= other.tpe) && + !afterRefchecks( root.thisType.memberType(member) matches root.thisType.memberType(other))) { debuglog("" + member.locationString + " " + member.infosString + other.locationString + " " + other.infosString); doubleDefError(member, other) @@ -733,13 +732,13 @@ abstract class Erasure extends AddInterfaces */ private def bridgeDefs(owner: Symbol): (List[Tree], immutable.Set[Symbol]) = { var toBeRemoved: immutable.Set[Symbol] = immutable.Set() - //println("computing bridges for " + owner)//DEBUG - assert(phase == currentRun.erasurePhase) + debuglog("computing bridges for " + owner)//DEBUG + assert(phase == currentRun.erasurePhase, phase) val site = owner.thisType val bridgesScope = newScope val bridgeTarget = new mutable.HashMap[Symbol, Symbol] var bridges: List[Tree] = List() - val opc = atPhase(currentRun.explicitouterPhase) { + val opc = beforeExplicitOuter { new overridingPairs.Cursor(owner) { override def parents: List[Type] = List(owner.info.parents.head) override def exclude(sym: Symbol): Boolean = @@ -750,9 +749,9 @@ abstract class Erasure extends AddInterfaces val member = opc.overriding val other = opc.overridden //println("bridge? " + member + ":" + member.tpe + member.locationString + " to " + other + ":" + other.tpe + other.locationString)//DEBUG - if (atPhase(currentRun.explicitouterPhase)(!member.isDeferred)) { + if (beforeExplicitOuter(!member.isDeferred)) { val otpe = erasure(owner, other.tpe) - val bridgeNeeded = atPhase(phase.next) ( + val bridgeNeeded = afterErasure ( !(other.tpe =:= member.tpe) && !(deconstMap(other.tpe) =:= deconstMap(member.tpe)) && { var e = bridgesScope.lookupEntry(member.name) @@ -767,15 +766,15 @@ abstract class Erasure extends AddInterfaces // the parameter symbols need to have the new owner bridge.setInfo(otpe.cloneInfo(bridge)) bridgeTarget(bridge) = member - atPhase(phase.next) { owner.info.decls.enter(bridge) } + afterErasure { owner.info.decls.enter(bridge) } if (other.owner == owner) { //println("bridge to same: "+other+other.locationString)//DEBUG - atPhase(phase.next) { owner.info.decls.unlink(other) } + afterErasure { owner.info.decls.unlink(other) } toBeRemoved += other } bridgesScope enter bridge bridges = - atPhase(phase.next) { + afterErasure { atPos(bridge.pos) { val bridgeDef = DefDef(bridge, @@ -789,7 +788,7 @@ abstract class Erasure extends AddInterfaces if ( member.isSynthetic // TODO: should we do this for user-defined unapplies as well? && ((member.name == nme.unapply) || (member.name == nme.unapplySeq)) // && (bridge.paramss.nonEmpty && bridge.paramss.head.nonEmpty && bridge.paramss.head.tail.isEmpty) // does the first argument list has exactly one argument -- for user-defined unapplies we can't be sure - && !(atPhase(phase.next)(member.tpe <:< other.tpe))) { // no static guarantees (TODO: is the subtype test ever true?) + && !(afterErasure(member.tpe <:< other.tpe))) { // no static guarantees (TODO: is the subtype test ever true?) import CODE._ val typeTest = gen.mkIsInstanceOf(REF(bridge.firstParam), member.tpe.params.head.tpe, any = true, wrapInApply = true) // any = true since we're before erasure (?), wrapInapply is true since we're after uncurry // println("unapp type test: "+ typeTest) @@ -846,9 +845,9 @@ abstract class Erasure extends AddInterfaces */ private val preTransformer = new TypingTransformer(unit) { def preErase(tree: Tree): Tree = tree match { - case ClassDef(mods, name, tparams, impl) => + case ClassDef(_,_,_,_) => debuglog("defs of " + tree.symbol + " = " + tree.symbol.info.decls) - treeCopy.ClassDef(tree, mods, name, List(), impl) + copyClassDef(tree)(tparams = Nil) case DefDef(_,_,_,_,_,_) => copyDefDef(tree)(tparams = Nil) case TypeDef(_, _, _, _) => @@ -1055,7 +1054,7 @@ abstract class Erasure extends AddInterfaces */ override def transform(tree: Tree): Tree = { val tree1 = preTransformer.transform(tree) - atPhase(phase.next) { + afterErasure { val tree2 = mixinTransformer.transform(tree1) debuglog("tree after addinterfaces: \n" + tree2) diff --git a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala index bc35084a4c..c15da6e9a9 100644 --- a/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala +++ b/src/compiler/scala/tools/nsc/transform/ExplicitOuter.scala @@ -170,7 +170,7 @@ abstract class ExplicitOuter extends InfoTransform } if (!clazz.isTrait && !parents.isEmpty) { for (mc <- clazz.mixinClasses) { - val mixinOuterAcc: Symbol = atPhase(phase.next)(outerAccessor(mc)) + val mixinOuterAcc: Symbol = afterExplicitOuter(outerAccessor(mc)) if (mixinOuterAcc != NoSymbol) { if (decls1 eq decls) decls1 = decls.cloneScope val newAcc = mixinOuterAcc.cloneSymbol(clazz, mixinOuterAcc.flags & ~DEFERRED) @@ -468,8 +468,10 @@ abstract class ExplicitOuter extends InfoTransform } } super.transform( - treeCopy.Template(tree, parents, self, - if (newDefs.isEmpty) decls else decls ::: newDefs.toList) + deriveTemplate(tree)(decls => + if (newDefs.isEmpty) decls + else decls ::: newDefs.toList + ) ) case DefDef(_, _, _, vparamss, _, rhs) => if (sym.isClassConstructor) { @@ -559,7 +561,7 @@ abstract class ExplicitOuter extends InfoTransform /** The transformation method for whole compilation units */ override def transformUnit(unit: CompilationUnit) { - atPhase(phase.next)(super.transformUnit(unit)) + afterExplicitOuter(super.transformUnit(unit)) } } diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala index aa37c966e3..8856024a30 100644 --- a/src/compiler/scala/tools/nsc/transform/Flatten.scala +++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala @@ -20,16 +20,14 @@ abstract class Flatten extends InfoTransform { /** Updates the owning scope with the given symbol; returns the old symbol. */ - private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = { - atPhase(phase.next) { - val scope = sym.owner.info.decls - val old = scope lookup sym.name - if (old ne NoSymbol) - scope unlink old + private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = afterFlatten { + val scope = sym.owner.info.decls + val old = scope lookup sym.name + if (old ne NoSymbol) + scope unlink old - scope enter sym - old - } + scope enter sym + old } private def liftClass(sym: Symbol) { @@ -53,7 +51,8 @@ abstract class Flatten extends InfoTransform { val clazz = pre.typeSymbol clazz.isClass && !clazz.isPackageClass && { // Cannot flatten here: class A[T] { object B } - atPhase(currentRun.erasurePhase.prev)(clazz.typeParams.isEmpty) + // was "at erasurePhase.prev" + beforeErasure(clazz.typeParams.isEmpty) } } @@ -67,10 +66,11 @@ abstract class Flatten extends InfoTransform { val decls1 = scopeTransform(clazz) { val decls1 = newScope if (clazz.isPackageClass) { - atPhase(phase.next)(decls foreach (decls1 enter _)) - } else { + afterFlatten { decls foreach (decls1 enter _) } + } + else { val oldowner = clazz.owner - atPhase(phase.next)(oldowner.info) + afterFlatten { oldowner.info } parents1 = parents mapConserve (this) for (sym <- decls) { @@ -122,11 +122,7 @@ abstract class Flatten extends InfoTransform { liftedDefs(sym.enclosingTopLevelClass.owner) += tree EmptyTree case Select(qual, name) if (sym.isStaticModule && !sym.owner.isPackageClass) => - atPhase(phase.next) { - atPos(tree.pos) { - gen.mkAttributedRef(sym) - } - } + afterFlatten(atPos(tree.pos)(gen.mkAttributedRef(sym))) case _ => tree } diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index 99cc7393aa..f2c3402d21 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -128,7 +128,7 @@ abstract class LambdaLift extends InfoTransform { if (!ss(sym)) { ss addEntry sym renamable addEntry sym - atPhase(currentRun.picklerPhase) { + beforePickler { // The param symbol in the MethodType should not be renamed, only the symbol in scope. This way, // parameter names for named arguments are not changed. Example: without cloning the MethodType, // def closure(x: Int) = { () => x } @@ -262,7 +262,7 @@ abstract class LambdaLift extends InfoTransform { } } - atPhase(phase.next) { + afterOwnPhase { for ((owner, freeValues) <- free.toList) { val newFlags = SYNTHETIC | ( if (owner.isClass) PARAMACCESSOR | PrivateLocal else PARAM ) debuglog("free var proxy: %s, %s".format(owner.fullLocationString, freeValues.toList.mkString(", "))) @@ -326,7 +326,7 @@ abstract class LambdaLift extends InfoTransform { lifted(MethodType(sym.info.params ::: addParams, sym.info.resultType))) copyDefDef(tree)(vparamss = List(vparams ++ freeParams)) - case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) => + case ClassDef(_, _, _, _) => // Disabled attempt to to add getters to freeParams // this does not work yet. Problem is that local symbols need local names // and references to local symbols need to be transformed into @@ -338,8 +338,7 @@ abstract class LambdaLift extends InfoTransform { // DefDef(getter, rhs) setPos tree.pos setType NoType // } // val newDefs = if (sym.isTrait) freeParams ::: (ps map paramGetter) else freeParams - treeCopy.ClassDef(tree, mods, name, tparams, - treeCopy.Template(impl, parents, self, body ::: freeParams)) + deriveClassDef(tree)(impl => deriveTemplate(impl)(_ ::: freeParams)) } case None => tree @@ -481,15 +480,14 @@ abstract class LambdaLift extends InfoTransform { /** Transform statements and add lifted definitions to them. */ override def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] = { def addLifted(stat: Tree): Tree = stat match { - case ClassDef(mods, name, tparams, impl @ Template(parents, self, body)) => + case ClassDef(_, _, _, _) => val lifted = liftedDefs get stat.symbol match { case Some(xs) => xs reverseMap addLifted case _ => log("unexpectedly no lifted defs for " + stat.symbol) ; Nil } - val result = treeCopy.ClassDef( - stat, mods, name, tparams, treeCopy.Template(impl, parents, self, body ::: lifted)) - liftedDefs -= stat.symbol - result + try deriveClassDef(stat)(impl => deriveTemplate(impl)(_ ::: lifted)) + finally liftedDefs -= stat.symbol + case DefDef(_, _, _, _, _, Block(Nil, expr)) if !stat.symbol.isConstructor => deriveDefDef(stat)(_ => expr) case _ => @@ -500,7 +498,7 @@ abstract class LambdaLift extends InfoTransform { override def transformUnit(unit: CompilationUnit) { computeFreeVars - atPhase(phase.next)(super.transformUnit(unit)) + afterOwnPhase(super.transformUnit(unit)) assert(liftedDefs.isEmpty, liftedDefs.keys mkString ", ") } } // class LambdaLifter diff --git a/src/compiler/scala/tools/nsc/transform/LazyVals.scala b/src/compiler/scala/tools/nsc/transform/LazyVals.scala index 38dfcd4307..75d3e443d4 100644 --- a/src/compiler/scala/tools/nsc/transform/LazyVals.scala +++ b/src/compiler/scala/tools/nsc/transform/LazyVals.scala @@ -93,7 +93,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD deriveDefDef(tree)(_ => if (LocalLazyValFinder.find(res)) typed(addBitmapDefs(sym, res)) else res) } - case Template(parents, self, body) => atOwner(currentOwner) { + case Template(_, _, body) => atOwner(currentOwner) { val body1 = super.transformTrees(body) var added = false val stats = @@ -105,8 +105,8 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD added = true typed(addBitmapDefs(sym, stat)) } else stat - case ValDef(mods, name, tpt, rhs) => - typed(treeCopy.ValDef(stat, mods, name, tpt, addBitmapDefs(stat.symbol, rhs))) + case ValDef(_, _, _, _) => + typed(deriveValDef(stat)(addBitmapDefs(stat.symbol, _))) case _ => stat } @@ -121,29 +121,29 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD }) toAdd0 } else List() - treeCopy.Template(tree, parents, self, innerClassBitmaps ++ stats) + deriveTemplate(tree)(_ => innerClassBitmaps ++ stats) } - case ValDef(mods, name, tpt, rhs0) if (!sym.owner.isModule && !sym.owner.isClass) => - val rhs = super.transform(rhs0) - treeCopy.ValDef(tree, mods, name, tpt, - if (LocalLazyValFinder.find(rhs)) typed(addBitmapDefs(sym, rhs)) else rhs) + case ValDef(_, _, _, _) if !sym.owner.isModule && !sym.owner.isClass => + deriveValDef(tree) { rhs0 => + val rhs = super.transform(rhs0) + if (LocalLazyValFinder.find(rhs)) typed(addBitmapDefs(sym, rhs)) else rhs + } case l@LabelDef(name0, params0, ifp0@If(_, _, _)) if name0.startsWith(nme.WHILE_PREFIX) => val ifp1 = super.transform(ifp0) val If(cond0, thenp0, elsep0) = ifp1 + if (LocalLazyValFinder.find(thenp0)) - treeCopy.LabelDef(l, name0, params0, - treeCopy.If(ifp1, cond0, typed(addBitmapDefs(sym.owner, thenp0)), elsep0)) + deriveLabelDef(l)(_ => treeCopy.If(ifp1, cond0, typed(addBitmapDefs(sym.owner, thenp0)), elsep0)) else l - case l@LabelDef(name0, params0, block@Block(stats0, _)) + case l@LabelDef(name0, params0, block@Block(stats0, expr)) if name0.startsWith(nme.WHILE_PREFIX) || name0.startsWith(nme.DO_WHILE_PREFIX) => val stats1 = super.transformTrees(stats0) if (LocalLazyValFinder.find(stats1)) - treeCopy.LabelDef(l, name0, params0, - treeCopy.Block(block, typed(addBitmapDefs(sym.owner, stats1.head))::stats1.tail, block.expr)) + deriveLabelDef(l)(_ => treeCopy.Block(block, typed(addBitmapDefs(sym.owner, stats1.head))::stats1.tail, expr)) else l @@ -168,9 +168,9 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD def isMatch(params: List[Ident]) = (params.tail corresponds methSym.tpe.params)(_.tpe == _.tpe) if (bmps.isEmpty) rhs else rhs match { - case Block(assign, l @ LabelDef(name, params, rhs1)) + case Block(assign, l @ LabelDef(name, params, _)) if name.toString == ("_" + methSym.name) && isMatch(params) => - Block(assign, treeCopy.LabelDef(l, name, params, typed(prependStats(bmps, rhs1)))) + Block(assign, deriveLabelDef(l)(rhs => typed(prependStats(bmps, rhs)))) case _ => prependStats(bmps, rhs) } @@ -242,7 +242,7 @@ abstract class LazyVals extends Transform with TypingTransformers with ast.TreeD bmps(n) else { val sym = meth.newVariable(nme.newBitmapName(nme.BITMAP_NORMAL, n), meth.pos).setInfo(IntClass.tpe) - atPhase(currentRun.typerPhase) { + beforeTyper { sym addAnnotation VolatileAttr } diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 0ee2f1cd5a..3a2482e816 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -71,7 +71,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * maps all other types to themselves. */ private def toInterface(tp: Type): Type = - atPhase(currentRun.mixinPhase)(tp.typeSymbol.toInterface).tpe + beforeMixin(tp.typeSymbol.toInterface).tpe private def isFieldWithBitmap(field: Symbol) = { field.info // ensure that nested objects are transformed @@ -103,7 +103,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { private val toInterfaceMap = new TypeMap { def apply(tp: Type): Type = mapOver( tp match { case TypeRef(pre, sym, args) if (sym.isImplClass) => - typeRef(pre, atPhase(currentRun.mixinPhase)(sym.toInterface), args) + typeRef(pre, beforeMixin(sym.toInterface), args) case _ => tp }) } @@ -123,7 +123,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { * @param mixinClass The mixin class that produced the superaccessor */ private def rebindSuper(base: Symbol, member: Symbol, mixinClass: Symbol): Symbol = - atPhase(currentRun.picklerPhase.next) { + afterPickler { var bcs = base.info.baseClasses.dropWhile(mixinClass !=).tail var sym: Symbol = NoSymbol debuglog("starting rebindsuper " + base + " " + member + ":" + member.tpe + @@ -131,7 +131,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { while (!bcs.isEmpty && sym == NoSymbol) { if (settings.debug.value) { val other = bcs.head.info.nonPrivateDecl(member.name); - log("rebindsuper " + bcs.head + " " + other + " " + other.tpe + + debuglog("rebindsuper " + bcs.head + " " + other + " " + other.tpe + " " + other.isDeferred) } sym = member.matchingSymbol(bcs.head, base.thisType).suchThat(sym => !sym.hasFlag(DEFERRED | BRIDGE)) @@ -147,7 +147,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { member.hasAccessorFlag && (!member.isDeferred || (member hasFlag lateDEFERRED)) /** Is member overridden (either directly or via a bridge) in base class sequence `bcs`? */ - def isOverriddenAccessor(member: Symbol, bcs: List[Symbol]): Boolean = atPhase(ownPhase) { + def isOverriddenAccessor(member: Symbol, bcs: List[Symbol]): Boolean = atOwnPhase { def hasOverridingAccessor(clazz: Symbol) = { clazz.info.nonPrivateDecl(member.name).alternatives.exists( sym => @@ -155,8 +155,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { !sym.hasFlag(MIXEDIN) && matchesType(sym.tpe, member.tpe, true)) } - bcs.head != member.owner && - (hasOverridingAccessor(bcs.head) || isOverriddenAccessor(member, bcs.tail)) + ( bcs.head != member.owner + && (hasOverridingAccessor(bcs.head) || isOverriddenAccessor(member, bcs.tail)) + ) } /** Add given member to given class, and mark member as mixed-in. @@ -241,7 +242,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ def addMixedinMembers(clazz: Symbol, unit : CompilationUnit) { def cloneBeforeErasure(iface: Symbol, clazz: Symbol, imember: Symbol): Symbol = { - val newSym = atPhase(currentRun.erasurePhase) { + val newSym = beforeErasure { val res = imember.cloneSymbol(clazz) // since we used the member (imember) from the interface that represents the trait that's being mixed in, // have to instantiate the interface type params (that may occur in imember's info) as they are seen from the class @@ -337,8 +338,8 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { case _ => // otherwise mixin a field as well // atPhase: the private field is moved to the implementation class by erasure, // so it can no longer be found in the member's owner (the trait) - val accessed = atPhase(currentRun.picklerPhase)(member.accessed) - val sym = atPhase(currentRun.erasurePhase){ // #3857, need to retain info before erasure when cloning (since cloning only carries over the current entry in the type history) + val accessed = beforePickler(member.accessed) + val sym = beforeErasure { // #3857, need to retain info before erasure when cloning (since cloning only carries over the current entry in the type history) clazz.newValue(nme.getterToLocal(member.name), member.pos).setInfo(member.tpe.resultType) // so we have a type history entry before erasure } sym.updateInfo(member.tpe.resultType) // info at current phase @@ -349,13 +350,15 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { setAnnotations accessed.annotations) } } - } else if (member.isSuperAccessor) { // mixin super accessors + } + else if (member.isSuperAccessor) { // mixin super accessors val member1 = addMember(clazz, member.cloneSymbol(clazz)) setPos clazz.pos assert(member1.alias != NoSymbol, member1) val alias1 = rebindSuper(clazz, member.alias, mixinClass) member1.asInstanceOf[TermSymbol] setAlias alias1 - } else if (member.isMethod && member.isModule && member.hasNoFlags(LIFTED | BRIDGE)) { + } + else if (member.isMethod && member.isModule && member.hasNoFlags(LIFTED | BRIDGE)) { // mixin objects: todo what happens with abstract objects? addMember(clazz, member.cloneSymbol(clazz, member.flags & ~(DEFERRED | lateDEFERRED)) setPos clazz.pos) } @@ -383,7 +386,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { var parents1 = parents var decls1 = decls if (!clazz.isPackageClass) { - atPhase(phase.next)(clazz.owner.info) + afterMixin(clazz.owner.info) if (clazz.isImplClass) { clazz setFlag lateMODULE var sourceModule = clazz.owner.info.decls.lookup(sym.name.toTermName) @@ -449,7 +452,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { && sym.owner == templ.symbol.owner && !sym.isLazy && !tree.isDef) { - log("added use in: " + currentOwner + " -- " + tree) + debuglog("added use in: " + currentOwner + " -- " + tree) usedIn(sym) ::= currentOwner } @@ -459,7 +462,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { } } SingleUseTraverser(templ) - log("usedIn: " + usedIn) + debuglog("usedIn: " + usedIn) usedIn filter { case (_, member :: Nil) => member.isValue && member.isLazy case _ => false @@ -515,7 +518,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { tree match { case Template(parents, self, body) => localTyper = erasure.newTyper(rootContext.make(tree, currentOwner)) - atPhase(phase.next)(currentOwner.owner.info)//todo: needed? + afterMixin(currentOwner.owner.info)//todo: needed? if (!currentOwner.isTrait && !isValueClass(currentOwner)) addMixedinMembers(currentOwner, unit) @@ -534,7 +537,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { else EmptyTree } else { - if (currentOwner.isTrait && sym.isSetter && !atPhase(currentRun.picklerPhase)(sym.isDeferred)) { + if (currentOwner.isTrait && sym.isSetter && !beforePickler(sym.isDeferred)) { sym.addAnnotation(TraitSetterAnnotationClass) } tree @@ -703,13 +706,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { 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) - 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))) + deriveDefDef(stat)(_ => beforeMixin(transform(rhs1))) case _ => stat } @@ -740,7 +737,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { def createBitmap: Symbol = { val sym = clazz0.newVariable(bitmapName, clazz0.pos) setInfo IntClass.tpe - atPhase(currentRun.typerPhase)(sym addAnnotation VolatileAttr) + beforeTyper(sym addAnnotation VolatileAttr) category match { case nme.BITMAP_TRANSIENT | nme.BITMAP_CHECKINIT_TRANSIENT => sym addAnnotation TransientAttr @@ -848,7 +845,9 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val nulls = lazyValNullables(lzyVal).toList sortBy (_.id) map nullify def syncBody = init ::: List(mkSetFlag(clazz, offset, lzyVal), UNIT) - log("nulling fields inside " + lzyVal + ": " + nulls) + if (nulls.nonEmpty) + log("nulling fields inside " + lzyVal + ": " + nulls) + val result = gen.mkDoubleCheckedLocking(clazz, cond, syncBody, nulls) typedPos(init.head.pos)(BLOCK(result, retVal)) } @@ -942,7 +941,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { private def checkedGetter(lhs: Tree) = { val sym = clazz.info decl lhs.symbol.getterName suchThat (_.isGetter) if (needsInitAndHasOffset(sym)) { - log("adding checked getter for: " + sym + " " + lhs.symbol.defaultFlagString) + debuglog("adding checked getter for: " + sym + " " + lhs.symbol.defaultFlagString) List(localTyper typed mkSetFlag(clazz, fieldOffset(sym), sym)) } else Nil @@ -1129,7 +1128,6 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { */ private def postTransform(tree: Tree): Tree = { val sym = tree.symbol - // assert(tree.tpe ne null, tree.getClass +" : "+ tree +" in "+ localTyper.context.tree) // change every node type that refers to an implementation class to its // corresponding interface, unless the node's symbol is an implementation class. if (tree.tpe.typeSymbol.isImplClass && ((sym eq null) || !sym.isImplClass)) @@ -1236,7 +1234,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { val tree1 = super.transform(preTransform(tree)) // localTyper needed when not flattening inner classes. parts after an // inner class will otherwise be typechecked with a wrong scope - try atPhase(phase.next)(postTransform(tree1)) + try afterMixin(postTransform(tree1)) finally localTyper = saved } } diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 1e1c9efebb..e5d1e348d6 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -134,6 +134,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case _ => false } + def unspecializedSymbol(sym: Symbol): Symbol = { + if (sym hasFlag SPECIALIZED) { + // add initialization from its generic class constructor + val genericName = nme.unspecializedName(sym.name) + val member = sym.owner.info.decl(genericName.toTypeName) + member + } + else NoSymbol + } + object TypeEnv { /** Return a new type environment binding specialized type parameters of sym to * the given args. Expects the lists to have the same length. @@ -251,7 +261,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val stvTypeParams = specializedTypeVars(target.info.typeParams map (_.info)) val stvResult = specializedTypeVars(target.info.resultType) - log("degenerate: " + target + " stv tparams: " + stvTypeParams + " stv info: " + stvResult) + debuglog("degenerate: " + target + " stv tparams: " + stvTypeParams + " stv info: " + stvResult) (stvTypeParams -- stvResult).nonEmpty } @@ -308,7 +318,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { else specializedTypeVars(sym).intersect(env.keySet) ) val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod) - log("specName(" + sym + ") env: " + env + " tvars: " + tvars) + debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars) specializedName(sym.name, methparams map env, others map env) } @@ -397,8 +407,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { tpes foreach (tp => buf ++= specializedTypeVars(tp)) buf.result } - def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = - atPhase(currentRun.typerPhase)(specializedTypeVars(sym.info)) + def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] = beforeTyper(specializedTypeVars(sym.info)) /** Return the set of @specialized type variables mentioned by the given type. * It only counts type variables that appear: @@ -539,7 +548,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { var res: List[Type] = Nil // log(specializedClass + ": seeking specialized parents of class with parents: " + parents.map(_.typeSymbol)) for (p <- parents) { - val stp = atPhase(phase.next)(specializedType(p)) + val stp = afterSpecialize(specializedType(p)) if (stp != p) if (p.typeSymbol.isTrait) res ::= stp else if (currentRun.compiles(clazz)) @@ -549,7 +558,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { res } - var parents = List(applyContext(atPhase(currentRun.typerPhase)(clazz.tpe))) + var parents = List(applyContext(beforeTyper(clazz.tpe))) // log("!!! Parents: " + parents + ", sym: " + parents.map(_.typeSymbol)) if (parents.head.typeSymbol.isTrait) parents = parents.head.parents.head :: parents @@ -563,7 +572,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // as with the parents and assign it to typeOfThis. if (clazz.typeOfThis.typeConstructor ne clazz.typeConstructor) { sClass.typeOfThis = applyContext(clazz.typeOfThis) - log("Rewriting self-type for specialized class:\n" + + debuglog("Rewriting self-type for specialized class:\n" + " " + clazz.defStringSeenAs(clazz.typeOfThis) + "\n" + " => " + sClass.defStringSeenAs(sClass.typeOfThis) ) @@ -571,7 +580,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { polyType(newClassTParams, ClassInfoType(parents ::: extraSpecializedMixins, decls1, sClass)) } - atPhase(phase.next)(sClass setInfo specializedInfoType) + afterSpecialize(sClass setInfo specializedInfoType) val fullEnv = outerEnv ++ env /** Enter 'sym' in the scope of the current specialized class. It's type is @@ -645,7 +654,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { }) } else - log("conflicting env for " + m + " env: " + env) + debuglog("conflicting env for " + m + " env: " + env) } else if (m.isDeferred) { // abstract methods val specMember = enterMember(cloneInSpecializedClass(m, _ | DEFERRED)) @@ -714,7 +723,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { typeEnv(specClass) = fullEnv specClass.name = specializedName(specClass, fullEnv).toTypeName enterMember(specClass) - log("entered specialized class " + specClass.fullName) + debuglog("entered specialized class " + specClass.fullName) info(specClass) = SpecializedInnerClass(m, fullEnv) } } @@ -751,7 +760,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (existing != NoSymbol) clazz.owner.info.decls.unlink(existing) - atPhase(phase.next)(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes + afterSpecialize(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes } if (subclasses.nonEmpty) clazz.resetFlag(FINAL) cleanAnyRefSpecCache(clazz, decls1) @@ -770,7 +779,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = { debuglog("normalizeMember: " + sym.fullName) sym :: ( - if (!sym.isMethod || atPhase(currentRun.typerPhase)(sym.typeParams.isEmpty)) Nil + if (!sym.isMethod || beforeTyper(sym.typeParams.isEmpty)) Nil else { var specializingOn = specializedParams(sym) val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info) @@ -828,7 +837,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (sym.isPrivate/* || sym.isProtected*/) { //sym.privateWithin = sym.enclosingPackage sym.resetFlag(PRIVATE).setFlag(PROTECTED) - log("-->d SETTING PRIVATE WITHIN TO " + sym.enclosingPackage + " for " + sym) + debuglog("-->d SETTING PRIVATE WITHIN TO " + sym.enclosingPackage + " for " + sym) } val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec)) @@ -911,7 +920,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { checkOverriddenTParams(overridden) val env = unify(overridden.info, overriding.info, emptyEnv, false) - def atNext = atPhase(phase.next)(overridden.owner.info.decl(specializedName(overridden, env))) + def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env))) debuglog("\t\tenv: " + env + "isValid: " + TypeEnv.isValid(env, overridden) + "found: " + atNext) if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) @@ -926,7 +935,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case (NoSymbol, _) => None case (overridden, env) => val om = specializedOverload(clazz, overridden, env) - log("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info)) + debuglog("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info)) typeEnv(om) = env addConcreteSpecMethod(overriding) info(om) = ( @@ -951,7 +960,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { } ) overloads(overriding) ::= Overload(om, env) - ifDebug(atPhase(phase.next)(assert( + ifDebug(afterSpecialize(assert( overridden.owner.info.decl(om.name) != NoSymbol, "Could not find " + om.name + " in " + overridden.owner.info.decls)) ) @@ -1102,7 +1111,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case cinfo @ ClassInfoType(parents, decls, clazz) if !unspecializableClass(cinfo) => val tparams = tpe.typeParams if (tparams.isEmpty) - atPhase(phase.next)(parents map (_.typeSymbol.info)) + afterSpecialize(parents map (_.typeSymbol.info)) val parents1 = parents map specializedType debuglog("transformInfo %s %s with parents1 %s ph: %s".format( @@ -1148,7 +1157,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if (warnings) reporter.warning(tvar.pos, "Bounds prevent specialization of " + tvar) - log("specvars: " + + debuglog("specvars: " + tvar.info.bounds.lo + ": " + specializedTypeVars(tvar.info.bounds.lo) + " " + subst(env, tvar.info.bounds.hi) + ": " + @@ -1275,7 +1284,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { /** The specialized symbol of 'tree.symbol' for tree.tpe, if there is one */ def specSym(qual: Tree): Option[Symbol] = { val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) - log("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s" + debuglog("[specSym] checking for rerouting: %s with \n\tsym.tpe: %s, \n\ttree.tpe: %s \n\tenv: %s \n\tname: %s" .format(tree, symbol.tpe, tree.tpe, env, specializedName(symbol, env))) if (!env.isEmpty) { // a method? val specCandidates = qual.tpe.member(specializedName(symbol, env)) @@ -1283,12 +1292,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { doesConform(symbol, tree.tpe, qual.tpe.memberType(s), env) } - log("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe) - log("[specSym] found specMember: " + specMember) + debuglog("[specSym] found: " + specCandidates.tpe + ", instantiated as: " + tree.tpe) + debuglog("[specSym] found specMember: " + specMember) if (specMember ne NoSymbol) if (TypeEnv.includes(typeEnv(specMember), env)) Some(specMember) else { - log("wrong environments for specialized member: \n\ttypeEnv(%s) = %s\n\tenv = %s".format(specMember, typeEnv(specMember), env)) + debuglog("wrong environments for specialized member: \n\ttypeEnv(%s) = %s\n\tenv = %s".format(specMember, typeEnv(specMember), env)) None } else None @@ -1298,11 +1307,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { curTree = tree tree match { case Apply(Select(New(tpt), nme.CONSTRUCTOR), args) => - log("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", "))) + debuglog("Attempting to specialize new %s(%s)".format(tpt, args.mkString(", "))) val found = findSpec(tpt.tpe) if (found.typeSymbol ne tpt.tpe.typeSymbol) { // the ctor can be specialized - log("** instantiated specialized type: " + found) + debuglog("** instantiated specialized type: " + found) try localTyper.typedPos(tree.pos)(New(found, transformTrees(args): _*)) catch { case te: TypeError => @@ -1331,7 +1340,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { ) val tree1 = gen.mkTypeApply(Select(qual1, specMember), residualTargs) - log("rewrote " + tree + " to " + tree1) + debuglog("rewrote " + tree + " to " + tree1) localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method case None => super.transform(tree) @@ -1339,8 +1348,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case Select(Super(_, _), name) if illegalSpecializedInheritance(currentClass) => val pos = tree.pos - log(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.") - log(pos.lineContent) + debuglog(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.") + debuglog(pos.lineContent) tree case Select(qual, name) => @@ -1424,7 +1433,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { deriveDefDef(tree1)(transform) case NormalizedMember(target) => - log("Normalized member: " + symbol + ", target: " + target) + debuglog("Normalized member: " + symbol + ", target: " + target) if (target.isDeferred || conflicting(typeEnv(symbol))) { deriveDefDef(tree)(_ => localTyper typed gen.mkSysErrorCall("Fatal error in code generation: this should never be called.")) } @@ -1438,7 +1447,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case SpecialOverride(target) => assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName) //debuglog("moving implementation, body of target " + target + ": " + body(target)) - log("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor)) + debuglog("%s is param accessor? %b".format(ddef.symbol, ddef.symbol.isParamAccessor)) // we have an rhs, specialize it val tree1 = addBody(ddef, target) (new ChangeOwnerTraverser(target, tree1.symbol))(tree1.rhs) @@ -1447,24 +1456,24 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { case SpecialOverload(original, env) => debuglog("completing specialized " + symbol.fullName + " calling " + original) - log("special overload " + original + " -> " + env) + debuglog("special overload " + original + " -> " + env) val t = DefDef(symbol, { vparamss => val fun = Apply(Select(This(symbol.owner), original), makeArguments(original, vparamss.head)) - log("inside defdef: " + symbol + "; type: " + symbol.tpe + "; owner: " + symbol.owner) + debuglog("inside defdef: " + symbol + "; type: " + symbol.tpe + "; owner: " + symbol.owner) gen.maybeMkAsInstanceOf(fun, symbol.owner.thisType.memberType(symbol).finalResultType, symbol.owner.thisType.memberType(original).finalResultType) }) - log("created special overload tree " + t) + debuglog("created special overload tree " + t) debuglog("created " + t) localTyper.typed(t) case fwd @ Forward(_) => - log("forward: " + fwd + ", " + ddef) + debuglog("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) + debuglog("-->d completed forwarder to specialized overload: " + fwd.target + ": " + rhs1) localTyper.typed(deriveDefDef(tree)(_ => rhs1)) case SpecializedAccessor(target) => @@ -1472,37 +1481,28 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { gen.mkAttributedRef(target) else Assign(gen.mkAttributedRef(target), Ident(vparamss.head.head.symbol)) - log("specialized accessor: " + target + " -> " + rhs1) + debuglog("specialized accessor: " + target + " -> " + rhs1) localTyper.typed(deriveDefDef(tree)(_ => rhs1)) case Abstract(targ) => - log("abstract: " + targ) + debuglog("abstract: " + targ) localTyper.typed(deriveDefDef(tree)(rhs => rhs)) } - case ValDef(mods, name, tpt, rhs) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor => + case ValDef(_, _, _, _) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor => assert(body.isDefinedAt(symbol.alias), body) - val tree1 = treeCopy.ValDef(tree, mods, name, tpt, body(symbol.alias).duplicate) + val tree1 = deriveValDef(tree)(_ => body(symbol.alias).duplicate) debuglog("now typing: " + tree1 + " in " + tree.symbol.owner.fullName) + val d = new Duplicator - val ValDef(mods1, name1, tpt1, rhs1) = d.retyped( + val newValDef = d.retyped( localTyper.context1.asInstanceOf[d.Context], tree1, symbol.alias.enclClass, symbol.enclClass, typeEnv(symbol.alias) ++ typeEnv(tree.symbol) ) - val t = treeCopy.ValDef(tree1, mods1, name1, tpt1, transform(rhs1)) - log("valdef " + tree + " -> " + t) - t - -// val tree1 = -// treeCopy.ValDef(tree, mods, name, tpt, -// localTyper.typed( -// Apply(Select(Super(currentClass, nme.EMPTY), symbol.alias.getter(symbol.alias.owner)), -// List()))) -// debuglog("replaced ValDef: " + tree1 + " in " + tree.symbol.owner.fullName) -// tree1 + deriveValDef(newValDef)(transform) case Apply(sel @ Select(sup @ Super(qual, name), name1), args) if (sup.symbol.info.parents != atPhase(phase.prev)(sup.symbol.info.parents)) => @@ -1525,7 +1525,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { val meth = addBody(tree, source) val d = new Duplicator - log("-->d DUPLICATING: " + meth) + debuglog("-->d DUPLICATING: " + meth) d.retyped( localTyper.context1.asInstanceOf[d.Context], meth, @@ -1590,7 +1590,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { if m.hasFlag(SPECIALIZED) && (m.sourceFile ne null) && satisfiable(typeEnv(m), !sClass.hasFlag(SPECIALIZED))) { - log("creating tree for " + m.fullName) + debuglog("creating tree for " + m.fullName) if (m.isMethod) { if (info(m).target.hasAccessorFlag) hasSpecializedFields = true if (m.isClassConstructor) { @@ -1646,7 +1646,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { buf += ClassDef(specCls, atPos(impl.pos)(Template(parents, emptyValDef, List())) .setSymbol(specCls.newLocalDummy(sym1.pos))) setPos tree.pos - log("created synthetic class: " + specCls + " of " + sym1 + " in env: " + env) + debuglog("created synthetic class: " + specCls + " of " + sym1 + " in env: " + env) } case _ => } @@ -1708,7 +1708,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { * that here are not garbage collected at the end of a compiler run! */ def addConcreteSpecMethod(m: Symbol) { - if (!forInteractive && currentRun.compiles(m)) concreteSpecMethods += m + if (currentRun.compiles(m)) concreteSpecMethods += m } private def makeArguments(fun: Symbol, vparams: List[Symbol]): List[Tree] = ( @@ -1724,7 +1724,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { informProgress("specializing " + unit) override def transform(tree: Tree) = { val resultTree = if (settings.nospecialization.value) tree - else atPhase(phase.next)(specializeCalls(unit).transform(tree)) + else afterSpecialize(specializeCalls(unit).transform(tree)) // Remove the final modifier and @inline annotation from anything in the // original class (since it's being overridden in at least onesubclass). diff --git a/src/compiler/scala/tools/nsc/transform/TailCalls.scala b/src/compiler/scala/tools/nsc/transform/TailCalls.scala index 93fcd27191..23697a4730 100644 --- a/src/compiler/scala/tools/nsc/transform/TailCalls.scala +++ b/src/compiler/scala/tools/nsc/transform/TailCalls.scala @@ -204,7 +204,7 @@ abstract class TailCalls extends Transform { fail(reason) } def rewriteTailCall(recv: Tree): Tree = { - log("Rewriting tail recursive call: " + fun.pos.lineContent.trim) + debuglog("Rewriting tail recursive call: " + fun.pos.lineContent.trim) ctx.accessed = true typedPos(fun.pos)(Apply(Ident(ctx.label), recv :: transformArgs)) @@ -262,11 +262,7 @@ abstract class TailCalls extends Transform { ) case CaseDef(pat, guard, body) => - treeCopy.CaseDef(tree, - pat, - guard, - transform(body) - ) + deriveCaseDef(tree)(transform) case If(cond, thenp, elsep) => treeCopy.If(tree, diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala index 4b587a3f41..f49c340bec 100644 --- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala +++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala @@ -370,7 +370,7 @@ abstract class UnCurry extends InfoTransform // when calling into scala varargs, make sure it's a sequence. def arrayToSequence(tree: Tree, elemtp: Type) = { - atPhase(phase.next) { + afterUncurry { localTyper.typedPos(pos) { val pt = arrayType(elemtp) val adaptedTree = // might need to cast to Array[elemtp], as arrays are not covariant @@ -394,7 +394,7 @@ abstract class UnCurry extends InfoTransform else if (tp.bounds.hi ne tp) getManifest(tp.bounds.hi) else localTyper.getManifestTree(tree, tp, false) } - atPhase(phase.next) { + afterUncurry { localTyper.typedPos(pos) { Apply(gen.mkAttributedSelect(tree, toArraySym), List(getManifest(tree.tpe.baseType(TraversableClass).typeArgs.head))) @@ -419,7 +419,7 @@ abstract class UnCurry extends InfoTransform else arrayToSequence(mkArray, varargsElemType) } - atPhase(phase.next) { + afterUncurry { if (isJava && isPrimitiveArray(suffix.tpe) && isArrayOfSymbol(fun.tpe.params.last.tpe, ObjectClass)) { suffix = localTyper.typedPos(pos) { gen.mkRuntimeCall(nme.toObjectArray, List(suffix)) @@ -594,7 +594,7 @@ abstract class UnCurry extends InfoTransform result setType uncurryTreeType(result.tpe) } - def postTransform(tree: Tree): Tree = atPhase(phase.next) { + def postTransform(tree: Tree): Tree = afterUncurry { def applyUnary(): Tree = { // TODO_NMT: verify that the inner tree of a type-apply also gets parens if the // whole tree is a polymorphic nullary method application @@ -620,13 +620,11 @@ abstract class UnCurry extends InfoTransform * In particular, this case will add: * - synthetic Java varargs forwarders for repeated parameters */ - case Template(parents, self, body) => + case Template(_, _, _) => localTyper = typer.atOwner(tree, currentClass) - val tmpl = if (!forMSIL || forMSIL) { - treeCopy.Template(tree, parents, self, transformTrees(newMembers.toList) ::: body) - } else super.transform(tree).asInstanceOf[Template] - newMembers.clear - tmpl + try deriveTemplate(tree)(transformTrees(newMembers.toList) ::: _) + finally newMembers.clear() + case dd @ DefDef(_, _, _, vparamss0, _, rhs0) => val flatdd = copyDefDef(dd)( vparamss = List(vparamss0.flatten), diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 179bea0035..29831c8469 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -36,7 +36,7 @@ abstract class Duplicators extends Analyzer { } else resetClassOwners envSubstitution = new SubstSkolemsTypeMap(env.keysIterator.toList, env.valuesIterator.toList) - log("retyped with env: " + env) + debuglog("retyped with env: " + env) (new BodyDuplicator(context)).typed(tree) } @@ -82,14 +82,14 @@ abstract class Duplicators extends Analyzer { val sym1 = context.scope.lookup(sym.name) // assert(sym1 ne NoSymbol, tpe) if ((sym1 ne NoSymbol) && (sym1 ne sym)) { - log("fixing " + sym + " -> " + sym1) + debuglog("fixing " + sym + " -> " + sym1) typeRef(NoPrefix, sym1, mapOverArgs(args, sym1.typeParams)) } else super.mapOver(tpe) case TypeRef(pre, sym, args) => val newsym = updateSym(sym) if (newsym ne sym) { - log("fixing " + sym + " -> " + newsym) + debuglog("fixing " + sym + " -> " + newsym) typeRef(mapOver(pre), newsym, mapOverArgs(args, newsym.typeParams)) } else super.mapOver(tpe) @@ -97,7 +97,7 @@ abstract class Duplicators extends Analyzer { case SingleType(pre, sym) => val sym1 = updateSym(sym) if (sym1 ne sym) { - log("fixing " + sym + " -> " + sym1) + debuglog("fixing " + sym + " -> " + sym1) singleType(mapOver(pre), sym1) } else super.mapOver(tpe) @@ -105,7 +105,7 @@ abstract class Duplicators extends Analyzer { case ThisType(sym) => val sym1 = updateSym(sym) if (sym1 ne sym) { - log("fixing " + sym + " -> " + sym1) + debuglog("fixing " + sym + " -> " + sym1) ThisType(sym1) } else super.mapOver(tpe) @@ -136,26 +136,26 @@ abstract class Duplicators extends Analyzer { private def invalidate(tree: Tree) { debuglog("attempting to invalidate " + tree.symbol + ", owner - " + (if (tree.symbol ne null) tree.symbol.owner else "<NULL>")) if (tree.isDef && tree.symbol != NoSymbol) { - log("invalid " + tree.symbol) + debuglog("invalid " + tree.symbol) invalidSyms(tree.symbol) = tree tree match { case ldef @ LabelDef(name, params, rhs) => - log("LabelDef " + name + " sym.info: " + ldef.symbol.info) + debuglog("LabelDef " + name + " sym.info: " + ldef.symbol.info) invalidSyms(ldef.symbol) = ldef // breakIf(true, this, ldef, context) val newsym = ldef.symbol.cloneSymbol(context.owner) newsym.setInfo(fixType(ldef.symbol.info)) ldef.symbol = newsym - log("newsym: " + newsym + " info: " + newsym.info) + debuglog("newsym: " + newsym + " info: " + newsym.info) case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) => - log("ValDef " + name + " sym.info: " + vdef.symbol.info) + debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info) invalidSyms(vdef.symbol) = vdef val newsym = vdef.symbol.cloneSymbol(context.owner) newsym.setInfo(fixType(vdef.symbol.info)) vdef.symbol = newsym - log("newsym: " + newsym + " info: " + newsym.info) + debuglog("newsym: " + newsym + " info: " + newsym.info) case DefDef(_, name, tparams, vparamss, _, rhs) => // invalidate parameters @@ -182,7 +182,7 @@ abstract class Duplicators extends Analyzer { } ddef.symbol = NoSymbol enterSym(context, ddef) - log("remapping this of " + oldClassOwner + " to " + newClassOwner) + debuglog("remapping this of " + oldClassOwner + " to " + newClassOwner) typed(ddef) } @@ -228,7 +228,7 @@ abstract class Duplicators extends Analyzer { ttree case Block(stats, res) => - log("invalidating block") + debuglog("invalidating block") invalidate(stats) invalidate(res) tree.tpe = null @@ -256,7 +256,7 @@ abstract class Duplicators extends Analyzer { case ldef @ LabelDef(name, params, rhs) => // log("label def: " + ldef) ldef.tpe = null - val params1 = params map { p => Ident(updateSym(p.symbol)) } + val params1 = params map (p => Ident(updateSym(p.symbol))) super.typed(treeCopy.LabelDef(tree, name, params1, rhs), mode, pt) case Bind(name, _) => @@ -266,13 +266,13 @@ abstract class Duplicators extends Analyzer { super.typed(tree, mode, pt) case Ident(_) if tree.symbol.isLabel => - log("Ident to labeldef " + tree + " switched to ") + debuglog("Ident to labeldef " + tree + " switched to ") tree.symbol = updateSym(tree.symbol) tree.tpe = null super.typed(tree, mode, pt) case Ident(_) if (origtreesym ne null) && origtreesym.isLazy => - log("Ident to a lazy val " + tree + ", " + tree.symbol + " updated to " + origtreesym) + debuglog("Ident to a lazy val " + tree + ", " + tree.symbol + " updated to " + origtreesym) tree.symbol = updateSym(origtreesym) tree.tpe = null super.typed(tree, mode, pt) @@ -336,7 +336,7 @@ abstract class Duplicators extends Analyzer { tree case _ => - log("default: " + tree) + debuglog("Duplicators default case: " + tree.summaryString) if (tree.hasSymbol && tree.symbol != NoSymbol && (tree.symbol.owner == definitions.AnyClass)) { tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==) } diff --git a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala index 915d7a98db..3ba8cefca8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala +++ b/src/compiler/scala/tools/nsc/typechecker/MethodSynthesis.scala @@ -82,7 +82,7 @@ trait MethodSynthesis { } private def finishMethod(method: Symbol, f: Symbol => Tree): Tree = - logResult("finishMethod")(localTyper typed ValOrDefDef(method, f(method))) + localTyper typed ValOrDefDef(method, f(method)) private def createInternal(name: Name, f: Symbol => Tree, info: Type): Tree = { val m = clazz.newMethod(name.toTermName, clazz.pos.focus, newMethodFlags(name)) @@ -200,7 +200,7 @@ trait MethodSynthesis { map (acc => atPos(vd.pos.focus)(acc derive annotations)) filterNot (_ eq EmptyTree) ) - log(trees.mkString("Accessor trees:\n ", "\n ", "\n")) + // log(trees.mkString("Accessor trees:\n ", "\n ", "\n")) if (vd.symbol.isLazy) List(stat) else trees case _ => @@ -282,7 +282,7 @@ trait MethodSynthesis { } } private def logDerived(result: Tree): Tree = { - log("[+derived] " + ojoin(mods.defaultFlagString, basisSym.accurateKindString, basisSym.getterName.decode) + debuglog("[+derived] " + ojoin(mods.defaultFlagString, basisSym.accurateKindString, basisSym.getterName.decode) + " (" + derivedSym + ")\n " + result) result @@ -376,7 +376,7 @@ trait MethodSynthesis { override def keepClean = !mods.isParamAccessor override def derivedTree = ( if (mods.isDeferred) EmptyTree - else treeCopy.ValDef(tree, mods | flagsExtra, name, tree.tpt, tree.rhs) + else copyValDef(tree)(mods = mods | flagsExtra, name = this.name) ) } case class Param(tree: ValDef) extends DerivedFromValDef { diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 3347d2e767..eb7ea51d2b 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -277,12 +277,16 @@ trait Namers extends MethodSynthesis { def assignAndEnterFinishedSymbol(tree: MemberDef): Symbol = { val sym = assignAndEnterSymbol(tree) sym setInfo completerOf(tree) - log("[+info] " + sym.fullLocationString) + // log("[+info] " + sym.fullLocationString) sym } private def logAssignSymbol(tree: Tree, sym: Symbol): Symbol = { - log("[+symbol] " + sym.debugLocationString) + sym.name.toTermName match { + case nme.IMPORT | nme.OUTER | nme.ANON_CLASS_NAME | nme.ANON_FUN_NAME | nme.CONSTRUCTOR => () + case _ => + log("[+symbol] " + sym.debugLocationString) + } tree.symbol = sym sym } diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index 3a3c244d1c..44a3abf1b2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -37,21 +37,17 @@ trait NamesDefaults { self: Analyzer => } def isNamed(arg: Tree) = nameOf(arg).isDefined - /** @param pos maps indicies from old to new */ + /** @param pos maps indices from old to new */ def reorderArgs[T: ClassManifest](args: List[T], pos: Int => Int): List[T] = { val res = new Array[T](args.length) - // (hopefully) faster than zipWithIndex - (0 /: args) { case (index, arg) => res(pos(index)) = arg; index + 1 } + foreachWithIndex(args)((arg, index) => res(pos(index)) = arg) res.toList } - /** @param pos maps indicies from new to old (!) */ + /** @param pos maps indices from new to old (!) */ def reorderArgsInv[T: ClassManifest](args: List[T], pos: Int => Int): List[T] = { val argsArray = args.toArray - val res = new mutable.ListBuffer[T] - for (i <- 0 until argsArray.length) - res += argsArray(pos(i)) - res.toList + argsArray.indices map (i => argsArray(pos(i))) toList } /** returns `true` if every element is equal to its index */ @@ -507,7 +503,7 @@ trait NamesDefaults { self: Analyzer => /** * Removes name assignments from args. Additionally, returns an array mapping - * argument indicies from call-site-order to definition-site-order. + * argument indices from call-site-order to definition-site-order. * * Verifies that names are not specified twice, positional args don't appear * after named ones. diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 89617e6f2c..4a92458403 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -528,13 +528,13 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R def uncurryAndErase(tp: Type) = erasure.erasure(sym, uncurry.transformInfo(sym, tp)) val tp1 = uncurryAndErase(clazz.thisType.memberType(sym)) val tp2 = uncurryAndErase(clazz.thisType.memberType(other)) - atPhase(currentRun.erasurePhase.next)(tp1 matches tp2) + afterErasure(tp1 matches tp2) }) def ignoreDeferred(member: Symbol) = ( (member.isAbstractType && !member.isFBounded) || ( member.isJavaDefined && - // the test requires atPhase(erasurePhase.next) so shouldn't be + // the test requires afterErasure so shouldn't be // done if the compiler has no erasure phase available (currentRun.erasurePhase == NoPhase || javaErasedOverridingSym(member) != NoSymbol) ) @@ -1175,7 +1175,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R case vsym => ValDef(vsym) } } - def createStaticModuleAccessor() = atPhase(phase.next) { + def createStaticModuleAccessor() = afterRefchecks { val method = ( sym.owner.newMethod(sym.name.toTermName, sym.pos, (sym.flags | STABLE) & ~MODULE) setInfoAndEnter NullaryMethodType(sym.moduleClass.tpe) @@ -1186,7 +1186,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R vdef, localTyper.typedPos(tree.pos) { val vsym = vdef.symbol - atPhase(phase.next) { + afterRefchecks { val rhs = gen.newModule(sym, vsym.tpe) val body = if (sym.owner.isTrait) rhs else gen.mkAssignAndReturn(vsym, rhs) DefDef(sym, body.changeOwner(vsym -> sym)) @@ -1222,12 +1222,12 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R else gen.mkAssignAndReturn(vsym, rhs) ) val lazyDef = atPos(tree.pos)(DefDef(lazySym, body.changeOwner(vsym -> lazySym))) - log("Made lazy def: " + lazyDef) + debuglog("Created lazy accessor: " + lazyDef) if (hasUnitType) List(typed(lazyDef)) else List( typed(ValDef(vsym)), - atPhase(phase.next)(typed(lazyDef)) + afterRefchecks(typed(lazyDef)) ) } @@ -1548,8 +1548,7 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R checkOverloadedRestrictions(currentOwner) val bridges = addVarargBridges(currentOwner) checkAllOverrides(currentOwner) - if (bridges.nonEmpty) treeCopy.Template(tree, parents, self, body ::: bridges) - else tree + if (bridges.nonEmpty) deriveTemplate(tree)(_ ::: bridges) else tree case dc@TypeTreeWithDeferredRefCheck() => assert(false, "adapt should have turned dc: TypeTreeWithDeferredRefCheck into tpt: TypeTree, with tpt.original == dc"); dc case tpt@TypeTree() => diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 0ab09b4fec..64f1662a22 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -177,7 +177,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT case ModuleDef(_, _, _) => checkCompanionNameClashes(sym) super.transform(tree) - case Template(parents, self, body) => + case Template(_, _, body) => val ownAccDefs = new ListBuffer[Tree] accDefs(currentOwner) = ownAccDefs @@ -189,7 +189,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT val body1 = atOwner(currentOwner)(transformTrees(body)) accDefs -= currentOwner ownAccDefs ++= body1 - treeCopy.Template(tree, parents, self, ownAccDefs.toList) + deriveTemplate(tree)(_ => ownAccDefs.toList) case TypeApply(sel @ Select(This(_), name), args) => mayNeedProtectedAccessor(sel, args, false) diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index cf90577959..c53b92c5be 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -248,11 +248,11 @@ trait SyntheticMethods extends ast.TreeDSL { } if (phase.id > currentRun.typerPhase.id) templ - else treeCopy.Template(templ, templ.parents, templ.self, + else deriveTemplate(templ)(body => if (clazz.isCase) caseTemplateBody() else synthesize() match { - case Nil => templ.body // avoiding unnecessary copy - case ms => templ.body ++ ms + case Nil => body // avoiding unnecessary copy + case ms => body ++ ms } ) } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 1c1f35aac2..ea8112f1a4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1503,12 +1503,12 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (templ.symbol == NoSymbol) templ setSymbol clazz.newLocalDummy(templ.pos) val self1 = templ.self match { - case vd @ ValDef(mods, name, tpt, EmptyTree) => + case vd @ ValDef(_, _, tpt, EmptyTree) => val tpt1 = checkNoEscaping.privates( clazz.thisSym, treeCopy.TypeTree(tpt).setOriginal(tpt) setType vd.symbol.tpe ) - treeCopy.ValDef(vd, mods, name, tpt1, EmptyTree) setType NoType + copyValDef(vd)(tpt = tpt1, rhs = EmptyTree) setType NoType } // was: // val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt)) @@ -1861,8 +1861,9 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { val restpe = ldef.symbol.tpe.resultType val rhs1 = typed(ldef.rhs, restpe) ldef.params foreach (param => param.tpe = param.symbol.tpe) - treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs1) setType restpe - } else { + deriveLabelDef(ldef)(_ => rhs1) setType restpe + } + else { val initpe = ldef.symbol.tpe.resultType val rhs1 = typed(ldef.rhs) val restpe = rhs1.tpe @@ -1875,7 +1876,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { context.owner.newLabel(ldef.name, ldef.pos) setInfo MethodType(List(), restpe)) val rhs2 = typed(resetAllAttrs(ldef.rhs), restpe) ldef.params foreach (param => param.tpe = param.symbol.tpe) - treeCopy.LabelDef(ldef, ldef.name, ldef.params, rhs2) setSymbol sym2 setType restpe + deriveLabelDef(ldef)(_ => rhs2) setSymbol sym2 setType restpe } } } @@ -3644,8 +3645,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (ps.isEmpty) ps = site.parents filter (_.typeSymbol.toInterface.name == mix) if (ps.isEmpty) { - if (settings.debug.value) - Console.println(site.parents map (_.typeSymbol.name))//debug + debuglog("Fatal: couldn't find site " + site + " in " + site.parents.map(_.typeSymbol.name)) if (phase.erasedTypes && context.enclClass.owner.isImplClass) { // println(qual1) // println(clazz) @@ -4112,7 +4112,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { } def adaptCase(cdef: CaseDef, tpe: Type): CaseDef = - treeCopy.CaseDef(cdef, cdef.pat, cdef.guard, adapt(cdef.body, mode, tpe)) + deriveCaseDef(cdef)(adapt(_, mode, tpe)) // begin typed1 val sym: Symbol = tree.symbol @@ -4630,7 +4630,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { case None => typed(tree, mode, pt) } - def findManifest(tp: Type, full: Boolean) = atPhase(currentRun.typerPhase) { + def findManifest(tp: Type, full: Boolean) = beforeTyper { inferImplicit( EmptyTree, appliedType((if (full) FullManifestClass else PartialManifestClass).typeConstructor, List(tp)), diff --git a/src/compiler/scala/tools/nsc/util/ProxyReport.scala b/src/compiler/scala/tools/nsc/util/ProxyReport.scala index 2f4f029308..4fc86c3a32 100644 --- a/src/compiler/scala/tools/nsc/util/ProxyReport.scala +++ b/src/compiler/scala/tools/nsc/util/ProxyReport.scala @@ -141,6 +141,6 @@ object ProxyReportRunner { s.processArguments(args.toList.tail, true) val g = new ProxyGlobal(s) val run = new g.Run() - g.atPhase(run.typerPhase.next)(g.proxyReport.generate(dir)) + g.afterTyper(g.proxyReport.generate(dir)) } } |