Skip to content

Fix #6255: Don't check unreachability for Expr[T] #6260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 17 additions & 13 deletions compiler/src/dotty/tools/dotc/transform/patmat/Space.scala
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
* C --> C if current owner is C !!!
*
*/
def showType(tp: Type): String = {
def showType(tp: Type, showTypeArgs: Boolean = false): String = {
val enclosingCls = ctx.owner.enclosingClass

def isOmittable(sym: Symbol) =
Expand All @@ -564,25 +564,25 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
case _ => tp.show
}

def refine(tp: Type): String = tp match {
def refine(tp: Type): String = tp.stripAnnots match {
case tp: RefinedType => refine(tp.parent)
case tp: AppliedType => refine(tp.typeConstructor)
case tp: AppliedType =>
refine(tp.typeConstructor) + (
if (showTypeArgs) tp.argInfos.map(refine).mkString("[", ",", "]")
else ""
)
case tp: ThisType => refine(tp.tref)
case tp: NamedType =>
val pre = refinePrefix(tp.prefix)
if (tp.name == tpnme.higherKinds) pre
else if (pre.isEmpty) tp.name.show.stripSuffix("$")
else pre + "." + tp.name.show.stripSuffix("$")
case tp: OrType => refine(tp.tp1) + " | " + refine(tp.tp2)
case _: TypeBounds => "_"
case _ => tp.show.stripSuffix("$")
}

val text = tp.stripAnnots match {
case tp: OrType => showType(tp.tp1) + " | " + showType(tp.tp2)
case tp => refine(tp)
}

if (text.isEmpty) enclosingCls.show.stripSuffix("$")
else text
refine(tp)
}

/** Whether the counterexample is satisfiable. The space is flattened and non-empty. */
Expand Down Expand Up @@ -646,7 +646,7 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
else if (tp.classSymbol.is(CaseClass) && !hasCustomUnapply(tp.classSymbol))
// use constructor syntax for case class
showType(tp) + params(tp).map(_ => "_").mkString("(", ", ", ")")
else if (decomposed) "_: " + showType(tp)
else if (decomposed) "_: " + showType(tp, showTypeArgs = true)
else "_"
case Prod(tp, fun, sym, params, _) =>
if (ctx.definitions.isTupleType(tp))
Expand Down Expand Up @@ -677,7 +677,6 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
}) ||
tpw.isRef(defn.BooleanClass) ||
tpw.typeSymbol.is(JavaEnum) ||
canDecompose(tpw) ||
(defn.isTupleType(tpw) && tpw.argInfos.exists(isCheckable(_)))
}

Expand Down Expand Up @@ -719,7 +718,12 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
}

private def redundancyCheckable(sel: Tree): Boolean =
!sel.tpe.hasAnnotation(defn.UncheckedAnnot)
// Ignore Expr for unreachability as a special case.
// Quote patterns produce repeated calls to the same unapply method, but with different implicit parameters.
// Since we assume that repeated calls to the same unapply method overlap
// and implicit parameters cannot normally differ between two patterns in one `match`,
// the easiest solution is just to ignore Expr.
!sel.tpe.hasAnnotation(defn.UncheckedAnnot) && !sel.tpe.widen.isRef(defn.QuotedExprClass)

def checkRedundancy(_match: Match): Unit = {
val Match(sel, cases) = _match
Expand Down
2 changes: 1 addition & 1 deletion tests/patmat/3144.check
Original file line number Diff line number Diff line change
@@ -1 +1 @@
6: Pattern Match Exhaustivity: _: Foo
6: Pattern Match Exhaustivity: _: Foo[T]
2 changes: 1 addition & 1 deletion tests/patmat/i4226b.check
Original file line number Diff line number Diff line change
@@ -1 +1 @@
11: Pattern Match Exhaustivity: Just(_), _: Empty
11: Pattern Match Exhaustivity: Just(_), _: Empty[Int]
7 changes: 7 additions & 0 deletions tests/patmat/i6255.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Foo {
def foo(x: quoted.Expr[Int]) given scala.tasty.Reflection: Unit = x match {
case '{ 1 } =>
case '{ 2 } =>
case _ =>
}
}
1 change: 1 addition & 0 deletions tests/patmat/i6255b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2: Pattern Match Exhaustivity: _: Expr[Int]
6 changes: 6 additions & 0 deletions tests/patmat/i6255b.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Foo {
def foo(x: quoted.Expr[Int]) given scala.tasty.Reflection: Unit = x match {
case '{ 1 } =>
case '{ 2 } =>
}
}
2 changes: 1 addition & 1 deletion tests/patmat/t9779.check
Original file line number Diff line number Diff line change
@@ -1 +1 @@
10: Pattern Match Exhaustivity: _: a.Elem
10: Pattern Match Exhaustivity: _: a.Elem[_]