summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala13
-rw-r--r--test/files/pos/t5071.scala18
-rw-r--r--test/files/run/spec-self.check2
-rw-r--r--test/files/run/spec-self.scala14
4 files changed, 46 insertions, 1 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index 0f07ac0641..80971b9917 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -503,7 +503,18 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
val extraSpecializedMixins = specializedParents(clazz.info.parents.map(applyContext))
if (extraSpecializedMixins.nonEmpty)
debuglog("specializeClass on " + clazz + " founds extra specialized mixins: " + extraSpecializedMixins.mkString(", "))
-
+ // If the class being specialized has a self-type, the self type may
+ // require specialization. First exclude classes whose self types have
+ // the same type constructor as the class itself, since they will
+ // already be covered. Then apply the current context to the self-type
+ // as with the parents and assign it to typeOfThis.
+ if (clazz.typeOfThis.typeConstructor ne clazz.typeConstructor) {
+ cls.typeOfThis = applyContext(clazz.typeOfThis)
+ log("Rewriting self-type for specialized class:\n" +
+ " " + clazz.defStringSeenAs(clazz.typeOfThis) + "\n" +
+ " => " + cls.defStringSeenAs(cls.typeOfThis)
+ )
+ }
val infoType = ClassInfoType(parents ::: extraSpecializedMixins, decls1, cls)
if (newClassTParams.isEmpty) infoType else PolyType(newClassTParams, infoType)
}
diff --git a/test/files/pos/t5071.scala b/test/files/pos/t5071.scala
new file mode 100644
index 0000000000..44ad6276f2
--- /dev/null
+++ b/test/files/pos/t5071.scala
@@ -0,0 +1,18 @@
+// abstract
+trait Foo[@specialized A, Repr] {
+ self: Repr =>
+}
+trait Bar[A] extends Foo[A, Object] { }
+class Baz extends Foo[Int, Baz] { }
+
+// concrete
+trait Bippy {
+ def f(x: Int) = 5
+}
+trait FooC[@specialized A] {
+ self: Bippy =>
+
+ f(10)
+}
+
+class BazC extends FooC[Int] with Bippy { }
diff --git a/test/files/run/spec-self.check b/test/files/run/spec-self.check
new file mode 100644
index 0000000000..e981f45c92
--- /dev/null
+++ b/test/files/run/spec-self.check
@@ -0,0 +1,2 @@
+5.0
+5.0
diff --git a/test/files/run/spec-self.scala b/test/files/run/spec-self.scala
new file mode 100644
index 0000000000..1c95e0a820
--- /dev/null
+++ b/test/files/run/spec-self.scala
@@ -0,0 +1,14 @@
+class Foo0 extends (() => Double) {
+ def apply() = 5.0d
+}
+
+class Foo1 extends (Double => Double) {
+ def apply(x: Double) = x
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ println((new Foo0)())
+ println((new Foo1)(5.0d))
+ }
+}