@@ -83,7 +83,9 @@ case class Typ(tp: Type, decomposed: Boolean = true) extends Space:
83
83
def canDecompose (using Context ): Boolean = decompose != SpaceEngine .ListOfTypNoType
84
84
85
85
def decompose (using Context ): List [Typ ] =
86
- if myDecompose == null then myDecompose = SpaceEngine .decompose(tp).map(Typ (_, decomposed = true ))
86
+ if myDecompose == null then myDecompose = tp match
87
+ case SpaceEngine .Parts (parts) => parts.map(Typ (_, decomposed = true ))
88
+ case _ => SpaceEngine .ListOfTypNoType
87
89
myDecompose
88
90
end Typ
89
91
@@ -581,18 +583,6 @@ object SpaceEngine {
581
583
582
584
/** Decompose a type into subspaces -- assume the type can be decomposed */
583
585
def decompose (tp : Type )(using Context ): List [Type ] = trace(i " decompose( $tp) " , debug) {
584
- var lastType : Type = NoType
585
- var lastParts : List [Type ] = Nil
586
- def dec (tp : Type ) =
587
- if tp eq lastType then lastParts
588
- else
589
- lastType = tp
590
- lastParts = decompose(tp)
591
- lastParts
592
- def canDec (tp : Type ) =
593
- lastParts = dec(tp)
594
- lastParts != ListOfNoType
595
-
596
586
def rec (tp : Type , mixins : List [Type ]): List [Type ] = tp.dealias match
597
587
case AndType (tp1, tp2) =>
598
588
var tpB = tp2
@@ -611,14 +601,14 @@ object SpaceEngine {
611
601
case tp if tp.isRef(defn.BooleanClass ) => List (ConstantType (Constant (true )), ConstantType (Constant (false )))
612
602
case tp if tp.isRef(defn.UnitClass ) => ConstantType (Constant (())) :: Nil
613
603
case tp if tp.classSymbol.isAllOf(JavaEnumTrait ) => tp.classSymbol.children.map(_.termRef)
614
- case tp : NamedType if canDec(tp.prefix) => dec(tp.prefix) .map(tp.derivedSelect)
604
+ case tp @ TypeRef ( Parts (parts), _) => parts .map(tp.derivedSelect)
615
605
616
- case tp @ AppliedType (tycon , targs) if tp.classSymbol.children.isEmpty && canDec(tycon) =>
606
+ case tp @ AppliedType (Parts (parts) , targs) if tp.classSymbol.children.isEmpty =>
617
607
// It might not obvious that it's OK to apply the type arguments of a parent type to child types.
618
608
// But this is guarded by `tp.classSymbol.children.isEmpty`,
619
609
// meaning we'll decompose to the same class, just not the same type.
620
610
// For instance, from i15029, `decompose((X | Y).Field[T]) = [X.Field[T], Y.Field[T]]`.
621
- dec(tycon) .map(tp.derivedAppliedType(_, targs))
611
+ parts .map(tp.derivedAppliedType(_, targs))
622
612
623
613
case tp if {
624
614
val cls = tp.classSymbol
@@ -665,6 +655,12 @@ object SpaceEngine {
665
655
val ListOfNoType = List (NoType )
666
656
val ListOfTypNoType = ListOfNoType .map(Typ (_, decomposed = true ))
667
657
658
+ object Parts :
659
+ def unapply (tp : Type )(using Context ): PartsExtractor = PartsExtractor (decompose(tp))
660
+
661
+ final class PartsExtractor (val get : List [Type ]) extends AnyVal :
662
+ def isEmpty : Boolean = get == ListOfNoType
663
+
668
664
/** Show friendly type name with current scope in mind
669
665
*
670
666
* E.g. C.this.B --> B if current owner is C
0 commit comments