Skip to content

Commit e374bc7

Browse files
yersultan-17Yersultan Sapar
authored andcommitted
Added compatible ObjC string for keypath argument of the dynamic member lookup subscript.
1 parent 7ee6319 commit e374bc7

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
@@ -361,6 +361,26 @@ namespace {
361361
return base.getOldType();
362362
}
363363

364+
/// Check whether it is possible to have an ObjC key path string for the keypath expression
365+
/// and set the key path string, if yes
366+
void checkAndSetObjCKeyPathString(KeyPathExpr *keyPath) {
367+
if (cs.getASTContext().LangOpts.EnableObjCInterop) {
368+
SmallString<64> compatStringBuf;
369+
if (buildObjCKeyPathString(keyPath, compatStringBuf)) {
370+
auto stringCopy = cs.getASTContext().AllocateCopy<char>(compatStringBuf.begin(),
371+
compatStringBuf.end());
372+
auto stringExpr = new (cs.getASTContext()) StringLiteralExpr(
373+
StringRef(stringCopy, compatStringBuf.size()),
374+
SourceRange(),
375+
/*implicit*/ true);
376+
cs.setType(
377+
stringExpr,
378+
cs.getASTContext().getStringDecl()->getDeclaredInterfaceType());
379+
keyPath->setObjCStringLiteralExpr(stringExpr);
380+
}
381+
}
382+
}
383+
364384
// Returns None if the AST does not contain enough information to recover
365385
// substitutions; this is different from an Optional(SubstitutionMap()),
366386
// indicating a valid call to a non-generic operator.
@@ -2007,6 +2027,11 @@ namespace {
20072027
keyPath->setParsedPath(componentExpr);
20082028
keyPath->resolveComponents(ctx, components);
20092029
cs.cacheExprTypes(keyPath);
2030+
2031+
// See whether there's an equivalent ObjC key path string we can produce
2032+
// for interop purposes.
2033+
checkAndSetObjCKeyPathString(keyPath);
2034+
20102035
return keyPath;
20112036
}
20122037

@@ -4711,22 +4736,7 @@ namespace {
47114736

47124737
// See whether there's an equivalent ObjC key path string we can produce
47134738
// for interop purposes.
4714-
if (cs.getASTContext().LangOpts.EnableObjCInterop) {
4715-
SmallString<64> compatStringBuf;
4716-
if (buildObjCKeyPathString(E, compatStringBuf)) {
4717-
auto stringCopy =
4718-
cs.getASTContext().AllocateCopy<char>(compatStringBuf.begin(),
4719-
compatStringBuf.end());
4720-
auto stringExpr = new (cs.getASTContext()) StringLiteralExpr(
4721-
StringRef(stringCopy, compatStringBuf.size()),
4722-
SourceRange(),
4723-
/*implicit*/ true);
4724-
cs.setType(
4725-
stringExpr,
4726-
cs.getASTContext().getStringDecl()->getDeclaredInterfaceType());
4727-
E->setObjCStringLiteralExpr(stringExpr);
4728-
}
4729-
}
4739+
checkAndSetObjCKeyPathString(E);
47304740

47314741
// The final component type ought to line up with the leaf type of the
47324742
// 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)