Skip to content

Commit 239b852

Browse files
authored
Merge pull request #4288 from jckarter/bridged-block-nullability-3.0
[3.0] SILGen: Don't pretend to handle ObjC APIs that "lie" about block return optionality.
2 parents 0993200 + c2a2ef8 commit 239b852

File tree

2 files changed

+29
-13
lines changed

2 files changed

+29
-13
lines changed

lib/SILGen/SILGenExpr.cpp

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,12 +2251,28 @@ RValue RValueEmitter::visitRebindSelfInConstructorExpr(
22512251
return SGF.emitEmptyTupleRValue(E, C);
22522252
}
22532253

2254-
static bool isNullableTypeInC(SILModule &M, Type ty) {
2254+
static bool isVerbatimNullableTypeInC(SILModule &M, Type ty) {
22552255
ty = ty->getLValueOrInOutObjectType()->getReferenceStorageReferent();
22562256

2257-
// Functions, class instances, and @objc existentials are all nullable.
2258-
if (ty->hasReferenceSemantics())
2257+
// Class instances, and @objc existentials are all nullable.
2258+
if (ty->hasReferenceSemantics()) {
2259+
// So are blocks, but we usually bridge them to Swift closures before we get
2260+
// a chance to check for optional promotion, so we're already screwed if
2261+
// an API lies about nullability.
2262+
if (auto fnTy = ty->getAs<AnyFunctionType>()) {
2263+
switch (fnTy->getRepresentation()) {
2264+
// Carried verbatim from C.
2265+
case FunctionTypeRepresentation::Block:
2266+
case FunctionTypeRepresentation::CFunctionPointer:
2267+
return true;
2268+
// Was already bridged.
2269+
case FunctionTypeRepresentation::Swift:
2270+
case FunctionTypeRepresentation::Thin:
2271+
return false;
2272+
}
2273+
}
22592274
return true;
2275+
}
22602276

22612277
// Other types like UnsafePointer can also be nullable.
22622278
const DeclContext *DC = M.getAssociatedContext();
@@ -2287,7 +2303,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
22872303
// Functions that return non-optional reference type and were imported from
22882304
// Objective-C.
22892305
if (auto func = dyn_cast<FuncDecl>(decl)) {
2290-
assert((isNullableTypeInC(M, func->getResultType())
2306+
assert((isVerbatimNullableTypeInC(M, func->getResultType())
22912307
|| func->getResultType()->hasArchetype())
22922308
&& "func's result type is not nullable?!");
22932309
return func->hasClangNode();
@@ -2296,7 +2312,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
22962312
// Computed properties of non-optional reference type that were imported from
22972313
// Objective-C.
22982314
if (auto var = dyn_cast<VarDecl>(decl)) {
2299-
assert((isNullableTypeInC(M, var->getType()->getReferenceStorageReferent())
2315+
assert((isVerbatimNullableTypeInC(M, var->getType()->getReferenceStorageReferent())
23002316
|| var->getType()->getReferenceStorageReferent()->hasArchetype())
23012317
&& "property's result type is not nullable?!");
23022318
return var->hasClangNode();
@@ -2305,7 +2321,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
23052321
// Subscripts of non-optional reference type that were imported from
23062322
// Objective-C.
23072323
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
2308-
assert((isNullableTypeInC(M, subscript->getElementType())
2324+
assert((isVerbatimNullableTypeInC(M, subscript->getElementType())
23092325
|| subscript->getElementType()->hasArchetype())
23102326
&& "subscript's result type is not nullable?!");
23112327
return subscript->hasClangNode();
@@ -2329,7 +2345,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M, Expr *expr) {
23292345
// get the function we're calling.
23302346
if (auto apply = dyn_cast<ApplyExpr>(expr)) {
23312347
// The result has to be a nullable type.
2332-
if (!isNullableTypeInC(M, apply->getType()))
2348+
if (!isVerbatimNullableTypeInC(M, apply->getType()))
23332349
return false;
23342350

23352351
auto getFuncDeclFromDynamicMemberLookup = [&](Expr *expr) -> FuncDecl * {
@@ -2382,25 +2398,25 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M, Expr *expr) {
23822398

23832399
// A reference to a member property.
23842400
if (auto member = dyn_cast<MemberRefExpr>(expr)) {
2385-
return isNullableTypeInC(M, member->getType()) &&
2401+
return isVerbatimNullableTypeInC(M, member->getType()) &&
23862402
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
23872403
}
23882404

23892405
// A reference to a subscript.
23902406
if (auto subscript = dyn_cast<SubscriptExpr>(expr)) {
2391-
return isNullableTypeInC(M, subscript->getType()) &&
2407+
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
23922408
mayLieAboutNonOptionalReturn(M, subscript->getDecl().getDecl());
23932409
}
23942410

23952411
// A reference to a member property found via dynamic lookup.
23962412
if (auto member = dyn_cast<DynamicMemberRefExpr>(expr)) {
2397-
return isNullableTypeInC(M, member->getType()) &&
2413+
return isVerbatimNullableTypeInC(M, member->getType()) &&
23982414
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
23992415
}
24002416

24012417
// A reference to a subscript found via dynamic lookup.
24022418
if (auto subscript = dyn_cast<DynamicSubscriptExpr>(expr)) {
2403-
return isNullableTypeInC(M, subscript->getType()) &&
2419+
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
24042420
mayLieAboutNonOptionalReturn(M, subscript->getMember().getDecl());
24052421
}
24062422

test/SILGen/lying_about_optional_return_objc.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ func optionalChainingForeignFunctionTypeProperties(b: BlockProperty?) {
66
// CHECK: enum $Optional<()>, #Optional.some!enumelt.1, {{%.*}} : $()
77
b?.readWriteBlock()
88

9-
// CHECK: unchecked_bitwise_cast
9+
// CHECK: enum $Optional
1010
_ = b?.readWriteBlock
1111

1212
// CHECK: enum $Optional<()>, #Optional.some!enumelt.1, {{%.*}} : $()
1313
b?.readOnlyBlock()
1414

15-
// CHECK: unchecked_bitwise_cast
15+
// CHECK: enum $Optional
1616
_ = b?.readOnlyBlock
1717

1818
// CHECK: unchecked_trivial_bit_cast

0 commit comments

Comments
 (0)