diff options
author | Martin Odersky <odersky@gmail.com> | 2009-09-30 09:57:20 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-09-30 09:57:20 +0000 |
commit | 49bfcbe509f3d7db654be949b1f4d778b2baf23f (patch) | |
tree | 821e91435d83b0cb53471882e26dd394ab7709fa /src/compiler | |
parent | c590eb86c61196b31b4a6f41fb25e92103d05cd9 (diff) | |
download | scala-49bfcbe509f3d7db654be949b1f4d778b2baf23f.tar.gz scala-49bfcbe509f3d7db654be949b1f4d778b2baf23f.tar.bz2 scala-49bfcbe509f3d7db654be949b1f4d778b2baf23f.zip |
fixed #2311.
Diffstat (limited to 'src/compiler')
4 files changed, 72 insertions, 45 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala index 949d1bf18f..6c29ab5cf3 100644 --- a/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala +++ b/src/compiler/scala/tools/nsc/symtab/BaseTypeSeqs.scala @@ -30,6 +30,7 @@ trait BaseTypeSeqs { import definitions._ class BaseTypeSeq(parents: List[Type], elems: Array[Type]) { + self => /** The number of types in the sequence */ def length: Int = elems.length @@ -90,7 +91,7 @@ trait BaseTypeSeqs { /** Return all evaluated types in this sequence as a list */ def toList: List[Type] = elems.toList - private def copy(head: Type, offset: Int): BaseTypeSeq = { + protected def copy(head: Type, offset: Int): BaseTypeSeq = { val arr = new Array[Type](elems.length + offset) compat.Platform.arraycopy(elems, 0, arr, offset, elems.length) arr(0) = head @@ -117,39 +118,31 @@ trait BaseTypeSeqs { new BaseTypeSeq(parents, arr) } + def lateMap(f: Type => Type): BaseTypeSeq = new BaseTypeSeq(parents map f, elems) { + override def apply(i: Int) = f(self.apply(i)) + override def rawElem(i: Int) = f(self.rawElem(i)) + override def typeSymbol(i: Int) = self.typeSymbol(i) + override def toList = self.toList map f + override protected def copy(head: Type, offset: Int) = (self map f).copy(head, offset) + override def map(g: Type => Type) = lateMap(g) + override def lateMap(g: Type => Type) = self.lateMap(x => g(f(x))) + override def exists(p: Type => Boolean) = elems exists (x => p(f(x))) + override protected def maxDepthOfElems: Int = elems map (x => maxDpth(f(x))) max + override def toString = elems.mkString("MBTS(", ",", ")") + } + def exists(p: Type => Boolean): Boolean = elems exists p -// (0 until length) exists (i => p(this(i))) - def normalize(parents: List[Type]) {} -/* - var j = 0 - while (j < elems.length) { - elems(j) match { - case RefinedType(variants, decls) => - // can't assert decls.isEmpty; see t0764 - //if (!decls.isEmpty) assert(false, "computing closure of "+this+":"+this.isInstanceOf[RefinedType]+"/"+closureCache(j)) - //Console.println("compute closure of "+this+" => glb("+variants+")") - elems(j) = mergePrefixAndArgs(variants, -1, maxBaseTypeSeqDepth(variants) + LubGlbMargin) match { - case Some(tp0) => tp0 - case None => throw new TypeError( - "the type intersection "+(parents mkString " with ")+" is malformed"+ - "\n --- because ---"+ - "\n no common type instance of base types "+(variants mkString ", and ")+" exists.") - } - case _ => - } - j += 1 - } - } -*/ - lazy val maxDepth: Int = { + lazy val maxDepth: Int = maxDepthOfElems + + protected def maxDepthOfElems = { var d = 0 for (i <- 0 until length) d = Math.max(d, maxDpth(elems(i))) d } /** The maximum depth of type `tp' */ - private def maxDpth(tp: Type): Int = tp match { + protected def maxDpth(tp: Type): Int = tp match { case TypeRef(pre, sym, args) => max(maxDpth(pre), maxDpth(args) + 1) case RefinedType(parents, decls) => @@ -190,7 +183,7 @@ trait BaseTypeSeqs { def baseTypeSingletonSeq(tp: Type): BaseTypeSeq = new BaseTypeSeq(List(), Array(tp)) /** Create the base type sequence of a compound type wuth given tp.parents */ - def compoundBaseTypeSeq(tp: Type/*tsym: Symbol, parents: List[Type]*/): BaseTypeSeq = { + def compoundBaseTypeSeq(tp: Type): BaseTypeSeq = { val tsym = tp.typeSymbol val parents = tp.parents // Console.println("computing baseTypeSeq of " + tsym.tpe + " " + parents)//DEBUG diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index e10ddb26d6..4aea770ff4 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1729,9 +1729,10 @@ trait Symbols { } override def unpackLocation = origin override def typeParams = info.typeParams //@M! (not deSkolemize.typeParams!!), also can't leave superclass definition: use info, not rawInfo - override def cloneSymbolImpl(owner: Symbol): Symbol = { - throw new Error("should not clone a type skolem") - } + + override def cloneSymbolImpl(owner: Symbol): Symbol = + new TypeSkolem(owner, pos, name, origin) + override def nameString: String = if (settings.debug.value) (super.nameString + "&" + level) else super.nameString diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index a359ec1c57..8bf9708c0c 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -265,6 +265,8 @@ trait Types { def typeOfThis: Type = typeSymbol.typeOfThis /** Map to a singleton type which is a subtype of this type. + * todo: change to singleton type of an existentgially defined variable + * of the right type instead of making this a `this` of a refined type. */ def narrow: Type = if (phase.erasedTypes) this @@ -1065,13 +1067,37 @@ trait Types { if (period != currentPeriod) { // no caching in IDE baseTypeSeqPeriod = currentPeriod if (!isValidForBaseClasses(period)) { - if (util.Statistics.enabled) - compoundBaseTypeSeqCount += 1 - baseTypeSeqCache = undetBaseTypeSeq - baseTypeSeqCache = memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe) -// println("normalizing baseTypeSeq of "+typeSymbol+"/"+parents+": "+baseTypeSeqCache)//DEBUG - baseTypeSeqCache.normalize(parents) -// println("normalized baseTypeSeq of "+typeSymbol+"/"+parents+": "+baseTypeSeqCache)//DEBUG + if (parents.exists(_.exists(_.isInstanceOf[TypeVar]))) { + // rename type vars to fresh type params, take base type sequence of + // resulting type, and rename back allthe entries in thats sequence + var tvs = Set[TypeVar]() + for (p <- parents) + for (t <- p) t match { + case tv: TypeVar => tvs += tv + case _ => + } + val varToParamMap = (Map[Type, Symbol]() /: tvs)((m, tv) => m + (tv -> tv.origin.typeSymbol.cloneSymbol)) + val paramToVarMap = Map[Symbol, Type]() ++ (varToParamMap map { case (t, tsym) => (tsym -> t) }) + val varToParam = new TypeMap { + def apply(tp: Type): Type = tp match { + case tv: TypeVar => varToParamMap(tp).tpe + case _ => mapOver(tp) + } + } + val paramToVar = new TypeMap { + def apply(tp: Type) = tp match { + case TypeRef(_, tsym, _) if paramToVarMap.isDefinedAt(tsym) => paramToVarMap(tsym) + case _ => mapOver(tp) + } + } + val bts = copyRefinedType(this.asInstanceOf[RefinedType], parents map varToParam, varToParam mapOver decls).baseTypeSeq + baseTypeSeqCache = bts lateMap paramToVar + } else { + if (util.Statistics.enabled) + compoundBaseTypeSeqCount += 1 + baseTypeSeqCache = undetBaseTypeSeq + baseTypeSeqCache = memo(compoundBaseTypeSeq(this))(_.baseTypeSeq updateHead typeSymbol.tpe) + } } //Console.println("baseTypeSeq(" + typeSymbol + ") = " + baseTypeSeqCache.toList);//DEBUG } @@ -2543,7 +2569,7 @@ A type's typeSymbol should never be inspected directly. } /** Map this function over given scope */ - private def mapOver(scope: Scope): Scope = { + def mapOver(scope: Scope): Scope = { val elems = scope.toList val elems1 = mapOver(elems) if (elems1 eq elems) scope @@ -3787,7 +3813,7 @@ A type's typeSymbol should never be inspected directly. secondTry case _ => if (constr2.inst != NoType) tp1 <:< constr2.inst - else isRelatable(tv2, tp1) && { constr2.lobounds = tp1 :: constr2.lobounds; true } + else isRelatable(tv2, tp1) && { assert(tp1 != tv2); constr2.lobounds = tp1 :: constr2.lobounds; true } } case _ => secondTry @@ -3995,7 +4021,7 @@ A type's typeSymbol should never be inspected directly. tp1 <:< bounds.hi case (_, tv2 @ TypeVar(_, constr2)) => if (constr2.inst != NoType) tp1 <:< constr2.inst - else isRelatable(tv2, tp1) && { constr2.lobounds = tp1 :: constr2.lobounds; true } + else isRelatable(tv2, tp1) && { assert(tp1 != tv2); constr2.lobounds = tp1 :: constr2.lobounds; true } case (tv1 @ TypeVar(_, constr1), _) => if (constr1.inst != NoType) constr1.inst <:< tp2 else isRelatable(tv1, tp2) && { constr1.hibounds = tp2 :: constr1.hibounds; true } diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index d8f54760a1..6c3b6af081 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -616,9 +616,17 @@ trait Infer { * @throws NoInstance */ def methTypeArgs(tparams: List[Symbol], formals: List[Type], restpe: Type, - argtpes: List[Type], pt: Type, - uninstantiated: ListBuffer[Symbol]): List[Type] = { + argtpes: List[Type], pt: Type, + uninstantiated: ListBuffer[Symbol]): List[Type] = { val tvars = tparams map freshVar + if (inferInfo) + println("methTypeArgs tparams = "+tparams+ + ", formals = "+formals+ + ", restpe = "+restpe+ + ", argtpes = "+argtpes+ + ", pt = "+pt+ + ", uninstantiated = "+uninstantiated+ + ", tvars = "+tvars+" "+(tvars map (_.constr))) if (formals.length != argtpes.length) { throw new NoInstance("parameter lists differ in length") } @@ -646,7 +654,8 @@ trait Infer { } () } -// println("solve "+tvars+" "+(tvars map (_.constr))) + if (inferInfo) + println("solve "+tvars+" "+(tvars map (_.constr))) val targs = solvedTypes(tvars, tparams, tparams map varianceInTypes(formals), false, lubDepth(formals) max lubDepth(argtpes)) // val res = @@ -1194,11 +1203,9 @@ trait Infer { val uninstantiated = new ListBuffer[Symbol] val targs = methTypeArgs(undetparams, formals, restpe, argtpes, pt, uninstantiated) checkBounds(fn.pos, NoPrefix, NoSymbol, undetparams, targs, "inferred ") - //Console.println("UNAPPLY subst type "+undetparams+" to "+targs+" in "+fn+" ( "+args+ ")") val treeSubst = new TreeTypeSubstituter(undetparams, targs) treeSubst.traverse(fn) treeSubst.traverseTrees(args) - //Console.println("UNAPPLY gives "+fn+" ( "+args+ "), argtpes = "+argtpes+", pt = "+pt) uninstantiated.toList } catch { case ex: NoInstance => |