Skip to content

Commit 1f4cca6

Browse files
committed
[CS] Fix nested subscript dynamic member lookups
Previously we would incorrectly attempt to treat a nested dynamic member lookup for a subscript as a member reference. Fix `isSubscriptMemberRef` such that we treat it as a subscript reference.
1 parent 2f658f1 commit 1f4cca6

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

lib/Sema/ConstraintLocator.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,9 +545,17 @@ void LocatorPathElt::dump(raw_ostream &out) const {
545545
/// e.g. `foo[0]` or `\Foo.[0]`
546546
bool ConstraintLocator::isSubscriptMemberRef() const {
547547
auto anchor = getAnchor();
548+
if (!anchor)
549+
return false;
550+
551+
// Look through dynamic member lookup since for a subscript reference the
552+
// dynamic member lookup is also a subscript reference.
548553
auto path = getPath();
554+
using KPDynamicMemberElt = LocatorPathElt::KeyPathDynamicMember;
555+
while (!path.empty() && path.back().is<KPDynamicMemberElt>())
556+
path = path.drop_back();
549557

550-
if (!anchor || path.empty())
558+
if (path.empty())
551559
return false;
552560

553561
return path.back().getKind() == ConstraintLocator::SubscriptMember;

test/Constraints/keypath_dynamic_member_lookup.swift

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,18 +227,18 @@ func test_keypath_dynamic_lookup_inside_keypath() {
227227
_ = \Lens<[[Int]]>.[0].count
228228
}
229229

230-
func test_recursive_dynamic_lookup(_ lens: Lens<Lens<Point>>) {
230+
func test_recursive_dynamic_lookup(_ pointLens: Lens<Lens<Point>>, _ arrLens: Lens<Lens<[Point]>>) {
231231
// CHECK: keypath $KeyPath<Point, Int>, (root $Point; stored_property #Point.x : $Int)
232232
// CHECK-NEXT: keypath $KeyPath<Lens<Point>, Lens<Int>>, (root $Lens<Point>; gettable_property $Lens<Int>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig : {{.*}})
233233
// CHECK: function_ref @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig
234-
_ = lens.x
234+
_ = pointLens.x
235235
// CHECK: keypath $KeyPath<Point, Int>, (root $Point; stored_property #Point.x : $Int)
236236
// CHECK: function_ref @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig
237-
_ = lens.obj.x
237+
_ = pointLens.obj.x
238238
// CHECK: [[FIRST_OBJ:%.*]] = struct_extract {{.*}} : $Lens<Lens<Point>>, #Lens.obj
239239
// CHECK-NEXT: [[SECOND_OBJ:%.*]] = struct_extract [[FIRST_OBJ]] : $Lens<Point>, #Lens.obj
240240
// CHECK-NEXT: struct_extract [[SECOND_OBJ]] : $Point, #Point.y
241-
_ = lens.obj.obj.y
241+
_ = pointLens.obj.obj.y
242242
// CHECK: keypath $KeyPath<Point, Int>, (root $Point; stored_property #Point.x : $Int)
243243
// CHECK-NEXT: keypath $KeyPath<Lens<Point>, Lens<Int>>, (root $Lens<Point>; gettable_property $Lens<Int>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig : {{.*}})
244244
// CHECK-NEXT: keypath $KeyPath<Lens<Lens<Point>>, Lens<Lens<Int>>>, (root $Lens<Lens<Point>>; gettable_property $Lens<Lens<Int>>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig : {{.*}})
@@ -249,6 +249,21 @@ func test_recursive_dynamic_lookup(_ lens: Lens<Lens<Point>>) {
249249
// CHECK-NEXT: keypath $KeyPath<Lens<Point>, Lens<Int>>, (root $Lens<Point>; gettable_property $Lens<Int>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig : {{.*}})
250250
// CHECK-NEXT: keypath $KeyPath<Lens<Lens<Rectangle>>, Lens<Lens<Int>>>, (root $Lens<Lens<Rectangle>>; settable_property $Lens<Lens<Point>>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig : {{.*}})
251251
_ = \Lens<Lens<Rectangle>>.topLeft.x
252+
253+
// CHECK: keypath $WritableKeyPath<Array<Point>, Point>, (root $Array<Point>; settable_property $Point, id @$sSayxSicig
254+
// CHECK-NEXT: keypath $WritableKeyPath<Lens<Array<Point>>, Lens<Point>>, (root $Lens<Array<Point>>; settable_property $Lens<Point>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig
255+
// CHECK: function_ref @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig
256+
// CHECK: keypath $KeyPath<Point, Int>, (root $Point; stored_property #Point.x : $Int)
257+
// CHECK-NEXT: keypath $KeyPath<Lens<Point>, Lens<Int>>, (root $Lens<Point>; gettable_property $Lens<Int>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig
258+
// CHECK: function_ref @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig
259+
_ = arrLens[0].x // arrLens[dynamicMember: \.[dynamicMember: \.[0]]][dynamicMember: \.[dynamicMember: \.x]]
260+
261+
_ = \Lens<Lens<[Point]>>.[0].x // \Lens<Lens<[Point]>>.[dynamicMember: \.[dynamicMember: \.[0]]].[dynamicMember: \.[dynamicMember: \.x]]
262+
// CHECK: keypath $WritableKeyPath<Array<Point>, Point>, (root $Array<Point>; settable_property $Point, id @$sSayxSicig
263+
// CHECK-NEXT: keypath $WritableKeyPath<Lens<Array<Point>>, Lens<Point>>, (root $Lens<Array<Point>>; settable_property $Lens<Point>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig
264+
// CHECK-NEXT: keypath $KeyPath<Point, Int>, (root $Point; stored_property #Point.x : $Int)
265+
// CHECK-NEXT: keypath $KeyPath<Lens<Point>, Lens<Int>>, (root $Lens<Point>; gettable_property $Lens<Int>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs7KeyPathCyxqd__G_tcluig
266+
// CHECK-NEXT: keypath $KeyPath<Lens<Lens<Array<Point>>>, Lens<Lens<Int>>>, (root $Lens<Lens<Array<Point>>>; settable_property $Lens<Lens<Point>>, id @$s29keypath_dynamic_member_lookup4LensV0B6MemberACyqd__Gs15WritableKeyPathCyxqd__G_tcluig
252267
}
253268

254269
@dynamicMemberLookup
@@ -558,3 +573,31 @@ struct S_54150 {
558573
// CHECK-NEXT: apply %{{.*}}<S_54150, T>({{.*}})
559574
}
560575
}
576+
577+
// https://github.com/swiftlang/swift/issues/56837
578+
@dynamicMemberLookup
579+
struct Issue56837<Value, Integer: FixedWidthInteger> {
580+
var value: Value
581+
init(_ value: Value) {
582+
self.value = value
583+
}
584+
subscript<T>(dynamicMember keyPath: KeyPath<Value, T>) -> T {
585+
get { return self.value[keyPath: keyPath] }
586+
}
587+
subscript(type value: Integer) -> Bool {
588+
get { return true }
589+
}
590+
}
591+
struct TestIssue56837 {
592+
typealias T1 = Issue56837<String, Int8>
593+
typealias T2 = Issue56837<T1, Int16>
594+
typealias T3 = Issue56837<T2, Int32>
595+
typealias T4 = Issue56837<T3, Int64>
596+
static func test() {
597+
let value: T4 = .init(.init(.init(.init("Swift"))))
598+
_ = value[type: Int64.max]
599+
_ = value[type: Int32.max]
600+
_ = value[type: Int16.max]
601+
_ = value[type: Int8.max]
602+
}
603+
}

0 commit comments

Comments
 (0)