@@ -663,6 +663,10 @@ class SpaceEngine(using Context) extends SpaceLogic {
663663 // For instance, from i15029, `decompose((X | Y).Field[T]) = [X.Field[T], Y.Field[T]]`.
664664 rec(tycon, Nil ).map(typ => Typ (tp.derivedAppliedType(typ.tp, targs)))
665665
666+ case tp @ AppliedType (tycon, _) if tp.classSymbol.children.isEmpty && ! canDecompose(tycon) && decomposableArgIdx(tp) >= 0 =>
667+ val (init, targ :: tail) = tp.args.splitAt(decomposableArgIdx(tp)): @ unchecked
668+ decompose(targ).map(typ => Typ (tp.derivedAppliedType(tycon, init ::: typ.tp :: tail)))
669+
666670 case tp : NamedType if canDecompose(tp.prefix) =>
667671 rec(tp.prefix, Nil ).map(typ => Typ (tp.derivedSelect(typ.tp)))
668672
@@ -708,6 +712,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
708712 def canDecompose (tp : Type ): Boolean =
709713 val res = tp.dealias match
710714 case AppliedType (tycon, _) if canDecompose(tycon) => true
715+ case tp : AppliedType if decomposableArgIdx(tp) >= 0 => true
711716 case tp : NamedType if canDecompose(tp.prefix) => true
712717 case _ : SingletonType => false
713718 case _ : OrType => true
@@ -724,6 +729,21 @@ class SpaceEngine(using Context) extends SpaceLogic {
724729 // debug.println(s"decomposable: ${tp.show} = $res")
725730 res
726731
732+ /** Returns the index of the type argument of `tp` that can be decomposed, if found, or `-1` if not. */
733+ private def decomposableArgIdx (tp : AppliedType )(using Context ): Int =
734+ tp.tycon.typeParams.zip(tp.args).indexWhere { (tparam, targ) =>
735+ if tparam.paramVarianceSign >= 0 then
736+ val typeparamCorrespondsToField =
737+ try comparing(_.typeparamCorrespondsToField(tp.tycon, tparam))
738+ catch case _ : RecursionOverflow => false // tests/pos/f-bounded-case-class.scala
739+ if typeparamCorrespondsToField then
740+ val cls = targ.classSymbol
741+ targ.baseType(cls) != tp.baseType(cls) // tests/patmat/enum-HList.scala
742+ && canDecompose(targ)
743+ else false
744+ else false
745+ }
746+
727747 /** Show friendly type name with current scope in mind
728748 *
729749 * E.g. C.this.B --> B if current owner is C
@@ -990,6 +1010,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
9901010 for (pat <- deferred.reverseIterator)
9911011 report.warning(MatchCaseUnreachable (), pat.srcPos)
9921012 if pat != EmptyTree // rethrow case of catch uses EmptyTree
1013+ && ! pat.symbol.isAllOf(SyntheticCase ) // from ExpandSAMs collect
9931014 && isSubspace(covered, prev)
9941015 then {
9951016 val nullOnly = isNullable && i == len - 1 && isWildcardArg(pat)
0 commit comments