Skip to content

Commit 05b667c

Browse files
committed
Fix #4661: Missing unreachable case warnings
1 parent ab84cfb commit 05b667c

File tree

5 files changed

+51
-64
lines changed

5 files changed

+51
-64
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala

Lines changed: 20 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
5757
def idClassTag: ClassTag[Id] = implicitly[ClassTag[Id]]
5858

5959
object Id extends IdExtractor {
60-
def unapply(x: Id): Option[String] = x match {
61-
case x: untpd.Ident => Some(x.name.toString) // TODO how to make sure it is not a Ident or TypeIdent? Check x.tpe?
62-
case _ => None
63-
}
60+
def unapply(x: Id): Option[String] = Some(x.name.toString)
6461
}
6562

6663
// ===== Trees ====================================================
@@ -77,10 +74,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
7774
def packageClauseClassTag: ClassTag[PackageClause] = implicitly[ClassTag[PackageClause]]
7875

7976
object PackageClause extends PackageClauseExtractor {
80-
def unapply(x: PackageClause)(implicit ctx: Context): Option[(Term, List[Tree])] = x match {
81-
case x: tpd.PackageDef @unchecked => Some((x.pid, x.stats))
82-
case _ => None
83-
}
77+
def unapply(x: PackageClause)(implicit ctx: Context): Option[(Term, List[Tree])] = Some((x.pid, x.stats))
8478
}
8579

8680
def PackageClauseDeco(pack: PackageClause): PackageClauseAPI = new PackageClauseAPI {
@@ -96,10 +90,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
9690
def importClassTag: ClassTag[Import] = implicitly[ClassTag[Import]]
9791

9892
object Import extends ImportExtractor {
99-
def unapply(x: Import)(implicit ctx: Context): Option[(Term, List[ImportSelector])] = x match {
100-
case x: tpd.Import @unchecked => Some((x.expr, x.selectors))
101-
case _ => None
102-
}
93+
def unapply(x: Import)(implicit ctx: Context): Option[(Term, List[ImportSelector])] = Some((x.expr, x.selectors))
10394
}
10495

10596
def ImportDeco(imp: Import): ImportAPI = new ImportAPI {
@@ -206,10 +197,8 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
206197
def defDefClassTag: ClassTag[DefDef] = implicitly[ClassTag[DefDef]]
207198

208199
object DefDef extends DefDefExtractor {
209-
def unapply(x: DefDef)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = x match {
210-
case x: tpd.DefDef @unchecked =>
211-
Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs)))
212-
case _ => None
200+
def unapply(x: DefDef)(implicit ctx: Context): Option[(String, List[TypeDef], List[List[ValDef]], TypeTree, Option[Term])] = {
201+
Some((x.name.toString, x.tparams, x.vparamss, x.tpt, optional(x.rhs)))
213202
}
214203
}
215204

@@ -227,10 +216,8 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
227216
def valDefClassTag: ClassTag[ValDef] = implicitly[ClassTag[ValDef]]
228217

229218
object ValDef extends ValDefExtractor {
230-
def unapply(x: ValDef)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = x match {
231-
case x: tpd.ValDef @unchecked =>
232-
Some((x.name.toString, x.tpt, optional(x.rhs)))
233-
case _ => None
219+
def unapply(x: ValDef)(implicit ctx: Context): Option[(String, TypeTree, Option[Term])] = {
220+
Some((x.name.toString, x.tpt, optional(x.rhs)))
234221
}
235222
}
236223

@@ -273,10 +260,8 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
273260
def packageDefClassTag: ClassTag[PackageDef] = implicitly[ClassTag[PackageDef]]
274261

275262
object PackageDef extends PackageDefExtractor {
276-
def unapply(x: PackageDef)(implicit ctx: Context): Option[(String, PackageDef)] = x match {
277-
case x: PackageDefinition =>
278-
Some((x.symbol.name.toString, FromSymbol.packageDef(x.symbol.owner)))
279-
case _ => None
263+
def unapply(x: PackageDef)(implicit ctx: Context): Option[(String, PackageDef)] = {
264+
Some((x.symbol.name.toString, FromSymbol.packageDef(x.symbol.owner)))
280265
}
281266
}
282267

@@ -546,11 +531,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
546531
}
547532

548533
object CaseDef extends CaseDefExtractor {
549-
def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = x match {
550-
case x: tpd.CaseDef @unchecked =>
551-
Some(x.pat, optional(x.guard), x.body)
552-
case _ => None
553-
}
534+
def unapply(x: CaseDef): Option[(Pattern, Option[Term], Term)] = Some(x.pat, optional(x.guard), x.body)
554535
}
555536

556537
// ----- Patterns -------------------------------------------------
@@ -916,30 +897,24 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
916897
}
917898

918899
object RecursiveType extends RecursiveTypeExtractor {
919-
def unapply(x: RecursiveType)(implicit ctx: Context): Option[Type] = x match {
920-
case tp: Types.RecType => Some(tp.underlying.stripTypeVar)
921-
case _ => None
922-
}
900+
def unapply(x: RecursiveType)(implicit ctx: Context): Option[Type] = Some(x.underlying.stripTypeVar)
923901
}
924902

925903
object MethodType extends MethodTypeExtractor {
926-
def unapply(x: MethodType)(implicit ctx: Context): Option[(List[String], List[Type], Type)] = x match {
927-
case x: MethodType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
928-
case _ => None
904+
def unapply(x: MethodType)(implicit ctx: Context): Option[(List[String], List[Type], Type)] = {
905+
Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
929906
}
930907
}
931908

932909
object PolyType extends PolyTypeExtractor {
933-
def unapply(x: PolyType)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match {
934-
case x: PolyType => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
935-
case _ => None
910+
def unapply(x: PolyType)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = {
911+
Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
936912
}
937913
}
938914

939915
object TypeLambda extends TypeLambdaExtractor {
940-
def unapply(x: TypeLambda)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = x match {
941-
case x: TypeLambda => Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
942-
case _ => None
916+
def unapply(x: TypeLambda)(implicit ctx: Context): Option[(List[String], List[TypeBounds], Type)] = {
917+
Some(x.paramNames.map(_.toString), x.paramInfos, x.resType)
943918
}
944919
}
945920

@@ -952,10 +927,7 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
952927
def typeBoundsClassTag: ClassTag[TypeBounds] = implicitly[ClassTag[TypeBounds]]
953928

954929
object TypeBounds extends TypeBoundsExtractor {
955-
def unapply(x: TypeBounds)(implicit ctx: Context): Option[(Type, Type)] = x match {
956-
case x: Types.TypeBounds => Some(x.lo, x.hi)
957-
case _ => None
958-
}
930+
def unapply(x: TypeBounds)(implicit ctx: Context): Option[(Type, Type)] = Some(x.lo, x.hi)
959931
}
960932

961933
def TypeBoundsDeco(tpe: TypeBounds): TypeBoundsAPI = new TypeBoundsAPI {
@@ -987,17 +959,11 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s
987959
object Constant extends ConstantModule {
988960

989961
object Unit extends UnitExtractor {
990-
def unapply(x: Constant): Boolean = x match {
991-
case x: Constants.Constant => x.tag == Constants.UnitTag
992-
case _ => false
993-
}
962+
def unapply(x: Constant): Boolean = x.tag == Constants.UnitTag
994963
}
995964

996965
object Null extends NullExtractor {
997-
def unapply(x: Constant): Boolean = x match {
998-
case x: Constants.Constant => x.tag == Constants.NullTag
999-
case _ => false
1000-
}
966+
def unapply(x: Constant): Boolean = x.tag == Constants.NullTag
1001967
}
1002968

1003969
object Boolean extends BooleanExtractor {

compiler/src/dotty/tools/dotc/transform/patmat/Space.scala

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,22 @@ class SpaceEngine(implicit ctx: Context) extends SpaceLogic {
293293
private val nullSpace = Typ(nullType)
294294

295295
override def intersectUnrelatedAtomicTypes(tp1: Type, tp2: Type) = {
296-
val and = AndType(tp1, tp2)
297-
// Precondition: !(tp1 <:< tp2) && !(tp2 <:< tp1)
298-
// Then, no leaf of the and-type tree `and` is a subtype of `and`.
299-
val res = inhabited(and)
296+
// Precondition: !isSubType(tp1, tp2) && !isSubType(tp2, tp1)
297+
if (tp1 == nullType || tp2 == nullType) {
298+
// Since projections of types don't include null, intersection with null is empty.
299+
Empty
300+
} else {
301+
val and = AndType(tp1, tp2)
302+
// Then, no leaf of the and-type tree `and` is a subtype of `and`.
303+
val res = inhabited(and)
300304

301-
debug.println(s"atomic intersection: ${and.show} = ${res}")
305+
debug.println(s"atomic intersection: ${and.show} = ${res}")
302306

303-
if (!res) Empty
304-
else if (tp1.isSingleton) Typ(tp1, true)
305-
else if (tp2.isSingleton) Typ(tp2, true)
306-
else Typ(and, true)
307+
if (!res) Empty
308+
else if (tp1.isSingleton) Typ(tp1, true)
309+
else if (tp2.isSingleton) Typ(tp2, true)
310+
else Typ(and, true)
311+
}
307312
}
308313

309314
/** Whether the extractor is irrefutable */

tests/patmat/file.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ object Test {
1212
case pf: PlainFile =>
1313
case _ =>
1414
}
15-
}
15+
}

tests/patmat/t4661.check

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
9: Match case Unreachable
2+
10: Match case Unreachable
3+
11: Match case Unreachable

tests/patmat/t4661.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
trait Foo
2+
class One extends Foo
3+
class Two extends Foo
4+
class Three extends Foo
5+
6+
object Test {
7+
def test(f: Foo) = f match {
8+
case f: Foo =>
9+
case f: One =>
10+
case f: Two =>
11+
case f: Three =>
12+
}
13+
}

0 commit comments

Comments
 (0)