diff options
author | Paul Phillips <paulp@improving.org> | 2013-04-08 18:28:24 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-04-08 23:08:07 -0700 |
commit | 7ee950fc3002632065e6f9e9b29e4c9be1138b88 (patch) | |
tree | a49d49bd4ebfdd8e79843b6b259a31bc0867598d /src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala | |
parent | 967087811f9215d72651fc62e0977291efa2ab43 (diff) | |
parent | 53e031f55386d131b1aaa5fb93ee1a3ac6bce646 (diff) | |
download | scala-7ee950fc3002632065e6f9e9b29e4c9be1138b88.tar.gz scala-7ee950fc3002632065e6f9e9b29e4c9be1138b88.tar.bz2 scala-7ee950fc3002632065e6f9e9b29e4c9be1138b88.zip |
Merge remote-tracking branch 'origin/2.10.x' into merge-2.10.x
* origin/2.10.x:
if starr.use.released fetch Scala ${starr.version} for STARR
assume build.release when maven.version.suffix is set
make quick.done depend on quick.bin again
SI-7321 Memory leak in specialize on multiple compiler runs.
Take the N^2 out of the compiler's TreeSet.
SI-6900 Fix tailrec for dependent method types
Simplify interplay between Uncurry Info- and Tree-Transformers
Refactor existential related code out of types.
Add a cautionary comment to TreeSymSubstitutor.
SI-6715 Shouldn't return "" from TermNames.originalName
Backport #2289's TermNames.unexpandedName as TermNames.originalName
SI-7147 Diagnostic for unexplained assertion in presentation compiler.
SI-6793 Don't use super param accessors if inaccessible.
Correct sorting example for Ordering in scaladoc
Conflicts:
bincompat-backward.whitelist.conf
bincompat-forward.whitelist.conf
build.xml
src/compiler/scala/tools/nsc/transform/UnCurry.scala
src/reflect/scala/reflect/internal/StdNames.scala
Diffstat (limited to 'src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala')
-rw-r--r-- | src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index 281a32caf6..34bd400186 100644 --- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala @@ -31,4 +31,81 @@ trait ExistentialsAndSkolems { } (new Deskolemizer).typeSkolems } + + def isRawParameter(sym: Symbol) = // is it a type parameter leaked by a raw type? + sym.isTypeParameter && sym.owner.isJavaDefined + + /** If we map a set of hidden symbols to their existential bounds, we + * have a problem: the bounds may themselves contain references to the + * hidden symbols. So this recursively calls existentialBound until + * the typeSymbol is not amongst the symbols being hidden. + */ + private def existentialBoundsExcludingHidden(hidden: List[Symbol]): Map[Symbol, Type] = { + def safeBound(t: Type): Type = + if (hidden contains t.typeSymbol) safeBound(t.typeSymbol.existentialBound.bounds.hi) else t + + def hiBound(s: Symbol): Type = safeBound(s.existentialBound.bounds.hi) match { + case tp @ RefinedType(parents, decls) => + val parents1 = parents mapConserve safeBound + if (parents eq parents1) tp + else copyRefinedType(tp, parents1, decls) + case tp => tp + } + + // Hanging onto lower bound in case anything interesting + // happens with it. + mapFrom(hidden)(s => s.existentialBound match { + case TypeBounds(lo, hi) => TypeBounds(lo, hiBound(s)) + case _ => hiBound(s) + }) + } + + /** Given a set `rawSyms` of term- and type-symbols, and a type + * `tp`, produce a set of fresh type parameters and a type so that + * it can be abstracted to an existential type. Every type symbol + * `T` in `rawSyms` is mapped to a clone. Every term symbol `x` of + * type `T` in `rawSyms` is given an associated type symbol of the + * following form: + * + * type x.type <: T with Singleton + * + * The name of the type parameter is `x.type`, to produce nice + * diagnostics. The Singleton parent ensures that the type + * parameter is still seen as a stable type. Type symbols in + * rawSyms are fully replaced by the new symbols. Term symbols are + * also replaced, except for term symbols of an Ident tree, where + * only the type of the Ident is changed. + */ + final def existentialTransform[T](rawSyms: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None)(creator: (List[Symbol], Type) => T): T = { + val allBounds = existentialBoundsExcludingHidden(rawSyms) + val typeParams: List[Symbol] = rawSyms map { sym => + val name = sym.name match { + case x: TypeName => x + case x => tpnme.singletonName(x) + } + def rawOwner0 = rawOwner.getOrElse(abort(s"no owner provided for existential transform over raw parameter: $sym")) + val bound = allBounds(sym) + val sowner = if (isRawParameter(sym)) rawOwner0 else sym.owner + val quantified = sowner.newExistential(name, sym.pos) + + quantified setInfo bound.cloneInfo(quantified) + } + // Higher-kinded existentials are not yet supported, but this is + // tpeHK for when they are: "if a type constructor is expected/allowed, + // tpeHK must be called instead of tpe." + val typeParamTypes = typeParams map (_.tpeHK) + def doSubst(info: Type) = info.subst(rawSyms, typeParamTypes) + + creator(typeParams map (_ modifyInfo doSubst), doSubst(tp)) + } + + /** + * Compute an existential type from hidden symbols `hidden` and type `tp`. + * @param hidden The symbols that will be existentially abstracted + * @param hidden The original type + * @param rawOwner The owner for Java raw types. + */ + final def packSymbols(hidden: List[Symbol], tp: Type, rawOwner: Option[Symbol] = None): Type = + if (hidden.isEmpty) tp + else existentialTransform(hidden, tp, rawOwner)(existentialAbstraction) } |