diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-05-23 11:01:19 -0700 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2012-05-23 11:01:19 -0700 |
commit | 019c7aa2f6440e2b99066da464e0c48e9f83c74e (patch) | |
tree | 60b88adaa566c74cc7960b0f6d3bb58026cd42e2 /src | |
parent | c28a8588e10187a5c1dd03dbc677da19ed7205f8 (diff) | |
parent | f026bbb2ee1d1f9bed8c3a401833bb535b856f6b (diff) | |
download | scala-019c7aa2f6440e2b99066da464e0c48e9f83c74e.tar.gz scala-019c7aa2f6440e2b99066da464e0c48e9f83c74e.tar.bz2 scala-019c7aa2f6440e2b99066da464e0c48e9f83c74e.zip |
Merge pull request #607 from paulp/may22-checkin
tests and misc improvements
Diffstat (limited to 'src')
12 files changed, 115 insertions, 108 deletions
diff --git a/src/compiler/scala/reflect/internal/InfoTransformers.scala b/src/compiler/scala/reflect/internal/InfoTransformers.scala index 96d9d8f076..e53f714c0c 100644 --- a/src/compiler/scala/reflect/internal/InfoTransformers.scala +++ b/src/compiler/scala/reflect/internal/InfoTransformers.scala @@ -20,12 +20,14 @@ trait InfoTransformers { def transform(sym: Symbol, tpe: Type): Type def insert(that: InfoTransformer) { - assert(this.pid != that.pid) + assert(this.pid != that.pid, this.pid) + if (that.pid < this.pid) { prev insert that } else if (next.pid <= that.pid && next.pid != NoPhase.id) { next insert that } else { + log("Inserting info transformer %s following %s".format(phaseOf(that.pid), phaseOf(this.pid))) that.next = next that.prev = this next.prev = that diff --git a/src/compiler/scala/reflect/internal/Phase.scala b/src/compiler/scala/reflect/internal/Phase.scala index 89d643aacf..68dc5ce783 100644 --- a/src/compiler/scala/reflect/internal/Phase.scala +++ b/src/compiler/scala/reflect/internal/Phase.scala @@ -7,9 +7,10 @@ package scala.reflect package internal abstract class Phase(val prev: Phase) { + if ((prev ne null) && (prev ne NoPhase)) + prev.nx = this type Id = Int - val id: Id = if (prev eq null) 0 else prev.id + 1 /** New flags visible after this phase has completed */ @@ -18,12 +19,13 @@ abstract class Phase(val prev: Phase) { /** New flags visible once this phase has started */ def newFlags: Long = 0l - private var fmask: Long = - if (prev eq null) Flags.InitialFlags else prev.flagMask | prev.nextFlags | newFlags + val fmask = ( + if (prev eq null) Flags.InitialFlags + else prev.flagMask | prev.nextFlags | newFlags + ) def flagMask: Long = fmask private var nx: Phase = this - if ((prev ne null) && (prev ne NoPhase)) prev.nx = this def next: Phase = nx def hasNext = next != this diff --git a/src/compiler/scala/reflect/internal/util/Origins.scala b/src/compiler/scala/reflect/internal/util/Origins.scala index 19b3adda9d..0bd5ad55ca 100644 --- a/src/compiler/scala/reflect/internal/util/Origins.scala +++ b/src/compiler/scala/reflect/internal/util/Origins.scala @@ -15,7 +15,7 @@ import Origins._ * You could do this: * * {{{ - * private lazy val origins = Origins[SymbolTable]("phase_=") + * private lazy val origins = Origins("arbitraryTag") * // Commented out original enclosed for contrast * // final def phase_=(p: Phase): Unit = { * final def phase_=(p: Phase): Unit = origins { @@ -23,7 +23,7 @@ import Origins._ * * And that's it. When the JVM exits it would issue a report something like this: {{{ - >> Origins scala.tools.nsc.symtab.SymbolTable.phase_= logged 145585 calls from 51 distinguished sources. + >> Origins tag 'arbitraryTag' logged 145585 calls from 51 distinguished sources. 71114 scala.tools.nsc.symtab.Symbols$Symbol.unsafeTypeParams(Symbols.scala:862) 16584 scala.tools.nsc.symtab.Symbols$Symbol.rawInfo(Symbols.scala:757) @@ -37,29 +37,21 @@ import Origins._ */ abstract class Origins { type Rep + type StackSlice = Array[StackTraceElement] + + def tag: String + def isCutoff(el: StackTraceElement): Boolean def newRep(xs: StackSlice): Rep def repString(rep: Rep): String - def originClass: String - - private var _tag: String = null - def tag: String = _tag - def setTag(tag: String): this.type = { - _tag = tag - this - } private val origins = new mutable.HashMap[Rep, Int] withDefaultValue 0 private def add(xs: Rep) = origins(xs) += 1 private def total = origins.values.foldLeft(0L)(_ + _) - // We find the right line by dropping any from around here and any - // from the method's origin class. - private def dropStackElement(cn: String) = - (cn startsWith OriginsName) || (cn startsWith originClass) - // Create a stack and whittle it down to the interesting part. - private def readStack(): Array[StackTraceElement] = - (new Throwable).getStackTrace dropWhile (el => dropStackElement(el.getClassName)) + def readStack(): Array[StackTraceElement] = ( + Thread.currentThread.getStackTrace dropWhile (x => !isCutoff(x)) dropWhile isCutoff drop 1 + ) def apply[T](body: => T): T = { add(newRep(readStack())) @@ -67,7 +59,7 @@ abstract class Origins { } def clear() = origins.clear() def show() = { - println("\n>> Origins %s.%s logged %s calls from %s distinguished sources.\n".format(originClass, tag, total, origins.keys.size)) + println("\n>> Origins tag '%s' logged %s calls from %s distinguished sources.\n".format(tag, total, origins.keys.size)) origins.toList sortBy (-_._2) foreach { case (k, v) => println("%7s %s".format(v, repString(k))) } @@ -79,29 +71,49 @@ abstract class Origins { } object Origins { - private type StackSlice = Array[StackTraceElement] - private val OriginsName = classOf[Origins].getName - private val counters = new mutable.HashSet[Origins] + private val counters = mutable.HashMap[String, Origins]() + private val thisClass = this.getClass.getName - { - // Console.println("\nOrigins loaded: registering shutdown hook to display results.") - sys.addShutdownHook(counters foreach (_.purge())) + locally { + sys.addShutdownHook(counters.values foreach (_.purge())) } - def apply[T: ClassTag](tag: String): Origins = apply(tag, classTag[T].erasure) - def apply(tag: String, clazz: Class[_]): Origins = apply(tag, new OneLine(clazz)) - def apply(tag: String, orElse: => Origins): Origins = { - counters find (_.tag == tag) getOrElse { - val res = orElse setTag tag - counters += res - res - } + case class OriginId(className: String, methodName: String) { + def matches(el: StackTraceElement) = ( + (methodName == el.getMethodName) && (className startsWith el.getClassName) + ) } - class OneLine(clazz: Class[_]) extends Origins { - type Rep = StackTraceElement - val originClass = clazz.getName stripSuffix MODULE_SUFFIX_STRING - def newRep(xs: StackSlice): Rep = xs(0) - def repString(rep: Rep) = " " + rep + def lookup(tag: String, orElse: String => Origins): Origins = + counters.getOrElseUpdate(tag, orElse(tag)) + def register(x: Origins): Origins = { + counters(x.tag) = x + x + } + + private def preCutoff(el: StackTraceElement) = ( + (el.getClassName == thisClass) + || (el.getClassName startsWith "java.lang.") + ) + private def findCutoff() = { + val cutoff = Thread.currentThread.getStackTrace dropWhile preCutoff head; + OriginId(cutoff.getClassName, cutoff.getMethodName) + } + + def apply(tag: String): Origins = counters.getOrElseUpdate(tag, new OneLine(tag, findCutoff())) + def apply(tag: String, frames: Int): Origins = counters.getOrElseUpdate(tag, new MultiLine(tag, findCutoff(), frames)) + + class OneLine(val tag: String, id: OriginId) extends Origins { + type Rep = StackTraceElement + def isCutoff(el: StackTraceElement) = id matches el + def newRep(xs: StackSlice): Rep = if ((xs eq null) || (xs.length == 0)) null else xs(0) + def repString(rep: Rep) = " " + rep + } + class MultiLine(val tag: String, id: OriginId, numLines: Int) extends Origins { + type Rep = List[StackTraceElement] + def isCutoff(el: StackTraceElement) = id matches el + def newRep(xs: StackSlice): Rep = (xs take numLines).toList + def repString(rep: Rep) = rep.map("\n " + _).mkString + override def readStack() = super.readStack() drop 1 } } diff --git a/src/compiler/scala/tools/nsc/ast/TreeGen.scala b/src/compiler/scala/tools/nsc/ast/TreeGen.scala index 23fcffd657..3a527676b4 100644 --- a/src/compiler/scala/tools/nsc/ast/TreeGen.scala +++ b/src/compiler/scala/tools/nsc/ast/TreeGen.scala @@ -208,6 +208,7 @@ abstract class TreeGen extends reflect.internal.TreeGen with TreeDSL { else AppliedTypeTree(Ident(clazz), targs map TypeTree) )) } + def mkSuperSelect = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) def wildcardStar(tree: Tree) = atPos(tree.pos) { Typed(tree, Ident(tpnme.WILDCARD_STAR)) } diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index adc490c8e1..6f1a8f488f 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -115,9 +115,7 @@ trait Trees extends reflect.internal.Trees { self: Global => // convert (implicit ... ) to ()(implicit ... ) if its the only parameter section if (vparamss1.isEmpty || !vparamss1.head.isEmpty && vparamss1.head.head.mods.isImplicit) vparamss1 = List() :: vparamss1; - val superRef: Tree = atPos(superPos) { - Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) - } + val superRef: Tree = atPos(superPos)(gen.mkSuperSelect) val superCall = (superRef /: argss) (Apply) List( atPos(wrappingPos(superPos, lvdefs ::: argss.flatten)) ( diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index c02a7e493e..a0524d6932 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -385,7 +385,7 @@ self => Nil, List(Nil), TypeTree(), - Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil)), Literal(Constant(()))) + Block(List(Apply(gen.mkSuperSelect, Nil)), Literal(Constant(()))) ) // def main diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index cb7d64b9fc..e5fc98f23c 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -308,8 +308,7 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => // body until now, because the typer knows that Any has no // constructor and won't accept a call to super.init. assert((clazz isSubClass AnyValClass) || clazz.info.parents.isEmpty, clazz) - val superCall = Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), Nil) - Block(List(superCall), expr) + Block(List(Apply(gen.mkSuperSelect, Nil)), expr) case Block(stats, expr) => // needs `hasSymbol` check because `supercall` could be a block (named / default args) diff --git a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala index 0905fa86c6..880f0f0157 100644 --- a/src/compiler/scala/tools/nsc/transform/InfoTransform.scala +++ b/src/compiler/scala/tools/nsc/transform/InfoTransform.scala @@ -37,7 +37,7 @@ trait InfoTransform extends Transform { val changesBaseClasses = InfoTransform.this.changesBaseClasses def transform(sym: Symbol, tpe: Type): Type = transformInfo(sym, tpe) } - infoTransformers.insert(infoTransformer) + infoTransformers insert infoTransformer } } } diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 07a10ecb1f..f2e109a5ad 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -1388,26 +1388,23 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { tree case Select(qual, name) => - debuglog("[%s] looking at Select: %s sym: %s: %s [tree.tpe: %s]".format( - tree.pos.safeLine, tree, symbol, symbol.info, tree.tpe)) + debuglog("specializing Select %s [tree.tpe: %s]".format(symbol.defString, tree.tpe)) //log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info)) if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) { // log("!!! unifying " + (symbol, symbol.tpe) + " and " + (tree, tree.tpe)) val env = unify(symbol.tpe, tree.tpe, emptyEnv, false) // log("!!! found env: " + env + "; overloads: " + overloads(symbol)) - debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env) if (!env.isEmpty) { + // debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env) val specMember = overload(symbol, env) - //log("!!! found member: " + specMember) if (specMember.isDefined) { - // log("** routing " + tree + " to " + specMember.get.sym.fullName) localTyper.typedOperator(atPos(tree.pos)(Select(transform(qual), specMember.get.sym.name))) - } else { + } + else { val qual1 = transform(qual) val specMember = qual1.tpe.member(specializedName(symbol, env)).suchThat(_.tpe matches subst(env, symbol.tpe)) if (specMember ne NoSymbol) { - // log("** using spec member " + specMember + ": " + specMember.tpe) val tree1 = atPos(tree.pos)(Select(qual1, specMember)) if (specMember.isMethod) localTyper.typedOperator(tree1) @@ -1450,10 +1447,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { // log("--> method: " + ddef + " in " + ddef.symbol.owner + ", " + info(symbol)) if (symbol.isConstructor) { - val t = atOwner(symbol) { - val superRef: Tree = Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR) - forwardCtorCall(tree.pos, superRef, vparamss, symbol.owner) - } + val t = atOwner(symbol)(forwardCtorCall(tree.pos, gen.mkSuperSelect, vparamss, symbol.owner)) + if (symbol.isPrimaryConstructor) localTyper.typedPos(symbol.pos)(deriveDefDef(tree)(_ => Block(List(t), Literal(Constant())))) else // duplicate the original constructor diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 2f2278251b..b4f42a5033 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -636,7 +636,7 @@ trait Namers extends MethodSynthesis { classAndNamerOfModule(m) = (tree, null) } val owner = tree.symbol.owner - if (settings.lint.value && owner.isPackageObjectClass) { + if (settings.lint.value && owner.isPackageObjectClass && !mods.isImplicit) { context.unit.warning(tree.pos, "it is not recommended to define classes/objects inside of package objects.\n" + "If possible, define " + tree.symbol + " in " + owner.skipPackageObject + " instead." diff --git a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala index d1f319311e..932e4548ef 100644 --- a/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala +++ b/src/compiler/scala/tools/nsc/typechecker/NamesDefaults.scala @@ -260,19 +260,18 @@ trait NamesDefaults { self: Analyzer => def argValDefs(args: List[Tree], paramTypes: List[Type], blockTyper: Typer): List[ValDef] = { val context = blockTyper.context val symPs = map2(args, paramTypes)((arg, tpe) => { - val byName = isByNameParamType(tpe) - val (argTpe, repeated) = - if (isScalaRepeatedParamType(tpe)) arg match { - case Typed(expr, Ident(tpnme.WILDCARD_STAR)) => - (expr.tpe, true) - case _ => - (seqType(arg.tpe), true) - } else (arg.tpe, false) - val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos) - val valType = if (byName) functionType(List(), argTpe) - else if (repeated) argTpe - else argTpe - s.setInfo(valType) + val byName = isByNameParamType(tpe) + val repeated = isScalaRepeatedParamType(tpe) + val argTpe = ( + if (repeated) arg match { + case Typed(expr, Ident(tpnme.WILDCARD_STAR)) => expr.tpe + case _ => seqType(arg.tpe) + } + else arg.tpe + ).widen // have to widen or types inferred from literal defaults will be singletons + val s = context.owner.newValue(unit.freshTermName("x$"), arg.pos) setInfo ( + if (byName) functionType(Nil, argTpe) else argTpe + ) (context.scope.enter(s), byName, repeated) }) map2(symPs, args) { diff --git a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala index a6a8d6009f..fde760c752 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TreeCheckers.scala @@ -14,22 +14,7 @@ import util.returning abstract class TreeCheckers extends Analyzer { import global._ - private val everything = ListBuffer[(Phase, Map[Tree, (Symbol, Type)])]() - private val currentTrees = mutable.Map[Tree, (Symbol, Type)]() - private val tpeOfTree = mutable.HashMap[Tree, Type]() - - if (settings.debug.value) { - sys addShutdownHook { - for ((ph, map) <- everything.toList) { - println("\n>>>> " + ph + "\n") - for ((tree, (sym, tpe)) <- map.toList.sortBy(_._1.summaryString)) { - println("%20s %20s %s".format(sym, tpe, ("" + tree) take 50)) - } - } - } - } - - private def classstr(x: AnyRef) = (x.getClass.getName split """\\.|\\$""").last + private def classstr(x: AnyRef) = x.getClass.getName split """\\.|\\$""" last; private def typestr(x: Type) = " (tpe = " + x + ")" private def treestr(t: Tree) = t + " [" + classstr(t) + "]" + typestr(t.tpe) private def ownerstr(s: Symbol) = "'" + s + "'" + s.locationString @@ -50,14 +35,13 @@ abstract class TreeCheckers extends Analyzer { object SymbolTracker extends Traverser { type PhaseMap = mutable.HashMap[Symbol, List[Tree]] - val defSyms = mutable.HashMap[Symbol, List[DefTree]]() withDefaultValue Nil - val newSyms = mutable.HashSet[Symbol]() val maps = ListBuffer[(Phase, PhaseMap)]() - val movedMsgs = ListBuffer[String]() - def prev = maps.init.last._2 def latest = maps.last._2 - def sortedNewSyms = newSyms.toList.distinct sortBy (_.name) + val defSyms = mutable.HashMap[Symbol, List[DefTree]]() + val newSyms = mutable.HashSet[Symbol]() + val movedMsgs = new ListBuffer[String] + def sortedNewSyms = newSyms.toList.distinct sortBy (_.name.toString) def inPrev(sym: Symbol) = { (maps.size >= 2) && (prev contains sym) @@ -108,21 +92,18 @@ abstract class TreeCheckers extends Analyzer { if (maps.isEmpty || maps.last._1 != ph) maps += ((ph, new PhaseMap)) - currentTrees.clear() traverse(unit.body) - everything += ((ph, currentTrees.toMap)) - reportChanges() } override def traverse(tree: Tree): Unit = { val sym = tree.symbol - currentTrees(tree) = ((sym, tree.tpe)) - if (sym != null && sym != NoSymbol) { record(sym, tree) tree match { - case x: DefTree => defSyms(sym) :+= x - case _ => () + case x: DefTree => + if (defSyms contains sym) defSyms(sym) = defSyms(sym) :+ x + else defSyms(sym) = List(x) + case _ => () } } @@ -130,6 +111,8 @@ abstract class TreeCheckers extends Analyzer { } } + lazy val tpeOfTree = mutable.HashMap[Tree, Type]() + def posstr(p: Position) = try p.source.path + ":" + p.line catch { case _: UnsupportedOperationException => p.toString } @@ -144,9 +127,20 @@ abstract class TreeCheckers extends Analyzer { def assertFn(cond: Boolean, msg: => Any) = if (!cond) errorFn(msg) + private def wrap[T](msg: => Any)(body: => Unit) { + try body + catch { case x => + Console.println("Caught " + x) + Console.println(msg) + x.printStackTrace + } + } + def checkTrees() { - informFn("[consistency check at the beginning of phase " + phase + "]") - currentRun.units foreach check + if (settings.verbose.value) + Console.println("[consistency check at the beginning of phase " + phase + "]") + + currentRun.units foreach (x => wrap(x)(check(x))) } def printingTypings[T](body: => T): T = { @@ -168,7 +162,7 @@ abstract class TreeCheckers extends Analyzer { informProgress("checking "+unit) val context = rootContext(unit) context.checking = true - tpeOfTree.clear() + tpeOfTree.clear SymbolTracker.check(phase, unit) val checker = new TreeChecker(context) runWithUnit(unit) { @@ -215,11 +209,11 @@ abstract class TreeCheckers extends Analyzer { tree.tpe = null saved }) - super.typed(tree, mode, pt) match { + wrap(tree)(super.typed(tree, mode, pt) match { case _: Literal => () case x if x ne tree => treesDiffer(tree, x) case _ => () - } + }) case _ => () } @@ -286,7 +280,12 @@ abstract class TreeCheckers extends Analyzer { if (sym.owner != currentOwner) { val expected = currentOwner.ownerChain find (x => cond(x)) getOrElse fail("DefTree can't find owner: ") if (sym.owner != expected) - fail("Expected owner %s (out of %s), found %s: ".format(expected, currentOwner.ownerChain, sym.owner)) + fail("""| + | currentOwner chain: %s + | symbol chain: %s""".stripMargin.format( + currentOwner.ownerChain take 3 mkString " -> ", + sym.ownerChain mkString " -> ") + ) } } } |