Skip to content

Commit bb67cf8

Browse files
authored
Merge pull request #21355 from technicated/tuple-keypaths-2
Tuple KeyPaths
2 parents 67f62a1 + b37c2d5 commit bb67cf8

37 files changed

+939
-162
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,8 @@ ERROR(expected_sil_value_ownership_kind,none,
485485
"expected value ownership kind in SIL code", ())
486486
ERROR(expected_sil_colon,none,
487487
"expected ':' before %0", (StringRef))
488+
ERROR(expected_sil_tuple_index,none,
489+
"expected tuple element index", ())
488490

489491
// SIL Values
490492
ERROR(sil_value_redefinition,none,

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,6 @@ ERROR(expr_swift_keypath_empty, none,
508508
"key path must have at least one component", ())
509509
ERROR(expr_string_interpolation_outside_string,none,
510510
"string interpolation can only appear inside a string literal", ())
511-
ERROR(unsupported_keypath_tuple_element_reference,none,
512-
"key path cannot reference tuple elements", ())
513-
ERROR(expr_keypath_unimplemented_tuple,none,
514-
"key path support for tuples is not implemented", ())
515511
ERROR(expr_keypath_subscript_index_not_hashable, none,
516512
"subscript index of type %0 in a key path must be Hashable", (Type))
517513
ERROR(expr_smart_keypath_application_type_mismatch,none,

include/swift/AST/Expr.h

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4906,6 +4906,7 @@ class KeyPathExpr : public Expr {
49064906
OptionalChain,
49074907
OptionalWrap,
49084908
Identity,
4909+
TupleElement,
49094910
};
49104911

49114912
private:
@@ -4922,7 +4923,12 @@ class KeyPathExpr : public Expr {
49224923
Expr *SubscriptIndexExpr;
49234924
const Identifier *SubscriptLabelsData;
49244925
const ProtocolConformanceRef *SubscriptHashableConformancesData;
4925-
unsigned SubscriptSize;
4926+
4927+
union {
4928+
unsigned SubscriptSize;
4929+
unsigned TupleIndex;
4930+
};
4931+
49264932
Kind KindValue;
49274933
Type ComponentType;
49284934
SourceLoc Loc;
@@ -4935,6 +4941,13 @@ class KeyPathExpr : public Expr {
49354941
Kind kind,
49364942
Type type,
49374943
SourceLoc loc);
4944+
4945+
// Private constructor for tuple element kind
4946+
Component(unsigned tupleIndex, Type elementType, SourceLoc loc)
4947+
: Component(nullptr, {}, nullptr, {}, {}, Kind::TupleElement,
4948+
elementType, loc) {
4949+
TupleIndex = tupleIndex;
4950+
}
49384951

49394952
public:
49404953
Component()
@@ -5054,6 +5067,13 @@ class KeyPathExpr : public Expr {
50545067
selfLoc);
50555068
}
50565069

5070+
static Component forTupleElement(unsigned fieldNumber,
5071+
Type elementType,
5072+
SourceLoc loc) {
5073+
return Component(fieldNumber, elementType, loc);
5074+
}
5075+
5076+
50575077
SourceLoc getLoc() const {
50585078
return Loc;
50595079
}
@@ -5077,6 +5097,7 @@ class KeyPathExpr : public Expr {
50775097
case Kind::OptionalForce:
50785098
case Kind::Property:
50795099
case Kind::Identity:
5100+
case Kind::TupleElement:
50805101
return true;
50815102

50825103
case Kind::UnresolvedSubscript:
@@ -5100,6 +5121,7 @@ class KeyPathExpr : public Expr {
51005121
case Kind::UnresolvedProperty:
51015122
case Kind::Property:
51025123
case Kind::Identity:
5124+
case Kind::TupleElement:
51035125
return nullptr;
51045126
}
51055127
llvm_unreachable("unhandled kind");
@@ -5118,6 +5140,7 @@ class KeyPathExpr : public Expr {
51185140
case Kind::UnresolvedProperty:
51195141
case Kind::Property:
51205142
case Kind::Identity:
5143+
case Kind::TupleElement:
51215144
llvm_unreachable("no subscript labels for this kind");
51225145
}
51235146
llvm_unreachable("unhandled kind");
@@ -5139,6 +5162,7 @@ class KeyPathExpr : public Expr {
51395162
case Kind::UnresolvedProperty:
51405163
case Kind::Property:
51415164
case Kind::Identity:
5165+
case Kind::TupleElement:
51425166
return {};
51435167
}
51445168
llvm_unreachable("unhandled kind");
@@ -5160,6 +5184,7 @@ class KeyPathExpr : public Expr {
51605184
case Kind::OptionalForce:
51615185
case Kind::Property:
51625186
case Kind::Identity:
5187+
case Kind::TupleElement:
51635188
llvm_unreachable("no unresolved name for this kind");
51645189
}
51655190
llvm_unreachable("unhandled kind");
@@ -5178,10 +5203,30 @@ class KeyPathExpr : public Expr {
51785203
case Kind::OptionalWrap:
51795204
case Kind::OptionalForce:
51805205
case Kind::Identity:
5206+
case Kind::TupleElement:
51815207
llvm_unreachable("no decl ref for this kind");
51825208
}
51835209
llvm_unreachable("unhandled kind");
51845210
}
5211+
5212+
unsigned getTupleIndex() const {
5213+
switch (getKind()) {
5214+
case Kind::TupleElement:
5215+
return TupleIndex;
5216+
5217+
case Kind::Invalid:
5218+
case Kind::UnresolvedProperty:
5219+
case Kind::UnresolvedSubscript:
5220+
case Kind::OptionalChain:
5221+
case Kind::OptionalWrap:
5222+
case Kind::OptionalForce:
5223+
case Kind::Identity:
5224+
case Kind::Property:
5225+
case Kind::Subscript:
5226+
llvm_unreachable("no field number for this kind");
5227+
}
5228+
llvm_unreachable("unhandled kind");
5229+
}
51855230

51865231
Type getComponentType() const {
51875232
return ComponentType;

include/swift/SIL/SILInstruction.h

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2410,6 +2410,7 @@ class KeyPathPatternComponent {
24102410
StoredProperty,
24112411
GettableProperty,
24122412
SettableProperty,
2413+
TupleElement,
24132414
OptionalChain,
24142415
OptionalForce,
24152416
OptionalWrap,
@@ -2436,6 +2437,7 @@ class KeyPathPatternComponent {
24362437
static unsigned getPackedKind(Kind k) {
24372438
switch (k) {
24382439
case Kind::StoredProperty:
2440+
case Kind::TupleElement:
24392441
return PackedStored;
24402442
case Kind::GettableProperty:
24412443
case Kind::SettableProperty:
@@ -2452,7 +2454,15 @@ class KeyPathPatternComponent {
24522454
llvm::PointerIntPair<void *, KindPackingBits, unsigned> ValueAndKind;
24532455
llvm::PointerIntPair<SILFunction *, 2,
24542456
ComputedPropertyId::KindType> SetterAndIdKind;
2455-
ComputedPropertyId::ValueType IdValue;
2457+
2458+
// If this component refers to a tuple element then TupleIndex is the
2459+
// 1-based index of the element in the tuple, in order to allow the
2460+
// discrimination of the TupleElement Kind from the StoredProperty Kind
2461+
union {
2462+
unsigned TupleIndex = 0;
2463+
ComputedPropertyId::ValueType IdValue;
2464+
};
2465+
24562466
ArrayRef<Index> Indices;
24572467
struct {
24582468
SILFunction *Equal;
@@ -2497,6 +2507,14 @@ class KeyPathPatternComponent {
24972507
&& "not an optional component");
24982508
}
24992509

2510+
/// Constructor for tuple element.
2511+
KeyPathPatternComponent(unsigned tupleIndex, CanType componentType)
2512+
: ValueAndKind((void*)((uintptr_t)Kind::TupleElement << KindPackingBits), PackedStored),
2513+
TupleIndex(tupleIndex + 1),
2514+
ComponentType(componentType)
2515+
{
2516+
}
2517+
25002518
public:
25012519
KeyPathPatternComponent() : ValueAndKind(nullptr, 0) {}
25022520

@@ -2508,7 +2526,8 @@ class KeyPathPatternComponent {
25082526
auto packedKind = ValueAndKind.getInt();
25092527
switch ((PackedKind)packedKind) {
25102528
case PackedStored:
2511-
return Kind::StoredProperty;
2529+
return TupleIndex
2530+
? Kind::TupleElement : Kind::StoredProperty;
25122531
case PackedComputed:
25132532
return SetterAndIdKind.getPointer()
25142533
? Kind::SettableProperty : Kind::GettableProperty;
@@ -2531,6 +2550,7 @@ class KeyPathPatternComponent {
25312550
case Kind::OptionalChain:
25322551
case Kind::OptionalForce:
25332552
case Kind::OptionalWrap:
2553+
case Kind::TupleElement:
25342554
llvm_unreachable("not a stored property");
25352555
}
25362556
llvm_unreachable("unhandled kind");
@@ -2542,6 +2562,7 @@ class KeyPathPatternComponent {
25422562
case Kind::OptionalChain:
25432563
case Kind::OptionalForce:
25442564
case Kind::OptionalWrap:
2565+
case Kind::TupleElement:
25452566
llvm_unreachable("not a computed property");
25462567
case Kind::GettableProperty:
25472568
case Kind::SettableProperty:
@@ -2557,6 +2578,7 @@ class KeyPathPatternComponent {
25572578
case Kind::OptionalChain:
25582579
case Kind::OptionalForce:
25592580
case Kind::OptionalWrap:
2581+
case Kind::TupleElement:
25602582
llvm_unreachable("not a computed property");
25612583
case Kind::GettableProperty:
25622584
case Kind::SettableProperty:
@@ -2572,6 +2594,7 @@ class KeyPathPatternComponent {
25722594
case Kind::OptionalChain:
25732595
case Kind::OptionalForce:
25742596
case Kind::OptionalWrap:
2597+
case Kind::TupleElement:
25752598
llvm_unreachable("not a settable computed property");
25762599
case Kind::SettableProperty:
25772600
return SetterAndIdKind.getPointer();
@@ -2585,6 +2608,7 @@ class KeyPathPatternComponent {
25852608
case Kind::OptionalChain:
25862609
case Kind::OptionalForce:
25872610
case Kind::OptionalWrap:
2611+
case Kind::TupleElement:
25882612
return {};
25892613
case Kind::GettableProperty:
25902614
case Kind::SettableProperty:
@@ -2599,6 +2623,7 @@ class KeyPathPatternComponent {
25992623
case Kind::OptionalChain:
26002624
case Kind::OptionalForce:
26012625
case Kind::OptionalWrap:
2626+
case Kind::TupleElement:
26022627
llvm_unreachable("not a computed property");
26032628
case Kind::GettableProperty:
26042629
case Kind::SettableProperty:
@@ -2612,6 +2637,7 @@ class KeyPathPatternComponent {
26122637
case Kind::OptionalChain:
26132638
case Kind::OptionalForce:
26142639
case Kind::OptionalWrap:
2640+
case Kind::TupleElement:
26152641
llvm_unreachable("not a computed property");
26162642
case Kind::GettableProperty:
26172643
case Kind::SettableProperty:
@@ -2633,6 +2659,7 @@ class KeyPathPatternComponent {
26332659
case Kind::OptionalChain:
26342660
case Kind::OptionalForce:
26352661
case Kind::OptionalWrap:
2662+
case Kind::TupleElement:
26362663
llvm_unreachable("not a computed property");
26372664
case Kind::GettableProperty:
26382665
case Kind::SettableProperty:
@@ -2647,13 +2674,29 @@ class KeyPathPatternComponent {
26472674
case Kind::OptionalChain:
26482675
case Kind::OptionalForce:
26492676
case Kind::OptionalWrap:
2677+
case Kind::TupleElement:
26502678
llvm_unreachable("not a computed property");
26512679
case Kind::GettableProperty:
26522680
case Kind::SettableProperty:
26532681
return ExternalSubstitutions;
26542682
}
26552683
llvm_unreachable("unhandled kind");
26562684
}
2685+
2686+
unsigned getTupleIndex() const {
2687+
switch (getKind()) {
2688+
case Kind::StoredProperty:
2689+
case Kind::OptionalChain:
2690+
case Kind::OptionalForce:
2691+
case Kind::OptionalWrap:
2692+
case Kind::GettableProperty:
2693+
case Kind::SettableProperty:
2694+
llvm_unreachable("not a tuple element");
2695+
case Kind::TupleElement:
2696+
return TupleIndex - 1;
2697+
}
2698+
llvm_unreachable("unhandled kind");
2699+
}
26572700

26582701
static KeyPathPatternComponent
26592702
forComputedGettableProperty(ComputedPropertyId identifier,
@@ -2701,10 +2744,16 @@ class KeyPathPatternComponent {
27012744
case Kind::StoredProperty:
27022745
case Kind::GettableProperty:
27032746
case Kind::SettableProperty:
2747+
case Kind::TupleElement:
27042748
llvm_unreachable("not an optional kind");
27052749
}
27062750
return KeyPathPatternComponent(kind, ty);
27072751
}
2752+
2753+
static KeyPathPatternComponent forTupleElement(unsigned tupleIndex,
2754+
CanType ty) {
2755+
return KeyPathPatternComponent(tupleIndex, ty);
2756+
}
27082757

27092758
void incrementRefCounts() const;
27102759
void decrementRefCounts() const;

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,6 +2635,11 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
26352635
OS << "identity";
26362636
OS << '\n';
26372637
break;
2638+
case KeyPathExpr::Component::Kind::TupleElement:
2639+
OS << "tuple_element ";
2640+
OS << "#" << component.getTupleIndex();
2641+
OS << " ";
2642+
break;
26382643
}
26392644
OS << "type=";
26402645
component.getComponentType().print(OS);

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
10341034
case KeyPathExpr::Component::Kind::UnresolvedProperty:
10351035
case KeyPathExpr::Component::Kind::Invalid:
10361036
case KeyPathExpr::Component::Kind::Identity:
1037+
case KeyPathExpr::Component::Kind::TupleElement:
10371038
// No subexpr to visit.
10381039
break;
10391040
}

lib/AST/Expr.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,7 @@ KeyPathExpr::Component::Component(ASTContext *ctxForCopyingLabels,
22062206
: Decl(decl), SubscriptIndexExpr(indexExpr), KindValue(kind),
22072207
ComponentType(type), Loc(loc)
22082208
{
2209+
assert(kind != Kind::TupleElement || subscriptLabels.empty());
22092210
assert(subscriptLabels.size() == indexHashables.size()
22102211
|| indexHashables.empty());
22112212
SubscriptLabelsData = subscriptLabels.data();
@@ -2242,6 +2243,7 @@ void KeyPathExpr::Component::setSubscriptIndexHashableConformances(
22422243
case Kind::UnresolvedProperty:
22432244
case Kind::Property:
22442245
case Kind::Identity:
2246+
case Kind::TupleElement:
22452247
llvm_unreachable("no hashable conformances for this kind");
22462248
}
22472249
}

lib/IDE/SourceEntityWalker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,7 @@ std::pair<bool, Expr *> SemaAnnotator::walkToExprPre(Expr *E) {
361361
break;
362362
}
363363

364+
case KeyPathExpr::Component::Kind::TupleElement:
364365
case KeyPathExpr::Component::Kind::Invalid:
365366
case KeyPathExpr::Component::Kind::UnresolvedProperty:
366367
case KeyPathExpr::Component::Kind::UnresolvedSubscript:

0 commit comments

Comments
 (0)