Skip to content

Commit 7881dc2

Browse files
committed
SILGen: Peephole existential-to-Any upcasts too.
Recognize an erasure of an opened existential and look through it.
1 parent ab622ab commit 7881dc2

File tree

2 files changed

+43
-17
lines changed

2 files changed

+43
-17
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3086,18 +3086,39 @@ namespace {
30863086

30873087
}
30883088

3089+
Expr *lookThroughExistentialErasures(Expr *argExpr) {
3090+
argExpr = argExpr->getSemanticsProvidingExpr();
3091+
3092+
// When converting from an existential type to a more general existential,
3093+
// the inner existential is opened first. Look through this pattern.
3094+
if (auto open = dyn_cast<OpenExistentialExpr>(argExpr)) {
3095+
auto subExpr = open->getSubExpr()->getSemanticsProvidingExpr();
3096+
while (auto erasure = dyn_cast<ErasureExpr>(subExpr)) {
3097+
subExpr = erasure->getSubExpr()->getSemanticsProvidingExpr();
3098+
}
3099+
// If we drilled down to the underlying opened existential, look
3100+
// through it.
3101+
if (subExpr == open->getOpaqueValue())
3102+
return open->getExistentialValue();
3103+
// TODO: Maybe there are other peepholes we could attempt on opened
3104+
// existentials?
3105+
return open;
3106+
}
3107+
3108+
// Look through ErasureExprs and try to bridge the underlying
3109+
// concrete value instead.
3110+
while (auto erasure = dyn_cast<ErasureExpr>(argExpr))
3111+
argExpr = erasure->getSubExpr()->getSemanticsProvidingExpr();
3112+
return argExpr;
3113+
}
3114+
30893115
/// Emit an argument expression that we know will be bridged to an
30903116
/// Objective-C object.
30913117
ManagedValue emitNativeToBridgedObjectArgument(Expr *argExpr,
30923118
SILType loweredSubstArgType,
30933119
AbstractionPattern origParamType,
30943120
SILParameterInfo param) {
3095-
argExpr = argExpr->getSemanticsProvidingExpr();
3096-
3097-
// Look through ErasureExprs and try to bridge the underlying
3098-
// concrete value instead.
3099-
while (auto erasure = dyn_cast<ErasureExpr>(argExpr))
3100-
argExpr = erasure->getSubExpr();
3121+
argExpr = lookThroughExistentialErasures(argExpr);
31013122

31023123
// Emit the argument.
31033124
auto contexts = getRValueEmissionContexts(loweredSubstArgType, param);

test/SILGen/objc_bridging_any.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,29 +16,34 @@ func passingToId<T: CP, U>(receiver: IdLover,
1616
generic: U,
1717
existential: P,
1818
any: Any) {
19-
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF:%.*]] : $IdLover,
19+
// CHECK: bb0([[SELF:%.*]] : $IdLover, [[STRING:%.*]] : $String, [[NSSTRING:%.*]] : $NSString, [[OBJECT:%.*]] : $AnyObject, [[CLASS_GENERIC:%.*]] : $T, [[CLASS_EXISTENTIAL:%.*]] : $CP
20+
21+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF]]
2022
// CHECK: [[BRIDGE_STRING:%.*]] = function_ref @_TFE10FoundationSS19_bridgeToObjectiveC
21-
// CHECK: [[NSSTRING:%.*]] = apply [[BRIDGE_STRING]]
22-
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING]] : $NSString : $NSString, $AnyObject
23+
// CHECK: [[BRIDGED:%.*]] = apply [[BRIDGE_STRING]]([[STRING]])
24+
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[BRIDGED]] : $NSString : $NSString, $AnyObject
2325
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
2426
receiver.takesId(string)
2527

26-
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF:%.*]] : $IdLover,
27-
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref {{%.*}} : $NSString : $NSString, $AnyObject
28+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF]] : $IdLover,
29+
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[NSSTRING]] : $NSString : $NSString, $AnyObject
2830
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
2931
receiver.takesId(nsString)
3032

31-
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF:%.*]] : $IdLover,
32-
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref {{%.*}} : $T : $T, $AnyObject
33+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF]] : $IdLover,
34+
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[CLASS_GENERIC]] : $T : $T, $AnyObject
3335
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
3436
receiver.takesId(classGeneric)
3537

36-
// TODO: Need to look through an (open_existential (erasure)) combo to upcast
37-
// an existential to Any.
38-
/*
38+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF]] : $IdLover,
39+
// CHECK: apply [[METHOD]]([[OBJECT]], [[SELF]])
3940
receiver.takesId(object)
41+
42+
// CHECK: [[METHOD:%.*]] = class_method [volatile] [[SELF]] : $IdLover,
43+
// CHECK: [[OPENED:%.*]] = open_existential_ref [[CLASS_EXISTENTIAL]] : $CP
44+
// CHECK: [[ANYOBJECT:%.*]] = init_existential_ref [[OPENED]]
45+
// CHECK: apply [[METHOD]]([[ANYOBJECT]], [[SELF]])
4046
receiver.takesId(classExistential)
41-
*/
4247

4348
// TODO: These cases need to perform a (to-be-implemented) universal
4449
// bridging conversion.

0 commit comments

Comments
 (0)