Skip to content

Commit a4e8fcf

Browse files
committed
Move phantom universe checks from Typer to TypeAssigner.
1 parent b62dfec commit a4e8fcf

File tree

2 files changed

+28
-53
lines changed

2 files changed

+28
-53
lines changed

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

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,8 +417,10 @@ trait TypeAssigner {
417417
def assignType(tree: untpd.Inlined, bindings: List[Tree], expansion: Tree)(implicit ctx: Context) =
418418
tree.withType(avoidingType(expansion, bindings))
419419

420-
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) =
420+
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) = {
421+
checkSameUniverse(thenp, elsep, "be combined in branches of if/else", tree.pos)
421422
tree.withType(thenp.tpe | elsep.tpe)
423+
}
422424

423425
def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context) =
424426
tree.withType(
@@ -428,8 +430,15 @@ trait TypeAssigner {
428430
def assignType(tree: untpd.CaseDef, body: Tree)(implicit ctx: Context) =
429431
tree.withType(body.tpe)
430432

431-
def assignType(tree: untpd.Match, cases: List[CaseDef])(implicit ctx: Context) =
433+
def assignType(tree: untpd.Match, cases: List[CaseDef])(implicit ctx: Context) = {
434+
if (tree.selector.typeOpt.isPhantom)
435+
ctx.error("Cannot pattern match on phantoms", tree.selector.pos)
436+
if (cases.nonEmpty) {
437+
val head = cases.head
438+
cases.tail.foreach(c => checkSameUniverse(head, c, "be combined in branches of a match", c.pos))
439+
}
432440
tree.withType(ctx.typeComparer.lub(cases.tpes))
441+
}
433442

434443
def assignType(tree: untpd.Return)(implicit ctx: Context) =
435444
tree.withType(defn.NothingType)
@@ -449,11 +458,15 @@ trait TypeAssigner {
449458
def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context) =
450459
tree.withType(ref.tpe)
451460

452-
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
461+
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
462+
checkSameUniverse(left, right, "be combined in `&`", tree.pos)
453463
tree.withType(left.tpe & right.tpe)
464+
}
454465

455-
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
466+
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
467+
checkSameUniverse(left, right, "be combined in `|`", tree.pos)
456468
tree.withType(left.tpe | right.tpe)
469+
}
457470

458471
/** Assign type of RefinedType.
459472
* Refinements are typed as if they were members of refinement class `refineCls`.
@@ -483,8 +496,10 @@ trait TypeAssigner {
483496
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) =
484497
tree.withType(ExprType(result.tpe))
485498

486-
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) =
499+
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) = {
500+
checkSameUniverse(lo, hi, "be combined in type bounds.", tree.pos)
487501
tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe))
502+
}
488503

489504
def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context) =
490505
tree.withType(NamedType.withFixedSym(NoPrefix, sym))
@@ -529,6 +544,12 @@ trait TypeAssigner {
529544

530545
def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context) =
531546
tree.withType(pid.symbol.valRef)
547+
548+
private def checkSameUniverse(tree1: Tree, tree2: Tree, relationship: => String, pos: Position)(implicit ctx: Context) = {
549+
if (tree1.tpe.topType != tree2.tpe.topType)
550+
ctx.error(ex"${tree1.tpe} and ${tree2.tpe} are in different universes. They cannot $relationship", pos)
551+
}
552+
532553
}
533554

534555
object TypeAssigner extends TypeAssigner

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

Lines changed: 2 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -665,12 +665,6 @@ 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.topType != elsep1.tpe.topType) {
669-
ctx.error(s"""if/else cannot have branches with types in different lattices:
670-
| ${thenp1.tpe.show} of lattice ${thenp1.tpe.topType.show}
671-
| ${elsep1.tpe.show} of lattice ${elsep1.tpe.topType.show}
672-
""".stripMargin, tree.pos)
673-
}
674668
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
675669
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
676670
}
@@ -842,8 +836,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
842836
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt)
843837
case _ =>
844838
val sel1 = typedExpr(tree.selector)
845-
if (sel1.tpe.isPhantom)
846-
ctx.error("Cannot pattern match on phantoms", sel1.pos)
847839
val selType = fullyDefinedType(sel1.tpe, "pattern selector", tree.pos).widen
848840

849841
val cases1 = typedCases(tree.cases, selType, pt.notApplied)
@@ -874,15 +866,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
874866
accu(Set.empty, selType)
875867
}
876868

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

888872
/** Type a case. Overridden in ReTyper, that's why it's separate from
@@ -1672,38 +1656,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
16721656

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

0 commit comments

Comments
 (0)