diff options
author | Paul Phillips <paulp@improving.org> | 2011-12-26 14:26:05 -0800 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-12-30 11:19:05 -0800 |
commit | d323f2f8d631404f10887d73e075e56a3fffc755 (patch) | |
tree | c2edc3e3d67b355ee717d88a189fb7ba023f0516 | |
parent | b2b59a124a2a8adf8e88c1e692c96263e0955b16 (diff) | |
download | scala-d323f2f8d631404f10887d73e075e56a3fffc755.tar.gz scala-d323f2f8d631404f10887d73e075e56a3fffc755.tar.bz2 scala-d323f2f8d631404f10887d73e075e56a3fffc755.zip |
Creator for existentials which flattens.
Currently it is possible to end up with nested existentials,
because existentialAbstraction only looks one level deeper.
This works harder to flatten them.
7 files changed, 22 insertions, 19 deletions
diff --git a/src/compiler/scala/reflect/internal/Importers.scala b/src/compiler/scala/reflect/internal/Importers.scala index 60b353a7c4..a4af4bf8f3 100644 --- a/src/compiler/scala/reflect/internal/Importers.scala +++ b/src/compiler/scala/reflect/internal/Importers.scala @@ -161,7 +161,7 @@ trait Importers { self: SymbolTable => case from.RefinedType(parents, decls) => RefinedType(parents map importType, importScope(decls), importSymbol(tpe.typeSymbol)) case from.ExistentialType(tparams, restpe) => - ExistentialType(tparams map importSymbol, importType(restpe)) + newExistentialType(tparams map importSymbol, importType(restpe)) case from.OverloadedType(pre, alts) => OverloadedType(importType(pre), alts map importSymbol) case from.AntiPolyType(pre, targs) => diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala index f37509af39..046689ae9f 100644 --- a/src/compiler/scala/reflect/internal/Types.scala +++ b/src/compiler/scala/reflect/internal/Types.scala @@ -2236,6 +2236,15 @@ A type's typeSymbol should never be inspected directly. } object PolyType extends PolyTypeExtractor + + /** A creator for existential types which flattens nested existentials. + */ + def newExistentialType(quantified: List[Symbol], underlying: Type): Type = + if (quantified.isEmpty) underlying + else underlying match { + case ExistentialType(qs, restpe) => newExistentialType(quantified ::: qs, restpe) + case _ => ExistentialType(quantified, underlying) + } case class ExistentialType(quantified: List[Symbol], override val underlying: Type) extends RewrappingTypeProxy @@ -2300,7 +2309,7 @@ A type's typeSymbol should never be inspected directly. } override def cloneInfo(owner: Symbol) = - createFromClonedSymbolsAtOwner(quantified, owner, underlying)(ExistentialType(_, _)) + createFromClonedSymbolsAtOwner(quantified, owner, underlying)(newExistentialType) override def atOwner(owner: Symbol) = if (quantified exists (_.owner != owner)) cloneInfo(owner) else this @@ -2999,7 +3008,7 @@ A type's typeSymbol should never be inspected directly. case TypeRef(pre, sym @ (NothingClass|AnyClass), _) => copyTypeRef(tycon, pre, sym, Nil) //@M drop type args to Any/Nothing case TypeRef(pre, sym, _) => copyTypeRef(tycon, pre, sym, args) case PolyType(tparams, restpe) => restpe.instantiateTypeParams(tparams, args) - case ExistentialType(tparams, restpe) => ExistentialType(tparams, appliedType(restpe, args)) + case ExistentialType(tparams, restpe) => newExistentialType(tparams, appliedType(restpe, args)) case st: SingletonType => appliedType(st.widen, args) // @M TODO: what to do? see bug1 case RefinedType(parents, decls) => RefinedType(parents map (appliedType(_, args)), decls) // MO to AM: please check case TypeBounds(lo, hi) => TypeBounds(appliedType(lo, args), appliedType(hi, args)) @@ -3112,11 +3121,7 @@ A type's typeSymbol should never be inspected directly. tparams1 exists { p1 => p1 == p || (p1.info contains p) } } } - if (tparams1.isEmpty) tpe1 - else tpe1 match { - case ExistentialType(tparams2, tpe2) => ExistentialType(tparams1 ::: tparams2, tpe2) - case _ => ExistentialType(tparams1, tpe1) - } + newExistentialType(tparams1, tpe1) } /** Remove any occurrences of type aliases from this type */ @@ -3432,7 +3437,7 @@ A type's typeSymbol should never be inspected directly. val tparams1 = mapOver(tparams) var result1 = this(result) if ((tparams1 eq tparams) && (result1 eq result)) tp - else ExistentialType(tparams1, result1.substSym(tparams, tparams1)) + else newExistentialType(tparams1, result1.substSym(tparams, tparams1)) case OverloadedType(pre, alts) => val pre1 = if (pre.isInstanceOf[ClassInfoType]) pre else this(pre) if (pre1 eq pre) tp @@ -3801,7 +3806,7 @@ A type's typeSymbol should never be inspected directly. case PolyType(bs, restp) => createFromClonedSymbols(bs, restp)((ps1, tp1) => PolyType(ps1, renameBoundSyms(tp1))) case ExistentialType(bs, restp) => - createFromClonedSymbols(bs, restp)(ExistentialType(_, _)) + createFromClonedSymbols(bs, restp)(newExistentialType) case _ => tp } diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala index 1a8540c158..9927560c8c 100644 --- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala +++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala @@ -378,7 +378,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ { // that it isn't right here. See #4757 for the immediate // motivation to fix it. val tparams = until(end, readSymbolRef) map (_ setFlag EXISTENTIAL) - ExistentialType(tparams, restpe) + newExistentialType(tparams, restpe) case ANNOTATEDtpe => var typeRef = readNat() diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e67ce90cfa..b73eaff524 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -682,8 +682,6 @@ abstract class ClassfileParser { while (!isDelimiter(sig(index))) { index += 1 } sig.subName(start, index) } - def existentialType(tparams: List[Symbol], tp: Type): Type = - if (tparams.isEmpty) tp else ExistentialType(tparams, tp) def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = { val tag = sig(index); index += 1 tag match { @@ -729,14 +727,14 @@ abstract class ClassfileParser { } accept('>') assert(xs.length > 0) - existentialType(existentials.toList, typeRef(pre, classSym, xs.toList)) + newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList)) } else if (classSym.isMonomorphicType) { tp } else { // raw type - existentially quantify all type parameters val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams) val t = typeRef(pre, classSym, eparams.map(_.tpe)) - val res = existentialType(eparams, t) + val res = newExistentialType(eparams, t) if (settings.debug.value && settings.verbose.value) println("raw type " + classSym + " -> " + res) res diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 5b38ddd092..67fa67b0f3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -180,7 +180,7 @@ trait Infer { case NullaryMethodType(restpe) => normalize(restpe) case ExistentialType(tparams, qtpe) => - ExistentialType(tparams, normalize(qtpe)) + newExistentialType(tparams, normalize(qtpe)) case tp1 => tp1 // @MAT aliases already handled by subtyping } diff --git a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala index cf8c0c596c..3d4f5e8724 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SyntheticMethods.scala @@ -50,7 +50,7 @@ trait SyntheticMethods extends ast.TreeDSL { /** To avoid unchecked warnings on polymorphic classes. */ def clazzTypeToTest(clazz: Symbol) = clazz.tpe.normalize match { - case TypeRef(_, sym, args) if args.nonEmpty => ExistentialType(sym.typeParams, clazz.tpe) + case TypeRef(_, sym, args) if args.nonEmpty => newExistentialType(sym.typeParams, clazz.tpe) case tp => tp } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index f6f783516c..a4c00e9f89 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2965,7 +2965,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { error(vd.pos, "illegal abstraction from value with volatile type "+vd.symbol.tpe) val tpt1 = typedType(tree.tpt, mode) existentialTransform(tree.whereClauses map (_.symbol), tpt1.tpe)((tparams, tp) => - TypeTree(ExistentialType(tparams, tp)) setOriginal tree + TypeTree(newExistentialType(tparams, tp)) setOriginal tree ) } @@ -4134,7 +4134,7 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser { if (isValueClass(pt.typeSymbol) || !isFullyDefined(pt)) arrayType(pt) else { val tparam = context.owner freshExistential "" setInfo TypeBounds.upper(pt) - ExistentialType(List(tparam), arrayType(tparam.tpe)) + newExistentialType(List(tparam), arrayType(tparam.tpe)) } val (expr1, baseClass) = expr0.tpe.typeSymbol match { case ArrayClass => (adapt(expr0, onlyStickyModes(mode), subArrayType(pt)), ArrayClass) |