diff --git a/include/swift/Sema/ConstraintLocatorPathElts.def b/include/swift/Sema/ConstraintLocatorPathElts.def index f6a26ba73af..86df71de2c4 100644 --- a/include/swift/Sema/ConstraintLocatorPathElts.def +++ b/include/swift/Sema/ConstraintLocatorPathElts.def @@ -198,6 +198,9 @@ CUSTOM_LOCATOR_PATH_ELT(PackElement) /// The shape of a parameter pack. SIMPLE_LOCATOR_PATH_ELT(PackShape) +/// The pattern of a pack expansion. +SIMPLE_LOCATOR_PATH_ELT(PackExpansionPattern) + /// An unresolved member. SIMPLE_LOCATOR_PATH_ELT(UnresolvedMember) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 5669f0250df..0b33764f8d6 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -2918,10 +2918,12 @@ namespace { CS.setType(binding, type); } - auto elementResultType = CS.getType(expr->getPatternExpr()); - auto patternTy = CS.createTypeVariable(CS.getConstraintLocator(expr), + auto *patternLoc = + CS.getConstraintLocator(expr, ConstraintLocator::PackExpansionPattern); + auto patternTy = CS.createTypeVariable(patternLoc, TVO_CanBindToPack | TVO_CanBindToHole); + auto elementResultType = CS.getType(expr->getPatternExpr()); CS.addConstraint(ConstraintKind::PackElementOf, elementResultType, patternTy, CS.getConstraintLocator(expr)); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 759f3e924e4..1dad1b4b48f 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -7559,9 +7559,10 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySubclassOfConstraint( for (unsigned i = 0, e = packType->getNumElements(); i < e; ++i) { auto eltType = packType->getElementType(i); if (auto *packExpansionType = eltType->getAs()) { - // FIXME: Locator element for pack expansion pattern + auto patternLoc = + locator.withPathElement(ConstraintLocator::PackExpansionPattern); addConstraint(ConstraintKind::SubclassOf, packExpansionType->getPatternType(), - classType, locator.withPathElement(LocatorPathElt::PackElement(i))); + classType, patternLoc); } else { addConstraint(ConstraintKind::SubclassOf, eltType, classType, locator.withPathElement(LocatorPathElt::PackElement(i))); @@ -7677,11 +7678,12 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( for (unsigned i = 0, e = packType->getNumElements(); i < e; ++i) { auto eltType = packType->getElementType(i); if (auto *packExpansionType = eltType->getAs()) { - // FIXME: Locator element for pack expansion pattern + auto patternLoc = + locator.withPathElement(ConstraintLocator::PackExpansionPattern); addConstraint(ConstraintKind::ConformsTo, packExpansionType->getPatternType(), protocol->getDeclaredInterfaceType(), - locator.withPathElement(LocatorPathElt::PackElement(i))); + patternLoc); } else { addConstraint(ConstraintKind::ConformsTo, eltType, protocol->getDeclaredInterfaceType(), diff --git a/lib/Sema/ConstraintLocator.cpp b/lib/Sema/ConstraintLocator.cpp index e4c2e47d665..009aa0be326 100644 --- a/lib/Sema/ConstraintLocator.cpp +++ b/lib/Sema/ConstraintLocator.cpp @@ -98,6 +98,7 @@ unsigned LocatorPathElt::getNewSummaryFlags() const { case ConstraintLocator::PackType: case ConstraintLocator::PackElement: case ConstraintLocator::PackShape: + case ConstraintLocator::PackExpansionPattern: case ConstraintLocator::PatternBindingElement: case ConstraintLocator::NamedPatternDecl: case ConstraintLocator::AnyPatternDecl: @@ -450,6 +451,11 @@ void LocatorPathElt::dump(raw_ostream &out) const { break; } + case ConstraintLocator::PackExpansionPattern: { + out << "pack expansion pattern"; + break; + } + case ConstraintLocator::PatternBindingElement: { auto patternBindingElt = elt.castTo(); diff --git a/lib/Sema/ConstraintSystem.cpp b/lib/Sema/ConstraintSystem.cpp index 7205520a0dd..223b5e58fa5 100644 --- a/lib/Sema/ConstraintSystem.cpp +++ b/lib/Sema/ConstraintSystem.cpp @@ -5330,6 +5330,14 @@ void constraints::simplifyLocator(ASTNode &anchor, case ConstraintLocator::PackShape: break; + case ConstraintLocator::PackExpansionPattern: { + if (auto *expansion = getAsExpr(anchor)) + anchor = expansion->getPatternExpr(); + + path = path.slice(1); + break; + } + case ConstraintLocator::PatternBindingElement: { auto pattern = path[0].castTo(); auto *patternBinding = cast(anchor.get());