From 9ea2cefb2079aebad2b215f6a699fe6262e2c7a7 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Fri, 14 Oct 2011 04:27:35 +0000 Subject: Another swing at r25823. I verified this creates identical library bytecode so I anticipate no regressions. Review by prokopec anyway. --- .../scala/tools/nsc/transform/SpecializeTypes.scala | 13 ++++++++++++- test/files/pos/t5071.scala | 18 ++++++++++++++++++ test/files/run/spec-self.check | 2 ++ test/files/run/spec-self.scala | 14 ++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 test/files/pos/t5071.scala create mode 100644 test/files/run/spec-self.check create mode 100644 test/files/run/spec-self.scala 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)) + } +} -- cgit v1.2.3