Skip to content

Commit 766a191

Browse files
committed
Merge pull request #67292 from sophiapoirier/pack-stored-propety-shadows-global
[ConstraintSystem] implement implicit pack materialization for abstract tuples instead of explicit '.element'
1 parent 241d0b8 commit 766a191

File tree

11 files changed

+149
-40
lines changed

11 files changed

+149
-40
lines changed

include/swift/AST/KnownIdentifiers.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,6 @@ IDENTIFIER(size)
325325
IDENTIFIER(speed)
326326
IDENTIFIER(unchecked)
327327
IDENTIFIER(unsafe)
328-
IDENTIFIER(element)
329328

330329
// The singleton instance of TupleTypeDecl in the Builtin module
331330
IDENTIFIER(TheTupleType)

include/swift/Sema/Constraint.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ enum class ConstraintKind : char {
234234
ExplicitGenericArguments,
235235
/// Both (first and second) pack types should have the same reduced shape.
236236
SameShape,
237+
/// The first type is a tuple containing a single unlabeled element that is a
238+
/// pack expansion. The second type is that pack expansion.
239+
MaterializePackExpansion,
237240
};
238241

239242
/// Classification of the different kinds of constraints.
@@ -703,6 +706,7 @@ class Constraint final : public llvm::ilist_node<Constraint>,
703706
case ConstraintKind::UnresolvedMemberChainBase:
704707
case ConstraintKind::PackElementOf:
705708
case ConstraintKind::SameShape:
709+
case ConstraintKind::MaterializePackExpansion:
706710
return ConstraintClassification::Relational;
707711

708712
case ConstraintKind::ValueMember:

include/swift/Sema/ConstraintSystem.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4938,6 +4938,13 @@ class ConstraintSystem {
49384938
TypeMatchOptions flags,
49394939
ConstraintLocatorBuilder locator);
49404940

4941+
/// Remove the tuple wrapping of left-hand type if it contains only a single
4942+
/// unlabeled element that is a pack expansion.
4943+
SolutionKind
4944+
simplifyMaterializePackExpansionConstraint(Type type1, Type type2,
4945+
TypeMatchOptions flags,
4946+
ConstraintLocatorBuilder locator);
4947+
49414948
public: // FIXME: Public for use by static functions.
49424949
/// Simplify a conversion constraint with a fix applied to it.
49434950
SolutionKind simplifyFixConstraint(ConstraintFix *fix, Type type1, Type type2,
@@ -5480,7 +5487,8 @@ class OpenPackElementType {
54805487
}
54815488

54825489
cs.addConstraint(ConstraintKind::PackElementOf, elementType,
5483-
packType, cs.getConstraintLocator(elementEnv));
5490+
packType->getRValueType(),
5491+
cs.getConstraintLocator(elementEnv));
54845492
return elementType;
54855493
}
54865494
};
@@ -6163,6 +6171,9 @@ void dumpAnchor(ASTNode anchor, SourceManager *SM, raw_ostream &out);
61636171

61646172
bool isSingleUnlabeledPackExpansionTuple(Type type);
61656173

6174+
/// \returns null if \c type is not a single unlabeled pack expansion tuple.
6175+
Type getPatternTypeOfSingleUnlabeledPackExpansionTuple(Type type);
6176+
61666177
} // end namespace constraints
61676178

61686179
template<typename ...Args>

lib/Sema/CSApply.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3852,9 +3852,8 @@ namespace {
38523852
auto packRefType = cs.getType(packRefExpr);
38533853
if (auto *tuple = packRefType->getRValueType()->getAs<TupleType>();
38543854
tuple && tuple->isSingleUnlabeledPackExpansion()) {
3855-
auto *expansion =
3856-
tuple->getElementType(0)->castTo<PackExpansionType>();
3857-
auto patternType = expansion->getPatternType();
3855+
auto patternType =
3856+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(tuple);
38583857
auto *materializedPackExpr = MaterializePackExpr::create(
38593858
cs.getASTContext(), packRefExpr, packRefExpr->getLoc(),
38603859
patternType, /*implicit*/ true);

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,7 @@ void PotentialBindings::infer(Constraint *constraint) {
14831483
case ConstraintKind::ExplicitGenericArguments:
14841484
case ConstraintKind::PackElementOf:
14851485
case ConstraintKind::SameShape:
1486+
case ConstraintKind::MaterializePackExpansion:
14861487
// Constraints from which we can't do anything.
14871488
break;
14881489

lib/Sema/CSDiagnostics.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6170,8 +6170,10 @@ bool InvalidPackElement::diagnoseAsError() {
61706170
}
61716171

61726172
bool InvalidPackReference::diagnoseAsError() {
6173-
emitDiagnostic(diag::pack_reference_outside_expansion,
6174-
packType);
6173+
auto patternType =
6174+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(packType);
6175+
auto diagnosisType = patternType ? patternType : packType;
6176+
emitDiagnostic(diag::pack_reference_outside_expansion, diagnosisType);
61756177
return true;
61766178
}
61776179

lib/Sema/CSGen.cpp

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1091,10 +1091,6 @@ namespace {
10911091

10921092
Type openPackElement(Type packType, ConstraintLocator *locator,
10931093
PackExpansionExpr *packElementEnvironment) {
1094-
// If 'each t' is written outside of a pack expansion expression, allow the
1095-
// type to bind to a hole. The invalid pack reference will be diagnosed when
1096-
// attempting to bind the type variable for the underlying pack reference to
1097-
// a pack type without TVO_CanBindToPack.
10981094
if (!packElementEnvironment) {
10991095
return CS.createTypeVariable(locator,
11001096
TVO_CanBindToHole | TVO_CanBindToNoEscape);
@@ -3103,8 +3099,14 @@ namespace {
31033099
llvm_unreachable("unsupported pack reference ASTNode");
31043100
}
31053101

3102+
auto *elementShape = CS.createTypeVariable(
3103+
CS.getConstraintLocator(pack, ConstraintLocator::PackShape),
3104+
TVO_CanBindToPack);
31063105
CS.addConstraint(
3107-
ConstraintKind::ShapeOf, expansionType->getCountType(), packType,
3106+
ConstraintKind::ShapeOf, elementShape, packType,
3107+
CS.getConstraintLocator(pack, ConstraintLocator::PackShape));
3108+
CS.addConstraint(
3109+
ConstraintKind::Equal, elementShape, expansionType->getCountType(),
31083110
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
31093111
}
31103112

@@ -3113,27 +3115,31 @@ namespace {
31133115

31143116
Type visitPackElementExpr(PackElementExpr *expr) {
31153117
auto packType = CS.getType(expr->getPackRefExpr());
3116-
3117-
if (isSingleUnlabeledPackExpansionTuple(packType)) {
3118-
packType =
3119-
addMemberRefConstraints(expr, expr->getPackRefExpr(),
3120-
DeclNameRef(CS.getASTContext().Id_element),
3121-
FunctionRefKind::Unapplied, {});
3122-
CS.setType(expr->getPackRefExpr(), packType);
3123-
}
3124-
31253118
auto *packEnvironment = CS.getPackEnvironment(expr);
3119+
auto elementType = openPackElement(
3120+
packType, CS.getConstraintLocator(expr), packEnvironment);
31263121
if (packEnvironment) {
31273122
auto expansionType =
31283123
CS.getType(packEnvironment)->castTo<PackExpansionType>();
31293124
CS.addConstraint(ConstraintKind::ShapeOf, expansionType->getCountType(),
3130-
packType,
3125+
elementType,
31313126
CS.getConstraintLocator(packEnvironment,
31323127
ConstraintLocator::PackShape));
3128+
auto *elementShape = CS.createTypeVariable(
3129+
CS.getConstraintLocator(expr, ConstraintLocator::PackShape),
3130+
TVO_CanBindToPack);
3131+
CS.addConstraint(
3132+
ConstraintKind::ShapeOf, elementShape, elementType,
3133+
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
3134+
CS.addConstraint(
3135+
ConstraintKind::Equal, elementShape, expansionType->getCountType(),
3136+
CS.getConstraintLocator(expr, ConstraintLocator::PackShape));
3137+
} else {
3138+
CS.recordFix(AllowInvalidPackReference::create(
3139+
CS, packType, CS.getConstraintLocator(expr->getPackRefExpr())));
31333140
}
31343141

3135-
return openPackElement(packType, CS.getConstraintLocator(expr),
3136-
packEnvironment);
3142+
return elementType;
31373143
}
31383144

31393145
Type visitMaterializePackExpr(MaterializePackExpr *expr) {

lib/Sema/CSSimplify.cpp

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,20 @@ static bool isPackExpansionType(Type type) {
129129

130130
bool constraints::isSingleUnlabeledPackExpansionTuple(Type type) {
131131
auto *tuple = type->getRValueType()->getAs<TupleType>();
132-
// TODO: drop no name requirement
133132
return tuple && (tuple->getNumElements() == 1) &&
134133
isPackExpansionType(tuple->getElementType(0)) &&
135134
!tuple->getElement(0).hasName();
136135
}
137136

137+
Type constraints::getPatternTypeOfSingleUnlabeledPackExpansionTuple(Type type) {
138+
if (!isSingleUnlabeledPackExpansionTuple(type)) {
139+
return {};
140+
}
141+
auto tuple = type->getRValueType()->castTo<TupleType>();
142+
auto *expansion = tuple->getElementType(0)->castTo<PackExpansionType>();
143+
return expansion->getPatternType();
144+
}
145+
138146
static bool containsPackExpansionType(ArrayRef<AnyFunctionType::Param> params) {
139147
return llvm::any_of(params, [&](const auto &param) {
140148
return isPackExpansionType(param.getPlainType());
@@ -2283,6 +2291,7 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
22832291
case ConstraintKind::ShapeOf:
22842292
case ConstraintKind::ExplicitGenericArguments:
22852293
case ConstraintKind::SameShape:
2294+
case ConstraintKind::MaterializePackExpansion:
22862295
llvm_unreachable("Bad constraint kind in matchTupleTypes()");
22872296
}
22882297

@@ -2643,6 +2652,7 @@ static bool matchFunctionRepresentations(FunctionType::ExtInfo einfo1,
26432652
case ConstraintKind::ShapeOf:
26442653
case ConstraintKind::ExplicitGenericArguments:
26452654
case ConstraintKind::SameShape:
2655+
case ConstraintKind::MaterializePackExpansion:
26462656
return true;
26472657
}
26482658

@@ -3161,6 +3171,7 @@ ConstraintSystem::matchFunctionTypes(FunctionType *func1, FunctionType *func2,
31613171
case ConstraintKind::ShapeOf:
31623172
case ConstraintKind::ExplicitGenericArguments:
31633173
case ConstraintKind::SameShape:
3174+
case ConstraintKind::MaterializePackExpansion:
31643175
llvm_unreachable("Not a relational constraint");
31653176
}
31663177

@@ -6817,6 +6828,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
68176828
case ConstraintKind::ShapeOf:
68186829
case ConstraintKind::ExplicitGenericArguments:
68196830
case ConstraintKind::SameShape:
6831+
case ConstraintKind::MaterializePackExpansion:
68206832
llvm_unreachable("Not a relational constraint");
68216833
}
68226834
}
@@ -9121,13 +9133,13 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
91219133
}
91229134

91239135
if (isSingleUnlabeledPackExpansionTuple(patternType)) {
9124-
auto *elementVar =
9125-
createTypeVariable(getConstraintLocator(locator), /*options=*/0);
9126-
addValueMemberConstraint(
9127-
patternType, DeclNameRef(getASTContext().Id_element), elementVar, DC,
9128-
FunctionRefKind::Unapplied, {},
9129-
getConstraintLocator(locator, {ConstraintLocator::Member}));
9130-
patternType = elementVar;
9136+
auto *packVar =
9137+
createTypeVariable(getConstraintLocator(locator), TVO_CanBindToPack);
9138+
addConstraint(ConstraintKind::MaterializePackExpansion, patternType,
9139+
packVar,
9140+
getConstraintLocator(locator, {ConstraintLocator::Member}));
9141+
addConstraint(ConstraintKind::PackElementOf, elementType, packVar, locator);
9142+
return SolutionKind::Solved;
91319143
}
91329144

91339145
// Let's try to resolve element type based on the pattern type.
@@ -9147,11 +9159,19 @@ ConstraintSystem::simplifyPackElementOfConstraint(Type first, Type second,
91479159
if (!shapeClass->is<PackArchetypeType>()) {
91489160
if (recordFix(AllowInvalidPackElement::create(*this, patternType, loc)))
91499161
return SolutionKind::Error;
9162+
} else {
9163+
auto envShape = PackExpansionEnvironments.find(loc);
9164+
if (envShape == PackExpansionEnvironments.end()) {
9165+
return SolutionKind::Error;
9166+
}
9167+
auto *fix = SkipSameShapeRequirement::create(
9168+
*this, envShape->second.second, shapeClass,
9169+
getConstraintLocator(loc, ConstraintLocator::PackShape));
9170+
if (recordFix(fix)) {
9171+
return SolutionKind::Error;
9172+
}
91509173
}
91519174

9152-
// Only other posibility is that there is a shape mismatch between
9153-
// elements of the pack expansion pattern which is detected separately.
9154-
91559175
recordAnyTypeVarAsPotentialHole(elementType);
91569176
return SolutionKind::Solved;
91579177
}
@@ -13504,6 +13524,37 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifySameShapeConstraint(
1350413524
return SolutionKind::Error;
1350513525
}
1350613526

13527+
ConstraintSystem::SolutionKind
13528+
ConstraintSystem::simplifyMaterializePackExpansionConstraint(
13529+
Type type1, Type type2, TypeMatchOptions flags,
13530+
ConstraintLocatorBuilder locator) {
13531+
auto formUnsolved = [&]() {
13532+
// If we're supposed to generate constraints, do so.
13533+
if (flags.contains(TMF_GenerateConstraints)) {
13534+
auto *explictGenericArgs =
13535+
Constraint::create(*this, ConstraintKind::MaterializePackExpansion,
13536+
type1, type2, getConstraintLocator(locator));
13537+
13538+
addUnsolvedConstraint(explictGenericArgs);
13539+
return SolutionKind::Solved;
13540+
}
13541+
13542+
return SolutionKind::Unsolved;
13543+
};
13544+
13545+
type1 = simplifyType(type1);
13546+
if (type1->hasTypeVariable()) {
13547+
return formUnsolved();
13548+
}
13549+
if (auto patternType =
13550+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(type1)) {
13551+
addConstraint(ConstraintKind::Equal, patternType, type2, locator);
13552+
return SolutionKind::Solved;
13553+
}
13554+
13555+
return SolutionKind::Error;
13556+
}
13557+
1350713558
ConstraintSystem::SolutionKind
1350813559
ConstraintSystem::simplifyExplicitGenericArgumentsConstraint(
1350913560
Type type1, Type type2, TypeMatchOptions flags,
@@ -15115,6 +15166,10 @@ ConstraintSystem::addConstraintImpl(ConstraintKind kind, Type first,
1511515166
return simplifyExplicitGenericArgumentsConstraint(
1511615167
first, second, subflags, locator);
1511715168

15169+
case ConstraintKind::MaterializePackExpansion:
15170+
return simplifyMaterializePackExpansionConstraint(first, second, subflags,
15171+
locator);
15172+
1511815173
case ConstraintKind::ValueMember:
1511915174
case ConstraintKind::UnresolvedValueMember:
1512015175
case ConstraintKind::ValueWitness:
@@ -15694,6 +15749,11 @@ ConstraintSystem::simplifyConstraint(const Constraint &constraint) {
1569415749
return simplifyExplicitGenericArgumentsConstraint(
1569515750
constraint.getFirstType(), constraint.getSecondType(),
1569615751
/*flags*/ llvm::None, constraint.getLocator());
15752+
15753+
case ConstraintKind::MaterializePackExpansion:
15754+
return simplifyMaterializePackExpansionConstraint(
15755+
constraint.getFirstType(), constraint.getSecondType(),
15756+
/*flags*/ llvm::None, constraint.getLocator());
1569715757
}
1569815758

1569915759
llvm_unreachable("Unhandled ConstraintKind in switch.");

lib/Sema/Constraint.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second,
8383
case ConstraintKind::ShapeOf:
8484
case ConstraintKind::ExplicitGenericArguments:
8585
case ConstraintKind::SameShape:
86+
case ConstraintKind::MaterializePackExpansion:
8687
assert(!First.isNull());
8788
assert(!Second.isNull());
8889
break;
@@ -173,6 +174,7 @@ Constraint::Constraint(ConstraintKind Kind, Type First, Type Second, Type Third,
173174
case ConstraintKind::ShapeOf:
174175
case ConstraintKind::ExplicitGenericArguments:
175176
case ConstraintKind::SameShape:
177+
case ConstraintKind::MaterializePackExpansion:
176178
llvm_unreachable("Wrong constructor");
177179

178180
case ConstraintKind::KeyPath:
@@ -322,6 +324,7 @@ Constraint *Constraint::clone(ConstraintSystem &cs) const {
322324
case ConstraintKind::ShapeOf:
323325
case ConstraintKind::ExplicitGenericArguments:
324326
case ConstraintKind::SameShape:
327+
case ConstraintKind::MaterializePackExpansion:
325328
return create(cs, getKind(), getFirstType(), getSecondType(), getLocator());
326329

327330
case ConstraintKind::ApplicableFunction:
@@ -580,6 +583,10 @@ void Constraint::print(llvm::raw_ostream &Out, SourceManager *sm,
580583
Out << " explicit generic argument binding ";
581584
break;
582585

586+
case ConstraintKind::MaterializePackExpansion:
587+
Out << " materialize pack expansion ";
588+
break;
589+
583590
case ConstraintKind::Disjunction:
584591
llvm_unreachable("disjunction handled above");
585592
case ConstraintKind::Conjunction:
@@ -750,6 +757,7 @@ gatherReferencedTypeVars(Constraint *constraint,
750757
case ConstraintKind::ShapeOf:
751758
case ConstraintKind::ExplicitGenericArguments:
752759
case ConstraintKind::SameShape:
760+
case ConstraintKind::MaterializePackExpansion:
753761
constraint->getFirstType()->getTypeVariables(typeVars);
754762
constraint->getSecondType()->getTypeVariables(typeVars);
755763
break;

lib/Sema/ConstraintSystem.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3608,9 +3608,8 @@ void ConstraintSystem::resolveOverload(ConstraintLocator *locator,
36083608
// In the future, _if_ the syntax allows for multiple expansions
36093609
// this code would have to be adjusted to project l-value from the
36103610
// base type just like TupleIndex does.
3611-
auto tuple = choice.getBaseType()->getRValueType()->castTo<TupleType>();
3612-
auto *expansion = tuple->getElementType(0)->castTo<PackExpansionType>();
3613-
adjustedRefType = expansion->getPatternType();
3611+
adjustedRefType =
3612+
getPatternTypeOfSingleUnlabeledPackExpansionTuple(choice.getBaseType());
36143613
refType = adjustedRefType;
36153614
break;
36163615
}
@@ -3866,7 +3865,8 @@ struct TypeSimplifier {
38663865
if (typeVar->getImpl().isPackExpansion() &&
38673866
!resolvedType->isEqual(typeVar) &&
38683867
!resolvedType->is<PackExpansionType>() &&
3869-
!resolvedType->is<PackType>()) {
3868+
!resolvedType->is<PackType>() &&
3869+
!resolvedType->is<PackArchetypeType>()) {
38703870
return resolvedType;
38713871
}
38723872
}

0 commit comments

Comments
 (0)