summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2007-08-29 15:57:30 +0000
committerMartin Odersky <odersky@gmail.com>2007-08-29 15:57:30 +0000
commit10bd9e9c8ea541b22ed87319e04f957621b20de7 (patch)
tree6a0fd9808d1259395a14fad4a9d162b668608ffd /src/compiler
parent840202e705c9d13ee59515fde29543db81bcea9c (diff)
downloadscala-10bd9e9c8ea541b22ed87319e04f957621b20de7.tar.gz
scala-10bd9e9c8ea541b22ed87319e04f957621b20de7.tar.bz2
scala-10bd9e9c8ea541b22ed87319e04f957621b20de7.zip
fix^2 of defect 15.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala22
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala63
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala25
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala7
4 files changed, 88 insertions, 29 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index f9ee9755d0..ef29cf04f9 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -15,6 +15,8 @@ abstract class TreePrinters {
val trees: Trees
import trees._
+ final val showOuterTests = false
+
class TreePrinter(out: PrintWriter) {
protected var indentMargin = 0
protected val indentStep = 2
@@ -125,6 +127,9 @@ abstract class TreePrinters {
def print(str: String) { out.print(str) }
def print(name: Name) { print(name.toString()) }
+ private var currentOwner: Symbol = NoSymbol
+ private var selectorType: Type = NoType
+
def printRaw(tree: Tree) {
tree match {
case EmptyTree =>
@@ -199,6 +204,8 @@ abstract class TreePrinters {
mkString("{", ",", "}"))
case Template(parents, self, body) =>
+ val currentOwner1 = currentOwner
+ if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner
printRow(parents, " with ")
if (!body.isEmpty) {
if (self.name != nme.WILDCARD) {
@@ -210,15 +217,28 @@ abstract class TreePrinters {
}
printColumn(body, "", ";", "}")
}
+ currentOwner = currentOwner1
case Block(stats, expr) =>
printColumn(stats ::: List(expr), "{", ";", "}")
case Match(selector, cases) =>
+ val selectorType1 = selectorType
+ selectorType = selector.tpe
print(selector); printColumn(cases, " match {", "", "}")
+ selectorType = selectorType1
case CaseDef(pat, guard, body) =>
- print("case "); print(pat); printOpt(" if ", guard)
+ print("case ");
+ def patConstr(pat: Tree): Tree = pat match {
+ case Apply(fn, args) => patConstr(fn)
+ case _ => pat
+ }
+ if (showOuterTests &&
+ needsOuterTest(
+ patConstr(pat).tpe.finalResultType, selectorType, currentOwner))
+ print("???")
+ print(pat); printOpt(" if ", guard)
print(" => "); print(body)
case Sequence(trees) =>
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index 97a037c8de..a634233d74 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -2713,6 +2713,69 @@ A type's typeSymbol should never be inspected directly.
ok
}
+ /** Is intersection of given types populated? That is,
+ * for all types tp1, tp2 in intersection
+ * for all common base classes bc of tp1 and tp2
+ * let bt1, bt2 be the base types of tp1, tp2 relative to class bc
+ * Then:
+ * bt1 and bt2 have the same prefix, and
+ * any correspondiong non-variant type arguments of bt1 and bt2 are the same
+ */
+ def isPopulated(tp1: Type, tp2: Type): Boolean = {
+ def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
+ case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
+ assert(sym1 == sym2)
+ pre1 =:= pre2 &&
+ !(List.map3(args1, args2, sym1.typeParams) {
+ (arg1, arg2, tparam) =>
+ //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
+ tparam.variance != 0 || arg1 =:= arg2
+ } contains false)
+ }
+ if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL))
+ tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol)
+ else tp1.baseClasses forall (bc =>
+ tp2.closurePos(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
+ }
+
+ /** Does a pattern of type `patType' need an outer test when executed against
+ * selector type `selType' in context defined by `currentOwner'?
+ */
+ def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
+ def createDummyClone(pre: Type): Type = {
+ val dummy = currentOwner.enclClass.newValue(NoPosition, nme.ANYNAME).setInfo(pre.widen)
+ singleType(ThisType(currentOwner.enclClass), dummy)
+ }
+ def maybeCreateDummyClone(pre: Type, sym: Symbol): Type = pre match {
+ case SingleType(pre1, sym1) =>
+ if (sym1.isModule && sym1.isStatic) {
+ NoType
+ } else if (sym1.isModule && sym.owner == sym1.moduleClass) {
+ val pre2 = maybeCreateDummyClone(pre1, sym1)
+ if (pre2 eq NoType) pre2
+ else singleType(pre2, sym1)
+ } else {
+ createDummyClone(pre)
+ }
+ case ThisType(clazz) =>
+ if (clazz.isModuleClass)
+ maybeCreateDummyClone(clazz.typeOfThis, sym)
+ else if (sym.owner == clazz && (sym.hasFlag(PRIVATE) || sym.privateWithin == clazz))
+ NoType
+ else
+ createDummyClone(pre)
+ case _ =>
+ NoType
+ }
+ patType match {
+ case TypeRef(pre, sym, args) =>
+ val pre1 = maybeCreateDummyClone(pre, sym)
+ (pre1 ne NoType) && isPopulated(typeRef(pre1, sym, args), selType)
+ case _ =>
+ false
+ }
+ }
+
/** Undo all changes to constraints to type variables upto `limit'
*/
private def undoTo(limit: UndoLog) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 11b8d555c0..beaa2ac5af 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -804,31 +804,6 @@ trait Infer {
}
}
- /** Is intersection of given types populated? That is,
- * for all types tp1, tp2 in intersection
- * for all common base classes bc of tp1 and tp2
- * let bt1, bt2 be the base types of tp1, tp2 relative to class bc
- * Then:
- * bt1 and bt2 have the same prefix, and
- * any correspondiong non-variant type arguments of bt1 and bt2 are the same
- */
- def isPopulated(tp1: Type, tp2: Type): Boolean = {
- def isConsistent(tp1: Type, tp2: Type): Boolean = (tp1, tp2) match {
- case (TypeRef(pre1, sym1, args1), TypeRef(pre2, sym2, args2)) =>
- assert(sym1 == sym2)
- pre1 =:= pre2 &&
- !(List.map3(args1, args2, sym1.typeParams) {
- (arg1, arg2, tparam) =>
- //if (tparam.variance == 0 && !(arg1 =:= arg2)) Console.println("inconsistent: "+arg1+"!="+arg2)//DEBUG
- tparam.variance != 0 || arg1 =:= arg2
- } contains false)
- }
- if (tp1.typeSymbol.isClass && tp1.typeSymbol.hasFlag(FINAL))
- tp1 <:< tp2 || isNumericValueClass(tp1.typeSymbol) && isNumericValueClass(tp2.typeSymbol)
- else tp1.baseClasses forall (bc =>
- tp2.closurePos(bc) < 0 || isConsistent(tp1.baseType(bc), tp2.baseType(bc)))
- }
-
/** Type with all top-level occurrences of abstract types replaced by their bounds */
def widen(tp: Type): Type = tp match { // @M don't normalize here (compiler loops on pos/bug1090.scala )
case TypeRef(_, sym, _) if sym.isAbstractType =>
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index b9a95c84db..3909b42ead 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -2601,7 +2601,7 @@ trait Typers { self: Analyzer =>
}
}
if (defSym.owner.isPackageClass) pre = defSym.owner.thisType
- if (defSym.isThisSym) typed1(This(defSym.owner), mode, pt)
+ if (defSym.isThisSym) typed1(This(defSym.owner) setPos tree.pos, mode, pt)
else {
val tree1 = if (qual == EmptyTree) tree
else atPos(tree.pos)(Select(qual, name))
@@ -2946,10 +2946,11 @@ trait Typers { self: Analyzer =>
if (tp1 eq tp0) tp else tp1
case _ => tp
}
+// Console.println("typing "+tree+" at "+tree.pos);//DEBUG
var tree1 = if (tree.tpe ne null) tree else typed1(tree, mode, dropExistential(pt))
- //Console.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams);//DEBUG
+// Console.println("typed "+tree1+":"+tree1.tpe+", "+context.undetparams);//DEBUG
val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
- //Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
+// Console.println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams);//DEBUG
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
result
} catch {