Skip to content

Commit f805aff

Browse files
committed
Move phantom universe checks from Typer to TypeAssigner.
1 parent 1ee5ff5 commit f805aff

File tree

2 files changed

+28
-54
lines changed

2 files changed

+28
-54
lines changed

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

+26-5
Original file line numberDiff line numberDiff line change
@@ -399,8 +399,10 @@ trait TypeAssigner {
399399
def assignType(tree: untpd.Inlined, bindings: List[Tree], expansion: Tree)(implicit ctx: Context) =
400400
tree.withType(avoidingType(expansion, bindings))
401401

402-
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) =
402+
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) = {
403+
checkSameUniverse(thenp, elsep, "be combined in branches of if/else", tree.pos)
403404
tree.withType(thenp.tpe | elsep.tpe)
405+
}
404406

405407
def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context) =
406408
tree.withType(
@@ -410,8 +412,15 @@ trait TypeAssigner {
410412
def assignType(tree: untpd.CaseDef, body: Tree)(implicit ctx: Context) =
411413
tree.withType(body.tpe)
412414

413-
def assignType(tree: untpd.Match, cases: List[CaseDef])(implicit ctx: Context) =
415+
def assignType(tree: untpd.Match, cases: List[CaseDef])(implicit ctx: Context) = {
416+
if (tree.selector.typeOpt.isPhantom)
417+
ctx.error("Cannot pattern match on phantoms", tree.selector.pos)
418+
if (cases.nonEmpty) {
419+
val head = cases.head
420+
cases.tail.foreach(c => checkSameUniverse(head, c, "be combined in branches of a match", c.pos))
421+
}
414422
tree.withType(ctx.typeComparer.lub(cases.tpes))
423+
}
415424

416425
def assignType(tree: untpd.Return)(implicit ctx: Context) =
417426
tree.withType(defn.NothingType)
@@ -431,11 +440,15 @@ trait TypeAssigner {
431440
def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context) =
432441
tree.withType(ref.tpe)
433442

434-
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
443+
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
444+
checkSameUniverse(left, right, "be combined in `&`", tree.pos)
435445
tree.withType(left.tpe & right.tpe)
446+
}
436447

437-
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
448+
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
449+
checkSameUniverse(left, right, "be combined in `|`", tree.pos)
438450
tree.withType(left.tpe | right.tpe)
451+
}
439452

440453
/** Assign type of RefinedType.
441454
* Refinements are typed as if they were members of refinement class `refineCls`.
@@ -465,8 +478,10 @@ trait TypeAssigner {
465478
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) =
466479
tree.withType(ExprType(result.tpe))
467480

468-
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) =
481+
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) = {
482+
checkSameUniverse(lo, hi, "be combined in type bounds.", tree.pos)
469483
tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe))
484+
}
470485

471486
def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context) =
472487
tree.withType(NamedType.withFixedSym(NoPrefix, sym))
@@ -511,6 +526,12 @@ trait TypeAssigner {
511526

512527
def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context) =
513528
tree.withType(pid.symbol.valRef)
529+
530+
private def checkSameUniverse(tree1: Tree, tree2: Tree, relationship: => String, pos: Position)(implicit ctx: Context) = {
531+
if (tree1.tpe.topType != tree2.tpe.topType)
532+
ctx.error(ex"${tree1.tpe} and ${tree2.tpe} are in different universes. They cannot $relationship", pos)
533+
}
534+
514535
}
515536

516537
object TypeAssigner extends TypeAssigner

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

+2-49
Original file line numberDiff line numberDiff line change
@@ -661,12 +661,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
661661
val cond1 = typed(tree.cond, defn.BooleanType)
662662
val thenp1 = typed(tree.thenp, pt.notApplied)
663663
val elsep1 = typed(tree.elsep orElse (untpd.unitLiteral withPos tree.pos), pt.notApplied)
664-
if (thenp1.tpe.topType != elsep1.tpe.topType) {
665-
ctx.error(s"""if/else cannot have branches with types in different lattices:
666-
| ${thenp1.tpe.show} of lattice ${thenp1.tpe.topType.show}
667-
| ${elsep1.tpe.show} of lattice ${elsep1.tpe.topType.show}
668-
""".stripMargin, tree.pos)
669-
}
670664
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
671665
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
672666
}
@@ -839,8 +833,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
839833
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt)
840834
case _ =>
841835
val sel1 = typedExpr(tree.selector)
842-
if (sel1.tpe.isPhantom)
843-
ctx.error("Cannot pattern match on phantoms", sel1.pos)
844836
val selType = widenForMatchSelector(
845837
fullyDefinedType(sel1.tpe, "pattern selector", tree.pos))
846838

@@ -872,15 +864,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
872864
accu(Set.empty, selType)
873865
}
874866

875-
val tpdCases = cases mapconserve (typedCase(_, pt, selType, gadtSyms))
876-
877-
if (tpdCases.nonEmpty) {
878-
val top = tpdCases.head.tpe.topType
879-
for (tpdCase <- tpdCases if tpdCase.tpe.topType != top)
880-
ctx.error(s"Pattern expected case to return a ${top.show} but was ${tpdCase.tpe.show}", tpdCase.pos)
881-
}
882-
883-
tpdCases
867+
cases mapconserve (typedCase(_, pt, selType, gadtSyms))
884868
}
885869

886870
/** Type a case. Overridden in ReTyper, that's why it's separate from
@@ -1673,38 +1657,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
16731657

16741658
def typedExpr(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree =
16751659
typed(tree, pt)(ctx retractMode Mode.PatternOrType)
1676-
def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = {
1677-
// todo: retract mode between Type and Pattern?
1678-
1679-
/** Check that there are not mixed Any/Phantom.Any types in `&`, `|` and type bounds,
1680-
* this includes Phantom.Any of different universes.
1681-
*/
1682-
def checkedTops(tree: untpd.Tree): Set[Type] = {
1683-
tree match {
1684-
case TypeBoundsTree(lo, hi) =>
1685-
val allTops = checkedTops(hi) union checkedTops(lo)
1686-
if (allTops.size <= 1) allTops
1687-
else {
1688-
ctx.error("Type can not be bounded at the same time by types in different latices: " +
1689-
allTops.map(_.show).mkString(", "), tree.pos)
1690-
Set.empty
1691-
}
1692-
case untpd.InfixOp(left, op, right) =>
1693-
val allTops = checkedTops(left) union checkedTops(right)
1694-
if (allTops.size <= 1) allTops
1695-
else {
1696-
ctx.error(s"Can not use ${op.show} mix types of different lattices: " +
1697-
allTops.map(_.show).mkString(", "), tree.pos)
1698-
Set.empty
1699-
}
1700-
case EmptyTree => Set.empty
1701-
case _ => Set(tree.typeOpt.topType)
1702-
}
1703-
}
1704-
checkedTops(tree)
1705-
1660+
def typedType(tree: untpd.Tree, pt: Type = WildcardType)(implicit ctx: Context): Tree = // todo: retract mode between Type and Pattern?
17061661
typed(tree, pt)(ctx addMode Mode.Type)
1707-
}
17081662
def typedPattern(tree: untpd.Tree, selType: Type = WildcardType)(implicit ctx: Context): Tree =
17091663
typed(tree, selType)(ctx addMode Mode.Pattern)
17101664

@@ -2168,5 +2122,4 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
21682122
}
21692123
}
21702124
}
2171-
21722125
}

0 commit comments

Comments
 (0)