@@ -417,11 +417,8 @@ trait TypeAssigner {
417
417
def assignType (tree : untpd.Inlined , bindings : List [Tree ], expansion : Tree )(implicit ctx : Context ) =
418
418
tree.withType(avoidingType(expansion, bindings))
419
419
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" ))
425
422
426
423
def assignType (tree : untpd.Closure , meth : Tree , target : Tree )(implicit ctx : Context ) =
427
424
tree.withType(
@@ -433,20 +430,16 @@ trait TypeAssigner {
433
430
434
431
def assignType (tree : untpd.Match , cases : List [CaseDef ])(implicit ctx : Context ) = {
435
432
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" ))
442
435
}
443
436
444
437
def assignType (tree : untpd.Return )(implicit ctx : Context ) =
445
438
tree.withType(defn.NothingType )
446
439
447
440
def assignType (tree : untpd.Try , expr : Tree , cases : List [CaseDef ])(implicit ctx : Context ) =
448
441
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 " ))
450
443
451
444
def assignType (tree : untpd.SeqLiteral , elems : List [Tree ], elemtpt : Tree )(implicit ctx : Context ) = {
452
445
val ownType = tree match {
@@ -459,15 +452,11 @@ trait TypeAssigner {
459
452
def assignType (tree : untpd.SingletonTypeTree , ref : Tree )(implicit ctx : Context ) =
460
453
tree.withType(ref.tpe)
461
454
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 `&`" ))
466
457
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 `|`" ))
471
460
472
461
/** Assign type of RefinedType.
473
462
* Refinements are typed as if they were members of refinement class `refineCls`.
@@ -497,10 +486,10 @@ trait TypeAssigner {
497
486
def assignType (tree : untpd.ByNameTypeTree , result : Tree )(implicit ctx : Context ) =
498
487
tree.withType(ExprType (result.tpe))
499
488
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 " ))
504
493
505
494
def assignType (tree : untpd.Bind , sym : Symbol )(implicit ctx : Context ) =
506
495
tree.withType(NamedType .withFixedSym(NoPrefix , sym))
@@ -546,12 +535,23 @@ trait TypeAssigner {
546
535
def assignType (tree : untpd.PackageDef , pid : Tree )(implicit ctx : Context ) =
547
536
tree.withType(pid.symbol.valRef)
548
537
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
+ }
554
549
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
+ }
555
555
}
556
556
557
557
object TypeAssigner extends TypeAssigner
0 commit comments