summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2012-04-05 17:17:39 -0700
committerMartin Odersky <odersky@gmail.com>2012-04-05 17:17:39 -0700
commit115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b (patch)
tree15265c311900918c79c5eda8d54c58fc145ef4a8 /src/compiler
parent7f79ef0e30f088b41b14763f44338c240acf1a63 (diff)
parent754b4a85e4093f25cc10f092fefdb34215097c94 (diff)
downloadscala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.gz
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.tar.bz2
scala-115f5467e3f3ff07abbba2b23c40c2ff0d7ddd1b.zip
Merge branch 'master' into topic/reflect
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala5
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala7
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala10
-rw-r--r--src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala168
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala3
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/RefChecks.scala15
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala11
11 files changed, 209 insertions, 23 deletions
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index bb11ca634a..256c1a6ced 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -62,6 +62,11 @@ abstract class SymbolTable extends api.Universe
result
}
+ final val traceSymbolActivity = sys.props contains "scalac.debug.syms"
+ object traceSymbols extends {
+ val global: SymbolTable.this.type = SymbolTable.this
+ } with util.TraceSymbolActivity
+
/** Are we compiling for Java SE? */
// def forJVM: Boolean
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 4842d47e4d..63d030531d 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -3,7 +3,6 @@
* @author Martin Odersky
*/
-
package scala.reflect
package internal
@@ -166,9 +165,11 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
private var rawpos = initPos
val id = nextId() // identity displayed when -uniqid
-
private[this] var _validTo: Period = NoPeriod
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbol(this)
+
def validTo = _validTo
def validTo_=(x: Period) { _validTo = x}
@@ -863,6 +864,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
else originalOwner(this) = rawowner
}
assert(!inReflexiveMirror, "owner_= is not thread-safe; cannot be run in reflexive code")
+ if (traceSymbolActivity)
+ traceSymbols.recordNewSymbolOwner(this, owner)
_rawowner = owner
}
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 5afa5343ed..786b680ff8 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -5059,6 +5059,8 @@ trait Types extends api.Types { self: SymbolTable =>
case (_, tv @ TypeVar(_,_)) => tv.registerTypeSelection(tr2.sym, tr1)
case _ => false
})
+ case _: SingleType =>
+ return isSameType2(tp2, tp1) // put singleton type on the left, caught below
case _ =>
}
case tt1: ThisType =>
@@ -5071,6 +5073,8 @@ trait Types extends api.Types { self: SymbolTable =>
tp2 match {
case st2: SingleType =>
if (equalSymsAndPrefixes(st1.sym, st1.pre, st2.sym, st2.pre)) return true
+ case TypeRef(pre2, sym2, Nil) =>
+ if (sym2.isModuleClass && equalSymsAndPrefixes(st1.sym, st1.pre, sym2.sourceModule, pre2)) return true
case _ =>
}
case ct1: ConstantType =>
@@ -5481,7 +5485,7 @@ trait Types extends api.Types { self: SymbolTable =>
* - handle typerefs, refined types, notnull and singleton types.
*/
def fourthTry = tp1 match {
- case tr1 @ TypeRef(_, sym1, _) =>
+ case tr1 @ TypeRef(pre1, sym1, _) =>
sym1 match {
case NothingClass => true
case NullClass =>
@@ -5495,8 +5499,8 @@ trait Types extends api.Types { self: SymbolTable =>
if (isRaw(sym1, tr1.args))
isSubType(rawToExistential(tp1), tp2, depth)
else if (sym1.isModuleClass) tp2 match {
- case SingleType(_, sym2) => sym1 == sym2
- case _ => false
+ case SingleType(pre2, sym2) => equalSymsAndPrefixes(sym1.sourceModule, pre1, sym2, pre2)
+ case _ => false
}
else if (sym1.isRefinementClass)
isSubType(sym1.info, tp2, depth)
diff --git a/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
new file mode 100644
index 0000000000..eb384f9a85
--- /dev/null
+++ b/src/compiler/scala/reflect/internal/util/TraceSymbolActivity.scala
@@ -0,0 +1,168 @@
+package scala.reflect.internal
+package util
+
+import scala.collection.{ mutable, immutable }
+
+trait TraceSymbolActivity {
+ val global: SymbolTable
+ import global._
+
+ if (traceSymbolActivity)
+ scala.sys addShutdownHook showAllSymbols()
+
+ private type Set[T] = scala.collection.immutable.Set[T]
+ private val Set = scala.collection.immutable.Set
+
+ val allSymbols = mutable.Map[Int, Symbol]()
+ val allChildren = mutable.Map[Int, List[Int]]() withDefaultValue Nil
+ val prevOwners = mutable.Map[Int, List[(Int, Phase)]]() withDefaultValue Nil
+ val symsCaused = mutable.Map[Int, Int]() withDefaultValue 0
+ val allTrees = mutable.Set[Tree]()
+
+ def recordSymbolsInTree(tree: Tree) {
+ allTrees += tree
+ }
+
+ def recordNewSymbol(sym: Symbol) {
+ if (sym.id > 1) {
+ allSymbols(sym.id) = sym
+ allChildren(sym.owner.id) ::= sym.id
+ }
+ }
+ def recordNewSymbolOwner(sym: Symbol, newOwner: Symbol) {
+ val sid = sym.id
+ val oid = sym.owner.id
+ val nid = newOwner.id
+
+ prevOwners(sid) ::= (oid -> phase)
+ allChildren(oid) = allChildren(oid) filterNot (_ == sid)
+ allChildren(nid) ::= sid
+ }
+
+ /** TODO.
+ */
+ private def reachableDirectlyFromSymbol(sym: Symbol): List[Symbol] = (
+ List(sym.owner, sym.alias, sym.thisSym)
+ ++ sym.children
+ ++ sym.info.parents.map(_.typeSymbol)
+ ++ sym.typeParams
+ ++ sym.paramss.flatten
+ )
+ private def reachable[T](inputs: Traversable[T], mkSymbol: T => Symbol): Set[Symbol] = {
+ def loop(seen: Set[Symbol], remaining: List[Symbol]): Set[Symbol] = {
+ remaining match {
+ case Nil => seen
+ case head :: rest =>
+ if ((head eq null) || (head eq NoSymbol) || seen(head)) loop(seen, rest)
+ else loop(seen + head, rest ++ reachableDirectlyFromSymbol(head).filterNot(seen))
+ }
+ }
+ loop(immutable.Set(), inputs.toList map mkSymbol filterNot (_ eq null) distinct)
+ }
+ private def treeList(t: Tree) = {
+ val buf = mutable.ListBuffer[Tree]()
+ t foreach (buf += _)
+ buf.toList
+ }
+
+ private def reachableFromSymbol(root: Symbol): Set[Symbol] =
+ reachable[Symbol](List(root, root.info.typeSymbol), x => x)
+
+ private def reachableFromTree(tree: Tree): Set[Symbol] =
+ reachable[Tree](treeList(tree), _.symbol)
+
+ private def signature(id: Int) = runBeforeErasure(allSymbols(id).defString)
+
+ private def dashes(s: Any): String = ("" + s) map (_ => '-')
+ private def show(s1: Any, ss: Any*) {
+ println("%-12s".format(s1) +: ss mkString " ")
+ }
+ private def showHeader(s1: Any, ss: Any*) {
+ show(s1, ss: _*)
+ show(dashes(s1), ss map dashes: _*)
+ }
+ private def showSym(sym: Symbol) {
+ def prefix = (" " * (sym.ownerChain.length - 1)) + sym.id
+ try println("%s#%s %s".format(prefix, sym.accurateKindString, sym.name.decode))
+ catch {
+ case x => println(prefix + " failed: " + x)
+ }
+ allChildren(sym.id).sorted foreach showIdAndRemove
+ }
+ private def showIdAndRemove(id: Int) {
+ allSymbols remove id foreach showSym
+ }
+ private def symbolStr(id: Int): String = {
+ if (id == 1) "NoSymbol" else {
+ val sym = allSymbols(id)
+ sym.accurateKindString + " " + sym.name.decode
+ }
+ }
+ private def ownerStr(id: Int): String = {
+ val sym = allSymbols(id)
+ sym.name.decode + "#" + sym.id
+ }
+
+ private def freq[T, U](xs: collection.Traversable[T])(fn: T => U): List[(U, Int)] = {
+ val ys = xs groupBy fn mapValues (_.size)
+ ys.toList sortBy (-_._2)
+ }
+
+ private def showMapFreq[T](xs: collection.Map[T, Traversable[_]])(showFn: T => String) {
+ xs.mapValues(_.size).toList.sortBy(-_._2) take 100 foreach { case (k, size) =>
+ show(size, showFn(k))
+ }
+ println("\n")
+ }
+ private def showFreq[T, U](xs: Traversable[T])(groupFn: T => U, showFn: U => String = (x: U) => "" + x) = {
+ showMapFreq(xs.toList groupBy groupFn)(showFn)
+ }
+ private lazy val findErasurePhase: Phase = {
+ var ph = phase
+ while (ph != NoPhase && ph.name != "erasure") {
+ ph = ph.prev
+ }
+ ph
+ }
+ private def runBeforeErasure[T](body: => T): T = atPhase(findErasurePhase)(body)
+
+ def showAllSymbols() {
+ if (!traceSymbolActivity) return
+ allSymbols(1) = NoSymbol
+
+ println("" + allSymbols.size + " symbols created.")
+ println("")
+
+ showHeader("descendants", "symbol")
+ showFreq(allSymbols.values flatMap (_.ownerChain drop 1))(_.id, symbolStr)
+
+ showHeader("children", "symbol")
+ showMapFreq(allChildren)(symbolStr)
+
+ if (prevOwners.nonEmpty) {
+ showHeader("prev owners", "symbol")
+ showMapFreq(prevOwners) { k =>
+ val owners = (((allSymbols(k).owner.id, NoPhase)) :: prevOwners(k)) map {
+ case (oid, NoPhase) => "-> owned by " + ownerStr(oid)
+ case (oid, ph) => "-> owned by %s (until %s)".format(ownerStr(oid), ph)
+ }
+ signature(k) :: owners mkString "\n "
+ }
+ }
+
+ val nameFreq = allSymbols.values.toList groupBy (_.name)
+ showHeader("frequency", "%-15s".format("name"), "owners")
+ showMapFreq(nameFreq) { name =>
+ "%-15s %s".format(name.decode, {
+ val owners = freq(nameFreq(name))(_.owner)
+
+ "%4s owners (%s)".format(
+ owners.size,
+ owners.take(3).map({ case (k, v) => v + "/" + k }).mkString(", ") + ", ..."
+ )
+ })
+ }
+
+ allSymbols.keys.toList.sorted foreach showIdAndRemove
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9ccd0c28db..6a30dc2a0f 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1356,6 +1356,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) extends Symb
inform(unitTimingsFormatted)
}
+ if (traceSymbolActivity)
+ units map (_.body) foreach (traceSymbols recordSymbolsInTree _)
+
// In case no phase was specified for -Xshow-class/object, show it now for sure.
if (opt.noShow)
showMembers()
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
index 7be115e777..9dc2a8de10 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/InteractiveTest.scala
@@ -55,6 +55,7 @@ abstract class InteractiveTest
with AskShutdown
with AskReload
with AskLoadedTyped
+ with AskType
with PresentationCompilerInstance
with CoreTestDefs
with InteractiveTestSettings { self =>
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
index 35d6723818..657ef23eed 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/AskCommand.scala
@@ -101,13 +101,13 @@ trait AskTypeAt extends AskCommand {
trait AskType extends AskCommand {
import compiler.Tree
- private[tests] def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
+ protected def askType(source: SourceFile, forceReload: Boolean)(implicit reporter: Reporter): Response[Tree] = {
ask {
compiler.askType(source, forceReload, _)
}
}
- private[tests] def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
+ protected def askType(sources: Seq[SourceFile], forceReload: Boolean)(implicit reporter: Reporter): Seq[Response[Tree]] = {
for(source <- sources) yield
askType(source, forceReload)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index a1ca4904f4..dba31f7bca 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -484,8 +484,7 @@ trait Infer {
else Some(
if (targ.typeSymbol == RepeatedParamClass) targ.baseType(SeqClass)
else if (targ.typeSymbol == JavaRepeatedParamClass) targ.baseType(ArrayClass)
- // this infers Foo.type instead of "object Foo" (see also widenIfNecessary)
- else if (targ.typeSymbol.isModuleClass || ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden)) targ
+ else if ((opt.experimental || opt.virtPatmat) && tvar.constr.avoidWiden) targ
else targ.widen
)
))
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 8604366bf2..1b505d1e5d 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -793,10 +793,7 @@ trait Namers extends MethodSynthesis {
val tpe1 = dropRepeatedParamType(tpe.deconst)
val tpe2 = tpe1.widen
- // This infers Foo.type instead of "object Foo"
- // See Infer#adjustTypeArgs for the polymorphic case.
- if (tpe.typeSymbolDirect.isModuleClass) tpe1
- else if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
+ if (sym.isVariable || sym.isMethod && !sym.hasAccessorFlag)
if (tpe2 <:< pt) tpe2 else tpe1
else if (isHidden(tpe)) tpe2
// In an attempt to make pattern matches involving method local vals
diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
index 045614e773..54b711cebc 100644
--- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala
@@ -951,17 +951,20 @@ abstract class RefChecks extends InfoTransform with reflect.internal.transform.R
override def traverse(tree: Tree) {
tree match {
- case ClassDef(_, _, _, _) |
- TypeDef(_, _, _, _) =>
+ case ClassDef(_, _, _, _) | TypeDef(_, _, _, _) =>
validateVariance(tree.symbol)
super.traverse(tree)
// ModuleDefs need not be considered because they have been eliminated already
case ValDef(_, _, _, _) =>
- validateVariance(tree.symbol)
+ if (!tree.symbol.hasLocalFlag)
+ validateVariance(tree.symbol)
case DefDef(_, _, tparams, vparamss, _, _) =>
- validateVariance(tree.symbol)
- traverseTrees(tparams)
- traverseTreess(vparamss)
+ // No variance check for object-private/protected methods/values.
+ if (!tree.symbol.hasLocalFlag) {
+ validateVariance(tree.symbol)
+ traverseTrees(tparams)
+ traverseTreess(vparamss)
+ }
case Template(_, _, _) =>
super.traverse(tree)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2aff00f6a5..36c81b09cd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2089,7 +2089,10 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
for (Apply(_, xs) <- cdef.pat ; x <- xs dropRight 1 ; if treeInfo isStar x)
StarPositionInPatternError(x)
- val pat1 = typedPattern(cdef.pat, pattpe)
+ // withoutAnnotations - see continuations-run/z1673.scala
+ // This adjustment is awfully specific to continuations, but AFAICS the
+ // whole AnnotationChecker framework is.
+ val pat1 = typedPattern(cdef.pat, pattpe.withoutAnnotations)
// When case classes have more than two parameter lists, the pattern ends
// up typed as a method. We only pattern match on the first parameter
// list, so substitute the final result type of the method, i.e. the type
@@ -2199,7 +2202,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
vparams map {p => if(p.tpt.tpe == null) typedType(p.tpt).tpe else p.tpt.tpe}
}
- def mkParams(methodSym: Symbol, formals: List[Type] = deriveFormals) = {
+ def mkParams(methodSym: Symbol, formals: List[Type]/* = deriveFormals*/) = {
selOverride match {
case None if targs.isEmpty => MissingParameterTypeAnonMatchError(tree, pt); (Nil, EmptyTree)
case None =>
@@ -2225,7 +2228,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
// rig the show so we can get started typing the method body -- later we'll correct the infos...
anonClass setInfo ClassInfoType(List(ObjectClass.tpe, pt, SerializableClass.tpe), newScope, anonClass)
val methodSym = anonClass.newMethod(nme.apply, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val (paramSyms, selector) = mkParams(methodSym, deriveFormals)
if (selector eq EmptyTree) EmptyTree
else {
@@ -2289,7 +2292,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
def isDefinedAtMethod = {
val methodSym = anonClass.newMethod(nme.isDefinedAt, tree.pos, FINAL)
- val (paramSyms, selector) = mkParams(methodSym)
+ val (paramSyms, selector) = mkParams(methodSym, deriveFormals)
if (selector eq EmptyTree) EmptyTree
else {
val methodBodyTyper = newTyper(context.makeNewScope(context.tree, methodSym)) // should use the DefDef for the context's tree, but it doesn't exist yet (we need the typer we're creating to create it)