Skip to content

Commit f67cb0d

Browse files
authored
Merge pull request #4281 from jckarter/bridged-block-nullability
SILGen: Don't pretend to handle ObjC APIs that "lie" about block return optionality.
2 parents ae69ffb + 8bd32a9 commit f67cb0d

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
@@ -2274,12 +2274,28 @@ RValue RValueEmitter::visitRebindSelfInConstructorExpr(
22742274
return SGF.emitEmptyTupleRValue(E, C);
22752275
}
22762276

2277-
static bool isNullableTypeInC(SILModule &M, Type ty) {
2277+
static bool isVerbatimNullableTypeInC(SILModule &M, Type ty) {
22782278
ty = ty->getLValueOrInOutObjectType()->getReferenceStorageReferent();
22792279

2280-
// Functions, class instances, and @objc existentials are all nullable.
2281-
if (ty->hasReferenceSemantics())
2280+
// Class instances, and @objc existentials are all nullable.
2281+
if (ty->hasReferenceSemantics()) {
2282+
// So are blocks, but we usually bridge them to Swift closures before we get
2283+
// a chance to check for optional promotion, so we're already screwed if
2284+
// an API lies about nullability.
2285+
if (auto fnTy = ty->getAs<AnyFunctionType>()) {
2286+
switch (fnTy->getRepresentation()) {
2287+
// Carried verbatim from C.
2288+
case FunctionTypeRepresentation::Block:
2289+
case FunctionTypeRepresentation::CFunctionPointer:
2290+
return true;
2291+
// Was already bridged.
2292+
case FunctionTypeRepresentation::Swift:
2293+
case FunctionTypeRepresentation::Thin:
2294+
return false;
2295+
}
2296+
}
22822297
return true;
2298+
}
22832299

22842300
// Other types like UnsafePointer can also be nullable.
22852301
const DeclContext *DC = M.getAssociatedContext();
@@ -2310,7 +2326,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
23102326
// Functions that return non-optional reference type and were imported from
23112327
// Objective-C.
23122328
if (auto func = dyn_cast<FuncDecl>(decl)) {
2313-
assert((isNullableTypeInC(M, func->getResultType())
2329+
assert((isVerbatimNullableTypeInC(M, func->getResultType())
23142330
|| func->getResultType()->hasArchetype())
23152331
&& "func's result type is not nullable?!");
23162332
return func->hasClangNode();
@@ -2319,7 +2335,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
23192335
// Computed properties of non-optional reference type that were imported from
23202336
// Objective-C.
23212337
if (auto var = dyn_cast<VarDecl>(decl)) {
2322-
assert((isNullableTypeInC(M, var->getType()->getReferenceStorageReferent())
2338+
assert((isVerbatimNullableTypeInC(M, var->getType()->getReferenceStorageReferent())
23232339
|| var->getType()->getReferenceStorageReferent()->hasArchetype())
23242340
&& "property's result type is not nullable?!");
23252341
return var->hasClangNode();
@@ -2328,7 +2344,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M,
23282344
// Subscripts of non-optional reference type that were imported from
23292345
// Objective-C.
23302346
if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
2331-
assert((isNullableTypeInC(M, subscript->getElementType())
2347+
assert((isVerbatimNullableTypeInC(M, subscript->getElementType())
23322348
|| subscript->getElementType()->hasArchetype())
23332349
&& "subscript's result type is not nullable?!");
23342350
return subscript->hasClangNode();
@@ -2352,7 +2368,7 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M, Expr *expr) {
23522368
// get the function we're calling.
23532369
if (auto apply = dyn_cast<ApplyExpr>(expr)) {
23542370
// The result has to be a nullable type.
2355-
if (!isNullableTypeInC(M, apply->getType()))
2371+
if (!isVerbatimNullableTypeInC(M, apply->getType()))
23562372
return false;
23572373

23582374
auto getFuncDeclFromDynamicMemberLookup = [&](Expr *expr) -> FuncDecl * {
@@ -2405,25 +2421,25 @@ static bool mayLieAboutNonOptionalReturn(SILModule &M, Expr *expr) {
24052421

24062422
// A reference to a member property.
24072423
if (auto member = dyn_cast<MemberRefExpr>(expr)) {
2408-
return isNullableTypeInC(M, member->getType()) &&
2424+
return isVerbatimNullableTypeInC(M, member->getType()) &&
24092425
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
24102426
}
24112427

24122428
// A reference to a subscript.
24132429
if (auto subscript = dyn_cast<SubscriptExpr>(expr)) {
2414-
return isNullableTypeInC(M, subscript->getType()) &&
2430+
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
24152431
mayLieAboutNonOptionalReturn(M, subscript->getDecl().getDecl());
24162432
}
24172433

24182434
// A reference to a member property found via dynamic lookup.
24192435
if (auto member = dyn_cast<DynamicMemberRefExpr>(expr)) {
2420-
return isNullableTypeInC(M, member->getType()) &&
2436+
return isVerbatimNullableTypeInC(M, member->getType()) &&
24212437
mayLieAboutNonOptionalReturn(M, member->getMember().getDecl());
24222438
}
24232439

24242440
// A reference to a subscript found via dynamic lookup.
24252441
if (auto subscript = dyn_cast<DynamicSubscriptExpr>(expr)) {
2426-
return isNullableTypeInC(M, subscript->getType()) &&
2442+
return isVerbatimNullableTypeInC(M, subscript->getType()) &&
24272443
mayLieAboutNonOptionalReturn(M, subscript->getMember().getDecl());
24282444
}
24292445

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)