diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-03-12 21:11:35 +0100 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2013-04-02 23:37:08 +0200 |
commit | 3ac185b6168a8f526446dacafd883ca5a1cf7a44 (patch) | |
tree | 18cf52185aae7122b9246174e6321381ee2edb02 | |
parent | f7c9adcd6156a301f3a1cc33f0e07289f44fbf7a (diff) | |
download | scala-3ac185b6168a8f526446dacafd883ca5a1cf7a44.tar.gz scala-3ac185b6168a8f526446dacafd883ca5a1cf7a44.tar.bz2 scala-3ac185b6168a8f526446dacafd883ca5a1cf7a44.zip |
Refactor existential related code out of types.
For imminent reuse in the subsequent commit.
The binary compatibility whitelist is updated to
ignore these, as they live in reflect.internal.
-rw-r--r-- | bincompat-backward.whitelist.conf | 24 | ||||
-rw-r--r-- | bincompat-forward.whitelist.conf | 48 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 70 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala | 77 |
4 files changed, 150 insertions, 69 deletions
diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index 4f627780e6..aa06e1d21c 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -160,6 +160,30 @@ filter { problemName=MissingFieldProblem }, { + matchName="scala.reflect.internal.ExistentialsAndSkolems.existentialTransform$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.existentialTransform" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.packSymbols" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.packSymbols$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.isRawParameter" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.Trees.substituteInfoParamsIntoDefDef" + problemName=MissingMethodProblem + }, + { matchName="scala.reflect.internal.ClassfileConstants.xxxunusedxxxx" problemName=MissingMethodProblem } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 76e189653b..d0893c5a28 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -356,6 +356,54 @@ filter { problemName=MissingMethodProblem }, { + matchName="scala.reflect.internal.ExistentialsAndSkolems.existentialTransform$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.existentialTransform" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.packSymbols" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.packSymbols$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.ExistentialsAndSkolems.isRawParameter" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.Trees.substituteInfoParamsIntoDefDef" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.existentialTransform$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.existentialTransform" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.substituteInfoParamsIntoDefDef" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.packSymbols" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.packSymbols$default$3" + problemName=MissingMethodProblem + }, + { + matchName="scala.reflect.internal.SymbolTable.isRawParameter" + problemName=MissingMethodProblem + }, + { matchName="scala.reflect.internal.ClassfileConstants.CONSTANT_INVOKEDYNAMIC" problemName=MissingMethodProblem }, diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index a98f20a971..34ba8b46f9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3767,77 +3767,9 @@ trait Typers extends Modes with Adaptations with Tags { } else res } - 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. - */ - 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. - */ - protected def existentialTransform[T](rawSyms: List[Symbol], tp: Type)(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) - } - val bound = allBounds(sym) - val sowner = if (isRawParameter(sym)) context.owner 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 raw hidden symbols `syms` and type `tp` */ - def packSymbols(hidden: List[Symbol], tp: Type): Type = - if (hidden.isEmpty) tp - else existentialTransform(hidden, tp)(existentialAbstraction) + def packSymbols(hidden: List[Symbol], tp: Type): Type = global.packSymbols(hidden, tp, Some(context0.owner)) def isReferencedFrom(ctx: Context, sym: Symbol): Boolean = ctx.owner.isTerm && diff --git a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala index 8b24678fd6..3bcb793926 100644 --- a/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala +++ b/src/reflect/scala/reflect/internal/ExistentialsAndSkolems.scala @@ -32,4 +32,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) } |