Skip to content

Commit 1a006f1

Browse files
committed
Move phantom universe checks from Typer to TypeAssigner.
1 parent 052433a commit 1a006f1

File tree

2 files changed

+28
-54
lines changed

2 files changed

+28
-54
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 & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -658,12 +658,6 @@ 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.topType != elsep1.tpe.topType) {
662-
ctx.error(s"""if/else cannot have branches with types in different lattices:
663-
| ${thenp1.tpe.show} of lattice ${thenp1.tpe.topType.show}
664-
| ${elsep1.tpe.show} of lattice ${elsep1.tpe.topType.show}
665-
""".stripMargin, tree.pos)
666-
}
667661
val thenp2 :: elsep2 :: Nil = harmonize(thenp1 :: elsep1 :: Nil)
668662
assignType(cpy.If(tree)(cond1, thenp2, elsep2), thenp2, elsep2)
669663
}
@@ -835,8 +829,6 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
835829
typed(desugar.makeCaseLambda(tree.cases, protoFormals.length, unchecked) withPos tree.pos, pt)
836830
case _ =>
837831
val sel1 = typedExpr(tree.selector)
838-
if (sel1.tpe.isPhantom)
839-
ctx.error("Cannot pattern match on phantoms", sel1.pos)
840832
val selType = widenForMatchSelector(
841833
fullyDefinedType(sel1.tpe, "pattern selector", tree.pos))
842834

@@ -868,15 +860,7 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
868860
accu(Set.empty, selType)
869861
}
870862

871-
val tpdCases = cases mapconserve (typedCase(_, pt, selType, gadtSyms))
872-
873-
if (tpdCases.nonEmpty) {
874-
val top = tpdCases.head.tpe.topType
875-
for (tpdCase <- tpdCases if tpdCase.tpe.topType != top)
876-
ctx.error(s"Pattern expected case to return a ${top.show} but was ${tpdCase.tpe.show}", tpdCase.pos)
877-
}
878-
879-
tpdCases
863+
cases mapconserve (typedCase(_, pt, selType, gadtSyms))
880864
}
881865

882866
/** Type a case. Overridden in ReTyper, that's why it's separate from
@@ -1669,38 +1653,8 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
16691653

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

@@ -2164,5 +2118,4 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
21642118
}
21652119
}
21662120
}
2167-
21682121
}

0 commit comments

Comments
 (0)