Skip to content

Commit e512518

Browse files
committed
Streamlining skolemization, specialization.
Skolemization code doesn't belong in Typers. I carved out a little place for it. Also simplifications in specialization.
1 parent 63d9ae6 commit e512518

File tree

6 files changed

+75
-58
lines changed

6 files changed

+75
-58
lines changed
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/* NSC -- new scala compiler
2+
* Copyright 2005-2011 LAMP/EPFL
3+
* @author Martin Odersky
4+
*/
5+
6+
package scala.reflect
7+
package internal
8+
9+
import scala.collection.{ mutable, immutable }
10+
import util._
11+
12+
/** The name of this trait defines the eventual intent better than
13+
* it does the initial contents.
14+
*/
15+
trait ExistentialsAndSkolems {
16+
self: SymbolTable =>
17+
18+
/** Map a list of type parameter symbols to skolemized symbols, which
19+
* can be deskolemized to the original type parameter. (A skolem is a
20+
* representation of a bound variable when viewed inside its scope.)
21+
* !!!Adriaan: this does not work for hk types.
22+
*/
23+
def deriveFreshSkolems(tparams: List[Symbol]): List[Symbol] = {
24+
class Deskolemizer extends LazyType {
25+
override val typeParams = tparams
26+
val typeSkolems = typeParams map (_.newTypeSkolem setInfo this)
27+
override def complete(sym: Symbol) {
28+
// The info of a skolem is the skolemized info of the
29+
// actual type parameter of the skolem
30+
sym setInfo sym.deSkolemize.info.substSym(typeParams, typeSkolems)
31+
}
32+
}
33+
(new Deskolemizer).typeSkolems
34+
}
35+
36+
/** Convert to corresponding type parameters all skolems of method
37+
* parameters which appear in `tparams`.
38+
*/
39+
def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
40+
class DeSkolemizeMap extends TypeMap {
41+
def apply(tp: Type): Type = tp match {
42+
case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
43+
mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
44+
case _ =>
45+
mapOver(tp)
46+
}
47+
}
48+
new DeSkolemizeMap mapOver tp
49+
}
50+
}

src/compiler/scala/reflect/internal/SymbolTable.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ abstract class SymbolTable extends api.Universe
1515
with Symbols
1616
with Types
1717
with Kinds
18+
with ExistentialsAndSkolems
1819
with Scopes
1920
with Definitions
2021
with Constants

src/compiler/scala/reflect/internal/Symbols.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2714,6 +2714,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
27142714
*/
27152715
def cloneSymbolsAndModify(syms: List[Symbol], infoFn: Type => Type): List[Symbol] =
27162716
cloneSymbols(syms) map (_ modifyInfo infoFn)
2717+
def cloneSymbolsAtOwnerAndModify(syms: List[Symbol], owner: Symbol, infoFn: Type => Type): List[Symbol] =
2718+
cloneSymbolsAtOwner(syms, owner) map (_ modifyInfo infoFn)
27172719

27182720
/** Functions which perform the standard clone/substituting on the given symbols and type,
27192721
* then call the creator function with the new symbols and type as arguments.

src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,18 +1226,18 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
12261226
val body: mutable.Map[Symbol, Tree] = new mutable.HashMap
12271227

12281228
/** Map a specializable method to its value parameter symbols. */
1229-
val parameters: mutable.Map[Symbol, List[List[Symbol]]] = new mutable.HashMap
1229+
val parameters = mutable.HashMap[Symbol, List[Symbol]]()
12301230

12311231
/** Collect method bodies that are concrete specialized methods.
12321232
*/
12331233
class CollectMethodBodies extends Traverser {
12341234
override def traverse(tree: Tree) = tree match {
1235-
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
1235+
case DefDef(mods, name, tparams, vparams :: Nil, tpt, rhs) =>
12361236
if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) {
12371237
debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
12381238
body(tree.symbol) = rhs
12391239
// body(tree.symbol) = tree // whole method
1240-
parameters(tree.symbol) = mmap(vparamss)(_.symbol)
1240+
parameters(tree.symbol) = vparams.map(_.symbol)
12411241
concreteSpecMethods -= tree.symbol
12421242
} // no need to descend further down inside method bodies
12431243

@@ -1531,12 +1531,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
15311531
}
15321532
}
15331533

1534-
private def reskolemize(tparams: List[TypeDef]): (List[Symbol], List[Symbol]) = {
1535-
val saved = tparams map (_.symbol)
1536-
localTyper skolemizeTypeParams tparams
1537-
(saved, tparams map (_.symbol))
1538-
}
1539-
15401534
private def duplicateBody(tree: DefDef, source: Symbol) = {
15411535
val symbol = tree.symbol
15421536
val meth = addBody(tree, source)
@@ -1560,36 +1554,37 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
15601554
*/
15611555
private def addBody(tree: DefDef, source: Symbol): DefDef = {
15621556
val symbol = tree.symbol
1563-
debuglog("specializing body of" + symbol.fullName + ": " + symbol.info)
1564-
val DefDef(mods, name, tparams, vparamss, tpt, _) = tree
1557+
debuglog("specializing body of" + symbol.defString)
1558+
val DefDef(mods, name, tparams, vparams :: Nil, tpt, _) = tree
15651559
// val (_, origtparams) = splitParams(source.typeParams)
15661560
val env = typeEnv(symbol)
15671561
val boundTvars = env.keySet
15681562
val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam)))
15691563
debuglog("substituting " + origtparams + " for " + symbol.typeParams)
15701564

15711565
// skolemize type parameters
1572-
val (oldtparams, newtparams) = reskolemize(tparams)
1566+
val oldtparams = tparams map (_.symbol)
1567+
val newtparams = deriveFreshSkolems(oldtparams)
1568+
map2(tparams, newtparams)(_ setSymbol _)
15731569

15741570
// create fresh symbols for value parameters to hold the skolem types
1575-
val vparamss1 = List(for (vdef <- vparamss.head; param = vdef.symbol) yield {
1576-
ValDef(param cloneSymbol symbol substInfo (oldtparams, newtparams))
1577-
})
1571+
val newSyms = cloneSymbolsAtOwnerAndModify(vparams map (_.symbol), symbol, _.substSym(oldtparams, newtparams))
15781572

15791573
// replace value and type parameters of the old method with the new ones
15801574
// log("Adding body for " + tree.symbol + " - origtparams: " + origtparams + "; tparams: " + tparams)
15811575
// log("Type vars of: " + source + ": " + source.typeParams)
15821576
// log("Type env of: " + tree.symbol + ": " + boundTvars)
15831577
// log("newtparams: " + newtparams)
15841578
val symSubstituter = new ImplementationAdapter(
1585-
parameters(source).flatten ::: origtparams,
1586-
vparamss1.flatten.map(_.symbol) ::: newtparams,
1579+
parameters(source) ::: origtparams,
1580+
newSyms ::: newtparams,
15871581
source.enclClass,
15881582
false) // don't make private fields public
1589-
val tmp = symSubstituter(body(source).duplicate)
1583+
1584+
val newBody = symSubstituter(body(source).duplicate)
15901585
tpt.tpe = tpt.tpe.substSym(oldtparams, newtparams)
15911586

1592-
treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, tmp)
1587+
treeCopy.DefDef(tree, mods, name, tparams, List(newSyms map ValDef), tpt, newBody)
15931588
}
15941589

15951590
/** Create trees for specialized members of 'sClass', based on the
@@ -1610,9 +1605,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
16101605
if (m.isMethod) {
16111606
if (info(m).target.hasAccessorFlag) hasSpecializedFields = true
16121607
if (m.isClassConstructor) {
1613-
val origParamss = parameters(info(m).target)
1608+
val origParams = parameters(info(m).target)
16141609
val vparams = (
1615-
map2(m.info.paramTypes, origParamss(0))((tp, sym) =>
1610+
map2(m.info.paramTypes, origParams)((tp, sym) =>
16161611
m.newValue(specializedName(sym, typeEnv(sClass)), sym.pos, sym.flags) setInfo tp
16171612
)
16181613
)

src/compiler/scala/tools/nsc/typechecker/Namers.scala

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ trait Namers extends MethodSynthesis {
12991299
catch typeErrorHandler(tree, ErrorType)
13001300

13011301
result match {
1302-
case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => typer.deskolemizeTypeParams(tparams)(result)
1302+
case PolyType(tparams @ (tp :: _), _) if tp.owner.isTerm => deskolemizeTypeParams(tparams)(result)
13031303
case _ => result
13041304
}
13051305
}
@@ -1439,8 +1439,11 @@ trait Namers extends MethodSynthesis {
14391439
private val ownerSym = owner.symbol
14401440
override val typeParams = tparams map (_.symbol) //@M
14411441
override val tree = restp.tree
1442-
if (ownerSym.isTerm)
1443-
typer skolemizeTypeParams tparams
1442+
1443+
if (ownerSym.isTerm) {
1444+
val skolems = deriveFreshSkolems(tparams map (_.symbol))
1445+
map2(tparams, skolems)(_ setSymbol _)
1446+
}
14441447

14451448
def completeImpl(sym: Symbol) = {
14461449
// @M an abstract type's type parameters are entered.

src/compiler/scala/tools/nsc/typechecker/Typers.scala

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3036,40 +3036,6 @@ trait Typers extends Modes with Adaptations with PatMatVirtualiser {
30363036
packSymbols(localSyms.toList, normalizedTpe)
30373037
}
30383038

3039-
/** Replace type parameters with their TypeSkolems, which can later
3040-
* be deskolemized to the original type param. (A skolem is a
3041-
* representation of a bound variable when viewed inside its scope)
3042-
* !!!Adriaan: this does not work for hk types.
3043-
*/
3044-
def skolemizeTypeParams(tparams: List[TypeDef]): List[TypeDef] = {
3045-
class Deskolemizer extends LazyType {
3046-
override val typeParams = tparams map (_.symbol)
3047-
val typeSkolems = typeParams map (_.newTypeSkolem setInfo this)
3048-
// Replace the symbols
3049-
def substitute() = map2(tparams, typeSkolems)(_ setSymbol _)
3050-
override def complete(sym: Symbol) {
3051-
// The info of a skolem is the skolemized info of the
3052-
// actual type parameter of the skolem
3053-
sym setInfo sym.deSkolemize.info.substSym(typeParams, typeSkolems)
3054-
}
3055-
}
3056-
(new Deskolemizer).substitute()
3057-
}
3058-
/** Convert to corresponding type parameters all skolems of method
3059-
* parameters which appear in `tparams`.
3060-
*/
3061-
def deskolemizeTypeParams(tparams: List[Symbol])(tp: Type): Type = {
3062-
class DeSkolemizeMap extends TypeMap {
3063-
def apply(tp: Type): Type = tp match {
3064-
case TypeRef(pre, sym, args) if sym.isTypeSkolem && (tparams contains sym.deSkolemize) =>
3065-
mapOver(typeRef(NoPrefix, sym.deSkolemize, args))
3066-
case _ =>
3067-
mapOver(tp)
3068-
}
3069-
}
3070-
new DeSkolemizeMap mapOver tp
3071-
}
3072-
30733039
def typedClassOf(tree: Tree, tpt: Tree, noGen: Boolean = false) =
30743040
if (!checkClassType(tpt, true, false) && noGen) tpt
30753041
else atPos(tree.pos)(gen.mkClassOf(tpt.tpe))

0 commit comments

Comments
 (0)