diff options
3 files changed, 16 insertions, 5 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala index 8f2b1b9797..086ff74b0e 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/analysis/CopyPropagation.scala @@ -511,7 +511,13 @@ abstract class CopyPropagation { /** Drop everything known about mutable record fields. * - * @param state ... + * A simple escape analysis would help here. Some of the records we + * track never leak to other methods, therefore they can not be changed. + * We should not drop their bindings in this case. A closure object + * would be such an example. Some complications: + * + * - outer pointers. An closure escapes as an outer pointer to another + * nested closure. */ final def invalidateRecords(state: copyLattice.State) { def shouldRetain(sym: Symbol): Boolean = { diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala index 6292968c7a..7ac989374b 100644 --- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala +++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala @@ -188,10 +188,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def specializedName(sym: Symbol, env: TypeEnv): Name = { val tvars = if (sym.isClass) env.keySet else specializedTypeVars(sym.info).intersect(env.keySet) - log("specName(" + sym + ") env " + env + " tvars: " + tvars + " stv: " + specializedTypeVars(sym.info) + " info: " + sym.info) val (methparams, others) = tvars.toList.partition(_.owner.isMethod) val tvars1 = methparams.sort(_.name.toString < _.name.toString) val tvars2 = others.sort(_.name.toString < _.name.toString) + log("specName(" + sym + ") env " + env) specializedName(sym.name, tvars1 map env, tvars2 map env) } @@ -552,18 +552,21 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers { private def normalizeMember(owner: Symbol, sym: Symbol, outerEnv: TypeEnv): List[Symbol] = { if (sym.isMethod && !sym.info.typeParams.isEmpty) { val (stps, tps) = splitParams(sym.info.typeParams) - val res = sym :: (for (env <- specializations(stps)) yield { + val res = sym :: (for (env <- specializations(stps) if needsSpecialization(env, sym)) yield { val keys = env.keys.toList; val vals = env.values.toList val specMember = sym.cloneSymbol(owner).setFlag(SPECIALIZED).resetFlag(DEFERRED) specMember.name = specializedName(sym, env) + typeEnv(specMember) = outerEnv ++ env val tps1 = cloneSymbols(tps) for (tp <- tps1) tp.setInfo(tp.info.subst(keys, vals)) - val methodType = sym.info.resultType.subst(keys ::: tps, vals ::: (tps1 map (_.tpe))) + // 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)) - log("expanded member: " + sym + " -> " + specMember + ": " + specMember.info + " env: " + env) + + log("expanded member: " + sym + ": " + sym.info + " -> " + specMember + ": " + specMember.info + " env: " + env) info(specMember) = NormalizedMember(sym) overloads(sym) = Overload(specMember, env) :: overloads(sym) specMember diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 0b95590aa3..6268db7024 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1094,6 +1094,8 @@ trait Namers { self: Analyzer => } if (!ainfos.isEmpty) annotated.setAnnotations(ainfos) + if (annotated.isTypeSkolem) + annotated.deSkolemize.setAnnotations(ainfos) case _ => } implicit val scopeKind = TypeSigScopeKind |