Merge pull request #84729 from xedin/rdar-161207705

[CSSimplify] Avoid simplifying dependent members until pack expansion…
This commit is contained in:
Pavel Yaskevich
2025-10-08 16:19:00 -07:00
committed by GitHub
3 changed files with 65 additions and 6 deletions

View File

@@ -7099,6 +7099,20 @@ static bool isTupleWithUnresolvedPackExpansion(Type type) {
return false;
}
static bool isDependentMemberTypeWithBaseThatContainsUnresolvedPackExpansions(
ConstraintSystem &cs, Type type) {
if (!type->is<DependentMemberType>())
return false;
auto baseTy = cs.getFixedTypeRecursive(type->getDependentMemberRoot(),
/*wantRValue=*/true);
llvm::SmallPtrSet<TypeVariableType *, 2> typeVars;
baseTy->getTypeVariables(typeVars);
return llvm::any_of(typeVars, [](const TypeVariableType *typeVar) {
return typeVar->getImpl().isPackExpansion();
});
}
ConstraintSystem::TypeMatchResult
ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
TypeMatchOptions flags,
@@ -7135,7 +7149,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
//
// along any unsolved path. No other returns should produce
// SolutionKind::Unsolved or inspect TMF_GenerateConstraints.
auto formUnsolvedResult = [&] {
auto formUnsolvedResult = [&](bool useOriginalTypes = false) {
// If we're supposed to generate constraints (i.e., this is a
// newly-generated constraint), do so now.
if (flags.contains(TMF_GenerateConstraints)) {
@@ -7144,8 +7158,13 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
// this new constraint will be solved at a later point.
// Obviously, this must not happen at the top level, or the
// algorithm would not terminate.
addUnsolvedConstraint(Constraint::create(*this, kind, type1, type2,
getConstraintLocator(locator)));
if (useOriginalTypes) {
addUnsolvedConstraint(Constraint::create(
*this, kind, origType1, origType2, getConstraintLocator(locator)));
} else {
addUnsolvedConstraint(Constraint::create(
*this, kind, type1, type2, getConstraintLocator(locator)));
}
return getTypeMatchSuccess();
}
@@ -7396,6 +7415,29 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
}
}
// Dependent members cannot be simplified if base type contains unresolved
// pack expansion type variables because they don't give enough information
// to substitution logic to form a correct type. For example:
//
// ```
// protocol P { associatedtype V }
// struct S<each T> : P { typealias V = (repeat (each T)?) }
// ```
//
// If pack expansion is represented as `$T1` and its pattern is `$T2`, a
// reference to `V` would get a type `S<Pack{$T}>.V` and simplified version
// would be `Optional<Pack{$T1}>` instead of `Pack{repeat Optional<$T2>}`
// because `$T1` is treated as a substitution for `each T` until bound.
if (isDependentMemberTypeWithBaseThatContainsUnresolvedPackExpansions(
*this, origType1) ||
isDependentMemberTypeWithBaseThatContainsUnresolvedPackExpansions(
*this, origType2)) {
// It's important to preserve the original types here because any attempt
// at simplification or canonicalization wouldn't produce a correct type
// util pack expansion type variables are bound.
return formUnsolvedResult(/*useOriginalTypes=*/true);
}
llvm::SmallVector<RestrictionOrFix, 4> conversionsOrFixes;
// Decompose parallel structure.