summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-07-28 22:26:57 +0000
committerPaul Phillips <paulp@improving.org>2011-07-28 22:26:57 +0000
commit5bbb198b246f43b80dba8f4466862b2ca8b9a9cb (patch)
tree0fbe11c29eb9e14f32a5fb6cb5d154a762b29b7a
parentcee5d977cbc2fff7c919a2d3026b81bd23120d9d (diff)
downloadscala-5bbb198b246f43b80dba8f4466862b2ca8b9a9cb.tar.gz
scala-5bbb198b246f43b80dba8f4466862b2ca8b9a9cb.tar.bz2
scala-5bbb198b246f43b80dba8f4466862b2ca8b9a9cb.zip
Expression type argument instantiation should n...
Expression type argument instantiation should not fail in a context expecting Unit if there is any valid instantiation, because value discarding should kick in and offer a literal (). Closes SI-4853, review by odersky.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala25
-rw-r--r--test/files/pos/bug4853.scala12
2 files changed, 30 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 185529ed74..13e0f13d4c 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -882,7 +882,10 @@ trait Typers extends Modes {
typed(atPos(tree.pos)(Select(qual, nme.apply)), mode, pt)
} else if (!context.undetparams.isEmpty && !inPolyMode(mode)) { // (9)
assert(!inHKMode(mode)) //@M
- instantiate(tree, mode, pt)
+ if ((mode & (EXPRmode | FUNmode)) == EXPRmode && (pt.typeSymbol == UnitClass))
+ instantiateExpectingUnit(tree, mode)
+ else
+ instantiate(tree, mode, pt)
} else if (tree.tpe <:< pt) {
tree
} else {
@@ -969,16 +972,24 @@ trait Typers extends Modes {
}
}
- /**
- * @param tree ...
- * @param mode ...
- * @param pt ...
- * @return ...
- */
def instantiate(tree: Tree, mode: Int, pt: Type): Tree = {
inferExprInstance(tree, context.extractUndetparams(), pt)
adapt(tree, mode, pt)
}
+ /** If the expected type is Unit: try instantiating type arguments
+ * with expected type Unit, but if that fails, try again with pt = WildcardType
+ * and discard the expression.
+ */
+ def instantiateExpectingUnit(tree: Tree, mode: Int): Tree = {
+ val savedUndetparams = context.undetparams
+ silent(_.instantiate(tree, mode, UnitClass.tpe)) match {
+ case t: Tree => t
+ case _ =>
+ context.undetparams = savedUndetparams
+ val valueDiscard = atPos(tree.pos)(Block(List(instantiate(tree, mode, WildcardType)), Literal(())))
+ typed(valueDiscard, mode, UnitClass.tpe)
+ }
+ }
def adaptToMember(qual: Tree, searchTemplate: Type): Tree = {
var qtpe = qual.tpe.widen
diff --git a/test/files/pos/bug4853.scala b/test/files/pos/bug4853.scala
new file mode 100644
index 0000000000..c91f2d6b05
--- /dev/null
+++ b/test/files/pos/bug4853.scala
@@ -0,0 +1,12 @@
+object Animal {
+ def main(args: Array[String]) { new Animal[Awake].goToSleep }
+}
+
+class Animal[A <: AwakeOrAsleep] {
+ def goToSleep[B >: A <: Awake]: Animal[Asleep] = new Animal[Asleep]
+ def wakeUp[B >: A <: Asleep]: Animal[Awake] = new Animal[Awake]
+}
+
+sealed trait AwakeOrAsleep
+trait Awake extends AwakeOrAsleep
+trait Asleep extends AwakeOrAsleep