Skip to content

Commit a0c03d0

Browse files
authored
Merge pull request #7761 from jckarter/nserror-linux-bridging
Sema/SIL: NSError has no special powers without ObjC interop.
2 parents 3ea8892 + d998692 commit a0c03d0

15 files changed

+262
-182
lines changed

lib/SIL/DynamicCasts.cpp

+18-11
Original file line numberDiff line numberDiff line change
@@ -1139,23 +1139,30 @@ bool swift::canUseScalarCheckedCastInstructions(SILModule &M,
11391139
// non-NSError superclass constraint. Casts to archetypes thus must always be
11401140
// indirect.
11411141
if (auto archetype = targetType->getAs<ArchetypeType>()) {
1142-
auto super = archetype->getSuperclass();
1143-
if (super.isNull())
1144-
return false;
1145-
11461142
// Only ever permit this if the source type is a reference type.
11471143
if (!objectType.isAnyClassReferenceType())
11481144
return false;
1145+
1146+
if (M.getASTContext().LangOpts.EnableObjCInterop) {
1147+
auto super = archetype->getSuperclass();
1148+
if (super.isNull())
1149+
return false;
11491150

1150-
// A base class constraint that isn't NSError rules out the archetype being
1151-
// bound to NSError.
1152-
if (auto nserror = M.Types.getNSErrorType())
1153-
return !super->isEqual(nserror);
1154-
// If NSError wasn't loaded, any base class constraint must not be NSError.
1155-
return true;
1151+
// A base class constraint that isn't NSError rules out the archetype being
1152+
// bound to NSError.
1153+
if (auto nserror = M.Types.getNSErrorType())
1154+
return !super->isEqual(nserror);
1155+
// If NSError wasn't loaded, any base class constraint must not be NSError.
1156+
return true;
1157+
} else {
1158+
// If ObjC bridging isn't enabled, we can do a scalar cast from any
1159+
// reference type to any class-constrained archetype.
1160+
return archetype->requiresClass();
1161+
}
11561162
}
11571163

1158-
if (targetType == M.Types.getNSErrorType()) {
1164+
if (M.getASTContext().LangOpts.EnableObjCInterop
1165+
&& targetType == M.Types.getNSErrorType()) {
11591166
// If we statically know the source is an NSError subclass, then the cast
11601167
// can go through the scalar path (and it's trivially true so can be
11611168
// killed).

lib/SIL/SILType.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,10 @@ SILType SILType::unwrapAnyOptionalType() const {
460460
/// Error existentials.
461461
static bool isBridgedErrorClass(SILModule &M,
462462
Type t) {
463+
// There's no bridging if ObjC interop is disabled.
464+
if (!M.getASTContext().LangOpts.EnableObjCInterop)
465+
return false;
466+
463467
if (!t)
464468
return false;
465469

lib/Sema/CSSimplify.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -3351,6 +3351,10 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
33513351
Type type2,
33523352
TypeMatchOptions flags,
33533353
ConstraintLocatorBuilder locator) {
3354+
// There's no bridging without ObjC interop.
3355+
if (!TC.Context.LangOpts.EnableObjCInterop)
3356+
return SolutionKind::Error;
3357+
33543358
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
33553359

33563360
/// Form an unresolved result.

lib/Sema/TypeCheckConstraints.cpp

+12-10
Original file line numberDiff line numberDiff line change
@@ -3365,16 +3365,18 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
33653365
// We can conditionally cast from NSError to an Error-conforming
33663366
// type. This is handled in the runtime, so it doesn't need a special cast
33673367
// kind.
3368-
if (auto errorTypeProto = Context.getProtocol(KnownProtocolKind::Error)) {
3369-
if (conformsToProtocol(toType, errorTypeProto, dc,
3370-
(ConformanceCheckFlags::InExpression|
3371-
ConformanceCheckFlags::Used)))
3372-
if (auto NSErrorTy = getNSErrorType(dc))
3373-
if (isSubtypeOf(fromType, NSErrorTy, dc)
3374-
// Don't mask "always true" warnings if NSError is cast to
3375-
// Error itself.
3376-
&& !isSubtypeOf(fromType, toType, dc))
3377-
return CheckedCastKind::ValueCast;
3368+
if (Context.LangOpts.EnableObjCInterop) {
3369+
if (auto errorTypeProto = Context.getProtocol(KnownProtocolKind::Error)) {
3370+
if (conformsToProtocol(toType, errorTypeProto, dc,
3371+
(ConformanceCheckFlags::InExpression|
3372+
ConformanceCheckFlags::Used)))
3373+
if (auto NSErrorTy = getNSErrorType(dc))
3374+
if (isSubtypeOf(fromType, NSErrorTy, dc)
3375+
// Don't mask "always true" warnings if NSError is cast to
3376+
// Error itself.
3377+
&& !isSubtypeOf(fromType, toType, dc))
3378+
return CheckedCastKind::ValueCast;
3379+
}
33783380
}
33793381

33803382
// The runtime doesn't support casts to CF types and always lets them succeed.

test/SIL/Parser/undef.sil

-8
Original file line numberDiff line numberDiff line change
@@ -244,14 +244,6 @@ bb0:
244244
bridge_object_to_word undef : $Builtin.BridgeObject to $Builtin.Word
245245
// CHECK: thin_to_thick_function undef : $@convention(thin) () -> () to $() -> ()
246246
thin_to_thick_function undef : $@convention(thin) () -> () to $() -> ()
247-
// CHECK: thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
248-
thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
249-
// CHECK: objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
250-
objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
251-
// CHECK: objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
252-
objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
253-
// CHECK: objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
254-
objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
255247
// CHECK: is_nonnull undef : $C
256248
is_nonnull undef : $C
257249

test/SIL/Parser/undef_objc.sil

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-sil-opt -assume-parsing-unqualified-ownership-sil %s | %target-sil-opt -assume-parsing-unqualified-ownership-sil | %FileCheck %s
2+
// REQUIRES: objc_interop
3+
4+
sil_stage raw
5+
6+
import Builtin
7+
import Swift
8+
9+
protocol P { }
10+
class C { }
11+
12+
sil @general_test : $() -> () {
13+
bb0:
14+
// CHECK: thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
15+
thick_to_objc_metatype undef : $@thick C.Type to $@objc_metatype C.Type
16+
// CHECK: objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
17+
objc_to_thick_metatype undef : $@objc_metatype C.Type to $@thick C.Type
18+
// CHECK: objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
19+
objc_metatype_to_object undef : $@objc_metatype C.Type to $AnyObject
20+
// CHECK: objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
21+
objc_existential_metatype_to_object undef : $@objc_metatype P.Type to $AnyObject
22+
unreachable
23+
}

test/SILGen/generic_casts.swift

+17-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck %s
1+
// RUN: %target-swift-frontend -Xllvm -sil-full-demangle -emit-silgen %s | %FileCheck --check-prefix=CHECK --check-prefix=CHECK-%target-runtime %s
22

33
protocol ClassBound : class {}
44
protocol NotClassBound {}
@@ -57,16 +57,21 @@ func opaque_archetype_is_class_archetype
5757
func class_archetype_to_class_archetype
5858
<T:ClassBound, U:ClassBound>(_ t:T) -> U {
5959
return t as! U
60-
// CHECK: unconditional_checked_cast_addr {{.*}} T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
61-
// CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
62-
// CHECK: return [[DOWNCAST]] : $U
60+
// Error bridging can change the identity of class-constrained archetypes.
61+
// CHECK-objc: unconditional_checked_cast_addr {{.*}} T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U
62+
// CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
63+
// CHECK-objc: return [[DOWNCAST]] : $U
64+
65+
// CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $T to $U
6366
}
6467

6568
// CHECK-LABEL: sil hidden @_TF13generic_casts34class_archetype_is_class_archetype{{.*}}
6669
func class_archetype_is_class_archetype
6770
<T:ClassBound, U:ClassBound>(_ t:T, u:U.Type) -> Bool {
6871
return t is U
69-
// CHECK: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
72+
// Error bridging can change the identity of class-constrained archetypes.
73+
// CHECK-objc: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
74+
// CHECK-native: checked_cast_br {{.*}} : $T to $U
7075
}
7176

7277
// CHECK-LABEL: sil hidden @_TF13generic_casts38opaque_archetype_to_addr_only_concrete{{.*}}
@@ -156,16 +161,19 @@ func opaque_existential_is_class_archetype
156161
func class_existential_to_class_archetype
157162
<T:ClassBound>(_ p:ClassBound) -> T {
158163
return p as! T
159-
// CHECK: unconditional_checked_cast_addr {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
160-
// CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
161-
// CHECK: return [[DOWNCAST]] : $T
164+
// CHECK-objc: unconditional_checked_cast_addr {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T
165+
// CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]]
166+
// CHECK-objc: return [[DOWNCAST]] : $T
167+
168+
// CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $ClassBound to $T
162169
}
163170

164171
// CHECK-LABEL: sil hidden @_TF13generic_casts36class_existential_is_class_archetype{{.*}}
165172
func class_existential_is_class_archetype
166173
<T:ClassBound>(_ p:ClassBound, _: T) -> Bool {
167174
return p is T
168-
// CHECK: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
175+
// CHECK-objc: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
176+
// CHECK-native: checked_cast_br {{.*}} : $ClassBound to $T
169177
}
170178

171179
// CHECK-LABEL: sil hidden @_TF13generic_casts40opaque_existential_to_addr_only_concrete{{.*}}

test/SILOptimizer/cse.sil

-116
Original file line numberDiff line numberDiff line change
@@ -720,104 +720,6 @@ bb2:
720720
%33 = return %32 : $()
721721
}
722722

723-
// CHECK-LABEL: sil @cse_value_metatype
724-
// CHECK: value_metatype $@objc_metatype
725-
// CHECK: objc_metatype_to_object
726-
// CHECK-NOT: value_metatype $@objc_metatype
727-
// CHECK: strong_release
728-
// CHECK: return
729-
sil @cse_value_metatype : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
730-
bb0(%0 : $T):
731-
%2 = value_metatype $@objc_metatype T.Type, %0 : $T
732-
%4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
733-
%5 = value_metatype $@objc_metatype T.Type, %0 : $T
734-
%7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
735-
strong_release %0 : $T
736-
%9 = tuple (%4: $AnyObject, %7: $AnyObject)
737-
return %9 : $(AnyObject, AnyObject)
738-
}
739-
740-
741-
@objc(XX) protocol XX {
742-
}
743-
744-
// CHECK-LABEL: sil @cse_existential_metatype
745-
// CHECK: existential_metatype $@objc_metatype
746-
// CHECK: objc_existential_metatype_to_object
747-
// CHECK-NOT: existential_metatype $@objc_metatype
748-
// CHECK: strong_release
749-
// CHECK: return
750-
sil @cse_existential_metatype : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
751-
bb0(%0 : $XX):
752-
%2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
753-
%4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
754-
%5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
755-
%6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
756-
strong_release %0 : $XX
757-
%7 = tuple (%4: $AnyObject, %6: $AnyObject)
758-
return %7 : $(AnyObject, AnyObject)
759-
}
760-
761-
// CHECK-LABEL: sil @nocse_existential_metatype_addr
762-
// CHECK: store
763-
// CHECK: existential_metatype $@thick Any.Type
764-
// CHECK: store
765-
// CHECK: existential_metatype $@thick Any.Type
766-
// CHECK: return
767-
sil @nocse_existential_metatype_addr : $@convention(thin) (@owned B, @owned B) -> (@thick Any.Type, @thick Any.Type) {
768-
bb0(%0 : $B, %1 : $B):
769-
%2 = alloc_stack $Any
770-
%3 = init_existential_addr %2 : $*Any, $B
771-
store %0 to %3 : $*B
772-
%5 = existential_metatype $@thick Any.Type, %2 : $*Any
773-
store %1 to %3 : $*B
774-
%7 = existential_metatype $@thick Any.Type, %2 : $*Any
775-
strong_release %1 : $B
776-
strong_release %0 : $B
777-
%99 = tuple (%5 : $@thick Any.Type, %7 : $@thick Any.Type)
778-
dealloc_stack %2 : $*Any
779-
return %99 : $(@thick Any.Type, @thick Any.Type)
780-
}
781-
782-
783-
// CHECK-LABEL: sil @cse_objc_metatype_to_object
784-
// CHECK: value_metatype $@objc_metatype
785-
// CHECK: objc_metatype_to_object
786-
// CHECK-NOT: value_metatype $@objc_metatype
787-
// CHECK-NOT: objc_metatype_to_object
788-
// CHECK: strong_release
789-
// CHECK: return
790-
sil @cse_objc_metatype_to_object : $@convention(thin) <T where T : AnyObject> (@owned T) -> @owned (AnyObject, AnyObject) {
791-
bb0(%0 : $T):
792-
%2 = value_metatype $@objc_metatype T.Type, %0 : $T
793-
%4 = objc_metatype_to_object %2 : $@objc_metatype T.Type to $AnyObject
794-
%5 = value_metatype $@objc_metatype T.Type, %0 : $T
795-
%7 = objc_metatype_to_object %5 : $@objc_metatype T.Type to $AnyObject
796-
strong_release %0 : $T
797-
%9 = tuple (%4: $AnyObject, %7: $AnyObject)
798-
return %9 : $(AnyObject, AnyObject)
799-
}
800-
801-
802-
// CHECK-LABEL: sil @cse_objc_existential_metatype_to_object
803-
// CHECK: existential_metatype $@objc_metatype
804-
// CHECK: objc_existential_metatype_to_object
805-
// CHECK-NOT: existential_metatype $@objc_metatype
806-
// CHECK-NOT: objc_existential_metatype_to_object
807-
// CHECK: strong_release
808-
// CHECK: return
809-
sil @cse_objc_existential_metatype_to_object : $@convention(thin) (@owned XX) -> @owned (AnyObject, AnyObject) {
810-
bb0(%0 : $XX):
811-
%2 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
812-
%4 = objc_existential_metatype_to_object %2 : $@objc_metatype XX.Type to $AnyObject
813-
%5 = existential_metatype $@objc_metatype XX.Type, %0 : $XX
814-
%6 = objc_existential_metatype_to_object %5 : $@objc_metatype XX.Type to $AnyObject
815-
strong_release %0 : $XX
816-
%7 = tuple (%4: $AnyObject, %6: $AnyObject)
817-
return %7 : $(AnyObject, AnyObject)
818-
}
819-
820-
821723
// CHECK-LABEL: sil @cse_raw_pointer_to_ref
822724
// CHECK: raw_pointer_to_ref
823725
// CHECK-NOT: raw_pointer_to_ref
@@ -937,24 +839,6 @@ bb0(%0 : $Enum1):
937839
return %3: $(Builtin.Int1, Builtin.Int1)
938840
}
939841

940-
941-
@objc
942-
class XXX {
943-
}
944-
945-
// CHECK-LABEL: sil @cse_objc_to_thick_metatype
946-
// CHECK: objc_to_thick_metatype
947-
// CHECK-NOT: objc_to_thick_metatype
948-
// CHECK: tuple
949-
// CHECK: return
950-
sil @cse_objc_to_thick_metatype : $@convention(thin) (@objc_metatype XXX.Type) -> (@thick XXX.Type, @thick XXX.Type) {
951-
bb0(%0 : $@objc_metatype XXX.Type):
952-
%1 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
953-
%2 = objc_to_thick_metatype %0 : $@objc_metatype XXX.Type to $@thick XXX.Type
954-
%3 = tuple (%1: $@thick XXX.Type, %2: $@thick XXX.Type)
955-
return %3: $(@thick XXX.Type, @thick XXX.Type)
956-
}
957-
958842
// CHECK-LABEL: sil @cse_bridge_object_to_ref
959843
// CHECK: bridge_object_to_ref
960844
// CHECK-NOT: bridge_object_to_ref

0 commit comments

Comments
 (0)