[CSSimplify] VariadicGenerics: Don't attempt to wrap optional into one-element tuple

If we have a tuple with unresolved pack expansion on one side
and an optional type on the other, prevent `matchTypes` from
wrapping optional into a one-element tuple because the matching
should be handled as part of the optional injection.

Resolves: rdar://152940244
(cherry picked from commit 6cfbafd968)
This commit is contained in:
Pavel Yaskevich
2025-06-17 18:25:22 -07:00
parent 4c31ceecd7
commit cb9925d556
2 changed files with 23 additions and 5 deletions

View File

@@ -7345,16 +7345,20 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
// match `$T3` and propagate `Pack{Int}` to `$T2`.
//
// This is also important for situations like: `$T2 conv (Int, $T_exp)`
// becuase expansion could be defaulted to an empty pack which means
// because expansion could be defaulted to an empty pack which means
// that under substitution that element would disappear and the type
// would be just `(Int)`.
//
// Notable exception here is `Any` which doesn't require wrapping and
// would be handled by existental promotion in cases where it's allowed.
// Notable exceptions here are: `Any` which doesn't require wrapping and
// would be handled by an existential promotion in cases where it's allowed,
// and `Optional<T>` which would be handled by optional injection.
if (isTupleWithUnresolvedPackExpansion(origType1) ||
isTupleWithUnresolvedPackExpansion(origType2)) {
if (desugar1->is<TupleType>() != desugar2->is<TupleType>() &&
(!desugar1->isAny() && !desugar2->isAny())) {
if (isa<TupleType>(desugar1) != isa<TupleType>(desugar2) &&
!desugar1->getOptionalObjectType() &&
!desugar2->getOptionalObjectType() &&
!desugar1->isAny() &&
!desugar2->isAny()) {
return matchTypes(
desugar1->is<TupleType>() ? type1
: TupleType::get({type1}, getASTContext()),