@@ -663,6 +663,10 @@ class SpaceEngine(using Context) extends SpaceLogic {
663
663
// For instance, from i15029, `decompose((X | Y).Field[T]) = [X.Field[T], Y.Field[T]]`.
664
664
rec(tycon, Nil ).map(typ => Typ (tp.derivedAppliedType(typ.tp, targs)))
665
665
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
+
666
670
case tp : NamedType if canDecompose(tp.prefix) =>
667
671
rec(tp.prefix, Nil ).map(typ => Typ (tp.derivedSelect(typ.tp)))
668
672
@@ -708,6 +712,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
708
712
def canDecompose (tp : Type ): Boolean =
709
713
val res = tp.dealias match
710
714
case AppliedType (tycon, _) if canDecompose(tycon) => true
715
+ case tp : AppliedType if decomposableArgIdx(tp) >= 0 => true
711
716
case tp : NamedType if canDecompose(tp.prefix) => true
712
717
case _ : SingletonType => false
713
718
case _ : OrType => true
@@ -724,6 +729,21 @@ class SpaceEngine(using Context) extends SpaceLogic {
724
729
// debug.println(s"decomposable: ${tp.show} = $res")
725
730
res
726
731
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
+
727
747
/** Show friendly type name with current scope in mind
728
748
*
729
749
* E.g. C.this.B --> B if current owner is C
@@ -990,6 +1010,7 @@ class SpaceEngine(using Context) extends SpaceLogic {
990
1010
for (pat <- deferred.reverseIterator)
991
1011
report.warning(MatchCaseUnreachable (), pat.srcPos)
992
1012
if pat != EmptyTree // rethrow case of catch uses EmptyTree
1013
+ && ! pat.symbol.isAllOf(SyntheticCase ) // from ExpandSAMs collect
993
1014
&& isSubspace(covered, prev)
994
1015
then {
995
1016
val nullOnly = isNullable && i == len - 1 && isWildcardArg(pat)
0 commit comments