Skip to content

Commit 747b060

Browse files
committed
RequirementMachine: Correct desugaring of same-type requirements with pack expansion on both sides
1 parent ccd6407 commit 747b060

File tree

4 files changed

+81
-13
lines changed

4 files changed

+81
-13
lines changed

include/swift/AST/TypeMatcher.h

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ namespace swift {
5151
/// or false to indicate that matching should exit early.
5252
template<typename ImplClass>
5353
class TypeMatcher {
54+
public:
55+
enum class Position : uint8_t {
56+
Type,
57+
Shape
58+
};
59+
60+
private:
5461
class MatchVisitor : public CanTypeVisitor<MatchVisitor, bool, Type, Type> {
5562
TypeMatcher &Matcher;
5663

@@ -192,11 +199,24 @@ class TypeMatcher {
192199

193200
bool visitPackExpansionType(CanPackExpansionType firstPE, Type secondType,
194201
Type sugaredFirstType) {
195-
if (auto secondInOut = secondType->getAs<PackExpansionType>()) {
196-
return this->visit(firstPE.getPatternType(),
197-
secondInOut->getPatternType(),
198-
sugaredFirstType->castTo<PackExpansionType>()
199-
->getPatternType());
202+
if (auto secondExpansion = secondType->getAs<PackExpansionType>()) {
203+
if (!this->visit(firstPE.getPatternType(),
204+
secondExpansion->getPatternType(),
205+
sugaredFirstType->castTo<PackExpansionType>()
206+
->getPatternType())) {
207+
return false;
208+
}
209+
210+
Matcher.asDerived().pushPosition(Position::Shape);
211+
if (!this->visit(firstPE.getCountType(),
212+
secondExpansion->getCountType(),
213+
sugaredFirstType->castTo<PackExpansionType>()
214+
->getCountType())) {
215+
return false;
216+
}
217+
Matcher.asDerived().popPosition(Position::Shape);
218+
219+
return true;
200220
}
201221

202222
return mismatch(firstPE.getPointer(), secondType, sugaredFirstType);
@@ -524,6 +544,9 @@ class TypeMatcher {
524544

525545
bool alwaysMismatchTypeParameters() const { return false; }
526546

547+
void pushPosition(Position pos) {}
548+
void popPosition(Position pos) {}
549+
527550
ImplClass &asDerived() { return static_cast<ImplClass &>(*this); }
528551

529552
const ImplClass &asDerived() const {

lib/AST/RequirementMachine/PropertyUnification.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
#include "swift/AST/Decl.h"
2626
#include "swift/AST/LayoutConstraint.h"
27-
#include "swift/AST/TypeMatcher.h"
2827
#include "swift/AST/Types.h"
2928
#include <algorithm>
3029
#include <vector>

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ static void desugarSameTypeRequirement(Requirement req, SourceLoc loc,
180180
SourceLoc loc;
181181
SmallVectorImpl<Requirement> &result;
182182
SmallVectorImpl<RequirementError> &errors;
183+
SmallVector<Position, 2> stack;
183184

184185
public:
185186
bool recordedErrors = false;
@@ -191,32 +192,53 @@ static void desugarSameTypeRequirement(Requirement req, SourceLoc loc,
191192

192193
bool alwaysMismatchTypeParameters() const { return true; }
193194

195+
void pushPosition(Position pos) {
196+
stack.push_back(pos);
197+
}
198+
199+
void popPosition(Position pos) {
200+
assert(stack.back() == pos);
201+
stack.pop_back();
202+
}
203+
204+
Position getPosition() const {
205+
if (stack.empty()) return Position::Type;
206+
return stack.back();
207+
}
208+
194209
bool mismatch(TypeBase *firstType, TypeBase *secondType,
195210
Type sugaredFirstType) {
211+
RequirementKind kind;
212+
switch (getPosition()) {
213+
case Position::Type:
214+
kind = RequirementKind::SameType;
215+
break;
216+
case Position::Shape:
217+
kind = RequirementKind::SameShape;
218+
break;
219+
}
220+
196221
// If one side is a parameter pack, this is a same-element requirement, which
197222
// is not yet supported.
198223
if (firstType->isParameterPack() != secondType->isParameterPack()) {
199224
errors.push_back(RequirementError::forSameElement(
200-
{RequirementKind::SameType, sugaredFirstType, secondType}, loc));
225+
{kind, sugaredFirstType, secondType}, loc));
201226
recordedErrors = true;
202227
return true;
203228
}
204229

205230
if (firstType->isTypeParameter() && secondType->isTypeParameter()) {
206-
result.emplace_back(RequirementKind::SameType,
207-
sugaredFirstType, secondType);
231+
result.emplace_back(kind, sugaredFirstType, secondType);
208232
return true;
209233
}
210234

211235
if (firstType->isTypeParameter()) {
212-
result.emplace_back(RequirementKind::SameType,
213-
sugaredFirstType, secondType);
236+
result.emplace_back(kind, sugaredFirstType, secondType);
214237
return true;
215238
}
216239

217240
if (secondType->isTypeParameter()) {
218-
result.emplace_back(RequirementKind::SameType,
219-
secondType, sugaredFirstType);
241+
result.emplace_back(kind, secondType, sugaredFirstType);
220242
return true;
221243
}
222244

test/Generics/pack-shape-requirements.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,27 @@ protocol Q: P where A: Q {}
8383
// CHECK-LABEL: sameType2
8484
// CHECK-NEXT: Generic signature: <each T, each U where repeat each T : Q, repeat each U : Q, repeat (each T).[P]A.[P]A == (each U).[P]A.[P]A>
8585
func sameType2<each T, each U>(_: repeat (each T, each U)) where repeat each T: Q, repeat each U: Q, repeat (each T).A.A == (each U).A.A {}
86+
87+
88+
//////
89+
///
90+
/// A same-type requirement between two pack expansion types
91+
/// should desugar to a same-shape requirement between their
92+
/// count types and a same-type requirement between their
93+
/// element types.
94+
///
95+
//////
96+
97+
typealias First<T, U> = T
98+
typealias Shape<each T> = (repeat First<(), each T>)
99+
100+
// CHECK-LABEL: sameTypeDesugar1
101+
// CHECK-NEXT: Generic signature: <each T, each U where (repeat (each T, each U)) : Any>
102+
func sameTypeDesugar1<each T, each U>(t: repeat each T, u: repeat each U)
103+
where Shape<repeat each T> == Shape<repeat each U> {}
104+
105+
// CHECK-LABEL: sameTypeDesugar2
106+
// CHECK-NEXT: Generic signature: <each T, each U where repeat each T : P, (repeat (each T, each U)) : Any, repeat each U : P>
107+
func sameTypeDesugar2<each T: P, each U: P>(t: repeat each T, u: repeat each U)
108+
where Shape<repeat (each T).A> == Shape<repeat (each U).A> {}
109+

0 commit comments

Comments
 (0)