Skip to content

Commit 09205df

Browse files
committed
Fix error on if/match with phantoms of different lattices.
1 parent 68e5486 commit 09205df

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
@@ -1264,9 +1264,9 @@ object messages {
12641264
hl"""|""".stripMargin
12651265
}
12661266

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

12711271
val explanation =
12721272
hl"""|""".stripMargin
@@ -1281,9 +1281,13 @@ object messages {
12811281
hl"""|""".stripMargin
12821282
}
12831283

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

12881292
val explanation =
12891293
hl"""|""".stripMargin

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
665665
val cond1 = typed(tree.cond, defn.BooleanType)
666666
val thenp1 = typed(tree.thenp, pt.notApplied)
667667
val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied)
668-
if (thenp1.tpe.isPhantom != elsep1.tpe.isPhantom)
669-
ctx.error(IfElsePhantom(), tree.pos)
668+
if (thenp1.tpe.topType != elsep1.tpe.topType)
669+
ctx.error(IfElsePhantom(thenp1, elsep1), tree.pos)
670670
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
671671
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
672672
}
@@ -872,9 +872,11 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
872872

873873
val tpdCases = cases mapconserve (typedCase(_, pt, selType, gadtSyms))
874874

875-
val phantomBranches = tpdCases.count(_.body.tpe.isPhantom)
876-
if (phantomBranches != 0 && phantomBranches != tpdCases.size)
877-
ctx.error(MatchPhantom(), tpdCases.head.pos)
875+
if (tpdCases.nonEmpty) {
876+
val top = tpdCases.head.tpe.topType
877+
for (tpdCase <- tpdCases if tpdCase.tpe.topType != top)
878+
ctx.error(MatchPhantom(tpdCase, top), tpdCase.pos)
879+
}
878880

879881
tpdCases
880882
}

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)