Skip to content

Commit 0322600

Browse files
Merge pull request #3782 from aschwaighofer/fix_astcontext_getbridgedtoobjc
Fix ASTContext::getBridgedToObjC to not return None under id-as-any
2 parents 6ad03e2 + f6e3f67 commit 0322600

File tree

5 files changed

+69
-4
lines changed

5 files changed

+69
-4
lines changed

lib/AST/ASTContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4060,6 +4060,9 @@ ASTContext::getBridgedToObjC(const DeclContext *dc, Type type,
40604060
return None;
40614061
}
40624062
}
4063+
} else {
4064+
// Under id-as-any, anything is bridged to objective c.
4065+
knownBridgedToObjC = true;
40634066
}
40644067

40654068
if (auto metaTy = type->getAs<MetatypeType>())

lib/SIL/DynamicCasts.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,32 @@ mayBridgeToObjectiveC(Module *M, CanType T) {
4545
return false;
4646
}
4747

48+
static bool
49+
mustBridgeToSwiftValueBox(Module *M, CanType T) {
50+
// If the target type is either an unknown dynamic type, or statically
51+
// known to bridge, the cast may succeed.
52+
if (T->hasArchetype())
53+
return false;
54+
55+
if (T->isAnyExistentialType())
56+
return false;
57+
58+
// getBridgedToObjC() might return a null-type for bridged foundation types
59+
// during compiling the standard library. Exclude this case here.
60+
if (auto N = T->getAnyNominal())
61+
if (M->getASTContext().isStandardLibraryTypeBridgedInFoundation(N))
62+
return false;
63+
64+
auto bridgeTy = M->getASTContext().getBridgedToObjC(M, T, nullptr);
65+
if (!bridgeTy.hasValue())
66+
return false;
67+
68+
if (bridgeTy->isNull())
69+
return true;
70+
71+
return false;
72+
}
73+
4874
static bool canClassOrSuperclassesHaveExtensions(ClassDecl *CD,
4975
bool isWholeModuleOpts) {
5076
while (CD) {
@@ -414,6 +440,24 @@ swift::classifyDynamicCast(Module *M,
414440
return DynamicCastFeasibility::WillFail;
415441
}
416442

443+
// Casts from a class into a non-class can never succeed if the target must
444+
// be bridged to a SwiftValueBox. You would need an AnyObject source for
445+
// that.
446+
if (!target.isAnyExistentialType() &&
447+
!target.getClassOrBoundGenericClass() &&
448+
!isa<ArchetypeType>(target) &&
449+
mustBridgeToSwiftValueBox(M, target)) {
450+
assert((target.getEnumOrBoundGenericEnum() ||
451+
target.getStructOrBoundGenericStruct() ||
452+
isa<TupleType>(target) ||
453+
isa<SILFunctionType>(target) ||
454+
isa<FunctionType>(target) ||
455+
isa<MetatypeType>(target)) &&
456+
"Target should be an enum, struct, tuple, metatype or function type");
457+
return DynamicCastFeasibility::WillFail;
458+
}
459+
460+
417461
// In the Objective-C runtime, class metatypes are also class instances.
418462
// The cast may succeed if the target type can be inhabited by a class
419463
// metatype.
@@ -439,6 +483,22 @@ swift::classifyDynamicCast(Module *M,
439483
// FIXME: Be more careful with bridging conversions from
440484
// NSArray, NSDictionary and NSSet as they may fail?
441485

486+
// We know that a cast from Int -> class foobar will fail.
487+
if (targetClass &&
488+
!source.isAnyExistentialType() &&
489+
!source.getClassOrBoundGenericClass() &&
490+
!isa<ArchetypeType>(source) &&
491+
mustBridgeToSwiftValueBox(M, source)) {
492+
assert((source.getEnumOrBoundGenericEnum() ||
493+
source.getStructOrBoundGenericStruct() ||
494+
isa<TupleType>(source) ||
495+
isa<SILFunctionType>(source) ||
496+
isa<FunctionType>(source) ||
497+
isa<MetatypeType>(source)) &&
498+
"Source should be an enum, struct, tuple, metatype or function type");
499+
return DynamicCastFeasibility::WillFail;
500+
}
501+
442502
// Check if there might be a bridging conversion.
443503
if (source->isBridgeableObjectType() && mayBridgeToObjectiveC(M, target)) {
444504
// Try to get the ObjC type which is bridged to target type.

lib/SILOptimizer/Utils/Local.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,8 @@ optimizeBridgedCasts(SILInstruction *Inst,
17561756
return nullptr;
17571757

17581758
auto BridgedSourceTy = getCastFromObjC(M, target, source);
1759+
if (!BridgedSourceTy)
1760+
return nullptr;
17591761

17601762
CanType CanBridgedTargetTy(BridgedTargetTy);
17611763
CanType CanBridgedSourceTy(BridgedSourceTy);

test/SILOptimizer/cast_folding_objc.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ print("test0=\(test0())")
205205
// CHECK: unconditional_checked_cast_addr
206206

207207
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyObjectToNonClassType
208-
// CHECK: builtin "int_trap"
208+
// CHECK-NOT: builtin "int_trap"
209209

210210
// CHECK-LABEL: sil [noinline] @{{.*}}testCastAnyToAnyClass{{.*}}
211211
// CHECK: unconditional_checked_cast_addr

test/SILOptimizer/specialize_unconditional_checked_cast.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,9 +343,9 @@ public func ExistentialToArchetype<T>(o o : AnyObject, t : T) -> T {
343343

344344
// AnyObject -> Non Class (should always fail)
345345
// CHECK-LABEL: sil shared [noinline] @_TTSg5Vs5UInt8___TF37specialize_unconditional_checked_cast22ExistentialToArchetype{{.*}} : $@convention(thin) (@owned AnyObject, UInt8) -> UInt8 {
346-
// CHECK: builtin "int_trap"()
347-
// CHECK: unreachable
348-
// CHECK-NEXT: }
346+
// CHECK-NOT: builtin "int_trap"()
347+
// CHECK-NOT: unreachable
348+
// CHECK: return
349349

350350
// AnyObject -> AnyObject
351351
// CHECK-LABEL: sil shared [noinline] @_TTSg5Ps9AnyObject____TF37specialize_unconditional_checked_cast22ExistentialToArchetype{{.*}} : $@convention(thin) (@owned AnyObject, @owned AnyObject) -> @owned AnyObject {

0 commit comments

Comments
 (0)