From 5b7c0d108f2536c360b6797c4df8eecc886b125d Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 24 Jan 2018 14:46:51 +0100 Subject: [PATCH 1/2] Fix #2104: Instantiate unapply result type variables Type variables in an unapply result should be fully instantiated before nested pattern matches. This is analogous to instantiating the scrutinee type of a match. --- .../dotty/tools/dotc/typer/Applications.scala | 2 +- tests/pos/i2104.scala | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i2104.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Applications.scala b/compiler/src/dotty/tools/dotc/typer/Applications.scala index c731d2054b5c..4936986e88d3 100644 --- a/compiler/src/dotty/tools/dotc/typer/Applications.scala +++ b/compiler/src/dotty/tools/dotc/typer/Applications.scala @@ -920,6 +920,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic => val ownType = if (selType <:< unapplyArgType) { unapp.println(i"case 1 $unapplyArgType ${ctx.typerState.constraint}") + fullyDefinedType(unapplyArgType, "pattern selector", tree.pos) selType } else if (isSubTypeOfParent(unapplyArgType, selType)(ctx.addMode(Mode.GADTflexible))) { maximizeType(unapplyArgType) match { @@ -952,7 +953,6 @@ trait Applications extends Compatibility { self: Typer with Dynamic => ex"Pattern type $unapplyArgType is neither a subtype nor a supertype of selector type $selType", tree.pos) } - val dummyArg = dummyTreeOfType(ownType) val unapplyApp = typedExpr(untpd.TypedSplice(Apply(unapplyFn, dummyArg :: Nil))) val unapplyImplicits = unapplyApp match { diff --git a/tests/pos/i2104.scala b/tests/pos/i2104.scala new file mode 100644 index 000000000000..b2066d6daad4 --- /dev/null +++ b/tests/pos/i2104.scala @@ -0,0 +1,20 @@ +case class Pair[A, B](_1: A, _2: B) + +trait Cons[+H, +T] + +object Cons { + def apply[H, T](h: H, t: T): Cons[H, T] = ??? + def unapply[H, T](t: Cons[H, T]): Option[Pair[H, T]] = ??? +} + + + +object Test { + def main(args: Array[String]): Unit = { + Cons(Option(1), None) match { + case Cons(Some(i), None) => + i: Int // error: found: Any(i), requires: Int + assert(i == 1) + } + } +} From 540b01119295a04c7e29f5430064a6214d3ebfb6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Wed, 24 Jan 2018 16:30:51 +0100 Subject: [PATCH 2/2] Fix ErrorMessages test --- .../test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala index f053d8705030..57f6638fccb0 100644 --- a/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala +++ b/compiler/test/dotty/tools/dotc/reporting/ErrorMessagesTests.scala @@ -811,8 +811,7 @@ class ErrorMessagesTests extends ErrorMessagesTest { .expect { (ictx, messages) => implicit val ctx: Context = ictx - assertMessageCount(1, messages) - val AnonymousFunctionMissingParamType(param, args, _, pt) :: Nil = messages + val AnonymousFunctionMissingParamType(param, args, _, pt) = messages.last assertEquals("x$1", param.show) assertEquals(s"List(ValDef(${param.show},TypeTree,EmptyTree))", args.toString) assertEquals("?", pt.show)