Skip to content

Commit c130351

Browse files
committed
[ConstraintSystem] Implement pack expansion variable resolution
A pack expansion type variable gets bound to its original pattern type when solver can infer a contextual type for it. This makes sure that pack expansion types are always matched via `matchTypes` without `simplifyType` involvement which can expand them prematurely.
1 parent ca534ef commit c130351

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3888,6 +3888,16 @@ class ConstraintSystem {
38883888
bool resolveClosure(TypeVariableType *typeVar, Type contextualType,
38893889
ConstraintLocatorBuilder locator);
38903890

3891+
/// Given the fact that contextual type is now available for the type
3892+
/// variable representing a pack expansion type, let's resolve the expansion.
3893+
///
3894+
/// \param typeVar The type variable representing pack expansion type.
3895+
/// \param locator The locator associated with contextual type.
3896+
///
3897+
/// \returns `true` if pack expansion has been resolved, `false` otherwise.
3898+
bool resolvePackExpansion(TypeVariableType *typeVar,
3899+
ConstraintLocatorBuilder locator);
3900+
38913901
/// Assign a fixed type to the given type variable.
38923902
///
38933903
/// \param typeVar The type variable to bind.

lib/Sema/CSSimplify.cpp

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4287,6 +4287,15 @@ ConstraintSystem::matchTypesBindTypeVar(
42874287
}
42884288
}
42894289

4290+
if (typeVar->getImpl().isPackExpansion()) {
4291+
if (!flags.contains(TMF_BindingTypeVariable))
4292+
return formUnsolvedResult();
4293+
4294+
return resolvePackExpansion(typeVar, locator)
4295+
? getTypeMatchSuccess()
4296+
: getTypeMatchFailure(locator);
4297+
}
4298+
42904299
// If we're attempting to bind a PackType or PackArchetypeType to a type
42914300
// variable that doesn't support it, we have a pack reference outside of a
42924301
// pack expansion expression.
@@ -4305,11 +4314,6 @@ ConstraintSystem::matchTypesBindTypeVar(
43054314
type = PlaceholderType::get(typeVar->getASTContext(), typeVar);
43064315
}
43074316

4308-
// FIXME: Add a fix for this.
4309-
if (typeVar->getImpl().isPackExpansion() && !type->is<PackExpansionType>()) {
4310-
return getTypeMatchFailure(locator);
4311-
}
4312-
43134317
// Binding to a pack expansion type is always an error in Swift 6 mode.
43144318
// This indicates that a pack expansion expression was used in a context
43154319
// that doesn't support it.
@@ -11229,6 +11233,29 @@ bool ConstraintSystem::resolveClosure(TypeVariableType *typeVar,
1122911233
return !generateConstraints(AnyFunctionRef{closure}, closure->getBody());
1123011234
}
1123111235

11236+
bool ConstraintSystem::resolvePackExpansion(TypeVariableType *typeVar,
11237+
ConstraintLocatorBuilder locator) {
11238+
// TODO: Pack expansion type variable can carry opened type.
11239+
auto expansion =
11240+
llvm::find_if(OpenedPackExpansionTypes, [&](const auto &expansion) {
11241+
return expansion.second->isEqual(typeVar);
11242+
});
11243+
11244+
assert(expansion != OpenedPackExpansionTypes.end());
11245+
11246+
assignFixedType(typeVar, expansion->first, getConstraintLocator(locator));
11247+
11248+
if (isDebugMode()) {
11249+
PrintOptions PO;
11250+
PO.PrintTypesForDebugging = true;
11251+
llvm::errs().indent(solverState->getCurrentIndent())
11252+
<< "(pack expansion variable " << typeVar->getString(PO)
11253+
<< " is bound to '" << expansion->first->getString(PO) << "')\n";
11254+
}
11255+
11256+
return true;
11257+
}
11258+
1123211259
ConstraintSystem::SolutionKind
1123311260
ConstraintSystem::simplifyDynamicTypeOfConstraint(
1123411261
Type type1, Type type2,

0 commit comments

Comments
 (0)