Skip to content

Commit bd5d0c3

Browse files
authored
Merge pull request swiftlang#33486 from yersultan-17/dynamicmemberkeypathobjcstringfix
Added ObjC string for keypath argument of @dynamicmemberlookup
2 parents aa92419 + e374bc7 commit bd5d0c3

File tree

2 files changed

+70
-16
lines changed

2 files changed

+70
-16
lines changed

lib/Sema/CSApply.cpp

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,26 @@ namespace {
398398
return base.getOldType();
399399
}
400400

401+
/// Check whether it is possible to have an ObjC key path string for the keypath expression
402+
/// and set the key path string, if yes
403+
void checkAndSetObjCKeyPathString(KeyPathExpr *keyPath) {
404+
if (cs.getASTContext().LangOpts.EnableObjCInterop) {
405+
SmallString<64> compatStringBuf;
406+
if (buildObjCKeyPathString(keyPath, compatStringBuf)) {
407+
auto stringCopy = cs.getASTContext().AllocateCopy<char>(compatStringBuf.begin(),
408+
compatStringBuf.end());
409+
auto stringExpr = new (cs.getASTContext()) StringLiteralExpr(
410+
StringRef(stringCopy, compatStringBuf.size()),
411+
SourceRange(),
412+
/*implicit*/ true);
413+
cs.setType(
414+
stringExpr,
415+
cs.getASTContext().getStringDecl()->getDeclaredInterfaceType());
416+
keyPath->setObjCStringLiteralExpr(stringExpr);
417+
}
418+
}
419+
}
420+
401421
// Returns None if the AST does not contain enough information to recover
402422
// substitutions; this is different from an Optional(SubstitutionMap()),
403423
// indicating a valid call to a non-generic operator.
@@ -2041,6 +2061,11 @@ namespace {
20412061
keyPath->setParsedPath(componentExpr);
20422062
keyPath->resolveComponents(ctx, components);
20432063
cs.cacheExprTypes(keyPath);
2064+
2065+
// See whether there's an equivalent ObjC key path string we can produce
2066+
// for interop purposes.
2067+
checkAndSetObjCKeyPathString(keyPath);
2068+
20442069
return keyPath;
20452070
}
20462071

@@ -4755,22 +4780,7 @@ namespace {
47554780

47564781
// See whether there's an equivalent ObjC key path string we can produce
47574782
// for interop purposes.
4758-
if (cs.getASTContext().LangOpts.EnableObjCInterop) {
4759-
SmallString<64> compatStringBuf;
4760-
if (buildObjCKeyPathString(E, compatStringBuf)) {
4761-
auto stringCopy =
4762-
cs.getASTContext().AllocateCopy<char>(compatStringBuf.begin(),
4763-
compatStringBuf.end());
4764-
auto stringExpr = new (cs.getASTContext()) StringLiteralExpr(
4765-
StringRef(stringCopy, compatStringBuf.size()),
4766-
SourceRange(),
4767-
/*implicit*/ true);
4768-
cs.setType(
4769-
stringExpr,
4770-
cs.getASTContext().getStringDecl()->getDeclaredInterfaceType());
4771-
E->setObjCStringLiteralExpr(stringExpr);
4772-
}
4773-
}
4783+
checkAndSetObjCKeyPathString(E);
47744784

47754785
// The final component type ought to line up with the leaf type of the
47764786
// key path.

test/SILGen/keypaths_objc.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,3 +113,47 @@ class OverrideFrameworkObjCProperty: A {
113113
func overrideFrameworkObjCProperty() {
114114
let _ = \OverrideFrameworkObjCProperty.counter
115115
}
116+
117+
@dynamicMemberLookup
118+
class DynamicClass<Root> {
119+
init() {}
120+
subscript<T>(dynamicMember member: KeyPath<Root, T>) -> DynamicClass<T> {
121+
fatalError()
122+
}
123+
}
124+
125+
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupSimple
126+
func dynamicMemberLookupSimple(foo: DynamicClass<Foo>, nonobjc: DynamicClass<NonObjC>) {
127+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
128+
_ = foo.bar
129+
// CHECK: keypath $KeyPath<Foo, Int>, (objc "int"
130+
_ = foo.int
131+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
132+
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
133+
_ = foo.bar.foo
134+
// CHECK: keypath $KeyPath<Foo, NonObjC>, (root
135+
_ = foo.nonobjc
136+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "thisIsADifferentName"
137+
_ = foo.differentName
138+
// CHECK: keypath $KeyPath<NonObjC, Int>, (root
139+
_ = nonobjc.x
140+
// CHECK: keypath $KeyPath<NonObjC, NSObject>, (root
141+
_ = nonobjc.y
142+
}
143+
144+
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupNestedKeypaths
145+
func dynamicMemberLookupNestedKeypaths(foo: DynamicClass<Foo>) {
146+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
147+
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
148+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
149+
_ = foo.bar.foo.bar
150+
}
151+
152+
// CHECK-LABEL: sil hidden [ossa] @{{.*}}dynamicMemberLookupMixedKeypaths
153+
func dynamicMemberLookupMixedKeypaths(foo: DynamicClass<Foo>) {
154+
// CHECK: keypath $KeyPath<Foo, Bar>, (objc "bar"
155+
// CHECK: keypath $KeyPath<Bar, Foo>, (objc "foo"
156+
// CHECK: keypath $KeyPath<Foo, NonObjC>, (root
157+
// CHECK: keypath $KeyPath<NonObjC, NSObject>, (root
158+
_ = foo.bar.foo.nonobjc.y
159+
}

0 commit comments

Comments
 (0)