@@ -237,8 +237,8 @@ extends tpd.TreeTraverser:
237237 // Don't map capture sets, since that would implicitly normalize sets that
238238 // are not well-formed.
239239 t.derivedAnnotatedType(t3, ann)
240- case _ =>
241- mapOverFollowingAliases(t)
240+ case t =>
241+ normalizeCaptures( mapOverFollowingAliases(t) )
242242
243243 private def transformExplicitType (tp : Type , boxed : Boolean , mapRoots : Boolean )(using Context ): Type =
244244 val tp1 = expandAliases(tp)
@@ -560,10 +560,8 @@ extends tpd.TreeTraverser:
560560 false
561561 }.showing(i " can have inferred capture $tp = $result" , capt)
562562
563- /** Add a capture set variable to `tp` if necessary, or maybe pull out
564- * an embedded capture set variable from a part of `tp`.
565- */
566- def decorate (tp : Type , mapRoots : Boolean , addedSet : Type => CaptureSet )(using Context ): Type = tp match
563+ /** Pull out an embedded capture set from a part of `tp` */
564+ def normalizeCaptures (tp : Type )(using Context ): Type = tp match
567565 case tp @ RefinedType (parent @ CapturingType (parent1, refs), rname, rinfo) =>
568566 CapturingType (tp.derivedRefinedType(parent1, rname, rinfo), refs, parent.isBoxed)
569567 case tp : RecType =>
@@ -575,33 +573,37 @@ extends tpd.TreeTraverser:
575573 // by `mapInferred`. Hence if the underlying type admits capture variables
576574 // a variable was already added, and the first case above would apply.
577575 case AndType (tp1 @ CapturingType (parent1, refs1), tp2 @ CapturingType (parent2, refs2)) =>
578- assert(refs1.elems.isEmpty)
579- assert(refs2.elems.isEmpty)
580576 assert(tp1.isBoxed == tp2.isBoxed)
581577 CapturingType (AndType (parent1, parent2), refs1 ** refs2, tp1.isBoxed)
582578 case tp @ OrType (tp1 @ CapturingType (parent1, refs1), tp2 @ CapturingType (parent2, refs2)) =>
583- assert(refs1.elems.isEmpty)
584- assert(refs2.elems.isEmpty)
585579 assert(tp1.isBoxed == tp2.isBoxed)
586580 CapturingType (OrType (parent1, parent2, tp.isSoft), refs1 ++ refs2, tp1.isBoxed)
587581 case tp @ OrType (tp1 @ CapturingType (parent1, refs1), tp2) =>
588582 CapturingType (OrType (parent1, tp2, tp.isSoft), refs1, tp1.isBoxed)
589583 case tp @ OrType (tp1, tp2 @ CapturingType (parent2, refs2)) =>
590584 CapturingType (OrType (tp1, parent2, tp.isSoft), refs2, tp2.isBoxed)
591585 case tp : LazyRef =>
592- decorate(tp.ref, mapRoots, addedSet)
593- case _ if tp.typeSymbol == defn.FromJavaObjectSymbol =>
586+ normalizeCaptures(tp.ref)
587+ case _ =>
588+ tp
589+
590+ /** Add a capture set variable to `tp` if necessary, or maybe pull out
591+ * an embedded capture set variable from a part of `tp`.
592+ */
593+ def decorate (tp : Type , mapRoots : Boolean , addedSet : Type => CaptureSet )(using Context ): Type =
594+ if tp.typeSymbol == defn.FromJavaObjectSymbol then
594595 // For capture checking, we assume Object from Java is the same as Any
595596 tp
596- case _ =>
597+ else
597598 def maybeAdd (target : Type , fallback : Type ) =
598599 if needsVariable(target) then CapturingType (target, addedSet(target))
599600 else fallback
600- val tp1 = tp.dealiasKeepAnnots
601- if tp1 ne tp then
601+ val tp0 = normalizeCaptures(tp)
602+ val tp1 = tp0.dealiasKeepAnnots
603+ if tp1 ne tp0 then
602604 val tp2 = transformExplicitType(tp1, boxed = false , mapRoots)
603- maybeAdd(tp2, if tp2 ne tp1 then tp2 else tp )
604- else maybeAdd(tp, tp )
605+ maybeAdd(tp2, if tp2 ne tp1 then tp2 else tp0 )
606+ else maybeAdd(tp0, tp0 )
605607
606608 /** Add a capture set variable to `tp` if necessary, or maybe pull out
607609 * an embedded capture set variable from a part of `tp`.
0 commit comments