summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-21 04:29:22 +0000
committerPaul Phillips <paulp@improving.org>2011-06-21 04:29:22 +0000
commit7d5b6fa1eefd098b4d08927b5a40497f4bb9c132 (patch)
treea42b883ff2cb87781019a20e47a9ee1ad2d39068 /src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
parentcf85a61beb205aea4f177ef569e6d219c667c894 (diff)
downloadscala-7d5b6fa1eefd098b4d08927b5a40497f4bb9c132.tar.gz
scala-7d5b6fa1eefd098b4d08927b5a40497f4bb9c132.tar.bz2
scala-7d5b6fa1eefd098b4d08927b5a40497f4bb9c132.zip
Performance-motivated work: going through Speci...
Performance-motivated work: going through SpecializeTypes and eliminating unnecessary intermediate data structures and multiple traversals of lists. Also trying to get that code under control: it dwarfs all other phases in terms of debugging output, and a too-large percentage of the source is commented out debugging code which looks past its sell-by date. I realize the patch is a little big for a very thorough review, but review by dragos, prokopec.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala1022
1 files changed, 459 insertions, 563 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 487716c457..e6fb738dbb 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -21,28 +21,44 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
override def changesBaseClasses = true
override def keepsTypeParams = true
- /** Concrete types for specialization */
-// final lazy val concreteTypes = List(definitions.IntClass.tpe, definitions.DoubleClass.tpe)
-
type TypeEnv = immutable.Map[Symbol, Type]
- def emptyEnv: TypeEnv = immutable.ListMap.empty[Symbol, Type]
+ def emptyEnv: TypeEnv = Map[Symbol, Type]()
+ private implicit val typeOrdering: Ordering[Type] = Ordering[String] on ("" + _.typeSymbol.name)
import definitions.{
- RootClass, BooleanClass, UnitClass, ArrayClass, ScalaValueClasses,
+ RootClass, BooleanClass, UnitClass, ArrayClass,
+ ScalaValueClasses, isValueClass, isScalaValueType,
SpecializedClass, RepeatedParamClass, JavaRepeatedParamClass,
- AnyRefClass, Predef_AnyRef, ObjectClass,
- isValueClass
+ AnyRefClass, ObjectClass, Predef_AnyRef,
+ uncheckedVarianceClass
+ }
+ private def isSpecialized(sym: Symbol) = sym hasAnnotation SpecializedClass
+ private def hasSpecializedFlag(sym: Symbol) = sym hasFlag SPECIALIZED
+ private def specializedTypes(tps: List[Symbol]) = tps filter isSpecialized
+ private def specializedOn(sym: Symbol) = sym getAnnotation SpecializedClass match {
+ case Some(AnnotationInfo(_, args, _)) => args
+ case _ => Nil
}
- private def isSpecialized(sym: Symbol) = sym hasAnnotation SpecializedClass
- private def isSpecializedOnAnyRef(sym: Symbol) = sym.getAnnotation(SpecializedClass) match {
- case Some(AnnotationInfo(_, args, _)) => args.exists(_.symbol == Predef_AnyRef)
- case _ => false
+ // If we replace `isBoundedGeneric` with (tp <:< AnyRefClass.tpe),
+ // then pos/spec-List.scala fails - why? Does this kind of check fail
+ // for similar reasons? Does `sym.isAbstractType` make a difference?
+ private def isSpecializedAnyRefSubtype(tp: Type, sym: Symbol) = (
+ specializedOn(sym).exists(_.symbol == Predef_AnyRef) // specialized on AnyRef
+ && !isValueClass(tp.typeSymbol)
+ && isBoundedGeneric(tp)
+ )
+ private def isBoundedGeneric(tp: Type) = tp match {
+ case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe)
+ case TypeRef(_, sym, _) => !isValueClass(sym)
+ case _ => false
}
- private def specializedOn(sym: Symbol) = sym.getAnnotation(SpecializedClass) match {
- case Some(AnnotationInfo(_, args, _)) => args
- case _ => Nil
+ @inline private def debuglog(msg: => String) {
+ if (settings.debug.value) log(msg)
+ }
+ @inline private def ifDebug(body: => Unit) {
+ if (settings.debug.value) { body }
}
object TypeEnv {
@@ -50,7 +66,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* the given args. Expects the lists to have the same length.
*/
def fromSpecialization(sym: Symbol, args: List[Type]): TypeEnv = {
- assert(sym.info.typeParams.length == args.length, sym + " args: " + args)
+ ifDebug(assert(sym.info.typeParams.length == args.length, sym + " args: " + args))
+
emptyEnv ++ (sym.info.typeParams zip args filter (kv => isSpecialized(kv._1)))
}
@@ -61,14 +78,8 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
def includes(t1: TypeEnv, t2: TypeEnv) = t1 forall {
case (sym, tpe) =>
- val t2tpopt = t2 get sym
- // log("includes: " + t2tpopt.map(_.getClass))
- // log(tpe.getClass)
- t2tpopt match {
- case Some(t2tp) => t2tp == tpe || {
- (!primitiveTypes.contains(tpe)) && (!isValueClass(t2tp.typeSymbol)) // u.t.b. (t2tp <:< AnyRefClass.tpe)
- }
- case None => false
+ t2 get sym exists { t2tp =>
+ (tpe == t2tp) || !(isScalaValueType(tpe) || isScalaValueType(t2tp)) // u.t.b. (t2tp <:< AnyRefClass.tpe)
}
}
@@ -81,21 +92,11 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* to a type for which `sym` is specialized.
*/
def isValid(env: TypeEnv, sym: Symbol): Boolean = {
- def validBinding(tvar: Symbol, tpe: Type, sym: Symbol) = (
- isSpecialized(tvar)
- && sym.typeParams.contains(tvar)
- && concreteTypes(tvar).contains(tpe)
- )
- env forall {
- case (tvar, tpe) =>
-// log("isValid: " + env + " sym: " + sym + " sym.tparams: " + sym.typeParams)
-// log("Flag " + tvar + ": " + tvar.hasAnnotation(SpecializedClass))
-// log("tparams contains: " + sym.typeParams.contains(tvar))
-// log("concreteTypes: " + concreteTypes.contains(tpe))
-
- validBinding(tvar, tpe, sym) || (
- (sym.owner != RootClass) && validBinding(tvar, tpe, sym.owner)
- )
+ env forall { case (tvar, tpe) =>
+ isSpecialized(tvar) && (concreteTypes(tvar) contains tpe) && {
+ (sym.typeParams contains tvar) ||
+ (sym.owner != RootClass && (sym.owner.typeParams contains tvar))
+ }
}
}
}
@@ -107,22 +108,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* 'cls' itself if cls is not a specialized subclass.
*/
def genericClass(cls: Symbol): Symbol =
- if (cls.hasFlag(SPECIALIZED))
- cls.info.parents.head.typeSymbol
- else
- cls
+ if (hasSpecializedFlag(cls)) cls.info.parents.head.typeSymbol
+ else cls
/** Map a method symbol to a list of its specialized overloads in the same class. */
- private val overloads: mutable.Map[Symbol, List[Overload]] = new mutable.HashMap[Symbol, List[Overload]] {
- override def default(key: Symbol): List[Overload] = Nil
- }
+ private val overloads: mutable.Map[Symbol, List[Overload]] =
+ new mutable.HashMap[Symbol, List[Overload]] {
+ override def default(key: Symbol): List[Overload] = Nil
+ }
case class Overload(sym: Symbol, env: TypeEnv) {
- override def toString: String =
- "specialized overload " + sym + " in " + env
+ override def toString = "specialized overload " + sym + " in " + env
}
-
/** Just to mark uncheckable */
override def newPhase(prev: scala.tools.nsc.Phase): StdPhase = new SpecializationPhase(prev)
class SpecializationPhase(prev: scala.tools.nsc.Phase) extends super.Phase(prev) {
@@ -181,11 +179,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
override lazy val degenerate = {
- log("degenerate: " + target +
- " stv tparams: " + specializedTypeVars(target.info.typeParams map (_.info)) +
- " stv info: " + specializedTypeVars(target.info.resultType))
- !(specializedTypeVars(target.info.typeParams map (_.info))
- -- specializedTypeVars(target.info.resultType)).isEmpty
+ val stvTypeParams = specializedTypeVars(target.info.typeParams map (_.info))
+ val stvResult = specializedTypeVars(target.info.resultType)
+
+ log("degenerate: " + target + " stv tparams: " + stvTypeParams + " stv info: " + stvResult)
+
+ (stvTypeParams -- stvResult).nonEmpty
}
}
@@ -193,12 +192,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
private val info: mutable.Map[Symbol, SpecializedInfo] = new mutable.HashMap[Symbol, SpecializedInfo]
/** Has `clazz` any type parameters that need be specialized? */
- def hasSpecializedParams(clazz: Symbol): Boolean =
- !specializedParams(clazz).isEmpty
+ def hasSpecializedParams(clazz: Symbol) =
+ clazz.info.typeParams exists isSpecialized
/** Return specialized type parameters. */
def specializedParams(sym: Symbol): List[Symbol] =
- splitParams(sym.info.typeParams)._1
+ sym.info.typeParams filter isSpecialized
def splitParams(tps: List[Symbol]) =
tps partition isSpecialized
@@ -208,49 +207,24 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* specialized type.
*/
def survivingArgs(sym: Symbol, args: List[Type]): List[Type] =
- for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !isSpecialized(tvar) || !isPrimitive(tpe))
+ for ((tvar, tpe) <- sym.info.typeParams.zip(args) if !isSpecialized(tvar) || !isScalaValueType(tpe))
yield tpe
- private def isBoundedGeneric(tp: Type) = tp match {
- case TypeRef(_, sym, _) if sym.isAbstractType => (tp <:< AnyRefClass.tpe)
- case TypeRef(_, sym, _) => !isValueClass(sym)
- case _ => false
- }
-
- private def str(tp: Type): AnyRef = tp match {
- case TypeRef(pre, sym, args) => (str(pre), sym, args)
- case _ => "nontpref sym: " + tp.typeSymbol + ", " + tp.getClass
- }
-
- // If we replace `isBoundedGeneric` with (tp <:< AnyRefClass.tpe), then pos/spec-List.scala fails - why?
- // Does this kind of check fail for similar reasons? Does `sym.isAbstractType` make a difference?
- private def subtypeOfAnyRef(tp: Type) = {
- // log(tp + " <:< AnyRef? tp has symbol: " + tp.typeSymbol + ", " + tp.typeSymbol.ownerChain)
- !isValueClass(tp.typeSymbol) && isBoundedGeneric(tp)
- }
-
val specializedType = new TypeMap {
override def apply(tp: Type): Type = tp match {
case TypeRef(pre, sym, args) if args.nonEmpty =>
val pre1 = this(pre)
// when searching for a specialized class, take care to map all
// type parameters that are subtypes of AnyRef to AnyRef
- // log("Mapping " + args.map(_.typeSymbol) + ", from " + sym + " with params " + sym.typeParams + " with annots " + sym.typeParams.map(_.annotations))
val args1 = (args zip sym.typeParams) map {
- case (x, orig) if isSpecializedOnAnyRef(orig) && subtypeOfAnyRef(x) => AnyRefClass.tpe // used to be: case x if x <:< AnyRefClass.tpe
- case (x, _) => x
+ case (tp, orig) if isSpecializedAnyRefSubtype(tp, orig) => AnyRefClass.tpe
+ case (tp, _) => tp
}
- // log("!!! specializedType " + tp + ", " + pre1 + ", " + args1)
specializedClass.get((sym, TypeEnv.fromSpecialization(sym, args1))) match {
- case Some(sym1) =>
- val surviving = survivingArgs(sym, args)
- // log("!!! survivers: " + surviving)
- assert(sym1.info.typeParams.length == surviving.length, sym1)
- typeRef(pre1, sym1, surviving)
- case None =>
- typeRef(pre1, sym, args)
+ case Some(sym1) => typeRef(pre1, sym1, survivingArgs(sym, args))
+ case None => typeRef(pre1, sym, args)
}
- case _ => tp // mapOver(tp)
+ case _ => tp
}
}
@@ -263,13 +237,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* type variables alphabetically.
*/
private def specializedName(sym: Symbol, env: TypeEnv): TermName = {
- val tvars = if (sym.isClass) env.keySet
- else specializedTypeVars(sym).intersect(env.keySet)
- val (methparams, others) = tvars.toList.partition(_.owner.isMethod)
- val tvars1 = methparams sortBy (_.name.toString)
- val tvars2 = others sortBy (_.name.toString)
- if (settings.debug.value) log("specName(%s) env: %s tvars: %s ".format(sym, env, (tvars1, tvars2)))
- specializedName(sym.name, tvars1 map env, tvars2 map env)
+ val tvars = (
+ if (sym.isClass) env.keySet
+ else specializedTypeVars(sym).intersect(env.keySet)
+ )
+ val (methparams, others) = tvars.toList sortBy ("" + _.name) partition (_.owner.isMethod)
+ debuglog("specName(" + sym + ") env: " + env + " tvars: " + tvars)
+
+ specializedName(sym.name, methparams map env, others map env)
}
/** Specialize name for the two list of types. The first one denotes
@@ -296,46 +271,38 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Return the types `sym` should be specialized at. This may be some of the primitive types
* or AnyRef. AnyRef means that a new type parameter T will be generated later, known to be a
* subtype of AnyRef (T <: AnyRef).
+ * These are in a meaningful order for stability purposes.
*/
- def concreteTypes(sym: Symbol): List[Type] = {
- sym.getAnnotation(SpecializedClass) match {
- case Some(AnnotationInfo(_, args, _)) =>
- args match {
- case Nil =>
- log(sym + " specialized on everything")
- primitiveTypes
- case _ =>
- val tpes = args map {
- t => if (t.symbol == Predef_AnyRef) {
- if (isBoundedGeneric(sym.tpe))
- reporter.warning(sym.pos, sym + " is always a subtype of " + AnyRefClass.tpe + ".")
- AnyRefClass.tpe
- } else t.symbol.companionClass.tpe
- }
- log(sym + " specialized on " + tpes)
- tpes
- }
- case _ =>
- Nil
+ def concreteTypes(sym: Symbol): List[Type] = (
+ if (!isSpecialized(sym)) Nil // no @specialized Annotation
+ else specializedOn(sym) match {
+ case Nil => primitiveTypes // specialized on everything
+ case args => // specialized on args
+ (args map { tp =>
+ if (tp.symbol == Predef_AnyRef) {
+ if (isBoundedGeneric(sym.tpe))
+ reporter.warning(sym.pos, sym + " is always a subtype of " + AnyRefClass.tpe + ".")
+ AnyRefClass.tpe
+ }
+ else tp.symbol.companionClass.tpe
+ }).sorted
}
- }
+ )
/** Return a list of all type environments for all specializations
* of @specialized types in `tps`.
*/
private def specializations(tps: List[Symbol]): List[TypeEnv] = {
- val stps = tps filter isSpecialized
- count(stps, concreteTypes _) map (tps => immutable.HashMap(stps zip tps: _*))
- }
-
- /** Generate all arrangements with repetitions from the list of values,
- * with 'pos' positions. For example, count(2, List(1, 2)) yields
- * List(List(1, 1), List(1, 2), List(2, 1), List(2, 2))
- */
- private def count[A, V](xs: List[A], values: A => List[V]): List[List[V]] = {
- if (xs.isEmpty) Nil
- else if (xs.tail.isEmpty) values(xs.head) map (_ :: Nil)
- else for (v <- values(xs.head); vs <- count(xs.tail, values)) yield v :: vs
+ // the keys in each TypeEnv
+ val keys: List[Symbol] = tps filter isSpecialized
+ // creating each permutation of concrete types
+ def loop(ctypes: List[List[Type]]): List[List[Type]] = ctypes match {
+ case Nil => Nil
+ case set :: Nil => set map (x => List(x))
+ case set :: sets => for (x <- set ; xs <- loop(sets)) yield x :: xs
+ }
+ // zip the keys with each permutation to create a TypeEnv
+ loop(keys map concreteTypes) map (keys zip _ toMap)
}
/** Does the given tpe need to be specialized in the environment 'env'?
@@ -350,18 +317,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
(isNormalizedMember(sym) && info(sym).typeBoundsIn(env))
}
- def isNormalizedMember(m: Symbol): Boolean =
- (m.hasFlag(SPECIALIZED) && (info.get(m) match {
- case Some(NormalizedMember(_)) => true
- case _ => false
- }))
-
-
- def specializedTypeVars(tpe: List[Type]): immutable.Set[Symbol] =
- tpe.foldLeft(immutable.ListSet.empty[Symbol]: immutable.Set[Symbol]) {
- (s, tp) => s ++ specializedTypeVars(tp)
- }
-
+ def isNormalizedMember(m: Symbol) = hasSpecializedFlag(m) && (info get m exists {
+ case NormalizedMember(_) => true
+ case _ => false
+ })
+ def specializedTypeVars(tpes: List[Type]): immutable.Set[Symbol] = {
+ val buf = Set.newBuilder[Symbol]
+ tpes foreach (tp => buf ++= specializedTypeVars(tp))
+ buf.result
+ }
def specializedTypeVars(sym: Symbol): immutable.Set[Symbol] =
atPhase(currentRun.typerPhase)(specializedTypeVars(sym.info))
@@ -375,70 +339,57 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case TypeRef(pre, sym, args) =>
if (sym.isAliasType)
specializedTypeVars(tpe.normalize)
- else if (sym.isTypeParameter && isSpecialized(sym)
- || (sym.isTypeSkolem && isSpecialized(sym.deSkolemize)))
- immutable.ListSet.empty + sym
+ else if (sym.isTypeParameter && isSpecialized(sym) || (sym.isTypeSkolem && isSpecialized(sym.deSkolemize)))
+ Set(sym)
else if (sym == ArrayClass)
specializedTypeVars(args)
- else {
- val extra = for ((tp, arg) <- sym.typeParams.zip(args) if isSpecialized(tp))
- yield specializedTypeVars(arg).toList
- immutable.ListSet.empty[Symbol] ++ extra.flatten
- }
-
- case PolyType(tparams, resTpe) =>
- specializedTypeVars(tparams map (_.info)) ++ specializedTypeVars(resTpe)
-
- case NullaryMethodType(resTpe) => // since this method may be run at phase typer (before uncurry, where NMTs are eliminated)
- specializedTypeVars(resTpe)
- case MethodType(argSyms, resTpe) =>
- specializedTypeVars(argSyms map (_.tpe)) ++ specializedTypeVars(resTpe)
-
- case ExistentialType(_, res) => specializedTypeVars(res)
- case AnnotatedType(_, tp, _) => specializedTypeVars(tp)
- case TypeBounds(lo, hi) => specializedTypeVars(lo) ++ specializedTypeVars(hi)
- case _ => immutable.ListSet.empty[Symbol]
+ else
+ specializedTypeVars(sym.typeParams zip args collect { case (tp, arg) if isSpecialized(tp) => arg })
+
+ case PolyType(tparams, resTpe) => specializedTypeVars(resTpe :: tparams.map(_.info))
+ // since this method may be run at phase typer (before uncurry, where NMTs are eliminated)
+ case NullaryMethodType(resTpe) => specializedTypeVars(resTpe)
+ case MethodType(argSyms, resTpe) => specializedTypeVars(resTpe :: argSyms.map(_.tpe))
+ case ExistentialType(_, res) => specializedTypeVars(res)
+ case AnnotatedType(_, tp, _) => specializedTypeVars(tp)
+ case TypeBounds(lo, hi) => specializedTypeVars(List(lo, hi))
+ case _ => Set()
}
- // holds mappings from regular type parameter symbols to symbols of specialized type parameters
- // which are subtypes of AnyRef
+ // holds mappings from regular type parameter symbols to symbols of
+ // specialized type parameters which are subtypes of AnyRef
private val anyrefSpecCache = mutable.Map[Symbol, Symbol]()
+
/** Returns the type parameter in the specialized class `cls` that corresponds to type parameter
* `sym` in the original class. It will create it if needed or use the one from the cache.
*/
- private def typeParamSubAnyRef(sym: Symbol, cls: Symbol) = anyrefSpecCache.get(sym) match {
- case Some(tsub) => tsub.tpe
- case None =>
- val tparam = cls.newTypeParameter(sym.pos, newTypeName(sym.name.toString + "$sp"))
- tparam.setInfo(TypeBounds(sym.info.bounds.lo, AnyRefClass.tpe))
- anyrefSpecCache.put(sym, tparam)
- tparam.tpe
- }
-
- /** Cleans the anyrefSpecCache of all type parameter symbols of a class */
- private def cleanAnyRefSpecCache(cls: Symbol, decls: List[Symbol]) = {
- // remove class type parameters
- cls.tpe match {
- case PolyType(tparams, _) => for (tp <- tparams) anyrefSpecCache.remove(tp)
- case _ =>
- }
-
- // remove mappings from normalized members to
- for (d <- decls) d.tpe match {
- case PolyType(tparams, _) => for (tp <- tparams) anyrefSpecCache.remove(tp)
- case _ =>
+ private def typeParamSubAnyRef(sym: Symbol, cls: Symbol) = (
+ anyrefSpecCache.getOrElseUpdate(sym,
+ cls.newTypeParameter(sym.pos, newTypeName(sym.name + "$sp"))
+ setInfo TypeBounds(sym.info.bounds.lo, AnyRefClass.tpe)
+ ).tpe
+ )
+
+ /** Cleans the anyrefSpecCache of all type parameter symbols of a class.
+ */
+ private def cleanAnyRefSpecCache(cls: Symbol, decls: List[Symbol]) = (
+ // remove class type parameters and those of normalized members.
+ cls :: decls foreach {
+ _.tpe match {
+ case PolyType(tparams, _) => anyrefSpecCache --= tparams
+ case _ => ()
+ }
}
- }
+ )
// holds mappings from members to the type variables in the class that they were already specialized for,
// so that they don't get specialized twice (this is for AnyRef specializations)
- private val wasSpecializedForTypeVars = mutable.Map[Symbol, immutable.Set[Symbol]]() withDefaultValue immutable.Set[Symbol]()
-
- def isPrimitive(tpe: Type) = primitiveTypes contains tpe
+ private val wasSpecializedForTypeVars =
+ mutable.Map[Symbol, immutable.Set[Symbol]]() withDefaultValue immutable.Set[Symbol]()
/** Type parameters that survive when specializing in the specified environment. */
def survivingParams(params: List[Symbol], env: TypeEnv) =
- params.filter(p => !isSpecialized(p) || !isPrimitive(env(p)))
+ params.filter(p => !isSpecialized(p) || !isScalaValueType(env(p)))
/** Produces the symbols from type parameters `syms` of the original owner,
* in the given type environment `env`. The new owner is `nowner`.
@@ -535,7 +486,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (p.typeSymbol.isTrait) res += stp
else if (currentRun.compiles(clazz))
reporter.warning(clazz.pos, p.typeSymbol + " must be a trait. Specialized version of "
- + clazz + " will inherit generic " + p) // TODO change to error
+ + clazz + " will inherit generic " + p) // TODO change to error
}
res.reverse.toList
}
@@ -550,9 +501,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (newClassTParams.isEmpty) infoType else PolyType(newClassTParams, infoType)
}
- // log("specializedClass " + cls + ": " + specializedInfoType)
atPhase(phase.next)(cls.setInfo(specializedInfoType))
-
val fullEnv = outerEnv ++ env
/** Enter 'sym' in the scope of the current specialized class. It's type is
@@ -587,56 +536,57 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* def m$I(x: Int) = <body>/adapted to env {A -> Int} // om
*/
def forwardToOverload(m: Symbol): Symbol = {
- // log("forw. to overload " + m)
- val specMember = enterMember(m.cloneSymbol(cls)).setFlag(OVERRIDE | SPECIALIZED).resetFlag(DEFERRED | CASEACCESSOR) // m1
- val om = specializedOverload(cls, m, env).setFlag(OVERRIDE)
- // log("created specialized overload" + om)
+ val specMember = (
+ enterMember(m cloneSymbol cls)
+ setFlag (OVERRIDE | SPECIALIZED)
+ resetFlag (DEFERRED | CASEACCESSOR)
+ ) // m1
- var original = info.get(m) match {
+ val om = specializedOverload(cls, m, env).setFlag(OVERRIDE)
+ val original = info.get(m) match {
case Some(NormalizedMember(tg)) => tg
- case _ => m
+ case _ => m
}
+ info(specMember) = Forward(om)
+ info(om) = if (original.isDeferred) Forward(original) else Implementation(original)
+ typeEnv(om) = env ++ typeEnv(m) // add the environment for any method tparams
- info(specMember) = Forward(om)
- info(om) = if (original.isDeferred) Forward(original) else Implementation(original)
- typeEnv(om) = env ++ typeEnv(m) // add the environment for any method tparams
- overloads(specMember) = Overload(om, typeEnv(om)) :: overloads(specMember)
-
+ overloads(specMember) ::= Overload(om, typeEnv(om))
enterMember(om)
}
- log("specializedClass: " + cls)
- for (m <- normMembers if needsSpecialization(outerEnv ++ env, m) && satisfiable(fullEnv)) {
- // log(" * looking at: " + m + "; wasspecfor: " + wasSpecializedForTypeVars(m))
- if (!m.isDeferred) addConcreteSpecMethod(m)
-
+ for (m <- normMembers ; if needsSpecialization(outerEnv ++ env, m) && satisfiable(fullEnv)) {
+ if (!m.isDeferred)
+ addConcreteSpecMethod(m)
// specialized members have to be overridable.
- if (m.hasFlag(PRIVATE))
+ if (m.isPrivate)
m.resetFlag(PRIVATE).setFlag(PROTECTED)
if (m.isConstructor) {
- val specCtor = enterMember(m.cloneSymbol(cls).setFlag(SPECIALIZED))
+ val specCtor = enterMember(m.cloneSymbol(cls) setFlag SPECIALIZED)
info(specCtor) = Forward(m)
-
- } else if (isNormalizedMember(m)) { // methods added by normalization
+ }
+ else if (isNormalizedMember(m)) { // methods added by normalization
val NormalizedMember(original) = info(m)
- if (!conflicting(env ++ typeEnv(m))) {
+ if (nonConflicting(env ++ typeEnv(m))) {
if (info(m).degenerate) {
- if (settings.debug.value) log("degenerate normalized member " + m + " info(m): " + info(m))
+ debuglog("degenerate normalized member " + m + " info(m): " + info(m))
val specMember = enterMember(m.cloneSymbol(cls)).setFlag(SPECIALIZED).resetFlag(DEFERRED)
- info(specMember) = Implementation(original)
+
+ info(specMember) = Implementation(original)
typeEnv(specMember) = env ++ typeEnv(m)
- } else {
- // log("om")
- val om = forwardToOverload(m)
- if (settings.debug.value) log("normalizedMember " + m + " om: " + om + " typeEnv(om): " + typeEnv(om))
}
- } else
+ else debuglog({
+ val om = forwardToOverload(m)
+ "normalizedMember " + m + " om: " + om + " typeEnv(om): " + typeEnv(om)
+ })
+ }
+ else
log("conflicting env for " + m + " env: " + env)
-
- } else if (m.isDeferred) { // abstract methods
+ }
+ else if (m.isDeferred) { // abstract methods
val specMember = enterMember(m.cloneSymbol(cls)).setFlag(SPECIALIZED).resetFlag(DEFERRED)
- if (settings.debug.value) log("deferred " + specMember.fullName + " is forwarded")
+ debuglog("deferred " + specMember.fullName + " is forwarded")
info(specMember) = new Forward(specMember) {
override def target = m.owner.info.member(specializedName(m, env))
@@ -648,20 +598,23 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} else if (m.isValue && !m.isMethod) { // concrete value definition
def mkAccessor(field: Symbol, name: Name) = {
- val sym = cls.newMethod(field.pos, name)
- .setFlag(SPECIALIZED | m.getter(clazz).flags)
- .resetFlag(LOCAL | PARAMACCESSOR | CASEACCESSOR | LAZY) // we rely on the super class to initialize param accessors
+ val sym = (
+ cls.newMethod(field.pos, name)
+ setFlag (SPECIALIZED | m.getter(clazz).flags)
+ resetFlag (LOCAL | PARAMACCESSOR | CASEACCESSOR | LAZY)
+ // we rely on the super class to initialize param accessors
+ )
info(sym) = SpecializedAccessor(field)
sym
}
-
def overrideIn(clazz: Symbol, sym: Symbol) = {
- val sym1 = sym.cloneSymbol(clazz)
- .setFlag(OVERRIDE | SPECIALIZED)
- .resetFlag(DEFERRED | CASEACCESSOR | PARAMACCESSOR | LAZY)
- sym1.setInfo(sym1.info.asSeenFrom(clazz.tpe, sym1.owner))
+ val sym1 = (
+ sym cloneSymbol clazz
+ setFlag (OVERRIDE | SPECIALIZED)
+ resetFlag (DEFERRED | CASEACCESSOR | PARAMACCESSOR | LAZY)
+ )
+ sym1 setInfo sym1.info.asSeenFrom(clazz.tpe, sym1.owner)
}
-
val specVal = specializedOverload(cls, m, env)
addConcreteSpecMethod(m)
@@ -669,21 +622,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
enterMember(specVal)
// create accessors
- if (settings.debug.value)
- log("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
+ debuglog("m: " + m + " isLocal: " + nme.isLocalName(m.name) + " specVal: " + specVal.name + " isLocal: " + nme.isLocalName(specVal.name))
if (nme.isLocalName(m.name)) {
val specGetter = mkAccessor(specVal, nme.localToGetter(specVal.name)).setInfo(MethodType(List(), specVal.info))
val origGetter = overrideIn(cls, m.getter(clazz))
info(origGetter) = Forward(specGetter)
enterMember(specGetter)
enterMember(origGetter)
- if (settings.debug.value) log("created accessors: " + specGetter + " orig: " + origGetter)
+ debuglog("created accessors: " + specGetter + " orig: " + origGetter)
clazz.caseFieldAccessors.find(_.name.startsWith(m.name)) foreach { cfa =>
val cfaGetter = overrideIn(cls, cfa)
info(cfaGetter) = SpecializedAccessor(specVal)
enterMember(cfaGetter)
- if (settings.debug.value) log("found case field accessor for " + m + " added override " + cfaGetter);
+ debuglog("found case field accessor for " + m + " added override " + cfaGetter);
}
if (specVal.isVariable && m.setter(clazz) != NoSymbol) {
@@ -712,49 +664,40 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
cls
}
- log("specializeClass " + clazz.fullName)
- val decls1 = (clazz.info.decls.toList flatMap { m: Symbol =>
+ val decls1 = clazz.info.decls.toList flatMap { m: Symbol =>
if (m.isAnonymousClass) List(m) else {
normalizeMember(m.owner, m, outerEnv) flatMap { normalizedMember =>
val ms = specializeMember(m.owner, normalizedMember, outerEnv, clazz.info.typeParams)
- // log(">>> specialized: " + normalizedMember + " into " + ms)
-// atPhase(currentRun.typerPhase)(println("normalizedMember.info: " + normalizedMember.info)) - bring the info to the typer phase
// interface traits have concrete members now
if (ms.nonEmpty && clazz.isTrait && clazz.isInterface)
clazz.resetFlag(INTERFACE)
if (normalizedMember.isMethod) {
val newTpe = subst(outerEnv, normalizedMember.info)
- if (newTpe != normalizedMember.info) // only do it when necessary, otherwise the method type might be at a later phase already
- normalizedMember.updateInfo(newTpe) :: ms
- else
- normalizedMember :: ms
- } else
- normalizedMember :: ms
+ // only do it when necessary, otherwise the method type might be at a later phase already
+ if (newTpe != normalizedMember.info) {
+ normalizedMember updateInfo newTpe
+ }
+ }
+ normalizedMember :: ms
}
}
- })
- //log("decls before: " + decls1 + ", overloads: " + overloads.mkString("\n"))
-
- var hasSubclasses = false
- // log("For " + clazz + " - " + specializations(clazz.info.typeParams))
- for (env <- specializations(clazz.info.typeParams) if satisfiable(env)) {
- val spc = specializedClass(env, decls1)
- // log("entered " + spc + " in " + clazz.owner)
- hasSubclasses = true
+ }
+
+ val subclasses = specializations(clazz.info.typeParams) filter satisfiable
+ subclasses foreach { env =>
+ val spc = specializedClass(env, decls1)
val existing = clazz.owner.info.decl(spc.name)
+
// a symbol for the specialized class already exists if there's a classfile for it.
// keeping both crashes the compiler on test/files/pos/spec-Function1.scala
- if (existing != NoSymbol) {
- // log("removing existing symbol for "+ existing)
+ if (existing != NoSymbol)
clazz.owner.info.decls.unlink(existing)
- }
- atPhase(phase.next)(clazz.owner.info.decls enter spc) //!! assumes fully specialized classes
+ atPhase(phase.next)(clazz.owner.info.decls enter spc) //!!! assumes fully specialized classes
}
- if (hasSubclasses) clazz.resetFlag(FINAL)
+ if (subclasses.nonEmpty) clazz.resetFlag(FINAL)
cleanAnyRefSpecCache(clazz, decls1)
- //log("decls: " + decls1 + ", overloads: " + overloads.mkString("\n"))
decls1
}
@@ -768,42 +711,50 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* // etc.
*/
private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = {
- if (settings.debug.value) log("normalizeMember: " + sym.fullName)
- if (sym.isMethod && !atPhase(currentRun.typerPhase)(sym.typeParams.isEmpty)) {
- var (specializingOn, _) = splitParams(sym.info.typeParams)
- val unusedStvars = specializingOn filterNot (specializedTypeVars(sym.info).toList contains)
- if (unusedStvars.nonEmpty && currentRun.compiles(sym) && !sym.isSynthetic) {
- reporter.warning(sym.pos, "%s %s unused or used in non-specializable positions."
- .format(unusedStvars.mkString("", ", ", ""), if (unusedStvars.length == 1) "is" else "are"))
- unusedStvars foreach (_.removeAnnotation(SpecializedClass))
- specializingOn = specializingOn filterNot (unusedStvars contains)
- // tps = sym.info.typeParams filterNot (_.hasAnnotation(SpecializedClass))
+ debuglog("normalizeMember: " + sym.fullName)
+ sym :: (
+ if (!sym.isMethod || atPhase(currentRun.typerPhase)(sym.typeParams.isEmpty)) Nil
+ else {
+ var specializingOn = specializedParams(sym)
+ val unusedStvars = specializingOn filterNot specializedTypeVars(sym.info)
+
+ if (unusedStvars.nonEmpty && currentRun.compiles(sym) && !sym.isSynthetic) {
+ reporter.warning(sym.pos,
+ "%s %s unused or used in non-specializable positions.".format(
+ unusedStvars.mkString("", ", ", ""),
+ if (unusedStvars.length == 1) "is" else "are")
+ )
+ unusedStvars foreach (_ removeAnnotation SpecializedClass)
+ specializingOn = specializingOn filterNot (unusedStvars contains)
+ }
+ for (env0 <- specializations(specializingOn) if needsSpecialization(env0, sym)) yield {
+ val tps = survivingParams(sym.info.typeParams, env0)
+ val specMember = sym.cloneSymbol(owner).setFlag(SPECIALIZED).resetFlag(DEFERRED)
+ val env = mapAnyRefsInSpecSym(env0, sym, specMember)
+ val (keys, vals) = env.toList.unzip
+
+ specMember.name = specializedName(sym, env)
+ log("normalizing: " + sym + " to " + specMember + " with params " + tps)
+
+ typeEnv(specMember) = outerEnv ++ env
+ val tps1 = produceTypeParameters(tps, specMember, env)
+ tps1 foreach (tp => tp.setInfo(tp.info.subst(keys, vals)))
+
+ // the cloneInfo is necessary so that method parameter symbols are cloned at the new owner
+ val methodType = sym.info.resultType.subst(keys ++ tps, vals ++ tps1.map(_.tpe)).cloneInfo(specMember)
+ specMember setInfo polyType(tps1, methodType)
+
+ debuglog("expanded member: " + sym + ": " + sym.info +
+ " -> " + specMember +
+ ": " + specMember.info +
+ " env: " + env
+ )
+ info(specMember) = NormalizedMember(sym)
+ overloads(sym) ::= Overload(specMember, env)
+ specMember
+ }
}
- val res = sym :: (for (env0 <- specializations(specializingOn) if needsSpecialization(env0, sym)) yield {
- val tps = survivingParams(sym.info.typeParams, env0)
- val specMember = sym.cloneSymbol(owner).setFlag(SPECIALIZED).resetFlag(DEFERRED)
- val env = mapAnyRefsInSpecSym(env0, sym, specMember)
- val keys = env.keysIterator.toList;
- val vals = env.valuesIterator.toList
- specMember.name = specializedName(sym, env)
- log("normalizing: " + sym + " to " + specMember + " with params " + tps)
-
- typeEnv(specMember) = outerEnv ++ env
- val tps1 = produceTypeParameters(tps, specMember, env) // cloneSymbols(tps)
- for (tp <- tps1) tp.setInfo(tp.info.subst(keys, vals))
- // the cloneInfo is necessary so that method parameter symbols are cloned at the new owner
- val methodType = sym.info.resultType.subst(keys ::: tps, vals ::: (tps1 map (_.tpe))).cloneInfo(specMember)
-
- specMember.setInfo(polyType(tps1, methodType))
-
- if (settings.debug.value) log("expanded member: " + sym + ": " + sym.info + " -> " + specMember + ": " + specMember.info + " env: " + env)
- info(specMember) = NormalizedMember(sym)
- overloads(sym) = Overload(specMember, env) :: overloads(sym)
- specMember
- })
- //stps foreach (_.removeAttribute(SpecializedClass))
- res
- } else List(sym)
+ )
}
/** Specialize member `m` w.r.t. to the outer environment and the type
@@ -817,40 +768,46 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
def specializeOn(tparams: List[Symbol]): List[Symbol] =
for (spec0 <- specializations(tparams)) yield {
val spec = mapAnyRefsInOrigCls(spec0, owner)
- // log("outer env: " + outerEnv)
- // log(spec)
- if (sym.hasFlag(PRIVATE)) sym.resetFlag(PRIVATE).setFlag(PROTECTED)
+ if (sym.isPrivate)
+ sym.resetFlag(PRIVATE).setFlag(PROTECTED)
+
sym.resetFlag(FINAL)
val specMember = subst(outerEnv)(specializedOverload(owner, sym, spec))
typeEnv(specMember) = typeEnv(sym) ++ outerEnv ++ spec
wasSpecializedForTypeVars(specMember) ++= spec collect { case (s, tp) if s.tpe == tp => s }
+
log("sym " + specMember + " was specialized for type vars " + wasSpecializedForTypeVars(specMember))
- if (settings.debug.value) log("added specialized overload: %s in env: %s".format(specMember, typeEnv(specMember)))
- overloads(sym) = Overload(specMember, spec) :: overloads(sym)
- // log("member spec: " + sym + " with owner " + sym.owner + " in env " + spec + " is " + specMember + " with tp " + specMember.tpe)
+ debuglog("added specialized overload: %s in env: %s".format(specMember, typeEnv(specMember)))
+
+ overloads(sym) ::= Overload(specMember, spec)
specMember
}
if (sym.isMethod) {
- if (settings.debug.value) log("specializeMember %s with tps: %s stvars(sym): %s".format(sym, tps, specializedTypeVars(sym)))
- val tps1 = if (sym.isConstructor) tps filter (tp => sym.info.paramTypes.contains(tp)) else tps
+ debuglog("specializeMember %s with tps: %s stvars(sym): %s".format(sym, tps, specializedTypeVars(sym)))
+
+ val tps1 = if (sym.isConstructor) tps filter (sym.info.paramTypes contains _) else tps
val tps2 = tps1 intersect specializedTypeVars(sym).toList
- if (!sym.isDeferred) addConcreteSpecMethod(sym)
+ if (!sym.isDeferred)
+ addConcreteSpecMethod(sym)
- val lst = specializeOn(tps2) map {m => info(m) = SpecialOverload(sym, typeEnv(m)); m}
- lst
- } else
- List()
+ val ms = specializeOn(tps2)
+ ms foreach (m => info(m) = SpecialOverload(sym, typeEnv(m)))
+ ms
+ }
+ else Nil
}
/** Return the specialized overload of `m`, in the given environment. */
private def specializedOverload(owner: Symbol, sym: Symbol, env: TypeEnv): Symbol = {
- val specMember = sym.cloneSymbol(owner) // this method properly duplicates the symbol's info
+ val specMember = sym.cloneSymbol(owner) // this method properly duplicates the symbol's info
specMember.name = specializedName(sym, env)
- specMember.setInfo(subst(env, specMember.info.asSeenFrom(owner.thisType, sym.owner)))
- .setFlag(SPECIALIZED)
- .resetFlag(DEFERRED | CASEACCESSOR | ACCESSOR | LAZY)
+ (specMember
+ setInfo subst(env, specMember.info.asSeenFrom(owner.thisType, sym.owner))
+ setFlag (SPECIALIZED)
+ resetFlag (DEFERRED | CASEACCESSOR | ACCESSOR | LAZY)
+ )
}
/** For each method m that overrides inherited method m', add a special
@@ -864,8 +821,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* this method will return List('apply$spec$II')
*/
private def specialOverrides(clazz: Symbol): List[Symbol] = {
- // log("--> specialOverrides(" + clazz + ")")
-
/** Return the overridden symbol in syms that needs a specialized overriding symbol,
* together with its specialization environment. The overridden symbol may not be
* the closest to 'overriding', in a given hierarchy.
@@ -874,81 +829,80 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* * m overrides a method whose type contains specialized type variables
* * there is a valid specialization environment that maps the overridden method type to m's type.
*/
- def needsSpecialOverride(overriding: Symbol, syms: List[Symbol]): (Symbol, TypeEnv) = {
- def missingSpecializations(baseTvar: Symbol, derivedTvar: Symbol): immutable.Set[Type] = {
- val baseSet = concreteTypes(baseTvar).toSet
- val derivedSet = concreteTypes(derivedTvar).toSet
- baseSet diff derivedSet
- }
-
+ def needsSpecialOverride(overriding: Symbol): (Symbol, TypeEnv) = {
def checkOverriddenTParams(overridden: Symbol) {
- if (currentRun.compiles(overriding))
- for ((baseTvar, derivedTvar) <- overridden.info.typeParams.zip(overriding.info.typeParams);
- val missing = missingSpecializations(baseTvar, derivedTvar)
- if missing.nonEmpty)
- reporter.error(derivedTvar.pos,
- "Type parameter has to be specialized at least for the same types as in the overridden method. Missing " +
- "types: " + missing.mkString("", ", ", ""))
+ for ((baseTvar, derivedTvar) <- overridden.info.typeParams.zip(overriding.info.typeParams)) {
+ val missing = concreteTypes(baseTvar).toSet -- concreteTypes(derivedTvar).toSet
+ if (missing.nonEmpty) {
+ reporter.error(derivedTvar.pos,
+ "Type parameter has to be specialized at least for the same types as in the overridden method. Missing "
+ + "types: " + missing.mkString("", ", ", "")
+ )
+ }
+ }
}
-
- // log("checking: " + overriding + " - isParamAccessor: " + overriding.isParamAccessor)
- if (!overriding.isParamAccessor) for (overridden <- syms) {
- if (settings.debug.value)
- log("Overridden: " + overridden.fullName + ": " + overridden.info
- + "\n by " + overriding.fullName + ": " + overriding.info)
- val stvars = specializedTypeVars(overridden.info)
- if (!stvars.isEmpty) {
- if (settings.debug.value) log("\t\tspecializedTVars: " + stvars)
- checkOverriddenTParams(overridden)
-
- val env = unify(overridden.info, overriding.info, emptyEnv, false)
- if (settings.debug.value)
- log("\t\tenv: " + env + "isValid: " + TypeEnv.isValid(env, overridden)
- + "found: " + atPhase(phase.next)(overridden.owner.info.decl(specializedName(overridden, env))))
- if (!TypeEnv.restrict(env, stvars).isEmpty
- && TypeEnv.isValid(env, overridden)
- && atPhase(phase.next)(overridden.owner.info.decl(specializedName(overridden, env))) != NoSymbol)
- return (overridden, env)
+ if (!overriding.isParamAccessor) {
+ for (overridden <- overriding.allOverriddenSymbols) {
+ debuglog(
+ "Overridden: " + overridden.fullName +
+ ": " + overridden.info +
+ "\n by " + overriding.fullName +
+ ": " + overriding.info
+ )
+ val stvars = specializedTypeVars(overridden.info)
+ if (stvars.nonEmpty) {
+ debuglog("\t\tspecializedTVars: " + stvars)
+ if (currentRun compiles overriding)
+ checkOverriddenTParams(overridden)
+
+ val env = unify(overridden.info, overriding.info, emptyEnv, false)
+ def atNext = atPhase(phase.next)(overridden.owner.info.decl(specializedName(overridden, env)))
+
+ debuglog("\t\tenv: " + env + "isValid: " + TypeEnv.isValid(env, overridden) + "found: " + atNext)
+ if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol)
+ return (overridden, env)
+ }
}
}
(NoSymbol, emptyEnv)
}
-
- val oms = new mutable.ListBuffer[Symbol]
- for (overriding <- clazz.info.decls;
- val (overridden, env) = needsSpecialOverride(overriding, overriding.allOverriddenSymbols)
- if overridden != NoSymbol) {
- val om = specializedOverload(clazz, overridden, env)
- log("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info))
- typeEnv(om) = env
- addConcreteSpecMethod(overriding)
- if (!overriding.isDeferred) { // concrete method
- // if the override is a normalized member, 'om' gets the implementation from
- // its original target, and adds the environment of the normalized member (that is,
- // any specialized /method/ type parameter bindings)
- info(om) = info.get(overriding) match {
- case Some(NormalizedMember(target)) =>
- typeEnv(om) = env ++ typeEnv(overriding)
- log(info.get(overriding))
- SpecialOverride(target)
- case _ =>
- log(overriding + ", " + overriding.info)
- SpecialOverride(overriding)
- }
- info(overriding) = Forward(om)
- om setPos overriding.pos
- } else { // abstract override
- if (settings.debug.value) log("abstract override " + overriding.fullName + " with specialized " + om.fullName)
- info(om) = Forward(overriding)
+ (clazz.info.decls flatMap { overriding =>
+ needsSpecialOverride(overriding) match {
+ case (NoSymbol, _) => None
+ case (overridden, env) =>
+ val om = specializedOverload(clazz, overridden, env)
+ log("Added specialized overload %s for %s in env: %s with type: %s".format(om, overriding.fullName, env, om.info))
+ typeEnv(om) = env
+ addConcreteSpecMethod(overriding)
+ info(om) = (
+ if (overriding.isDeferred) { // abstract override
+ debuglog("abstract override " + overriding.fullName + " with specialized " + om.fullName)
+ Forward(overriding)
+ }
+ else {
+ // if the override is a normalized member, 'om' gets the
+ // implementation from its original target, and adds the
+ // environment of the normalized member (that is, any
+ // specialized /method/ type parameter bindings)
+ val impl = info get overriding match {
+ case Some(NormalizedMember(target)) =>
+ typeEnv(om) = env ++ typeEnv(overriding)
+ target
+ case _ =>
+ overriding
+ }
+ info(overriding) = Forward(om setPos overriding.pos)
+ SpecialOverride(impl)
+ }
+ )
+ overloads(overriding) ::= Overload(om, env)
+ ifDebug(atPhase(phase.next)(assert(
+ overridden.owner.info.decl(om.name) != NoSymbol,
+ "Could not find " + om.name + " in " + overridden.owner.info.decls))
+ )
+ Some(om)
}
- overloads(overriding) = Overload(om, env) :: overloads(overriding)
- oms += om
- atPhase(phase.next)(
- assert(overridden.owner.info.decl(om.name) != NoSymbol,
- "Could not find " + om.name + " in " + overridden.owner.info.decls))
- }
- log("special overrides(%s) = %s".format(clazz, oms))
- oms.toList
+ }).toList
}
case object UnifyError extends scala.util.control.ControlThrowable
@@ -959,15 +913,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*
* If `strict` is true, a UnifyError is thrown if unification is impossible.
*/
- private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = {
-// println("\tunify \t" + tp1 + "\n\t\t" + tp2)
- //log("Unify - " + (tp1.getClass, tp2.getClass))
- (tp1, tp2) match {
+ private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
case (TypeRef(_, sym1, _), _) if isSpecialized(sym1) =>
log("Unify - basic case: " + tp1 + ", " + tp2)
- if (definitions.isValueClass(tp2.typeSymbol))
- env + ((sym1, tp2))
- else if (isSpecializedOnAnyRef(sym1) && subtypeOfAnyRef(tp2)) // u.t.b. tp2 <:< AnyRefClass.tpe
+ if (isValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
env + ((sym1, tp2))
else
if (strict) throw UnifyError else env
@@ -990,17 +939,16 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case (PolyType(_, res), other) =>
unify(res, other, env, strict)
case (ThisType(_), ThisType(_)) => env
- case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
- case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
- case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
- case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
+ case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
+ case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
+ case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
+ case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
case (RefinedType(_, _), RefinedType(_, _)) => env
- case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
- case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
+ case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
+ case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
case _ =>
log("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass))
env
- }
}
private def unify(tp1: List[Type], tp2: List[Type], env: TypeEnv, strict: Boolean): TypeEnv =
@@ -1008,7 +956,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (!strict) unify(args._1, args._2, env, strict)
else {
val nenv = unify(args._1, args._2, emptyEnv, strict)
- if (env.keySet.intersect(nenv.keySet) == Set()) env ++ nenv
+ if (env.keySet intersect nenv.keySet isEmpty) env ++ nenv
else {
log("could not unify: u(" + args._1 + ", " + args._2 + ") yields " + nenv + ", env: " + env)
throw UnifyError
@@ -1016,8 +964,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
- private def specializedTypes(tps: List[Symbol]) = tps.filter(_.hasAnnotation(SpecializedClass))
-
/** Map class symbols to the type environments where they were created. */
val typeEnv: mutable.Map[Symbol, TypeEnv] = new mutable.HashMap[Symbol, TypeEnv] {
override def default(key: Symbol) = emptyEnv
@@ -1034,44 +980,38 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def subst(env: TypeEnv, tpe: Type): Type = {
class FullTypeMap(from: List[Symbol], to: List[Type]) extends SubstTypeMap(from, to) {
-
override def mapOver(tp: Type): Type = tp match {
case ClassInfoType(parents, decls, clazz) =>
- val parents1 = parents mapConserve (this);
+ val parents1 = parents mapConserve this
val declsList = decls.toList
- val decls1 = mapOver(declsList);
+ val decls1 = mapOver(declsList)
+
if ((parents1 eq parents) && (decls1 eq declsList)) tp
else ClassInfoType(parents1, new Scope(decls1), clazz)
+
case AnnotatedType(annots, atp, selfsym) =>
val annots1 = mapOverAnnotations(annots)
- val atp1 = this(atp)
+ val atp1 = this(atp)
+
if ((annots1 eq annots) && (atp1 eq atp)) tp
else if (annots1.isEmpty) atp1
- else if (atp1 ne atp) {
- val annots2 = annots1.filter(_.atp.typeSymbol != definitions.uncheckedVarianceClass)
- if (annots2.isEmpty) atp1
- else AnnotatedType(annots2, atp1, selfsym)
- } else
- AnnotatedType(annots1, atp1, selfsym)
-
+ else if (atp1 eq atp) AnnotatedType(annots1, atp1, selfsym)
+ else annots1.filter(_.atp.typeSymbol != uncheckedVarianceClass) match {
+ case Nil => atp1
+ case annots2 => AnnotatedType(annots2, atp1, selfsym)
+ }
case _ => super.mapOver(tp)
}
}
- // disabled because of bugs in std. collections
- //val (keys, values) = env.iterator.toList.unzip
- val keys = env.keysIterator.toList
- val values = env.valuesIterator.toList
+ val (keys, values) = env.toList.unzip
(new FullTypeMap(keys, values))(tpe)
-// tpe.subst(keys, values)
}
private def subst(env: TypeEnv)(decl: Symbol): Symbol = {
- val tpe = subst(env, decl.info)
- decl.setInfo(if (decl.isConstructor) tpe match {
- case MethodType(args, resTpe) => MethodType(args, decl.owner.tpe)
- } else tpe)
- // log((decl, decl.tpe.bounds.hi))
- // decl
+ decl setInfo (subst(env, decl.info) match {
+ case MethodType(args, _) if decl.isConstructor => MethodType(args, decl.owner.tpe)
+ case tpe => tpe
+ })
}
/** Checks if the type parameter symbol is not specialized
@@ -1101,40 +1041,33 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* If it is a 'no-specialization' run, it is applied only to loaded symbols.
*/
override def transformInfo(sym: Symbol, tpe: Type): Type = {
- val res = if (!settings.nospecialization.value || !currentRun.compiles(sym)) tpe match {
+ if (settings.nospecialization.value && currentRun.compiles(sym)) tpe
+ else tpe match {
case PolyType(targs, ClassInfoType(base, decls, clazz))
if clazz != RepeatedParamClass
&& clazz != JavaRepeatedParamClass
&& !clazz.isJavaDefined =>
val parents = base map specializedType
- // log("!!! %s[%s]) Parents: %s -> %s".format(sym, targs, base, parents))
- // for (t <- targs; p <- parents) notSpecializedIn(t, p)
- if (settings.debug.value) log("transformInfo (poly) " + clazz + " with parents1: " + parents + " ph: " + phase)
-// if (clazz.name.toString == "$colon$colon")
-// (new Throwable).printStackTrace
- polyType(targs, ClassInfoType(parents,
- new Scope(specializeClass(clazz, typeEnv(clazz)) ::: specialOverrides(clazz)),
- clazz))
+ debuglog("transformInfo (poly) " + clazz + " with parents1: " + parents + " ph: " + phase)
+ polyType(targs, ClassInfoType(
+ parents,
+ new Scope(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz)),
+ clazz)
+ )
case ClassInfoType(base, decls, clazz) if !clazz.isPackageClass && !clazz.isJavaDefined =>
- atPhase(phase.next)(base.map(_.typeSymbol.info))
+ atPhase(phase.next)(base map (_.typeSymbol.info))
+ // side effecting? parents is not used except to log.
val parents = base map specializedType
- if (settings.debug.value) log("transformInfo " + clazz + " with parents1: " + parents + " ph: " + phase)
- val res = ClassInfoType(base map specializedType,
- new Scope(specializeClass(clazz, typeEnv(clazz)) ::: specialOverrides(clazz)),
- clazz)
- res
-
+ debuglog("transformInfo " + clazz + " with parents1: " + parents + " ph: " + phase)
+ ClassInfoType(
+ base map specializedType,
+ new Scope(specializeClass(clazz, typeEnv(clazz)) ++ specialOverrides(clazz)),
+ clazz
+ )
case _ =>
tpe
- } else tpe
- res
-
- }
-
- def conflicting(env: TypeEnv): Boolean = {
- val silent = (pos: Position, str: String) => ()
- conflicting(env, silent)
+ }
}
/** Is any type variable in `env` conflicting with any if its type bounds, when
@@ -1142,13 +1075,9 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*
* A conflicting type environment could still be satisfiable.
*/
- def conflicting(env: TypeEnv, warn: (Position, String) => Unit): Boolean =
- env exists { case (tvar, tpe) =>
- if (!((subst(env, tvar.info.bounds.lo) <:< tpe)
- && (tpe <:< subst(env, tvar.info.bounds.hi)))) {
- warn(tvar.pos, "Bounds prevent specialization for " + tvar)
- true
- } else false
+ def conflicting(env: TypeEnv) = !nonConflicting(env)
+ def nonConflicting(env: TypeEnv) = env forall { case (tvar, tpe) =>
+ (subst(env, tvar.info.bounds.lo) <:< tpe) && (tpe <:< subst(env, tvar.info.bounds.hi))
}
/** The type environment is sound w.r.t. to all type bounds or only soft
@@ -1157,31 +1086,32 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* that does not fall within the bounds, but whose bounds contain
* type variables that are @specialized, (that could become satisfiable).
*/
- def satisfiable(env: TypeEnv, warn: (Position, String) => Unit): Boolean = {
+ def satisfiable(env: TypeEnv): Boolean = satisfiable(env, false)
+ def satisfiable(env: TypeEnv, warnings: Boolean): Boolean = {
def matches(tpe1: Type, tpe2: Type): Boolean = {
val t1 = subst(env, tpe1)
val t2 = subst(env, tpe2)
((t1 <:< t2)
- || !specializedTypeVars(t1).isEmpty
- || !specializedTypeVars(t2).isEmpty)
+ || specializedTypeVars(t1).nonEmpty
+ || specializedTypeVars(t2).nonEmpty)
}
env forall { case (tvar, tpe) =>
- ((matches(tvar.info.bounds.lo, tpe)
- && matches(tpe, tvar.info.bounds.hi))
- || { warn(tvar.pos, "Bounds prevent specialization of " + tvar);
- log("specvars: "
- + tvar.info.bounds.lo + ": " + specializedTypeVars(tvar.info.bounds.lo)
- + " " + subst(env, tvar.info.bounds.hi) + ": " + specializedTypeVars(subst(env, tvar.info.bounds.hi)))
- false })
+ matches(tvar.info.bounds.lo, tpe) && matches(tpe, tvar.info.bounds.hi) || {
+ if (warnings)
+ reporter.warning(tvar.pos, "Bounds prevent specialization of " + tvar)
+
+ log("specvars: " +
+ tvar.info.bounds.lo + ": " +
+ specializedTypeVars(tvar.info.bounds.lo) + " " +
+ subst(env, tvar.info.bounds.hi) + ": " +
+ specializedTypeVars(subst(env, tvar.info.bounds.hi))
+ )
+ false
+ }
}
}
- def satisfiable(env: TypeEnv): Boolean = {
- val silent = (pos: Position, str: String) => ()
- satisfiable(env, silent)
- }
-
class Duplicator extends {
val global: SpecializeTypes.this.global.type = SpecializeTypes.this.global
} with typechecker.Duplicators
@@ -1217,12 +1147,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
override def transform(tree: Tree): Tree = tree match {
case Select(qual, name) =>
val sym = tree.symbol
- if (sym.hasFlag(PRIVATE))
- if (settings.debug.value)
- log("seeing private member %s, currentClass: %s, owner: %s, isAccessible: %b, isLocalName: %b"
- .format(sym, currentClass, sym.owner.enclClass, isAccessible(sym), nme.isLocalName(sym.name)))
+ if (sym.isPrivate) debuglog(
+ "seeing private member %s, currentClass: %s, owner: %s, isAccessible: %b, isLocalName: %b".format(
+ sym, currentClass, sym.owner.enclClass, isAccessible(sym), nme.isLocalName(sym.name))
+ )
if (shouldMakePublic(sym) && !isAccessible(sym)) {
- if (settings.debug.value) log("changing private flag of " + sym)
+ debuglog("changing private flag of " + sym)
sym.makeNotPrivate(sym.owner)
}
super.transform(tree)
@@ -1234,13 +1164,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
/** Return the generic class corresponding to this specialized class. */
def originalClass(clazz: Symbol): Symbol =
- if (clazz.hasFlag(SPECIALIZED)) {
+ if (hasSpecializedFlag(clazz)) {
val (originalName, _, _) = nme.splitSpecializedName(clazz.name)
clazz.owner.info.decl(originalName).suchThat(_.isClass)
} else NoSymbol
def illegalSpecializedInheritance(clazz: Symbol): Boolean = {
- clazz.hasFlag(SPECIALIZED) && originalClass(clazz).info.parents.exists { p =>
+ hasSpecializedFlag(clazz) && originalClass(clazz).info.parents.exists { p =>
hasSpecializedParams(p.typeSymbol) && !p.typeSymbol.isTrait
}
}
@@ -1258,8 +1188,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
override def traverse(tree: Tree) = tree match {
case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
if (concreteSpecMethods(tree.symbol) || tree.symbol.isConstructor) {
- if (settings.debug.value)
- log("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
+ debuglog("!!! adding body of a defdef %s, symbol %s: %s".format(tree, tree.symbol, rhs))
body(tree.symbol) = rhs
// body(tree.symbol) = tree // whole method
parameters(tree.symbol) = vparamss map (_ map (_.symbol))
@@ -1333,23 +1262,23 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case TypeApply(Select(qual, name), targs)
if (!specializedTypeVars(symbol.info).isEmpty && name != nme.CONSTRUCTOR) =>
- if (settings.debug.value) log("checking typeapp for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe)
+ debuglog("checking typeapp for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe)
val qual1 = transform(qual)
// log(">>> TypeApply: " + tree + ", qual1: " + qual1)
specSym(qual1) match {
case Some(specMember) =>
- if (settings.debug.value) log("found " + specMember.fullName)
- assert(symbol.info.typeParams.length == targs.length)
- // log("!!! In TypeApply: " + specMember + "; " + symbol)
+ debuglog("found " + specMember.fullName)
+ ifDebug(assert(symbol.info.typeParams.length == targs.length, symbol.info.typeParams + " / " + targs))
+
val env = typeEnv(specMember)
- // log("env: " + env)
- def isResidual(env: TypeEnv, tvar: Symbol) =
- !env.isDefinedAt(tvar) || (env.isDefinedAt(tvar) && !isValueClass(env(tvar).typeSymbol))
- val residualTargs =
- for ((tvar, targ) <- symbol.info.typeParams.zip(targs) if isResidual(env, tvar))
- yield targ
- assert(residualTargs.length == specMember.info.typeParams.length,
+ val residualTargs = symbol.info.typeParams zip targs collect {
+ case (tvar, targ) if !env.contains(tvar) || !isValueClass(env(tvar).typeSymbol) => targ
+ }
+
+ ifDebug(assert(residualTargs.length == specMember.info.typeParams.length,
"residual: %s, tparams: %s, env: %s".format(residualTargs, symbol.info.typeParams, env))
+ )
+
val tree1 = maybeTypeApply(Select(qual1, specMember), residualTargs)
log("rewrote " + tree + " to " + tree1)
localTyper.typedOperator(atPos(tree.pos)(tree1)) // being polymorphic, it must be a method
@@ -1364,15 +1293,15 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
tree
case Select(qual, name) =>
- if (settings.debug.value)
- log("[%s] looking at Select: %s sym: %s: %s [tree.tpe: %s]".format(tree.pos.line, tree, symbol, symbol.info, tree.tpe))
+ debuglog("[%s] looking at Select: %s sym: %s: %s [tree.tpe: %s]".format(
+ tree.pos.line, tree, symbol, symbol.info, tree.tpe))
//log("!!! select " + tree + " -> " + symbol.info + " specTypeVars: " + specializedTypeVars(symbol.info))
if (specializedTypeVars(symbol.info).nonEmpty && name != nme.CONSTRUCTOR) {
// log("!!! unifying " + (symbol, symbol.tpe) + " and " + (tree, tree.tpe))
val env = unify(symbol.tpe, tree.tpe, emptyEnv, false)
// log("!!! found env: " + env + "; overloads: " + overloads(symbol))
- if (settings.debug.value) log("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env)
+ debuglog("checking for rerouting: " + tree + " with sym.tpe: " + symbol.tpe + " tree.tpe: " + tree.tpe + " env: " + env)
if (!env.isEmpty) {
val specMember = overload(symbol, env)
//log("!!! found member: " + specMember)
@@ -1397,7 +1326,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} else overloads(symbol).find(_.sym.info =:= symbol.info) match {
case Some(specMember) =>
val qual1 = transform(qual)
- if (settings.debug.value) log("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym))
+ debuglog("** routing " + tree + " to " + specMember.sym.fullName + " tree: " + Select(qual1, specMember.sym))
localTyper.typedOperator(atPos(tree.pos)(Select(qual1, specMember.sym)))
case None =>
super.transform(tree)
@@ -1442,7 +1371,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
assert(body.isDefinedAt(target), "sym: " + symbol.fullName + " target: " + target.fullName)
// we have an rhs, specialize it
val tree1 = duplicateBody(ddef, target)
- if (settings.debug.value) log("implementation: " + tree1)
+ debuglog("implementation: " + tree1)
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1
treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs))
@@ -1456,7 +1385,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
} else {
// we have an rhs, specialize it
val tree1 = duplicateBody(ddef, target)
- if (settings.debug.value) log("implementation: " + tree1)
+ debuglog("implementation: " + tree1)
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1
treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs))
}
@@ -1469,14 +1398,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// we have an rhs, specialize it
val tree1 = addBody(ddef, target)
(new ChangeOwnerTraverser(target, tree1.symbol))(tree1.rhs)
- if (settings.debug.value)
- log("changed owners, now: " + tree1)
+ debuglog("changed owners, now: " + tree1)
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree1
treeCopy.DefDef(tree1, mods, name, tparams, vparamss, tpt, transform(rhs))
case SpecialOverload(original, env) =>
- if (settings.debug.value) log("completing specialized " + symbol.fullName + " calling " + original)
+ debuglog("completing specialized " + symbol.fullName + " calling " + original)
log("special overload " + original + " -> " + env)
val t = DefDef(symbol, { vparamss =>
val fun = Apply(Select(This(symbol.owner), original),
@@ -1488,14 +1416,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
symbol.owner.thisType.memberType(original).finalResultType)
})
log("created special overload tree " + t)
- if (settings.debug.value) log("created " + t)
+ debuglog("created " + t)
localTyper.typed(t)
case fwd @ Forward(_) =>
log("forward: " + fwd + ", " + ddef)
val rhs1 = forwardCall(tree.pos, gen.mkAttributedRef(symbol.owner.thisType, fwd.target), vparamss)
- if (settings.debug.value)
- log("completed forwarder to specialized overload: " + fwd.target + ": " + rhs1)
+ debuglog("completed forwarder to specialized overload: " + fwd.target + ": " + rhs1)
localTyper.typed(treeCopy.DefDef(tree, mods, name, tparams, vparamss, tpt, rhs1))
case SpecializedAccessor(target) =>
@@ -1508,16 +1435,17 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
case ValDef(mods, name, tpt, rhs) if symbol.hasFlag(SPECIALIZED) && !symbol.isParamAccessor =>
- assert(body.isDefinedAt(symbol.alias))
+ assert(body.isDefinedAt(symbol.alias), body)
val tree1 = treeCopy.ValDef(tree, mods, name, tpt, body(symbol.alias).duplicate)
- if (settings.debug.value) log("now typing: " + tree1 + " in " + tree.symbol.owner.fullName)
+ debuglog("now typing: " + tree1 + " in " + tree.symbol.owner.fullName)
val d = new Duplicator
- val tree2 = d.retyped(localTyper.context1.asInstanceOf[d.Context],
- tree1,
- symbol.alias.enclClass,
- symbol.enclClass,
- typeEnv(symbol.alias) ++ typeEnv(tree.symbol))
- val ValDef(mods1, name1, tpt1, rhs1) = tree2
+ val ValDef(mods1, name1, tpt1, rhs1) = d.retyped(
+ localTyper.context1.asInstanceOf[d.Context],
+ tree1,
+ symbol.alias.enclClass,
+ symbol.enclClass,
+ typeEnv(symbol.alias) ++ typeEnv(tree.symbol)
+ )
val t = treeCopy.ValDef(tree1, mods1, name1, tpt1, transform(rhs1))
log("valdef " + tree + " -> " + t)
t
@@ -1527,18 +1455,18 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
// localTyper.typed(
// Apply(Select(Super(currentClass, nme.EMPTY), symbol.alias.getter(symbol.alias.owner)),
// List())))
-// if (settings.debug.value) log("replaced ValDef: " + tree1 + " in " + tree.symbol.owner.fullName)
+// debuglog("replaced ValDef: " + tree1 + " in " + tree.symbol.owner.fullName)
// tree1
case Apply(sel @ Select(sup @ Super(qual, name), name1), args)
if (sup.symbol.info.parents != atPhase(phase.prev)(sup.symbol.info.parents)) =>
def parents = sup.symbol.info.parents
- if (settings.debug.value) log(tree + " parents changed from: " + atPhase(phase.prev)(parents) + " to: " + parents)
+ debuglog(tree + " parents changed from: " + atPhase(phase.prev)(parents) + " to: " + parents)
val res = localTyper.typed(
Apply(Select(Super(qual, name) setPos sup.pos, name1) setPos sel.pos, transformTrees(args)) setPos tree.pos)
- if (settings.debug.value) log("retyping call to super, from: " + symbol + " to " + res.symbol)
+ debuglog("retyping call to super, from: " + symbol + " to " + res.symbol)
res
case _ =>
@@ -1555,28 +1483,19 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
private def duplicateBody(tree: DefDef, source: Symbol) = {
val symbol = tree.symbol
- val meth = addBody(tree, source)
- if (settings.debug.value) log("now typing: " + meth + " in " + symbol.owner.fullName)
+ val meth = addBody(tree, source)
+ debuglog("now typing: " + meth + " in " + symbol.owner.fullName)
+
val d = new Duplicator
- try {
- // log("duplicating tree: " + tree + "; " + symbol.owner)
- // log("source: " + source + "; owner: " + source.owner)
- // log("source encl class: " + source.enclClass)
- // log("symbol encl class: " + symbol.enclClass)
- // log(meth)
- d.retyped(localTyper.context1.asInstanceOf[d.Context],
- meth,
- source.enclClass,
- symbol.enclClass,
- typeEnv(source) ++ typeEnv(symbol))
- } catch {
- case e =>
- println("error compiling %s [%s]".format(unit, tree.pos))
- throw e
- }
+ d.retyped(
+ localTyper.context1.asInstanceOf[d.Context],
+ meth,
+ source.enclClass,
+ symbol.enclClass,
+ typeEnv(source) ++ typeEnv(symbol)
+ )
}
-
/** Put the body of 'source' as the right hand side of the method 'tree'.
* The destination method gets fresh symbols for type and value parameters,
* and the body is updated to the new symbols, and owners adjusted accordingly.
@@ -1585,13 +1504,13 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
*/
private def addBody(tree: DefDef, source: Symbol): DefDef = {
val symbol = tree.symbol
- if (settings.debug.value) log("specializing body of" + symbol.fullName + ": " + symbol.info)
+ debuglog("specializing body of" + symbol.fullName + ": " + symbol.info)
val DefDef(mods, name, tparams, vparamss, tpt, _) = tree
// val (_, origtparams) = splitParams(source.typeParams)
val env = typeEnv(symbol)
val boundTvars = env.keySet
- val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isPrimitive(env(tparam)))
- if (settings.debug.value) log("substituting " + origtparams + " for " + symbol.typeParams)
+ val origtparams = source.typeParams.filter(tparam => !boundTvars(tparam) || !isScalaValueType(env(tparam)))
+ debuglog("substituting " + origtparams + " for " + symbol.typeParams)
// skolemize type parameters
val (oldtparams, newtparams) = reskolemize(tparams)
@@ -1617,10 +1536,6 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, tmp)
}
- def warn(clazz: Symbol)(pos: Position, err: String) =
- if (!clazz.hasFlag(SPECIALIZED))
- unit.warning(pos, err)
-
/** Create trees for specialized members of 'cls', based on the
* symbols that are already there.
*/
@@ -1634,7 +1549,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
for (m <- cls.info.decls.toList
if m.hasFlag(SPECIALIZED)
&& (m.sourceFile ne null)
- && satisfiable(typeEnv(m), warn(cls))) {
+ && satisfiable(typeEnv(m), !cls.hasFlag(SPECIALIZED))) {
log("creating tree for " + m.fullName)
if (m.isMethod) {
if (info(m).target.hasAccessorFlag) hasSpecializedFields = true
@@ -1760,40 +1675,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (currentRun.compiles(m)) concreteSpecMethods += m
}
- private def makeArguments(fun: Symbol, vparams: List[Symbol]): List[Tree] = {
- def needsCast(tp1: Type, tp2: Type): Boolean =
- !(tp1 <:< tp2)
-
+ private def makeArguments(fun: Symbol, vparams: List[Symbol]): List[Tree] = (
//! TODO: make sure the param types are seen from the right prefix
- for ((tp, arg) <- fun.info.paramTypes zip vparams) yield {
- if (needsCast(arg.tpe, tp)) {
- //log("tp: " + tp + " " + tp.typeSymbol.owner)
- gen.mkAsInstanceOf(Ident(arg), tp)
- } else Ident(arg)
- }
- }
-
+ for ((tp, arg) <- fun.info.paramTypes zip vparams) yield
+ gen.maybeMkAsInstanceOf(Ident(arg), tp, arg.tpe)
+ )
private def findSpec(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) =>
- if (args.isEmpty) tp
- else {
- specializedType(tp)
- /*log("looking for " + specializedName(sym.name, args) + " in " + pre)
- val sym1 = pre.member(specializedName(sym.name, args))
- assert(sym1 != NoSymbol, "pre: " + pre.typeSymbol + " ph: " + phase + " with: " + pre.members)
- TypeRef(pre, sym1, Nil)*/
- }
- case _ => tp
+ case TypeRef(pre, sym, _ :: _) => specializedType(tp)
+ case _ => tp
}
class SpecializationTransformer(unit: CompilationUnit) extends Transformer {
informProgress("specializing " + unit)
override def transform(tree: Tree) =
if (settings.nospecialization.value) tree
- else atPhase(phase.next) {
- val res = specializeCalls(unit).transform(tree)
- res
- }
+ else atPhase(phase.next)(specializeCalls(unit).transform(tree))
}
def printSpecStats() {