summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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