From 9dca4a61a6d903a5de0072bca657dbf151d437ec Mon Sep 17 00:00:00 2001 From: Yichen Xu Date: Tue, 31 May 2022 08:08:47 +0800 Subject: [PATCH 1/2] Consider GADT upper bounds when upcasting the scrutinee type (cherry picked from commit 172e957422f31ab0b5305e5127a52203cc9ea409) --- .../dotc/core/PatternTypeConstrainer.scala | 27 ++++++++++++++----- tests/pos/i15274.orig.scala | 21 +++++++++++++++ tests/pos/i15274.scala | 6 +++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 tests/pos/i15274.orig.scala create mode 100644 tests/pos/i15274.scala diff --git a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala index ac7cbf6c36a6..de2d3d658508 100644 --- a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala +++ b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala @@ -138,13 +138,28 @@ trait PatternTypeConstrainer { self: TypeComparer => val andType = buildAndType(baseClasses) !andType.exists || constrainPatternType(pat, andType) case _ => - val upcasted: Type = scrut match { - case scrut: TypeProxy => scrut.superType - case _ => NoType + def tryGadtBounds = scrut match { + case scrut: TypeRef => + ctx.gadt.bounds(scrut.symbol) match { + case tb: TypeBounds => + val hi = tb.hi + constrainPatternType(pat, hi) + case null => false + } + case _ => false } - if (upcasted.exists) - tryConstrainSimplePatternType(pat, upcasted) || constrainUpcasted(upcasted) - else true + + def trySuperType = + val upcasted: Type = scrut match { + case scrut: TypeProxy => + scrut.superType + case _ => NoType + } + if (upcasted.exists) + tryConstrainSimplePatternType(pat, upcasted) || constrainUpcasted(upcasted) + else true + + tryGadtBounds || trySuperType } } diff --git a/tests/pos/i15274.orig.scala b/tests/pos/i15274.orig.scala new file mode 100644 index 000000000000..5d6887028f4f --- /dev/null +++ b/tests/pos/i15274.orig.scala @@ -0,0 +1,21 @@ +enum Format[A]: + case Str[Next](next: Format[Next]) extends Format[(String, Next)] + case Num[Next](next: Format[Next]) extends Format[(Int, Next)] + case Constant[Next](value: String, next: Format[Next]) extends Format[Next] + case Done extends Format[Unit] + +def printf[A](format: Format[A], params: A): Unit = (format, params) match + case (Format.Done, ()) => + () + + case (Format.Constant(value, next), params) => + println(value) + printf(next, params) + + case (Format.Str(next), (str, rest)) => + println(str) + printf(next, rest) + + case (Format.Num(next), (i, rest)) => + println(i) + printf(next, rest) diff --git a/tests/pos/i15274.scala b/tests/pos/i15274.scala new file mode 100644 index 000000000000..2862fd8f8cbc --- /dev/null +++ b/tests/pos/i15274.scala @@ -0,0 +1,6 @@ +enum Format[A]: + case Str[Next](next: Format[Next]) extends Format[(String, Next)] + +def printf[A](format: Format[A], params: A): Unit = (format, params) match + case (Format.Str(next), (str, rest)) => + val s: String = str From 1c3a2866ca450716af07c2827883d448bdf70a78 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 7 Jun 2022 10:38:15 +0100 Subject: [PATCH 2/2] Constrain patterns by both GADT upper bound & upcast --- .../src/dotty/tools/dotc/core/PatternTypeConstrainer.scala | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala index de2d3d658508..119c3342fa81 100644 --- a/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala +++ b/compiler/src/dotty/tools/dotc/core/PatternTypeConstrainer.scala @@ -144,9 +144,9 @@ trait PatternTypeConstrainer { self: TypeComparer => case tb: TypeBounds => val hi = tb.hi constrainPatternType(pat, hi) - case null => false + case null => true } - case _ => false + case _ => true } def trySuperType = @@ -159,7 +159,7 @@ trait PatternTypeConstrainer { self: TypeComparer => tryConstrainSimplePatternType(pat, upcasted) || constrainUpcasted(upcasted) else true - tryGadtBounds || trySuperType + tryGadtBounds && trySuperType } }