Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/swift/Sema/ConstraintSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -3759,6 +3759,11 @@ class ConstraintSystem {
RememberChoice_t rememberChoice,
ConstraintLocatorBuilder locator,
ConstraintFix *compatFix = nullptr);

/// Add a materialize constraint for a pack expansion.
TypeVariableType *
addMaterializePackExpansionConstraint(Type patternType,
ConstraintLocatorBuilder locator);

/// Add a disjunction constraint.
void
Expand Down
10 changes: 9 additions & 1 deletion lib/AST/GenericSignature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,16 @@ void GenericSignatureImpl::forEachParam(

for (auto req : getRequirements()) {
GenericTypeParamType *gp;
bool isCanonical = false;
switch (req.getKind()) {
case RequirementKind::SameType: {
if (req.getSecondType()->isParameterPack() !=
req.getFirstType()->isParameterPack()) {
// This is a same-element requirement, which does not make
// type parameters non-canonical.
isCanonical = true;
}

if (auto secondGP = req.getSecondType()->getAs<GenericTypeParamType>()) {
// If two generic parameters are same-typed, then the right-hand one
// is non-canonical.
Expand Down Expand Up @@ -136,7 +144,7 @@ void GenericSignatureImpl::forEachParam(
}

unsigned index = GenericParamKey(gp).findIndexIn(genericParams);
genericParamsAreCanonical[index] = false;
genericParamsAreCanonical[index] = isCanonical;
}

// Call the callback with each parameter and the result of the above analysis.
Expand Down
5 changes: 5 additions & 0 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3843,6 +3843,11 @@ namespace {
auto *locator = cs.getConstraintLocator(expr);
auto *environment = cs.getPackElementEnvironment(locator,
expansionTy->getCountType()->getCanonicalType());

// Assert that we have an opened element environment, otherwise we'll get
// an ASTVerifier crash when pack archetypes or element archetypes appear
// inside the pack expansion expression.
assert(environment);
expr->setGenericEnvironment(environment);

return expr;
Expand Down
11 changes: 1 addition & 10 deletions lib/Sema/CSGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3198,18 +3198,9 @@ namespace {
auto expansionType =
CS.getType(packEnvironment)->castTo<PackExpansionType>();
CS.addConstraint(ConstraintKind::ShapeOf, expansionType->getCountType(),
elementType,
packType,
CS.getConstraintLocator(packEnvironment,
ConstraintLocator::PackShape));
auto *elementShape = CS.createTypeVariable(
CS.getConstraintLocator(expr, ConstraintLocator::PackShape),
TVO_CanBindToPack);
CS.addConstraint(
ConstraintKind::ShapeOf, elementShape, elementType,
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
CS.addConstraint(
ConstraintKind::Equal, elementShape, expansionType->getCountType(),
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
} else {
CS.recordFix(AllowInvalidPackReference::create(
CS, packType, CS.getConstraintLocator(expr->getPackRefExpr())));
Expand Down
22 changes: 17 additions & 5 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9313,11 +9313,7 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
}

if (isSingleUnlabeledPackExpansionTuple(patternType)) {
auto *packVar =
createTypeVariable(getConstraintLocator(locator), TVO_CanBindToPack);
addConstraint(ConstraintKind::MaterializePackExpansion, patternType,
packVar,
getConstraintLocator(locator, {ConstraintLocator::Member}));
auto *packVar = addMaterializePackExpansionConstraint(patternType, locator);
addConstraint(ConstraintKind::PackElementOf, elementType, packVar, locator);
return SolutionKind::Solved;
}
Expand Down Expand Up @@ -13440,6 +13436,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyShapeOfConstraint(
return SolutionKind::Solved;
}

if (isSingleUnlabeledPackExpansionTuple(packTy)) {
auto *packVar = addMaterializePackExpansionConstraint(packTy, locator);
addConstraint(ConstraintKind::ShapeOf, shapeTy, packVar, locator);
return SolutionKind::Solved;
}

// Map element archetypes to the pack context to check for equality.
if (packTy->hasElementArchetype()) {
auto *packEnv = DC->getGenericEnvironmentOfContext();
Expand Down Expand Up @@ -15623,6 +15625,16 @@ void ConstraintSystem::addExplicitConversionConstraint(
addDisjunctionConstraint(constraints, locator, rememberChoice);
}

TypeVariableType *ConstraintSystem::addMaterializePackExpansionConstraint(
Type patternType, ConstraintLocatorBuilder locator) {
assert(isSingleUnlabeledPackExpansionTuple(patternType));
TypeVariableType *packVar =
createTypeVariable(getConstraintLocator(locator), TVO_CanBindToPack);
addConstraint(ConstraintKind::MaterializePackExpansion, patternType, packVar,
getConstraintLocator(locator, {ConstraintLocator::Member}));
return packVar;
}

ConstraintSystem::SolutionKind
ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
auto matchKind = constraint.getKind();
Expand Down
10 changes: 10 additions & 0 deletions test/Constraints/pack-expansion-expressions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -734,3 +734,13 @@ do {
}
}
}

// Pack Iteration
do {
func test<each T>(_ t: repeat each T) {
func nested() -> (repeat (Int, each T)) {}
for (x, y) in repeat each nested() {}
// expected-warning@-1 {{immutable value 'x' was never used; consider replacing with '_' or removing it}}
// expected-warning@-2 {{immutable value 'y' was never used; consider replacing with '_' or removing it}}
}
}