diff options
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 25 | ||||
-rw-r--r-- | test/files/pos/bug4853.scala | 12 |
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 |