Skip to content

Commit 75c1b6e

Browse files
authored
Merge pull request #64166 from hborla/parameter-pack-substitution
2 parents c93a235 + 1845d0d commit 75c1b6e

26 files changed

+186
-48
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2733,6 +2733,9 @@ ERROR(requires_not_suitable_archetype,none,
27332733
ERROR(invalid_shape_requirement,none,
27342734
"invalid same-shape requirement between %0 and %1",
27352735
(Type, Type))
2736+
ERROR(unsupported_same_element,none,
2737+
"same-element requirements are not yet supported",
2738+
())
27362739

27372740
ERROR(requires_generic_params_made_equal,none,
27382741
"same-type requirement makes generic parameters %0 and %1 equivalent",

include/swift/Sema/ConstraintSystem.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,8 @@ class Solution {
14871487

14881488
/// The pack expansion environment that can open pack elements for
14891489
/// a given locator.
1490-
llvm::DenseMap<ConstraintLocator *, UUID> PackExpansionEnvironments;
1490+
llvm::DenseMap<ConstraintLocator *, std::pair<UUID, Type>>
1491+
PackExpansionEnvironments;
14911492

14921493
/// The locators of \c Defaultable constraints whose defaults were used.
14931494
llvm::SmallPtrSet<ConstraintLocator *, 2> DefaultedConstraints;
@@ -2228,7 +2229,8 @@ class ConstraintSystem {
22282229
llvm::SmallMapVector<ConstraintLocator *, OpenedArchetypeType *, 4>
22292230
OpenedExistentialTypes;
22302231

2231-
llvm::SmallMapVector<ConstraintLocator *, UUID, 4> PackExpansionEnvironments;
2232+
llvm::SmallMapVector<ConstraintLocator *, std::pair<UUID, Type>, 4>
2233+
PackExpansionEnvironments;
22322234

22332235
/// The set of functions that have been transformed by a result builder.
22342236
llvm::MapVector<AnyFunctionRef, AppliedBuilderTransform>
@@ -3191,9 +3193,6 @@ class ConstraintSystem {
31913193
std::pair<Type, OpenedArchetypeType *> openExistentialType(
31923194
Type type, ConstraintLocator *locator);
31933195

3194-
/// Add the given pack expansion as an opened pack element environment.
3195-
void addPackElementEnvironment(PackExpansionExpr *expr);
3196-
31973196
/// Get the opened element generic environment for the given locator.
31983197
GenericEnvironment *getPackElementEnvironment(ConstraintLocator *locator,
31993198
CanType shapeClass);

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5147,6 +5147,7 @@ GenericEnvironment::forOpenedElement(GenericSignature signature,
51475147
if (found != openedElementEnvironments.end()) {
51485148
auto *existingEnv = found->second;
51495149
assert(existingEnv->getGenericSignature().getPointer() == signature.getPointer());
5150+
assert(existingEnv->getOpenedElementShapeClass()->isEqual(shapeClass));
51505151
assert(existingEnv->getOpenedElementUUID() == uuid);
51515152

51525153
return existingEnv;

lib/AST/Decl.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4670,8 +4670,12 @@ static Type computeNominalType(NominalTypeDecl *decl, DeclTypeKind kind) {
46704670
// the generic parameter list directly instead of looking
46714671
// at the signature.
46724672
SmallVector<Type, 4> args;
4673-
for (auto param : decl->getGenericParams()->getParams())
4674-
args.push_back(param->getDeclaredInterfaceType());
4673+
for (auto param : decl->getGenericParams()->getParams()) {
4674+
auto argTy = param->getDeclaredInterfaceType();
4675+
if (param->isParameterPack())
4676+
argTy = PackType::getSingletonPackExpansion(argTy);
4677+
args.push_back(argTy);
4678+
}
46754679

46764680
return BoundGenericType::get(decl, ParentTy, args);
46774681
}

lib/AST/GenericEnvironment.cpp

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,10 +681,37 @@ GenericEnvironment::mapElementTypeIntoPackContext(Type type) const {
681681
}, LookUpConformanceInSignature(sig.getPointer()));
682682
}
683683

684+
namespace {
685+
/// A function suitable for use as a \c TypeSubstitutionFn that produces
686+
/// correct forwarding substitutions for a generic environment.
687+
///
688+
/// This differs from QueryInterfaceTypeSubstitutions only in that it
689+
/// always produces PackTypes for pack parameters.
690+
class BuildForwardingSubstitutions {
691+
QueryInterfaceTypeSubstitutions Query;
692+
693+
public:
694+
BuildForwardingSubstitutions(const GenericEnvironment *self)
695+
: Query(self) { }
696+
697+
Type operator()(SubstitutableType *type) const;
698+
};
699+
} // end anonymous namespace
700+
701+
Type BuildForwardingSubstitutions::operator()(SubstitutableType *type) const {
702+
if (auto resultType = Query(type)) {
703+
auto param = type->castTo<GenericTypeParamType>();
704+
if (!param->isParameterPack())
705+
return resultType;
706+
return PackType::getSingletonPackExpansion(resultType);
707+
}
708+
return Type();
709+
}
710+
684711
SubstitutionMap GenericEnvironment::getForwardingSubstitutionMap() const {
685712
auto genericSig = getGenericSignature();
686713
return SubstitutionMap::get(genericSig,
687-
QueryInterfaceTypeSubstitutions(this),
714+
BuildForwardingSubstitutions(this),
688715
MakeAbstractConformanceForGenericType());
689716
}
690717

lib/AST/GenericSignature.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -579,10 +579,13 @@ unsigned GenericParamKey::findIndexIn(
579579

580580
SubstitutionMap GenericSignatureImpl::getIdentitySubstitutionMap() const {
581581
return SubstitutionMap::get(const_cast<GenericSignatureImpl *>(this),
582-
[](SubstitutableType *t) -> Type {
583-
return Type(cast<GenericTypeParamType>(t));
584-
},
585-
MakeAbstractConformanceForGenericType());
582+
[](SubstitutableType *t) -> Type {
583+
auto param = cast<GenericTypeParamType>(t);
584+
if (!param->isParameterPack())
585+
return param;
586+
return PackType::getSingletonPackExpansion(param);
587+
},
588+
MakeAbstractConformanceForGenericType());
586589
}
587590

588591
GenericTypeParamType *GenericSignatureImpl::getSugaredType(

lib/AST/RequirementMachine/Diagnostics.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,15 @@ bool swift::rewriting::diagnoseRequirementErrors(
209209

210210
break;
211211
}
212+
213+
case RequirementError::Kind::UnsupportedSameElement: {
214+
if (error.requirement.hasError())
215+
break;
216+
217+
ctx.Diags.diagnose(loc, diag::unsupported_same_element);
218+
diagnosedError = true;
219+
break;
220+
}
212221
}
213222
}
214223

lib/AST/RequirementMachine/Diagnostics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ struct RequirementError {
4242
RecursiveRequirement,
4343
/// A redundant requirement, e.g. T == T.
4444
RedundantRequirement,
45+
/// A not-yet-supported same-element requirement, e.g. each T == Int.
46+
UnsupportedSameElement,
4547
} kind;
4648

4749
/// The invalid requirement.
@@ -100,6 +102,10 @@ struct RequirementError {
100102
SourceLoc loc) {
101103
return {Kind::RecursiveRequirement, req, loc};
102104
}
105+
106+
static RequirementError forSameElement(Requirement req, SourceLoc loc) {
107+
return {Kind::UnsupportedSameElement, req, loc};
108+
}
103109
};
104110

105111
/// Policy for the fixit that transforms 'T : S' where 'S' is not a protocol

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,15 @@ static void desugarSameTypeRequirement(Type lhs, Type rhs, SourceLoc loc,
194194

195195
bool mismatch(TypeBase *firstType, TypeBase *secondType,
196196
Type sugaredFirstType) {
197+
// If one side is a parameter pack, this is a same-element requirement, which
198+
// is not yet supported.
199+
if (firstType->isParameterPack() != secondType->isParameterPack()) {
200+
errors.push_back(RequirementError::forSameElement(
201+
{RequirementKind::SameType, sugaredFirstType, secondType}, loc));
202+
recordedErrors = true;
203+
return true;
204+
}
205+
197206
if (firstType->isTypeParameter() && secondType->isTypeParameter()) {
198207
result.emplace_back(RequirementKind::SameType,
199208
sugaredFirstType, secondType);

lib/AST/SubstitutionMap.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,11 @@ SubstitutionMap SubstitutionMap::get(GenericSignature genericSig,
226226

227227
// Record the replacement.
228228
Type replacement = Type(gp).subst(subs, lookupConformance);
229+
230+
assert((!replacement || replacement->hasError() ||
231+
gp->isParameterPack() == replacement->is<PackType>()) &&
232+
"replacement for pack parameter must be a pack type");
233+
229234
replacementTypes.push_back(replacement);
230235
});
231236

0 commit comments

Comments
 (0)