summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-05-07 13:55:52 -0700
committerPaul Phillips <paulp@improving.org>2012-05-07 13:55:52 -0700
commit728b5d0bcd6c1e16bae0afcf5cf85bf5d3dee435 (patch)
tree3897cb05341c9feb7c580b4b2e403fe389994ef3
parent0efe9b02fa951ed8d81c70f4e3deb8462280f1c2 (diff)
parenta11a57735e73d66147f9f6166687ad7bc04feca8 (diff)
downloadscala-728b5d0bcd6c1e16bae0afcf5cf85bf5d3dee435.tar.gz
scala-728b5d0bcd6c1e16bae0afcf5cf85bf5d3dee435.tar.bz2
scala-728b5d0bcd6c1e16bae0afcf5cf85bf5d3dee435.zip
Merge commit 'refs/pull/491/head' into develop
-rw-r--r--src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala32
-rw-r--r--test/files/run/t5629.check2
-rw-r--r--test/files/run/t5629.scala36
-rw-r--r--test/files/run/t5629b.check10
-rw-r--r--test/files/run/t5629b.scala41
5 files changed, 108 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
index f6296acdca..e0f34b47c8 100644
--- a/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
+++ b/src/compiler/scala/tools/nsc/transform/SpecializeTypes.scala
@@ -752,9 +752,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
}
}
}
-
+
val subclasses = specializations(clazz.info.typeParams) filter satisfiable
- subclasses foreach { env =>
+ subclasses foreach {
+ env =>
val spc = specializedClass(env, decls1)
val existing = clazz.owner.info.decl(spc.name)
@@ -928,7 +929,7 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
if (currentRun compiles overriding)
checkOverriddenTParams(overridden)
- val env = unify(overridden.info, overriding.info, emptyEnv, false)
+ val env = unify(overridden.info, overriding.info, emptyEnv, false, true)
def atNext = afterSpecialize(overridden.owner.info.decl(specializedName(overridden, env)))
if (TypeEnv.restrict(env, stvars).nonEmpty && TypeEnv.isValid(env, overridden) && atNext != NoSymbol) {
@@ -990,8 +991,10 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
* Fails if such an environment cannot be found.
*
* If `strict` is true, a UnifyError is thrown if unification is impossible.
+ *
+ * If `tparams` is true, then the methods tries to unify over type params in polytypes as well.
*/
- private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean): TypeEnv = (tp1, tp2) match {
+ private def unify(tp1: Type, tp2: Type, env: TypeEnv, strict: Boolean, tparams: Boolean = false): TypeEnv = (tp1, tp2) match {
case (TypeRef(_, sym1, _), _) if sym1.isSpecialized =>
debuglog("Unify " + tp1 + ", " + tp2)
if (isPrimitiveValueClass(tp2.typeSymbol) || isSpecializedAnyRefSubtype(tp2, sym1))
@@ -1020,17 +1023,20 @@ abstract class SpecializeTypes extends InfoTransform with TypingTransformers {
debuglog("Unify polytypes " + tp1 + " and " + tp2)
if (strict && tparams1.length != tparams2.length)
unifyError(tp1, tp2)
+ else if (tparams && tparams1.length == tparams2.length)
+ unify(res1 :: tparams1.map(_.info), res2 :: tparams2.map(_.info), env, strict)
else
unify(res1, res2, env, strict)
- case (PolyType(_, res), other) => unify(res, other, env, strict)
- case (ThisType(_), ThisType(_)) => env
- case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
- case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
- case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
- case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
- case (RefinedType(_, _), RefinedType(_, _)) => env
- case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
- case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
+ case (PolyType(_, res), other) => unify(res, other, env, strict)
+ case (ThisType(_), ThisType(_)) => env
+ case (_, SingleType(_, _)) => unify(tp1, tp2.underlying, env, strict)
+ case (SingleType(_, _), _) => unify(tp1.underlying, tp2, env, strict)
+ case (ThisType(_), _) => unify(tp1.widen, tp2, env, strict)
+ case (_, ThisType(_)) => unify(tp1, tp2.widen, env, strict)
+ case (RefinedType(_, _), RefinedType(_, _)) => env
+ case (AnnotatedType(_, tp1, _), tp2) => unify(tp2, tp1, env, strict)
+ case (ExistentialType(_, res1), _) => unify(tp2, res1, env, strict)
+ case (TypeBounds(lo1, hi1), TypeBounds(lo2, hi2)) => unify(List(lo1, hi1), List(lo2, hi2), env, strict)
case _ =>
debuglog("don't know how to unify %s [%s] with %s [%s]".format(tp1, tp1.getClass, tp2, tp2.getClass))
env
diff --git a/test/files/run/t5629.check b/test/files/run/t5629.check
new file mode 100644
index 0000000000..6a2d630f4e
--- /dev/null
+++ b/test/files/run/t5629.check
@@ -0,0 +1,2 @@
+int child got: 33
+any child got: 33
diff --git a/test/files/run/t5629.scala b/test/files/run/t5629.scala
new file mode 100644
index 0000000000..69feddd3a5
--- /dev/null
+++ b/test/files/run/t5629.scala
@@ -0,0 +1,36 @@
+
+
+
+import scala.{specialized => spec}
+
+
+
+trait GrandParent[@spec(Int) -A] {
+ def foo(a: A): Unit
+ def bar[B <: A](b: B): Unit = println("grandparent got: %s" format b)
+}
+
+
+trait Parent[@spec(Int) -A] extends GrandParent[A] {
+ def foo(a: A) = bar(a)
+}
+
+
+class IntChild extends Parent[Int] {
+ override def bar[B <: Int](b: B): Unit = println("int child got: %s" format b)
+}
+
+
+class AnyChild extends Parent[Any] {
+ override def bar[B <: Any](b: B): Unit = println("any child got: %s" format b)
+}
+
+
+object Test {
+
+ def main(args: Array[String]) {
+ new IntChild().foo(33)
+ new AnyChild().foo(33)
+ }
+
+}
diff --git a/test/files/run/t5629b.check b/test/files/run/t5629b.check
new file mode 100644
index 0000000000..1bc0248c3d
--- /dev/null
+++ b/test/files/run/t5629b.check
@@ -0,0 +1,10 @@
+=== pf(1):
+MySmartPF.apply entered...
+newPF.applyOrElse entered...
+default
+scala.MatchError: () (of class scala.runtime.BoxedUnit)
+=== pf(42):
+MySmartPF.apply entered...
+newPF.applyOrElse entered...
+ok
+=== done
diff --git a/test/files/run/t5629b.scala b/test/files/run/t5629b.scala
new file mode 100644
index 0000000000..6c908081b9
--- /dev/null
+++ b/test/files/run/t5629b.scala
@@ -0,0 +1,41 @@
+
+
+
+
+
+object Test extends App {
+
+ trait MyPF[@specialized(Int) -A] extends (A => Unit) {
+ def isDefinedAt(x: A): Boolean
+ def applyOrElse[A1 <: A](x: A1, default: A1 => Unit): Unit = {
+ println("MyPF.applyOrElse entered...")
+ if (isDefinedAt(x)) apply(x) else default(x)
+ }
+ }
+
+ trait MySmartPF[@specialized(Int) -A] extends MyPF[A] {
+ def apply(x: A): Unit = {
+ println("MySmartPF.apply entered...")
+ applyOrElse(x, { _: Any => throw new MatchError })
+ }
+ }
+
+ type T = Int
+ //type T = Any
+
+ def newPF(test: T): MyPF[T] = new MySmartPF[T] {
+ def isDefinedAt(x: T): Boolean = x != test
+ override def applyOrElse[A1 <: T](x: A1, default: A1 => Unit): Unit = {
+ println("newPF.applyOrElse entered...")
+ if (x != test) { println("ok"); () } else { println("default"); default(x) }
+ }
+ }
+
+ val pf = newPF(1)
+ println("=== pf(1):")
+ try { pf(1) } catch { case x => println(x) }
+ println("=== pf(42):")
+ pf(42)
+ println("=== done")
+
+}