@@ -3414,20 +3414,85 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
3414
3414
3415
3415
def typedType (tree : untpd.Tree , pt : Type = WildcardType , mapPatternBounds : Boolean = false )(using Context ): Tree =
3416
3416
val tree1 = withMode(Mode .Type ) { typed(tree, pt) }
3417
+ val tree2 = tree1 match
3418
+ case inferredTree : InferredTypeTree if inferredTree.hasType =>
3419
+ inferredTree.tpe match
3420
+ case or : OrType =>
3421
+ val res = flattenOr(or)
3422
+ tree1.withType(res)
3423
+ case _ =>
3424
+ tree1
3425
+ case _ =>
3426
+ tree1
3417
3427
if mapPatternBounds && ctx.mode.is(Mode .Pattern ) && ! ctx.isAfterTyper then
3418
- tree1 match
3419
- case tree1 : TypeBoundsTree =>
3428
+ tree2 match
3429
+ case tree2 : TypeBoundsTree =>
3420
3430
// Associate a pattern-bound type symbol with the wildcard.
3421
3431
// The bounds of the type symbol can be constrained when comparing a pattern type
3422
3432
// with an expected type in typedTyped. The type symbol and the defining Bind node
3423
3433
// are eliminated once the enclosing pattern has been typechecked; see `indexPattern`
3424
3434
// in `typedCase`.
3425
3435
val boundName = WildcardParamName .fresh().toTypeName
3426
- val wildcardSym = newPatternBoundSymbol(boundName, tree1.tpe & pt, tree.span)
3427
- untpd.Bind (boundName, tree1).withType(wildcardSym.typeRef)
3428
- case tree1 =>
3429
- tree1
3430
- else tree1
3436
+ val wildcardSym = newPatternBoundSymbol(boundName, tree2.tpe & pt, tree.span)
3437
+ untpd.Bind (boundName, tree2).withType(wildcardSym.typeRef)
3438
+ case tree2 =>
3439
+ tree2
3440
+ else tree2
3441
+
3442
+ private def flattenOr (tp : Type )(using Context ): Type =
3443
+ var options : List [Type ] = Nil
3444
+ var doUpdate : Boolean = false
3445
+
3446
+ def offer (next : Type ): Unit =
3447
+ // By checking at insert time, we will never add an element to the internal state if it is invalidated by
3448
+ // a later element. Thus as extract time, we only need to validate for those prepended after that point
3449
+ next match
3450
+ case OrType (o1, o2) =>
3451
+ offer(o1)
3452
+ offer(o2)
3453
+ case _ =>
3454
+ if (! options.exists(prior => next <:< prior))
3455
+ options = next :: options
3456
+ else
3457
+ doUpdate = true
3458
+
3459
+ offer(tp)
3460
+ if (doUpdate)
3461
+ val typesToAdd = options.reverse.tails.flatMap {
3462
+ case curr :: allLaterAdditions
3463
+ if ! allLaterAdditions.exists(later => curr <:< later) =>
3464
+ Some (curr)
3465
+ case _ =>
3466
+ doUpdate = true
3467
+ None
3468
+ }
3469
+
3470
+ def addHelper (add : Type , orTree : List [Option [Type ]], iter : Int = 0 ): List [Option [Type ]] =
3471
+ orTree match
3472
+ case None :: more =>
3473
+ var res = Some (add) :: more
3474
+ for (i <- 1 to iter) {
3475
+ res = None :: res
3476
+ }
3477
+ res
3478
+ case Some (next) :: more =>
3479
+ addHelper(add | next, more, iter + 1 )
3480
+ case Nil =>
3481
+ var res : List [Option [Type ]] = List (Some (add))
3482
+ for (i <- 1 to iter) {
3483
+ res = None :: res
3484
+ }
3485
+ res
3486
+
3487
+ val res = typesToAdd.foldLeft[List [Option [Type ]]](Nil ) {
3488
+ case (orTree, add) =>
3489
+ addHelper(add, orTree)
3490
+ }.flatten.reduceLeft(_ | _)
3491
+ // println(s"${tp.show} ===> ${res.show} (${ctx.tree.show})")
3492
+ res
3493
+ else
3494
+ tp
3495
+
3431
3496
3432
3497
def typedPattern (tree : untpd.Tree , selType : Type = WildcardType )(using Context ): Tree =
3433
3498
withMode(Mode .Pattern )(typed(tree, selType))
0 commit comments