Skip to content

Commit 1377ab7

Browse files
committed
Turn on ‘as’ bridging on Darwin.
1 parent 8151350 commit 1377ab7

File tree

14 files changed

+389
-91
lines changed

14 files changed

+389
-91
lines changed

lib/SIL/DynamicCasts.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1139,22 +1139,19 @@ bool swift::canUseScalarCheckedCastInstructions(SILModule &M,
11391139
if (!objectType.isAnyClassReferenceType())
11401140
return false;
11411141

1142-
if (M.getASTContext().LangOpts.EnableObjCInterop) {
11431142
auto super = archetype->getSuperclass();
11441143
if (super.isNull())
11451144
return false;
11461145

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

11601157
if (M.getASTContext().LangOpts.EnableObjCInterop

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3660,10 +3660,7 @@ namespace {
36603660
auto *locator = cs.getConstraintLocator(expr);
36613661

36623662
if (!choice) {
3663-
if (tc.Context.LangOpts.EnableObjCInterop)
3664-
choice = solution.getDisjunctionChoice(locator);
3665-
else
3666-
choice = 0;
3663+
choice = solution.getDisjunctionChoice(locator);
36673664
}
36683665

36693666
// Handle the coercion/bridging of the underlying subexpression, where

lib/Sema/CSSimplify.cpp

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,11 +3637,6 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
36373637
Type type2,
36383638
TypeMatchOptions flags,
36393639
ConstraintLocatorBuilder locator) {
3640-
// There's no bridging without ObjC interop, so we shouldn't have set up
3641-
// bridging constraints without it.
3642-
assert(TC.Context.LangOpts.EnableObjCInterop
3643-
&& "bridging constraint w/o ObjC interop?!");
3644-
36453640
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
36463641

36473642
/// Form an unresolved result.
@@ -5086,14 +5081,11 @@ void ConstraintSystem::addExplicitConversionConstraint(
50865081
coerceConstraint->setFavored();
50875082
constraints.push_back(coerceConstraint);
50885083

5089-
// Bridging.
5090-
if (getASTContext().LangOpts.EnableObjCInterop) {
5091-
// The source type can be explicitly converted to the destination type.
5092-
Constraint *bridgingConstraint =
5093-
Constraint::create(*this, ConstraintKind::BridgingConversion,
5094-
fromType, toType, locatorPtr);
5095-
constraints.push_back(bridgingConstraint);
5096-
}
5084+
// The source type can be explicitly converted to the destination type.
5085+
Constraint *bridgingConstraint =
5086+
Constraint::create(*this, ConstraintKind::BridgingConversion,
5087+
fromType, toType, locatorPtr);
5088+
constraints.push_back(bridgingConstraint);
50975089

50985090
if (allowFixes && shouldAttemptFixes()) {
50995091
Constraint *downcastConstraint =
@@ -5104,8 +5096,8 @@ void ConstraintSystem::addExplicitConversionConstraint(
51045096
}
51055097

51065098
addDisjunctionConstraint(constraints, locator,
5107-
getASTContext().LangOpts.EnableObjCInterop && allowFixes ? RememberChoice
5108-
: ForgetChoice);
5099+
allowFixes ? RememberChoice
5100+
: ForgetChoice);
51095101
}
51105102

51115103
ConstraintSystem::SolutionKind

lib/Sema/Constraint.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -612,10 +612,6 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
612612
assert((kind != ConstraintKind::LiteralConformsTo) ||
613613
second->is<ProtocolType>());
614614

615-
// Bridging constraints require bridging to be enabled.
616-
assert(kind != ConstraintKind::BridgingConversion
617-
|| cs.TC.Context.LangOpts.EnableObjCInterop);
618-
619615
// Create the constraint.
620616
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
621617
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2878,8 +2878,7 @@ bool TypeChecker::isExplicitlyConvertibleTo(Type type1, Type type2,
28782878

28792879
bool TypeChecker::isObjCBridgedTo(Type type1, Type type2, DeclContext *dc,
28802880
bool *unwrappedIUO) {
2881-
return (Context.LangOpts.EnableObjCInterop &&
2882-
typesSatisfyConstraint(type1, type2,
2881+
return (typesSatisfyConstraint(type1, type2,
28832882
/*openArchetypes=*/false,
28842883
ConstraintKind::BridgingConversion,
28852884
dc, unwrappedIUO));
@@ -3391,9 +3390,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
33913390
}
33923391

33933392
// Check for a bridging conversion.
3394-
// Anything bridges to AnyObject in ObjC interop mode.
3395-
if (Context.LangOpts.EnableObjCInterop
3396-
&& toType->isAnyObject())
3393+
// Anything bridges to AnyObject.
3394+
if (toType->isAnyObject())
33973395
return CheckedCastKind::BridgingCoercion;
33983396

33993397
// Do this check later in Swift 3 mode so that we check for NSNumber and

stdlib/public/core/BridgeObjectiveC.swift

Lines changed: 210 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#if _runtime(_ObjC)
1413
/// A Swift Array or Dictionary of types conforming to
1514
/// `_ObjectiveCBridgeable` can be passed to Objective-C as an NSArray or
1615
/// NSDictionary, respectively. The elements of the resulting NSArray
@@ -83,6 +82,8 @@ public protocol _ObjectiveCBridgeable {
8382
-> Self
8483
}
8584

85+
#if _runtime(_ObjC)
86+
8687
//===--- Bridging for metatypes -------------------------------------------===//
8788

8889
/// A stand-in for a value of metatype type.
@@ -640,3 +641,211 @@ public func _getObjCTypeEncoding<T>(_ type: T.Type) -> UnsafePointer<Int8> {
640641
}
641642

642643
#endif
644+
645+
//===--- Bridging without the ObjC runtime --------------------------------===//
646+
647+
#if !_runtime(_ObjC)
648+
649+
/// Convert `x` from its Objective-C representation to its Swift
650+
/// representation.
651+
/// COMPILER_INTRINSIC
652+
@_inlineable // FIXME(sil-serialize-all)
653+
public func _forceBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable> (
654+
_ x: T._ObjectiveCType,
655+
_: T.Type
656+
) -> T {
657+
var result: T?
658+
T._forceBridgeFromObjectiveC(x, result: &result)
659+
return result!
660+
}
661+
662+
/// Attempt to convert `x` from its Objective-C representation to its Swift
663+
/// representation.
664+
/// COMPILER_INTRINSIC
665+
@_inlineable // FIXME(sil-serialize-all)
666+
public func _conditionallyBridgeFromObjectiveC_bridgeable<T:_ObjectiveCBridgeable>(
667+
_ x: T._ObjectiveCType,
668+
_: T.Type
669+
) -> T? {
670+
var result: T?
671+
T._conditionallyBridgeFromObjectiveC (x, result: &result)
672+
return result
673+
}
674+
675+
public // SPI(Foundation)
676+
protocol _NSSwiftValue: class {
677+
init(_ value: Any)
678+
var value: Any { get }
679+
static var null: AnyObject { get }
680+
}
681+
682+
@usableFromInline
683+
internal class _SwiftValue {
684+
@usableFromInline
685+
let value: Any
686+
687+
@usableFromInline
688+
init(_ value: Any) {
689+
self.value = value
690+
}
691+
692+
@usableFromInline
693+
static let null = _SwiftValue(Optional<Any>.none as Any)
694+
}
695+
696+
// Internal stdlib SPI
697+
@_silgen_name("swift_unboxFromSwiftValueWithType")
698+
public func swift_unboxFromSwiftValueWithType<T>(
699+
_ source: inout AnyObject,
700+
_ result: UnsafeMutablePointer<T>
701+
) -> Bool {
702+
703+
if source === _nullPlaceholder {
704+
if let unpacked = Optional<Any>.none as? T {
705+
result.initialize(to: unpacked)
706+
return true
707+
}
708+
}
709+
710+
if let box = source as? _SwiftValue {
711+
if let value = box.value as? T {
712+
result.initialize(to: value)
713+
return true
714+
}
715+
} else if let box = source as? _NSSwiftValue {
716+
if let value = box.value as? T {
717+
result.initialize(to: value)
718+
return true
719+
}
720+
}
721+
722+
return false
723+
}
724+
725+
// Internal stdlib SPI
726+
@_silgen_name("swift_swiftValueConformsTo")
727+
public func _swiftValueConformsTo<T>(_ type: T.Type) -> Bool {
728+
_assertSwiftValueFlavorIsConsistent()
729+
if let foundationType = _typeByName("Foundation._SwiftValue") {
730+
return foundationType is T.Type
731+
} else {
732+
return _SwiftValue.self is T.Type
733+
}
734+
}
735+
736+
@_silgen_name("_swift_extractDynamicValue")
737+
public func _extractDynamicValue<T>(_ value: T) -> AnyObject?
738+
739+
@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible")
740+
public func _bridgeToObjectiveCUsingProtocolIfPossible<T>(_ value: T) -> AnyObject?
741+
742+
@usableFromInline
743+
protocol _Unwrappable {
744+
func unwrap() -> Any?
745+
}
746+
747+
extension Optional: _Unwrappable {
748+
func unwrap() -> Any? {
749+
return self
750+
}
751+
}
752+
753+
// This is a best-effort tripmine for detecting the situation
754+
// (which should never happen) of Swift._SwiftValue and
755+
// Foundation._SwiftValue/Foundation.NSNull being used
756+
// in the same process.
757+
758+
@usableFromInline
759+
internal enum _SwiftValueFlavor: Equatable {
760+
case stdlib
761+
case foundation
762+
}
763+
764+
@usableFromInline
765+
func _currentSwiftValueFlavor() -> _SwiftValueFlavor {
766+
if _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type != nil {
767+
return .foundation
768+
} else {
769+
return .stdlib
770+
}
771+
}
772+
773+
@usableFromInline
774+
internal var _selectedSwiftValueFlavor: _SwiftValueFlavor = _currentSwiftValueFlavor()
775+
776+
@usableFromInline
777+
internal func _assertSwiftValueFlavorIsConsistent() {
778+
assert(_selectedSwiftValueFlavor == _currentSwiftValueFlavor())
779+
}
780+
781+
@usableFromInline
782+
internal var _nullPlaceholder: AnyObject {
783+
_assertSwiftValueFlavorIsConsistent()
784+
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
785+
return foundationType.null
786+
} else {
787+
return _SwiftValue.null
788+
}
789+
}
790+
791+
@usableFromInline
792+
func _makeSwiftValue(_ value: Any) -> AnyObject {
793+
_assertSwiftValueFlavorIsConsistent()
794+
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
795+
return foundationType.init(value)
796+
} else {
797+
return _SwiftValue(value)
798+
}
799+
}
800+
801+
/// Bridge an arbitrary value to an Objective-C object.
802+
///
803+
/// - If `T` is a class type, it is always bridged verbatim, the function
804+
/// returns `x`;
805+
///
806+
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`,
807+
/// returns the result of `x._bridgeToObjectiveC()`;
808+
///
809+
/// - otherwise, we use **boxing** to bring the value into Objective-C.
810+
/// The value is wrapped in an instance of a private Objective-C class
811+
/// that is `id`-compatible and dynamically castable back to the type of
812+
/// the boxed value, but is otherwise opaque.
813+
///
814+
/// COMPILER_INTRINSIC
815+
@inlinable // FIXME(sil-serialize-all)
816+
public func _bridgeAnythingToObjectiveC<T>(_ x: T) -> AnyObject {
817+
var done = false
818+
var result: AnyObject!
819+
820+
var source: Any = x
821+
822+
if let dynamicSource = _extractDynamicValue(x) {
823+
result = dynamicSource as AnyObject
824+
done = true
825+
}
826+
827+
if !done, let wrapper = source as? _Unwrappable {
828+
if let value = wrapper.unwrap() {
829+
result = value as AnyObject
830+
} else {
831+
result = _nullPlaceholder
832+
}
833+
834+
done = true
835+
}
836+
837+
if !done {
838+
if type(of: source) as? AnyClass != nil {
839+
result = unsafeBitCast(x, to: AnyObject.self)
840+
} else if let object = _bridgeToObjectiveCUsingProtocolIfPossible(source) {
841+
result = object
842+
} else {
843+
result = _makeSwiftValue(source)
844+
}
845+
}
846+
847+
return result
848+
}
849+
850+
#endif // !_runtime(_ObjC)
851+

stdlib/public/core/Codable.swift.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ public enum EncodingError : Error {
11801180
public var _userInfo: AnyObject? {
11811181
// The error dictionary must be returned as an AnyObject. We can do this
11821182
// only on platforms with bridging, unfortunately.
1183-
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
1183+
#if _runtime(_ObjC)
11841184
let context: Context
11851185
switch self {
11861186
case .invalidValue(_, let c): context = c
@@ -1290,7 +1290,7 @@ public enum DecodingError : Error {
12901290
public var _userInfo: AnyObject? {
12911291
// The error dictionary must be returned as an AnyObject. We can do this
12921292
// only on platforms with bridging, unfortunately.
1293-
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
1293+
#if _runtime(_ObjC)
12941294
let context: Context
12951295
switch self {
12961296
case .keyNotFound(_, let c): context = c

0 commit comments

Comments
 (0)