Skip to content

Commit 3338d82

Browse files
committed
Fix error on if/match with phantoms of different lattices.
1 parent 4ffa991 commit 3338d82

File tree

3 files changed

+41
-13
lines changed

3 files changed

+41
-13
lines changed

compiler/src/dotty/tools/dotc/reporting/diagnostic/messages.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,9 +1267,9 @@ object messages {
12671267
hl"""|""".stripMargin
12681268
}
12691269

1270-
case class MatchPhantom()(implicit ctx: Context) extends Message(MatchPhantomID) {
1270+
case class MatchPhantom(tpdCase: tpd.CaseDef, expected: Type)(implicit ctx: Context) extends Message(MatchPhantomID) {
12711271
val kind = "Phantom restriction"
1272-
val msg = "Pattern matches cannot return phantom and non phantoms"
1272+
val msg = s"Pattern expected case to return a ${expected.show} but was ${tpdCase.tpe.show}"
12731273

12741274
val explanation =
12751275
hl"""|""".stripMargin
@@ -1284,9 +1284,13 @@ object messages {
12841284
hl"""|""".stripMargin
12851285
}
12861286

1287-
case class IfElsePhantom()(implicit ctx: Context) extends Message(IfElsePhantomID) {
1287+
case class IfElsePhantom(thenp: tpd.Tree, elsep: tpd.Tree)(implicit ctx: Context) extends Message(IfElsePhantomID) {
12881288
val kind = "Phantom restriction"
1289-
val msg = "Cannot yield a phantom type in one of the if branches and not in the other one."
1289+
val msg =
1290+
s"""if/else cannot have branches with types in different lattices:
1291+
| ${thenp.tpe.show} of lattice ${thenp.tpe.topType.show}
1292+
| ${elsep.tpe.show} of lattice ${elsep.tpe.topType.show}
1293+
""".stripMargin
12901294

12911295
val explanation =
12921296
hl"""|""".stripMargin

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,8 +658,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
658658
val cond1 = typed(tree.cond, defn.BooleanType)
659659
val thenp1 = typed(tree.thenp, pt.notApplied)
660660
val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied)
661-
if (thenp1.tpe.isPhantom != elsep1.tpe.isPhantom)
662-
ctx.error(IfElsePhantom(), tree.pos)
661+
if (thenp1.tpe.topType != elsep1.tpe.topType)
662+
ctx.error(IfElsePhantom(thenp1, elsep1), tree.pos)
663663
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
664664
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
665665
}
@@ -866,9 +866,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
866866

867867
val tpdCases = cases mapconserve (typedCase(_, pt, selType, gadtSyms))
868868

869-
val phantomBranches = tpdCases.count(_.body.tpe.isPhantom)
870-
if (phantomBranches != 0 && phantomBranches != tpdCases.size)
871-
ctx.error(MatchPhantom(), tpdCases.head.pos)
869+
if (tpdCases.nonEmpty) {
870+
val top = tpdCases.head.tpe.topType
871+
for (tpdCase <- tpdCases if tpdCase.tpe.topType != top)
872+
ctx.error(MatchPhantom(tpdCase, top), tpdCase.pos)
873+
}
872874

873875
tpdCases
874876
}

tests/neg/phantom-expr.scala

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11

22
class Foo {
33
import Boo._
4+
import Boo1._
45

56
type Blinky <: BooAny
67
type Inky <: BooAny
@@ -9,15 +10,36 @@ class Foo {
910
val inky = Boo.boo[Inky]
1011

1112
val b = true
12-
def fooIf1 = if (b) { blinky } else { "" } // error
13-
def fooIf2 = if (b) { "" } else { blinky } // error
13+
def fooIf1 =
14+
if (b) blinky // error
15+
else ""
1416

15-
def fooMatch1 = blinky match { case _: Blinky => () } // error
16-
def fooMatch2 = 1 match { case 1 => 2 case _ => blinky } // error
17+
def fooIf2 =
18+
if (b) "" // error
19+
else blinky
20+
21+
def fooIf3 =
22+
if (b) boo1 // error
23+
else blinky
24+
25+
def fooMatch1 = blinky match { // error
26+
case _: Blinky => ()
27+
}
28+
def fooMatch2 = 1 match { case 1 => 2
29+
case _ => blinky // error
30+
}
31+
def fooMatch3 = 1 match {
32+
case 1 => boo1
33+
case _ => blinky // error
34+
}
1735
}
1836

1937
object Boo extends Phantom {
2038
type BooAny = this.Any
2139
def boo[B <: BooAny]: B = assume[B]
2240
}
2341

42+
object Boo1 extends Phantom {
43+
type Boo1Any = this.Any
44+
def boo1: Boo1Any = assume[Boo1Any]
45+
}

0 commit comments

Comments
 (0)