Skip to content

Commit 075db56

Browse files
committed
SILGen: Handle key paths with @objc optional subscript components
1 parent 8462493 commit 075db56

File tree

2 files changed

+34
-6
lines changed

2 files changed

+34
-6
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,11 +2867,20 @@ static SILFunction *getOrCreateKeyPathGetter(SILGenModule &SGM,
28672867

28682868
// Emit a dynamic method branch if the storage decl is an @objc optional
28692869
// requirement, or just a load otherwise.
2870-
if (property->getAttrs().hasAttribute<OptionalAttr>() &&
2871-
isa<VarDecl>(property)) {
2872-
resultRValue = subSGF.emitDynamicMemberRef(
2873-
loc, baseSubstValue.getValue(), ConcreteDeclRef(property, subs),
2874-
propertyType, SGFContext());
2870+
if (property->getAttrs().hasAttribute<OptionalAttr>()) {
2871+
const auto declRef = ConcreteDeclRef(property, subs);
2872+
2873+
if (isa<VarDecl>(property)) {
2874+
resultRValue =
2875+
subSGF.emitDynamicMemberRef(loc, baseSubstValue.getValue(), declRef,
2876+
propertyType, SGFContext());
2877+
} else {
2878+
assert(isa<SubscriptDecl>(property));
2879+
2880+
resultRValue = subSGF.emitDynamicSubscriptGetterApply(
2881+
loc, baseSubstValue.getValue(), declRef,
2882+
std::move(subscriptIndices), propertyType, SGFContext());
2883+
}
28752884
} else {
28762885
resultRValue = subSGF.emitRValueForStorageLoad(
28772886
loc, baseSubstValue, baseType, /*super*/ false, property,
@@ -3635,8 +3644,14 @@ SILGenModule::emitKeyPathComponentForDecl(SILLocation loc,
36353644
baseSubscriptTy = genSubscriptTy->substGenericArgs(subs);
36363645
auto baseSubscriptInterfaceTy = cast<AnyFunctionType>(
36373646
baseSubscriptTy->mapTypeOutOfContext()->getCanonicalType());
3647+
36383648
auto componentTy = baseSubscriptInterfaceTy.getResult();
3639-
3649+
if (decl->getAttrs().hasAttribute<OptionalAttr>()) {
3650+
// The component type for an @objc optional requirement needs to be
3651+
// wrapped in an optional
3652+
componentTy = OptionalType::get(componentTy)->getCanonicalType();
3653+
}
3654+
36403655
SmallVector<IndexTypePair, 4> indexTypes;
36413656
lowerKeyPathSubscriptIndexTypes(*this, indexTypes,
36423657
decl, subs,

test/SILGen/keypaths_objc.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,17 +160,30 @@ func dynamicMemberLookupMixedKeypaths(foo: DynamicClass<Foo>) {
160160

161161
@objc protocol ObjCProtoOptional {
162162
@objc optional var optionalProperty: Bool { get }
163+
164+
@objc optional subscript(_: Int) -> Bool { get }
163165
}
164166

165167
// CHECK-LABEL: sil hidden [ossa] @{{.*}}0B28ProtocolOptionalRequirementsyyF
166168
// CHECK: keypath $KeyPath<ObjCProtoOptional, Optional<Bool>>, (objc "optionalProperty"; root $ObjCProtoOptional; gettable_property $Optional<Bool>, id #ObjCProtoOptional.optionalProperty!getter.foreign : <Self where Self : ObjCProtoOptional> (Self) -> () -> Bool, getter @$[[PROP_GETTER:[_a-zA-Z0-9]+]]
169+
// CHECK: keypath $KeyPath<ObjCProtoOptional, Optional<Bool>>, (root $ObjCProtoOptional; gettable_property $Optional<Bool>, id #ObjCProtoOptional.subscript!getter.foreign : <Self where Self : ObjCProtoOptional> (Self) -> (Int) -> Bool, getter @$[[SUBSCR_GETTER:[_a-zA-Z0-9]+]]
167170
// CHECK: } // end sil function '${{.*}}0B28ProtocolOptionalRequirementsyyF'
168171
//
169172
// CHECK: sil shared [thunk] [ossa] @$[[PROP_GETTER]] : $@convention(thin) (@in_guaranteed ObjCProtoOptional) -> @out Optional<Bool> {
170173
// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $ObjCProtoOptional to $[[OPENED_TY:@opened\("[-A-F0-9]+"\) ObjCProtoOptional]]
171174
// CHECK: dynamic_method_br [[BASE]] : $[[OPENED_TY]], #ObjCProtoOptional.optionalProperty!getter.foreign, bb1
172175
// CHECK: bb1({{%[0-9]+}} : $@convention(objc_method) ([[OPENED_TY]]) -> ObjCBool)
173176
// CHECK: } // end sil function '$[[PROP_GETTER]]'
177+
//
178+
// CHECK: sil shared [thunk] [ossa] @$[[SUBSCR_GETTER]] : $@convention(thin) (@in_guaranteed ObjCProtoOptional, UnsafeRawPointer) -> @out Optional<Bool> {
179+
// CHECK: [[BASE:%[0-9]+]] = open_existential_ref {{%[0-9]+}} : $ObjCProtoOptional to $[[OPENED_TY:@opened\("[-A-F0-9]+"\) ObjCProtoOptional]]
180+
// CHECK: [[INDEX:%[0-9]+]] = load [trivial] {{%[0-9]+}} : $*Int
181+
// CHECK: dynamic_method_br [[BASE]] : $[[OPENED_TY]], #ObjCProtoOptional.subscript!getter.foreign, bb1, bb2
182+
// CHECK: bb1({{%[0-9]+}} : $@convention(objc_method) (Int, [[OPENED_TY]]) -> ObjCBool):
183+
// CHECK: %17 = apply {{%[0-9]+}}([[INDEX]]) : $@callee_guaranteed (Int) -> Bool
184+
// CHECK: bb2:
185+
// CHECK: } // end sil function '$[[SUBSCR_GETTER]]'
174186
func objcProtocolOptionalRequirements() {
175187
_ = \ObjCProtoOptional.optionalProperty
188+
_ = \ObjCProtoOptional.[0]
176189
}

0 commit comments

Comments
 (0)