Skip to content

Commit 40ab53a

Browse files
committed
Polishings of Typer and TypeAssigner
1 parent 07c02c8 commit 40ab53a

File tree

5 files changed

+47
-47
lines changed

5 files changed

+47
-47
lines changed

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

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -417,11 +417,8 @@ 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) = {
421-
val sameUniverse = checkSameUniverse(thenp, elsep, "be combined in branches of if/else", tree.pos)
422-
val tpe = if (sameUniverse) thenp.tpe | elsep.tpe else thenp.tpe
423-
tree.withType(tpe)
424-
}
420+
def assignType(tree: untpd.If, thenp: Tree, elsep: Tree)(implicit ctx: Context) =
421+
tree.withType(lubInSameUniverse(thenp :: elsep :: Nil, "branches of an if/else"))
425422

426423
def assignType(tree: untpd.Closure, meth: Tree, target: Tree)(implicit ctx: Context) =
427424
tree.withType(
@@ -433,20 +430,16 @@ trait TypeAssigner {
433430

434431
def assignType(tree: untpd.Match, cases: List[CaseDef])(implicit ctx: Context) = {
435432
if (tree.selector.typeOpt.isPhantom)
436-
ctx.error("Cannot pattern match on phantoms", tree.selector.pos)
437-
val sameUniverse = cases.isEmpty || cases.tail.forall { c =>
438-
checkSameUniverse(cases.head, c, "be combined in branches of a match", c.pos)
439-
}
440-
val tpe = if (sameUniverse) ctx.typeComparer.lub(cases.tpes) else cases.head.tpe
441-
tree.withType(tpe)
433+
ctx.error("cannot pattern match on values of a phantom type", tree.selector.pos)
434+
tree.withType(lubInSameUniverse(cases, "branches of a match"))
442435
}
443436

444437
def assignType(tree: untpd.Return)(implicit ctx: Context) =
445438
tree.withType(defn.NothingType)
446439

447440
def assignType(tree: untpd.Try, expr: Tree, cases: List[CaseDef])(implicit ctx: Context) =
448441
if (cases.isEmpty) tree.withType(expr.tpe)
449-
else tree.withType(ctx.typeComparer.lub(expr.tpe :: cases.tpes))
442+
else tree.withType(lubInSameUniverse(expr :: cases, "branches of a try"))
450443

451444
def assignType(tree: untpd.SeqLiteral, elems: List[Tree], elemtpt: Tree)(implicit ctx: Context) = {
452445
val ownType = tree match {
@@ -459,15 +452,11 @@ trait TypeAssigner {
459452
def assignType(tree: untpd.SingletonTypeTree, ref: Tree)(implicit ctx: Context) =
460453
tree.withType(ref.tpe)
461454

462-
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
463-
checkSameUniverse(left, right, "be combined in `&`", tree.pos)
464-
tree.withType(left.tpe & right.tpe)
465-
}
455+
def assignType(tree: untpd.AndTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
456+
tree.withType(inSameUniverse(_ & _, left.tpe, right, "an `&`"))
466457

467-
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) = {
468-
checkSameUniverse(left, right, "be combined in `|`", tree.pos)
469-
tree.withType(left.tpe | right.tpe)
470-
}
458+
def assignType(tree: untpd.OrTypeTree, left: Tree, right: Tree)(implicit ctx: Context) =
459+
tree.withType(inSameUniverse(_ | _, left.tpe, right, "an `|`"))
471460

472461
/** Assign type of RefinedType.
473462
* Refinements are typed as if they were members of refinement class `refineCls`.
@@ -497,10 +486,10 @@ trait TypeAssigner {
497486
def assignType(tree: untpd.ByNameTypeTree, result: Tree)(implicit ctx: Context) =
498487
tree.withType(ExprType(result.tpe))
499488

500-
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) = {
501-
checkSameUniverse(lo, hi, "be combined in type bounds.", tree.pos)
502-
tree.withType(if (lo eq hi) TypeAlias(lo.tpe) else TypeBounds(lo.tpe, hi.tpe))
503-
}
489+
def assignType(tree: untpd.TypeBoundsTree, lo: Tree, hi: Tree)(implicit ctx: Context) =
490+
tree.withType(
491+
if (lo eq hi) TypeAlias(lo.tpe)
492+
else inSameUniverse(TypeBounds(_, _), lo.tpe, hi, "type bounds"))
504493

505494
def assignType(tree: untpd.Bind, sym: Symbol)(implicit ctx: Context) =
506495
tree.withType(NamedType.withFixedSym(NoPrefix, sym))
@@ -546,12 +535,23 @@ trait TypeAssigner {
546535
def assignType(tree: untpd.PackageDef, pid: Tree)(implicit ctx: Context) =
547536
tree.withType(pid.symbol.valRef)
548537

549-
private def checkSameUniverse(tree1: Tree, tree2: Tree, relationship: => String, pos: Position)(implicit ctx: Context): Boolean = {
550-
val sameUniverse = tree1.tpe.topType == tree2.tpe.topType
551-
if (!sameUniverse) ctx.error(ex"${tree1.tpe} and ${tree2.tpe} are in different universes. They cannot $relationship", pos)
552-
sameUniverse
553-
}
538+
/** Ensure that `tree2`'s type is in the same universe as `tree1`. If that's the case, return
539+
* `op` applied to both types.
540+
* If not, issue an error and return `tree1`'s type.
541+
*/
542+
private def inSameUniverse(op: (Type, Type) => Type, tp1: Type, tree2: Tree, relationship: => String)(implicit ctx: Context): Type =
543+
if (tp1.topType == tree2.tpe.topType)
544+
op(tp1, tree2.tpe)
545+
else {
546+
ctx.error(ex"$tp1 and ${tree2.tpe} are in different universes. They cannot be combined in $relationship", tree2.pos)
547+
tp1
548+
}
554549

550+
private def lubInSameUniverse(trees: List[Tree], relationship: => String)(implicit ctx: Context): Type =
551+
trees match {
552+
case first :: rest => (first.tpe /: rest)(inSameUniverse(_ | _, _, _, relationship))
553+
case Nil => defn.NothingType
554+
}
555555
}
556556

557557
object TypeAssigner extends TypeAssigner

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,13 +1334,9 @@ class Typer extends Namer with TypeAssigner with Applications with Implicits wit
13341334
cls, isRequired, cdef.pos)
13351335
}
13361336

1337-
// Check that phantom lattices are defined in an `object`
1338-
if (cls.classParents.exists(_.classSymbol eq defn.PhantomClass)) {
1339-
if (!cls.is(Module))
1340-
ctx.error("Only object can extend scala.Phantom", cdef.pos)
1341-
else if (!cls.owner.is(Module) && !cls.owner.is(Package))
1342-
ctx.error("An object extending scala.Phantom must be a top level object or in another object.", cdef.pos)
1343-
}
1337+
// Check that phantom lattices are defined in a static object
1338+
if (cls.classParents.exists(_.classSymbol eq defn.PhantomClass) && !cls.isStaticOwner)
1339+
ctx.error("only static objects can extend scala.Phantom", cdef.pos)
13441340

13451341
// check value class constraints
13461342
checkDerivedValueClass(cls, body1)

tests/neg/phantom-AndOr.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ class BooFunDef1 {
33
import Boo._
44

55
def fun1(b: BooAny | Any) = ??? // error
6-
def fun2(b: BooAny | Any | Any) = ??? // error
6+
def fun2(b: BooAny | Any | Any) = ??? // error // error
77
def fun3(b: Any | BooAny | Any) = ??? // error
88
def fun4(b: BooAny | BooAny | Any) = ??? // error
99

1010
def fun5(b: BooAny & Any) = ??? // error
1111
def fun6(b: Any & BooAny & Any) = ??? // error
12-
def fun7(b: BooAny & Any & Any) = ??? // error
12+
def fun7(b: BooAny & Any & Any) = ??? // error // error
1313
def fun8(b: Any & Any & BooAny) = ??? // error
1414
}
1515

tests/neg/phantom-expr.scala

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ class Foo {
1111

1212
val b = true
1313
def fooIf1 =
14-
if (b) blinky // error
15-
else ""
14+
if (b) blinky
15+
else "" // error
1616

1717
def fooIf2 =
18-
if (b) "" // error
19-
else blinky
18+
if (b) ""
19+
else blinky // error
2020

2121
def fooIf3 =
22-
if (b) boo1 // error
23-
else blinky
22+
if (b) boo1
23+
else blinky // error
2424

2525
def fooMatch1 = blinky match { // error
2626
case _: Blinky => ()
@@ -32,6 +32,10 @@ class Foo {
3232
case 1 => boo1
3333
case _ => blinky // error
3434
}
35+
def fooTry =
36+
try 1
37+
catch { case ex: Exception => blinky // error
38+
}
3539
}
3640

3741
object Boo extends Phantom {
@@ -42,4 +46,4 @@ object Boo extends Phantom {
4246
object Boo1 extends Phantom {
4347
type Boo1Any = this.Any
4448
def boo1: Boo1Any = assume
45-
}
49+
}

tests/neg/phantom-multiversal-AndOr.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ class BooFunDef1 {
55

66
def fun1(b: One | A) = ??? // error
77
def fun2(b: A | One) = ??? // error
8-
def fun3(b: A | One | Any) = ??? // error
8+
def fun3(b: A | One | Any) = ??? // error // error
99

1010
def fun4(b: A & One) = ??? // error
1111
def fun5(b: One & A) = ??? // error
12-
def fun6(b: A & One & Any) = ??? // error
12+
def fun6(b: A & One & Any) = ??? // error // error
1313
}
1414

1515
object Universe1 extends Phantom {

0 commit comments

Comments
 (0)