diff options
author | Martin Odersky <odersky@gmail.com> | 2009-08-15 20:12:37 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-08-15 20:12:37 +0000 |
commit | fe72ad6351aa3e06c894972e959fa768ed60a515 (patch) | |
tree | ec2de6807adba0e76dab26c1c803a389ebce7586 /src | |
parent | 43b445579feb1499d3f405c64a45666037255f7d (diff) | |
download | scala-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)
Diffstat (limited to 'src')
-rw-r--r-- | src/actors/scala/actors/ActorGC.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Global.scala | 2 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/Settings.scala | 1 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 55 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Infer.scala | 25 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 5 | ||||
-rw-r--r-- | src/library/scala/util/parsing/combinator/PackratParsers.scala | 12 |
7 files changed, 68 insertions, 34 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") } |