summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2011-01-04 10:19:08 +0000
committerIulian Dragos <jaguarul@gmail.com>2011-01-04 10:19:08 +0000
commit1f4d528702ca32ed01e500ea2ef2e9b2ebbe07d1 (patch)
treea48dc80ebb0774b0098a28ba9ae344dd7c318cc7 /src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
parent7c34a1af9612cc696fef9f4d62d1a9a9ef8ff9ae (diff)
downloadscala-1f4d528702ca32ed01e500ea2ef2e9b2ebbe07d1.tar.gz
scala-1f4d528702ca32ed01e500ea2ef2e9b2ebbe07d1.tar.bz2
scala-1f4d528702ca32ed01e500ea2ef2e9b2ebbe07d1.zip
Fixed infinite loop on call to super from a spe...
Fixed infinite loop on call to super from a specialized method. This happened only on illegal specialized inheritance. Closes #3651, no review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala')
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala52
1 files changed, 51 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 650e52c9d6..5f4a90b84b 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -1002,6 +1002,19 @@ 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)) {
+ 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 =>
+ hasSpecializedParams(p.typeSymbol) && !p.typeSymbol.isTrait
+ }
+ }
+
def specializeCalls(unit: CompilationUnit) = new TypingTransformer(unit) {
/** Map a specializable method to it's rhs, when not deferred. */
val body: mutable.Map[Symbol, Tree] = new mutable.HashMap
@@ -1086,6 +1099,12 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
case None => super.transform(tree)
}
+ case Select(Super(_, _), name) if illegalSpecializedInheritance(currentClass) =>
+ val pos = tree.pos
+ log(pos.source.file.name+":"+pos.line+": not specializing call to super inside illegal specialized inheritance class.")
+ log(pos.lineContent)
+ 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))
@@ -1403,9 +1422,40 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
atPos(pos) { (receiver /: argss) (Apply) }
}
+ /** Forward to the generic class constructor. If the current class initializes
+ * specialized fields corresponding to parameters, it passes null to the superclass
+ * constructor. This saves the boxing cost for initializing generic fields that are
+ * never used.
+ *
+ * For example:
+ * {{{
+ * case class Tuple2[T, U](x: T, y: U)
+ *
+ * class Tuple2$II {
+ * val _x$I: Int = ..
+ * def x = _x$I
+ * // same for y
+ * def this(x: Int, y: Int) {
+ * super.this(null.asInstanceOf[Int], null.asInstanceOf[Int])
+ * }
+ * }
+ * }}
+ */
private def forwardCtorCall(pos: util.Position, receiver: Tree, paramss: List[List[ValDef]], clazz: Symbol): Tree = {
+
+ /** A constructor parameter `f' initializes a specialized field
+ * iff:
+ * - it is specialized itself
+ * - there is a getter for the original (non-specialized) field in the same class
+ * - there is a getter for the specialized field in the same class
+ */
+ def initializesSpecializedField(f: Symbol): Boolean =
+ (f.name.endsWith("$sp")
+ && clazz.info.member(nme.originalName(f.name)).isPublic
+ && (clazz.info.decl(f.name).suchThat(_.isGetter) != NoSymbol))
+
val argss = paramss map (_ map (x =>
- if (x.name.endsWith("$sp") && clazz.info.member(nme.originalName(x.name)).isPublic)
+ if (initializesSpecializedField(x.symbol))
gen.mkAsInstanceOf(Literal(Constant(null)), x.symbol.tpe)
else
Ident(x.symbol))