summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-08-15 20:12:37 +0000
committerMartin Odersky <odersky@gmail.com>2009-08-15 20:12:37 +0000
commitfe72ad6351aa3e06c894972e959fa768ed60a515 (patch)
treeec2de6807adba0e76dab26c1c803a389ebce7586
parent43b445579feb1499d3f405c64a45666037255f7d (diff)
downloadscala-fe72ad6351aa3e06c894972e959fa768ed60a515.tar.gz
scala-fe72ad6351aa3e06c894972e959fa768ed60a515.tar.bz2
scala-fe72ad6351aa3e06c894972e959fa768ed60a515.zip
Fixed #1560 (which was a typing hole, so some l...
Fixed #1560 (which was a typing hole, so some library classes had to be fixed)
-rw-r--r--src/actors/scala/actors/ActorGC.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala2
-rw-r--r--src/compiler/scala/tools/nsc/Settings.scala1
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala55
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala25
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala5
-rw-r--r--src/library/scala/util/parsing/combinator/PackratParsers.scala12
-rw-r--r--test/files/neg/bug987.check29
-rw-r--r--test/files/pos/looping-jsig.scala2
9 files changed, 85 insertions, 48 deletions
diff --git a/src/actors/scala/actors/ActorGC.scala b/src/actors/scala/actors/ActorGC.scala
index 45ddb8c067..67493e91cd 100644
--- a/src/actors/scala/actors/ActorGC.scala
+++ b/src/actors/scala/actors/ActorGC.scala
@@ -92,7 +92,7 @@ trait ActorGC extends IScheduler {
case Some(r) =>
// invoking clear will not cause r to be enqueued
r.clear()
- refSet -= r
+ refSet -= r.asInstanceOf[Reference[t] forSome { type t <: Reactor }]
case None =>
// do nothing
}
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 9ceb470565..1f2c0a21aa 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -350,7 +350,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
} with Analyzer
/** Switch to turn on detailed type logs */
- var printTypings = false
+ var printTypings = settings.Ytyperdebug.value
// phaseName = "superaccessors"
object superAccessors extends {
diff --git a/src/compiler/scala/tools/nsc/Settings.scala b/src/compiler/scala/tools/nsc/Settings.scala
index f788151aef..d99644303d 100644
--- a/src/compiler/scala/tools/nsc/Settings.scala
+++ b/src/compiler/scala/tools/nsc/Settings.scala
@@ -795,6 +795,7 @@ trait ScalacSettings {
val specialize = BooleanSetting ("-Yspecialize", "Specialize generic code on types.")
val Yrangepos = BooleanSetting ("-Yrangepos", "Use range positions for syntax trees.")
val Yidedebug = BooleanSetting ("-Yide-debug", "Generate, validate and output trees using the interactive compiler.")
+ val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements")
/**
* -P "Plugin" settings
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala
index e40df44b96..f0158ee722 100644
--- a/src/compiler/scala/tools/nsc/symtab/Types.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Types.scala
@@ -505,6 +505,11 @@ trait Types {
/** Apply `f' to each part of this type */
def foreach(f: Type => Unit) { new ForEachTypeTraverser(f).traverse(this) }
+ /** Apply `f' to each part of this type; children get mapped before their parents */
+ def map(f: Type => Type): Type = new TypeMap {
+ def apply(x: Type) = f(mapOver(x))
+ } apply this
+
/** Is there part of this type which satisfies predicate `p'? */
def exists(p: Type => Boolean): Boolean = !find(p).isEmpty
@@ -3488,23 +3493,25 @@ A type's typeSymbol should never be inspected directly.
if (subsametypeRecursions == 0) undoLog = List()
}
- def hasDifferentTypeSymbol(sym: Symbol, tp: Type): Boolean = {
- // assert(sym.isAbstractType)
- sym ne tp.typeSymbol
+ def isDifferentType(tp1: Type, tp2: Type): Boolean = try {
+ subsametypeRecursions += 1
+ val lastUndoLog = undoLog
+ val result = isSameType0(tp1, tp2)
+ undoTo(lastUndoLog)
+ !result
+ } finally {
+ subsametypeRecursions -= 1
+ if (subsametypeRecursions == 0) undoLog = List()
+ }
+
+ def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = tp1 match {
+ case TypeRef(pre1, sym1, _) =>
+ tp2 match {
+ case TypeRef(pre2, sym2, _) => sym1 != sym2 || isDifferentType(pre1, pre2)
+ case _ => true
+ }
+ case _ => true
}
- // `hasDifferentTypeSymbol` is a faster version of `isDifferentTypeConstructor`,
- // which was only ever called when `tp1.typeSymbolDirect.isAbstractType`
- // def isDifferentTypeConstructor(tp1: Type, tp2: Type): Boolean = {
- // try {
- // subsametypeRecursions += 1
- // val lastUndoLog = undoLog
- // val result = isSameType0(tp1.typeConstructor(true), tp2.typeConstructor(true))
- // undoTo(lastUndoLog)
- // !result
- // } finally {
- // subsametypeRecursions -= 1
- // if (subsametypeRecursions == 0) undoLog = List()
- // }
def normalizePlus(tp: Type) =
if (isRawType(tp)) rawToExistential(tp)
@@ -3815,7 +3822,8 @@ A type's typeSymbol should never be inspected directly.
isSubType(tp1.normalize, tp2.normalize, depth)
} else if (sym2.isAbstractType) {
val tp2a = tp2.bounds.lo
- hasDifferentTypeSymbol(sym2, tp2a) && tp1 <:< tp2a || fourthTry
+// isDifferentTypeConstructor(tp2a, tp2.pre, sym2) && tp1 <:< tp2a || fourthTry
+ isDifferentTypeConstructor(tp2, tp2a) && tp1 <:< tp2a || fourthTry
} else if (sym2 == NotNullClass) {
tp1.isNotNull
} else if (sym2 == SingletonClass) {
@@ -3882,7 +3890,7 @@ A type's typeSymbol should never be inspected directly.
isSubType(tp1.normalize, tp2.normalize, depth)
} else if (sym1.isAbstractType) {
val tp1a = tp1.bounds.hi
- hasDifferentTypeSymbol(sym1, tp1a) && tp1a <:< tp2
+ isDifferentTypeConstructor(tp1, tp1a) && tp1a <:< tp2
} else if (sym1 == NothingClass) {
true
} else if (sym1 == NullClass) {
@@ -3946,9 +3954,9 @@ A type's typeSymbol should never be inspected directly.
else (sym1.name == sym2.name) && isUnifiable(pre1, pre2)) &&
(sym2 == AnyClass || isSubArgs(args1, args2, sym1.typeParams)) //@M: Any is kind-polymorphic
||
- sym1.isAbstractType && hasDifferentTypeSymbol(sym1, tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
+ sym1.isAbstractType && isDifferentTypeConstructor(tp1, tp1.bounds.hi) && (tp1.bounds.hi <:< tp2)
||
- sym2.isAbstractType && hasDifferentTypeSymbol(sym2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
+ sym2.isAbstractType && isDifferentTypeConstructor(tp2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo)
||
sym2.isClass &&
({ val base = tp1 baseType sym2; !(base eq tp1) && (base <:< tp2) })
@@ -4002,7 +4010,7 @@ A type's typeSymbol should never be inspected directly.
isSubType0(tp1a, tp2a, depth)
})
case (_, TypeRef(pre2, sym2, args2))
- if (sym2.isAbstractType && hasDifferentTypeSymbol(sym2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) ||
+ if (sym2.isAbstractType && isDifferentTypeConstructor(tp2, tp2.bounds.lo) && (tp1 <:< tp2.bounds.lo) ||
sym2 == NotNullClass && tp1.isNotNull) =>
true
case (_, TypeRef(pre2, sym2, args2))
@@ -4577,13 +4585,14 @@ A type's typeSymbol should never be inspected directly.
val l = lub(as, decr(depth))
val g = glb(as, decr(depth))
if (l <:< g) l
- else if(!(tparam.info.bounds contains tparam)){ //@M can't deal with f-bounds, see #2251
+ else { // Martin: I removed this, because incomplete. Not sure there is a good way to fix it. For the moment we
+ // just err on the conservative side, i.e. with a bound that is too high.
+ // if(!(tparam.info.bounds contains tparam)){ //@M can't deal with f-bounds, see #2251
val owner = commonOwner(as)
val qvar = makeFreshExistential("", commonOwner(as), mkTypeBounds(g, l))
capturedParams += qvar
qvar.tpe
}
- else NoType
}
}
try {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
index 25956b2a29..b2ae89700c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala
@@ -459,6 +459,29 @@ trait Infer {
/* -- Type instantiation------------------------------------------------ */
+ /** Replace any (possibly bounded) wildcard types in type `tp`
+ * by existentially bound variables.
+ */
+ def makeFullyDefined(tp: Type): Type = {
+ val tparams = new ListBuffer[Symbol]
+ def addTypeParam(bounds: TypeBounds): Type = {
+ val tparam =
+ context.owner.newAbstractType(context.tree.pos.focus, newTypeName("_"+tparams.size))
+ .setFlag(EXISTENTIAL)
+ .setInfo(bounds)
+ tparams += tparam
+ tparam.tpe
+ }
+ val tp1 = tp map {
+ case WildcardType =>
+ addTypeParam(TypeBounds(NothingClass.tpe, AnyClass.tpe))
+ case BoundedWildcardType(bounds) =>
+ addTypeParam(bounds)
+ case t => t
+ }
+ existentialAbstraction(tparams.toList, tp1)
+ }
+
/** Return inferred type arguments of polymorphic expression, given
* its type parameters and result type and a prototype <code>pt</code>.
* If no minimal type variables exist that make the
@@ -1229,7 +1252,7 @@ trait Infer {
ptvars foreach instantiateTypeVar
} else { if (settings.debug.value) Console.println("no instance: "); instError }
} else { if (settings.debug.value) Console.println("not a subtype " + restpe.instantiateTypeParams(undetparams, tvars) + " of " + ptWithWildcards); instError }
- } else { if (settings.debug.value) Console.println("not fuly defined: " + pt); instError }
+ } else { if (settings.debug.value) Console.println("not fully defined: " + pt); instError }
}
def instBounds(tvar: TypeVar): (Type, Type) = {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 30098885ff..ff200b22fd 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3641,7 +3641,7 @@ trait Typers { self: Analyzer =>
if (util.Statistics.enabled) idcnt += 1
if ((name == nme.WILDCARD && (mode & (PATTERNmode | FUNmode)) == PATTERNmode) ||
(name == nme.WILDCARD.toTypeName && (mode & TYPEmode) != 0))
- tree setType pt
+ tree setType makeFullyDefined(pt)
else
typedIdent(name)
@@ -3720,7 +3720,8 @@ trait Typers { self: Analyzer =>
tree1.tpe = addAnnotations(tree1, tree1.tpe)
val result = if (tree1.isEmpty) tree1 else adapt(tree1, mode, pt)
- if (printTypings) println("adapted "+tree1+":"+tree1.tpe+" to "+pt+", "+context.undetparams); //DEBUG
+ if (printTypings) println("adapted "+tree1+":"+tree1.tpe.widen+" to "+pt+", "+context.undetparams); //DEBUG
+// for (t <- tree1.tpe) assert(t != WildcardType)
// if ((mode & TYPEmode) != 0) println("type: "+tree1+" has type "+tree1.tpe)
if (phase.id <= currentRun.typerPhase.id) signalDone(context.asInstanceOf[analyzer.Context], tree, result)
result
diff --git a/src/library/scala/util/parsing/combinator/PackratParsers.scala b/src/library/scala/util/parsing/combinator/PackratParsers.scala
index da09eff597..cc0b1877e7 100644
--- a/src/library/scala/util/parsing/combinator/PackratParsers.scala
+++ b/src/library/scala/util/parsing/combinator/PackratParsers.scala
@@ -133,8 +133,8 @@ trait PackratParsers extends Parsers {
private case class MemoEntry[+T](var r: Either[LR,ParseResult[_]]){
def getResult: ParseResult[T] = r match {
- case Left(LR(res,_,_)) => res
- case Right(res) => res
+ case Left(LR(res,_,_)) => res.asInstanceOf[ParseResult[T]]
+ case Right(res) => res.asInstanceOf[ParseResult[T]]
}
}
@@ -226,9 +226,9 @@ to update each parser involved in the recursion.
private def lrAnswer[T](p: Parser[T], in: PackratReader[Elem], growable: LR): ParseResult[T] = growable match {
//growable will always be having a head, we can't enter lrAnswer otherwise
case LR(seed ,rule, Some(head)) =>
- if(head.getHead != p) /*not head rule, so not growing*/ seed
+ if(head.getHead != p) /*not head rule, so not growing*/ seed.asInstanceOf[ParseResult[T]]
else {
- in.updateCacheAndGet(p, MemoEntry(Right[LR, ParseResult[T]](seed)))
+ in.updateCacheAndGet(p, MemoEntry(Right[LR, ParseResult[T]](seed.asInstanceOf[ParseResult[T]])))
seed match {
case f@Failure(_,_) => f
case e@Error(_,_) => e
@@ -287,7 +287,7 @@ to update each parser involved in the recursion.
case MemoEntry(Left(recDetect)) => {
setupLR(p, inMem, recDetect)
//all setupLR does is change the heads of the recursions, so the seed will stay the same
- recDetect match {case LR(seed, _, _) => seed}
+ recDetect match {case LR(seed, _, _) => seed.asInstanceOf[ParseResult[T]]}
}
case MemoEntry(Right(res: ParseResult[T])) => res
}
@@ -301,7 +301,7 @@ to update each parser involved in the recursion.
//store the head into the recursionHeads
rest.recursionHeads.put(rest.pos, head /*match {case Head(hp,involved,_) => Head(hp,involved,involved)}*/)
val oldRes: ParseResult[T] = rest.getFromCache(p).get match {
- case MemoEntry(Right(x)) => x
+ case MemoEntry(Right(x)) => x.asInstanceOf[ParseResult[T]]
case _ => throw new Exception("impossible match")
}
diff --git a/test/files/neg/bug987.check b/test/files/neg/bug987.check
index ec2ca621fd..4cad622ab8 100644
--- a/test/files/neg/bug987.check
+++ b/test/files/neg/bug987.check
@@ -1,16 +1,19 @@
-bug987.scala:15: error: the type intersection D with ScalaObject is malformed
- --- because ---
-no common type instance of base types B[C], and B[D] exists.
+bug987.scala:15: error: illegal inheritance;
+ class E inherits different type instances of trait B:
+B[D] and B[C]
class E extends D
- ^
-bug987.scala:20: error: the type intersection D with ScalaObject is malformed
- --- because ---
-no common type instance of base types B[C], and B[D] exists.
+ ^
+bug987.scala:20: error: illegal inheritance;
+ class F inherits different type instances of trait B:
+B[D] and B[C]
class F extends D
- ^
-bug987.scala:25: error: the type intersection C with B[D] with ScalaObject is malformed
- --- because ---
-no common type instance of base types B[D], and B[C] exists.
+ ^
+bug987.scala:25: error: illegal inheritance;
+ class D inherits different type instances of trait B:
+B[D] and B[C]
abstract class D extends C with B[D] {}
- ^
-three errors found
+ ^
+bug987.scala:25: error: type arguments [D] do not conform to trait B's type parameter bounds [T <: B[T]]
+abstract class D extends C with B[D] {}
+ ^
+four errors found
diff --git a/test/files/pos/looping-jsig.scala b/test/files/pos/looping-jsig.scala
index 15ccd75cb0..6e3313c463 100644
--- a/test/files/pos/looping-jsig.scala
+++ b/test/files/pos/looping-jsig.scala
@@ -14,5 +14,5 @@ trait BugTrack {
def amethod[T](p: =>A[T]): A[T] = A(in => cache.get(p) match {
case Some(res) => res
case None => p(in)
- }).giveMeSame
+ }).giveMeSame.asInstanceOf[A[T]]
}