summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala90
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Duplicators.scala5
-rw-r--r--test/files/pos/spec-constr.scala7
4 files changed, 67 insertions, 44 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index c2ad1fd426..af9c28232d 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -27,6 +27,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
import collection.mutable
private val guardedCtorStats: mutable.Map[Symbol, List[Tree]] = new mutable.HashMap[Symbol, List[Tree]]
+ private val ctorParams: mutable.Map[Symbol, List[Symbol]] = new mutable.HashMap[Symbol, List[Symbol]]
def transformClassTemplate(impl: Template): Template = {
val clazz = impl.symbol.owner // the transformed class
@@ -300,7 +301,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
case _ => false
}
- log("merging: " + originalStats.mkString("\n") + " : " + specializedStats.mkString("\n"))
+ log("merging: " + originalStats.mkString("\n") + "\nwith\n" + specializedStats.mkString("\n"))
val res = for (s <- originalStats; val stat = s.duplicate) yield {
log("merge: looking at " + stat)
val stat1 = stat match {
@@ -314,8 +315,13 @@ abstract class Constructors extends Transform with ast.TreeDSL {
}
if (stat1 eq stat) {
+ assert(ctorParams(genericClazz).length == constrParams.length)
+ // this is just to make private fields public
+ (new specializeTypes.ImplementationAdapter(ctorParams(genericClazz), constrParams, null, true))(stat1)
+
// statements coming from the original class need retyping in the current context
if (settings.debug.value) log("retyping " + stat1)
+
val d = new specializeTypes.Duplicator
d.retyped(localTyper.context1.asInstanceOf[d.Context],
stat1,
@@ -350,6 +356,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
if (usesSpecializedField && shouldGuard && postfix.nonEmpty) {
// save them for duplication in the specialized subclass
guardedCtorStats(clazz) = postfix
+ ctorParams(clazz) = constrParams
val tree =
If(
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 60634c467f..ede742bcf7 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -933,6 +933,52 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val global: SpecializeTypes.this.global.type = SpecializeTypes.this.global
} with typechecker.Duplicators
+ /** A tree symbol substituter that substitutes on type skolems.
+ * If a type parameter is a skolem, it looks for the original
+ * symbol in the 'from' and maps it to the corresponding new
+ * symbol. The new symbol should probably be a type skolem as
+ * well (not enforced).
+ *
+ * All private members are made protected in order to be accessible from
+ * specialized classes.
+ */
+ class ImplementationAdapter(from: List[Symbol],
+ to: List[Symbol],
+ targetClass: Symbol,
+ addressFields: Boolean) extends TreeSymSubstituter(from, to) {
+ override val symSubst = new SubstSymMap(from, to) {
+ override def matches(sym1: Symbol, sym2: Symbol) =
+ if (sym2.isTypeSkolem) sym2.deSkolemize eq sym1
+ else sym1 eq sym2
+ }
+
+ private def isAccessible(sym: Symbol): Boolean =
+ (currentClass == sym.owner.enclClass) && (currentClass != targetClass)
+
+ private def shouldMakePublic(sym: Symbol): Boolean =
+ sym.hasFlag(PRIVATE | PROTECTED) && (addressFields || !nme.isLocalName(sym.name))
+
+ /** All private members that are referenced are made protected,
+ * in order to be accessible from specialized subclasses.
+ */
+ 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 (shouldMakePublic(sym) && !isAccessible(sym)) {
+ if (settings.debug.value) log("changing private flag of " + sym)
+ sym.makeNotPrivate(sym.owner)
+ }
+ super.transform(tree)
+
+ case _ =>
+ super.transform(tree)
+ }
+ }
+
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
@@ -1217,54 +1263,14 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val symSubstituter = new ImplementationAdapter(
parameters(source).flatten ::: origtparams,
vparamss1.flatten.map(_.symbol) ::: newtparams,
- source.enclClass)
+ source.enclClass,
+ false) // don't make private fields public
val tmp = symSubstituter(body(source).duplicate)
tpt.tpe = tpt.tpe.substSym(oldtparams, newtparams)
treeCopy.DefDef(tree, mods, name, tparams, vparamss1, tpt, tmp)
}
- /** A tree symbol substituter that substitutes on type skolems.
- * If a type parameter is a skolem, it looks for the original
- * symbol in the 'from' and maps it to the corresponding new
- * symbol. The new symbol should probably be a type skolem as
- * well (not enforced).
- *
- * All private members are made protected in order to be accessible from
- * specialized classes.
- */
- class ImplementationAdapter(from: List[Symbol], to: List[Symbol], targetClass: Symbol) extends TreeSymSubstituter(from, to) {
- override val symSubst = new SubstSymMap(from, to) {
- override def matches(sym1: Symbol, sym2: Symbol) =
- if (sym2.isTypeSkolem) sym2.deSkolemize eq sym1
- else sym1 eq sym2
- }
-
- private def isAccessible(sym: Symbol): Boolean =
- (currentClass == sym.owner.enclClass) && (currentClass != targetClass)
-
- /** All private members that are referenced are made protected,
- * in order to be accessible from specialized subclasses.
- */
- 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 " + sym + " targetClass: " + currentClass + " owner: " + sym.owner.enclClass)
- if (sym.hasFlag(PRIVATE | PROTECTED) && !nme.isLocalName(sym.name) && !isAccessible(sym)) {
- if (settings.debug.value) log("changing private flag of " + sym)
-// tree.symbol.resetFlag(PRIVATE).setFlag(PROTECTED)
- sym.makeNotPrivate(sym.owner)
-// tree.symbol.resetFlag(PRIVATE | PROTECTED)
-// tree.symbol.privateWithin = NoSymbol
- }
- super.transform(tree)
-
- case _ =>
- super.transform(tree)
- }
- }
-
def warn(clazz: Symbol)(pos: Position, err: String) =
if (!clazz.hasFlag(SPECIALIZED))
unit.warning(pos, err)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
index 78f43296b4..dbc3ffbe17 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala
@@ -189,6 +189,7 @@ abstract class Duplicators extends Analyzer {
if (tree.hasSymbol && tree.symbol != NoSymbol
&& !tree.symbol.isLabel // labels cannot be retyped by the type checker as LabelDef has no ValDef/return type trees
&& invalidSyms.isDefinedAt(tree.symbol)) {
+ if (settings.debug.value) log("removed symbol " + tree.symbol)
tree.symbol = NoSymbol
}
@@ -240,7 +241,9 @@ abstract class Duplicators extends Analyzer {
case Select(th @ This(_), sel) if (oldClassOwner ne null) && (th.symbol == oldClassOwner) =>
log("selection on this, no type ascription required")
- super.typed(atPos(tree.pos)(Select(This(newClassOwner), sel)), mode, pt)
+ // we use the symbol name instead of the tree name because the symbol may have been
+ // name mangled, rendering the tree name obsolete
+ super.typed(atPos(tree.pos)(Select(This(newClassOwner), tree.symbol.name)), mode, pt)
case This(_) if (oldClassOwner ne null) && (tree.symbol == oldClassOwner) =>
// val tree1 = Typed(This(newClassOwner), TypeTree(fixType(tree.tpe.widen)))
diff --git a/test/files/pos/spec-constr.scala b/test/files/pos/spec-constr.scala
new file mode 100644
index 0000000000..e908b65a41
--- /dev/null
+++ b/test/files/pos/spec-constr.scala
@@ -0,0 +1,7 @@
+class SparseArray2[@specialized(Int) T:ClassManifest](val maxSize: Int, initialLength:Int = 3) {
+ private var data = new Array[T](initialLength);
+ private var index = new Array[Int](initialLength);
+
+ // comment out to compile correctly
+ data.length + 3;
+}