summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
diff options
context:
space:
mode:
authorVlad Ureche <vlad.ureche@gmail.com>2013-06-12 14:58:09 +0200
committerVlad Ureche <vlad.ureche@gmail.com>2013-06-12 19:34:33 +0200
commitc43b504ac1d843a580683a78eca0cb55bb427c15 (patch)
tree1f39bc2d0a760c6bee8fd92d6b95e6f2b97e51c8 /src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
parentc0ba5eb196cc3c7174c9278dd4d050513e55b4ce (diff)
downloadscala-c43b504ac1d843a580683a78eca0cb55bb427c15.tar.gz
scala-c43b504ac1d843a580683a78eca0cb55bb427c15.tar.bz2
scala-c43b504ac1d843a580683a78eca0cb55bb427c15.zip
SI-7343 Fixed phase ordering in specialization
Specialization rewires class parents during info transformation, and the new info then guides the tree changes. But if a symbol is created during duplication, which runs after specialization, its info is not visited and thus the corresponding tree is not specialized. One manifestation is the following: ``` object Test { class Parent[@specialized(Int) T] def spec_method[@specialized(Int) T](t: T, expectedXSuper: String) = { class X extends Parent[T]() // even in the specialized variant, the local X class // doesn't extend Parent$mcI$sp, since its symbol has // been created after specialization and was not seen // by specialzation's info transformer. ... } } ``` We can fix this by forcing duplication to take place before specialization. Review by @dragos, @paulp or @axel22.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 39716d4ed0..5ef5d4031b 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1264,7 +1264,35 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
protected override def newBodyDuplicator(context: Context) = new BodyDuplicator(context)
+ }
+ /** Introduced to fix SI-7343: Phase ordering problem between Duplicators and Specialization.
+ * brief explanation: specialization rewires class parents during info transformation, and
+ * the new info then guides the tree changes. But if a symbol is created during duplication,
+ * which runs after specialization, its info is not visited and thus the corresponding tree
+ * is not specialized. One manifestation is the following:
+ * ```
+ * object Test {
+ * class Parent[@specialized(Int) T]
+ *
+ * def spec_method[@specialized(Int) T](t: T, expectedXSuper: String) = {
+ * class X extends Parent[T]()
+ * // even in the specialized variant, the local X class
+ * // doesn't extend Parent$mcI$sp, since its symbol has
+ * // been created after specialization and was not seen
+ * // by specialzation's info transformer.
+ * ...
+ * }
+ * }
+ * ```
+ * We fix this by forcing duplication to take place before specialization.
+ *
+ * Note: The constructors phase (which also uses duplication) comes after erasure and uses the
+ * post-erasure typer => we must protect it from the beforeSpecialization phase shifting.
+ */
+ class SpecializationDuplicator(casts: Map[Symbol, Type]) extends Duplicator(casts) {
+ override def retyped(context: Context, tree: Tree, oldThis: Symbol, newThis: Symbol, env: scala.collection.Map[Symbol, Type]): Tree =
+ beforeSpecialize(super.retyped(context, tree, oldThis, newThis, env))
}
/** A tree symbol substituter that substitutes on type skolems.
@@ -1637,7 +1665,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val tree1 = deriveValDef(tree)(_ => body(symbol.alias).duplicate)
debuglog("now typing: " + tree1 + " in " + tree.symbol.owner.fullName)
- val d = new Duplicator(emptyEnv)
+ val d = new SpecializationDuplicator(emptyEnv)
val newValDef = d.retyped(
localTyper.context1.asInstanceOf[d.Context],
tree1,
@@ -1664,7 +1692,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val symbol = tree.symbol
val meth = addBody(tree, source)
- val d = new Duplicator(castmap)
+ val d = new SpecializationDuplicator(castmap)
debuglog("-->d DUPLICATING: " + meth)
d.retyped(
localTyper.context1.asInstanceOf[d.Context],