diff options
author | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-08-20 22:04:34 +0000 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@epfl.ch> | 2007-08-20 22:04:34 +0000 |
commit | f8b2b21050e7a2ca0f537ef70e3e0c8eead43abc (patch) | |
tree | 108dab0bcef5917662e29b62ca9deb0ced05f415 | |
parent | f69c8e975a7b5eee1566c63f9732a38a3f253407 (diff) | |
download | scala-f8b2b21050e7a2ca0f537ef70e3e0c8eead43abc.tar.gz scala-f8b2b21050e7a2ca0f537ef70e3e0c8eead43abc.tar.bz2 scala-f8b2b21050e7a2ca0f537ef70e3e0c8eead43abc.zip |
Martin: please review
fixed 1210 for real (I hope), fix is in mapOver in Types.scala Also in
this commit: small fix to `undoTo` (added check that log is not empty)
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 70 | ||||
-rwxr-xr-x | test/files/pos/bug1210a.scala | 18 |
2 files changed, 44 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index 740a3774f9..abe0d183f9 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -95,6 +95,17 @@ trait Types { */ var intersectionWitness = new HashMap[List[Type], Type] + // @M toString that is safe during debugging (does not normalize, ...) + def debugString(tp: Type): String = tp match { + case TypeRef(pre, sym, args) => "TypeRef"+(debugString(pre), sym, args map debugString) + case ThisType(sym) => "ThisType("+sym+")" + case SingleType(pre, sym) => "SingleType"+(debugString(pre), sym) + case RefinedType(parents, defs) => "RefinedType"+(parents map debugString, defs.toList) + case ClassInfoType(parents, defs, clazz) => "ClassInfoType"+(parents map debugString, defs.toList, clazz) + case PolyType(tparams, result) => "PolyType"+(tparams, debugString(result)) + case _ => "" + } + /** A proxy for a type (identified by field `underlying') that forwards most * operations to it (for exceptions, see WrappingProxy, which forwards even more operations. * every operation that is overridden for some kind of types should be forwarded. @@ -1358,22 +1369,16 @@ A type's typeSymbol should never be inspected directly. override def normalize = if (sym.isAliasType) { // beta-reduce - if (!isHigherKinded /*degenerate case, see comments below*/ || - sym.info.typeParams.length == args.length) { - //transform(sym.info.resultType).normalize // cycles have been checked in typeRef - val xform=transform(sym.info.resultType) + if (sym.info.typeParams.length == args.length || !isHigherKinded) { +/* !isHigherKinded && sym.info.typeParams.length != args.length only happens when compiling e.g., + `val x: Class' with -Xgenerics, while `type Class = java.lang.Class' had already been compiled without -Xgenerics */ + val xform = transform(sym.info.resultType) assert(xform ne this, this) - if(xform eq this) xform else xform.normalize // @M TODO: why is this necessary? - }/* else if (!isHigherKinded) { // sym.info.typeParams.length != args.length - log("Error: normalizing "+sym.rawname+" with mismatch between type params "+sym.info.typeParams+" and args "+args) - transform(sym.info.resultType).normalize // technically wrong, but returning `this' is even worse (cycle!) - // only happens when compiling `val x: Class' with -Xgenerics, - // when `type Class = java.lang.Class' has already been compiled (without -Xgenerics) - }*/ else PolyType(typeParams, transform(sym.info.resultType).normalize) + xform.normalize // cycles have been checked in typeRef + } else PolyType(typeParams, transform(sym.info.resultType).normalize) // eta-expand // @M TODO: should not use PolyType, as that's the type of a polymorphic value -- we really want a type *function* - } else if (isHigherKinded) { // eta-expand + } else if (isHigherKinded) { // @M TODO: should not use PolyType, as that's the type of a polymorphic value -- we really want a type *function* - // @M TODO: transform? PolyType(typeParams, typeRef(pre, sym, higherKindedArgs)) } else if (sym.isRefinementClass) { sym.info @@ -1824,23 +1829,10 @@ A type's typeSymbol should never be inspected directly. if (sym1.hasFlag(LOCKED)) throw new TypeError("illegal cyclic reference involving " + sym1) sym1.setFlag(LOCKED) - //println("locking "+sym1+sym1.locationString+"/"+sym1.isAliasType+"/"+sym1.ownerChain) - def follow(tp: Type): Unit = transform(tp) match { - case tp2 @ TypeRef(_, sym2, _) => - if (sym2.isAliasType) { - if (sym2.hasFlag(LOCKED)) - throw new TypeError("illegal cyclic reference involving " + sym2) - sym2.setFlag(LOCKED) - follow(sym2.info) - sym2.resetFlag(LOCKED) - } - case _ => - } - follow(sym1.info) - //println("unlocking "+sym1) + transform(sym1.info) // check there are no cycles sym1.resetFlag(LOCKED) - //result // @M: original version -- this would expand the type alias immediately - rawTypeRef(pre, sym1, args) //@MAT -- don't expand type alias, but still check there are no cycles + + rawTypeRef(pre, sym1, args) // don't expand type alias (cycles checked above) } else { val pre1 = removeSuper(pre, sym1) if (pre1 ne pre) { @@ -2182,14 +2174,16 @@ A type's typeSymbol should never be inspected directly. } /** Map this function over given list of symbols */ - def mapOver(syms: List[Symbol]): List[Symbol] = { - val infos = syms map (_.info) - val infos1 = List.mapConserve(infos)(this) - if (infos1 eq infos) syms - else { - val syms1 = syms map (_.cloneSymbol) - List.map2(syms1, infos1) { - ((sym1, info1) => sym1.setInfo(info1.substSym(syms, syms1))) + def mapOver(origSyms: List[Symbol]): List[Symbol] = { + val origInfos = origSyms map (_.info) + val newInfos = List.mapConserve(origInfos)(this) + if (newInfos eq origInfos) origSyms // short path in case nothing changes due to map + else { // map is not the identity --> do cloning properly + val clonedSyms = origSyms map (_.cloneSymbol) + val clonedInfos = clonedSyms map (_.info) + val transformedInfos = List.mapConserve(clonedInfos)(this) + List.map2(clonedSyms, transformedInfos) { + ((newSym, newInfo) => newSym.setInfo(newInfo)) } } } @@ -2703,7 +2697,7 @@ A type's typeSymbol should never be inspected directly. /** Undo all changes to constraints to type variables upto `limit' */ private def undoTo(limit: UndoLog) { - while (undoLog ne limit) { + while ((undoLog ne limit) && !undoLog.isEmpty) { // @M added `&& !undoLog.isEmpty` val (tv, constr) = undoLog.head undoLog = undoLog.tail tv.constr = constr diff --git a/test/files/pos/bug1210a.scala b/test/files/pos/bug1210a.scala index a349a26753..7daf7f1179 100755 --- a/test/files/pos/bug1210a.scala +++ b/test/files/pos/bug1210a.scala @@ -1,9 +1,15 @@ -object Test { - def id[T](f: T => T): T = error("bla") +// both styles of abstraction should behave the same +// related to 1210 because that bug broke the OO version below +trait OO { + abstract class Test { self => + type T - abstract class M[Settings] { - type selfType = M[Settings] - - val v: selfType = id[M.this.selfType](x => x.v) + val v: Test {type T = self.T} = self.v.v } } + +trait FP { + abstract class Test[T] { + val v: Test[T] = v.v + } +}
\ No newline at end of file |