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 /src | |
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.
Diffstat (limited to 'src')
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) |