From 0cffdf38d9e2d88e66d8649d317f8815716b2748 Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Fri, 2 Mar 2012 17:58:08 +0100 Subject: SI-5189 1/2: inferConstrInst uses correct variance fixed concurrent.impl.Promise by making FState invariant (it would be unsound to make it covariant) --- src/compiler/scala/tools/nsc/typechecker/Infer.scala | 2 +- src/library/scala/concurrent/impl/Promise.scala | 10 ++++++++-- test/files/neg/t5189.check | 6 ++++++ test/files/neg/t5189.scala | 5 +++++ 4 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 test/files/neg/t5189.check create mode 100644 test/files/neg/t5189.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index 310198ec0c..7b72169ba9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1068,7 +1068,7 @@ trait Infer { try { // debuglog("TVARS "+ (tvars map (_.constr))) // look at the argument types of the primary constructor corresponding to the pattern - val variances = undetparams map varianceInType(ctorTp) + val variances = undetparams map varianceInType(ctorTp.paramTypes.headOption getOrElse ctorTp) val targs = solvedTypes(tvars, undetparams, variances, true, lubDepth(List(resTp, pt))) // checkBounds(tree, NoPrefix, NoSymbol, undetparams, targs, "inferred ") // no checkBounds here. If we enable it, test bug602 fails. diff --git a/src/library/scala/concurrent/impl/Promise.scala b/src/library/scala/concurrent/impl/Promise.scala index 585f71f3cf..0087b71ea8 100644 --- a/src/library/scala/concurrent/impl/Promise.scala +++ b/src/library/scala/concurrent/impl/Promise.scala @@ -80,8 +80,10 @@ object Promise { def EmptyPending[T](): FState[T] = emptyPendingValue.asInstanceOf[FState[T]] /** Represents the internal state. + * + * [adriaan] it's unsound to make FState covariant (tryComplete won't type check) */ - sealed trait FState[+T] { def value: Option[Try[T]] } + sealed trait FState[T] { def value: Option[Try[T]] } case class Pending[T](listeners: List[Try[T] => Any] = Nil) extends FState[T] { def value: Option[Try[T]] = None @@ -155,7 +157,11 @@ object Promise { def tryComplete(v: Try[T]): List[Try[T] => Any] = { getState match { case cur @ Pending(listeners) => - if (updateState(cur, if (v.isFailure) Failure(Some(v.asInstanceOf[util.Failure[T]])) else Success(Some(v.asInstanceOf[util.Success[T]])))) listeners + val newState = + if (v.isFailure) Failure(Some(v.asInstanceOf[util.Failure[T]])) + else Success(Some(v.asInstanceOf[util.Success[T]])) + + if (updateState(cur, newState)) listeners else tryComplete(v) case _ => null } diff --git a/test/files/neg/t5189.check b/test/files/neg/t5189.check new file mode 100644 index 0000000000..7762f465dc --- /dev/null +++ b/test/files/neg/t5189.check @@ -0,0 +1,6 @@ +t5189.scala:3: error: type mismatch; + found : Nothing => Any + required: Any => Any + def f(x: Any): Any => Any = x match { case Foo(bar) => bar } + ^ +one error found \ No newline at end of file diff --git a/test/files/neg/t5189.scala b/test/files/neg/t5189.scala new file mode 100644 index 0000000000..19e8e74667 --- /dev/null +++ b/test/files/neg/t5189.scala @@ -0,0 +1,5 @@ +class TestNeg1 { + case class Foo[T, U](f: T => U) + def f(x: Any): Any => Any = x match { case Foo(bar) => bar } + // uh-oh, Any => Any should be Nothing => Any. +} -- cgit v1.2.3