Permalink
Browse files

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.
  • Loading branch information...
retronym committed Mar 12, 2013
1 parent f7c9adc commit 3ac185b6168a8f526446dacafd883ca5a1cf7a44
@@ -159,6 +159,30 @@ filter {
matchName="scala.reflect.internal.Names#NameOps.name"
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
@@ -355,6 +355,54 @@ filter {
matchName="scala.reflect.internal.StdNames#TermNames.SelectFromTypeTree"
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
@@ -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 &&
@@ -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)
}

0 comments on commit 3ac185b

Please sign in to comment.