Skip to content

Commit 6e5605a

Browse files
authored
Merge pull request #16022 from millenomi/LinuxAsBridging
Turn on ‘as’ bridging on Linux.
2 parents 551809d + 7b8db8f commit 6e5605a

File tree

15 files changed

+324
-111
lines changed

15 files changed

+324
-111
lines changed

lib/SIL/DynamicCasts.cpp

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

1137-
if (M.getASTContext().LangOpts.EnableObjCInterop) {
11381137
auto super = archetype->getSuperclass();
11391138
if (super.isNull())
11401139
return false;
11411140

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

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

lib/Sema/CSApply.cpp

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

36883688
if (!choice) {
3689-
if (tc.Context.LangOpts.EnableObjCInterop)
3690-
choice = solution.getDisjunctionChoice(locator);
3691-
else
3692-
choice = 0;
3689+
choice = solution.getDisjunctionChoice(locator);
36933690
}
36943691

36953692
// 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
@@ -3627,11 +3627,6 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
36273627
Type type2,
36283628
TypeMatchOptions flags,
36293629
ConstraintLocatorBuilder locator) {
3630-
// There's no bridging without ObjC interop, so we shouldn't have set up
3631-
// bridging constraints without it.
3632-
assert(TC.Context.LangOpts.EnableObjCInterop
3633-
&& "bridging constraint w/o ObjC interop?!");
3634-
36353630
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
36363631

36373632
/// Form an unresolved result.
@@ -5076,14 +5071,11 @@ void ConstraintSystem::addExplicitConversionConstraint(
50765071
coerceConstraint->setFavored();
50775072
constraints.push_back(coerceConstraint);
50785073

5079-
// Bridging.
5080-
if (getASTContext().LangOpts.EnableObjCInterop) {
5081-
// The source type can be explicitly converted to the destination type.
5082-
Constraint *bridgingConstraint =
5083-
Constraint::create(*this, ConstraintKind::BridgingConversion,
5084-
fromType, toType, locatorPtr);
5085-
constraints.push_back(bridgingConstraint);
5086-
}
5074+
// The source type can be explicitly converted to the destination type.
5075+
Constraint *bridgingConstraint =
5076+
Constraint::create(*this, ConstraintKind::BridgingConversion,
5077+
fromType, toType, locatorPtr);
5078+
constraints.push_back(bridgingConstraint);
50875079

50885080
if (allowFixes && shouldAttemptFixes()) {
50895081
Constraint *downcastConstraint =
@@ -5094,8 +5086,8 @@ void ConstraintSystem::addExplicitConversionConstraint(
50945086
}
50955087

50965088
addDisjunctionConstraint(constraints, locator,
5097-
getASTContext().LangOpts.EnableObjCInterop && allowFixes ? RememberChoice
5098-
: ForgetChoice);
5089+
allowFixes ? RememberChoice
5090+
: ForgetChoice);
50995091
}
51005092

51015093
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
@@ -2881,8 +2881,7 @@ bool TypeChecker::isExplicitlyConvertibleTo(Type type1, Type type2,
28812881

28822882
bool TypeChecker::isObjCBridgedTo(Type type1, Type type2, DeclContext *dc,
28832883
bool *unwrappedIUO) {
2884-
return (Context.LangOpts.EnableObjCInterop &&
2885-
typesSatisfyConstraint(type1, type2,
2884+
return (typesSatisfyConstraint(type1, type2,
28862885
/*openArchetypes=*/false,
28872886
ConstraintKind::BridgingConversion,
28882887
dc, unwrappedIUO));
@@ -3394,9 +3393,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
33943393
}
33953394

33963395
// Check for a bridging conversion.
3397-
// Anything bridges to AnyObject in ObjC interop mode.
3398-
if (Context.LangOpts.EnableObjCInterop
3399-
&& toType->isAnyObject())
3396+
// Anything bridges to AnyObject.
3397+
if (toType->isAnyObject())
34003398
return CheckedCastKind::BridgingCoercion;
34013399

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

stdlib/public/SDK/ObjectiveC/ObjectiveC.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13+
#if _runtime(_ObjC)
14+
1315
@_exported
1416
import ObjectiveC
1517
import _SwiftObjectiveCOverlayShims
@@ -225,3 +227,5 @@ extension NSObject : CVarArg {
225227
}
226228
}
227229

230+
#endif
231+

stdlib/public/core/BridgeObjectiveC.swift

Lines changed: 199 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,200 @@ 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+
/// COMPILER_INTRISIC
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+
@_silgen_name("_swift_extractDynamicValue")
726+
public func _extractDynamicValue<T>(_ value: T) -> AnyObject?
727+
728+
@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible")
729+
public func _bridgeToObjectiveCUsingProtocolIfPossible<T>(_ value: T) -> AnyObject?
730+
731+
@usableFromInline
732+
protocol _Unwrappable {
733+
func unwrap() -> Any?
734+
}
735+
736+
extension Optional: _Unwrappable {
737+
func unwrap() -> Any? {
738+
return self
739+
}
740+
}
741+
742+
// This is a best-effort tripmine for detecting the situation
743+
// (which should never happen) of Swift._SwiftValue and
744+
// Foundation._SwiftValue/Foundation.NSNull being used
745+
// in the same process.
746+
747+
@usableFromInline
748+
internal enum _SwiftValueFlavor: Equatable {
749+
case stdlib
750+
case foundation
751+
}
752+
753+
@usableFromInline
754+
func _currentSwiftValueFlavor() -> _SwiftValueFlavor {
755+
if _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type != nil {
756+
return .foundation
757+
} else {
758+
return .stdlib
759+
}
760+
}
761+
762+
@usableFromInline
763+
internal var _selectedSwiftValueFlavor: _SwiftValueFlavor = _currentSwiftValueFlavor()
764+
765+
@usableFromInline
766+
internal func _assertSwiftValueFlavorIsConsistent() {
767+
assert(_selectedSwiftValueFlavor == _currentSwiftValueFlavor())
768+
}
769+
770+
@usableFromInline
771+
internal var _nullPlaceholder: AnyObject {
772+
_assertSwiftValueFlavorIsConsistent()
773+
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
774+
return foundationType.null
775+
} else {
776+
return _SwiftValue.null
777+
}
778+
}
779+
780+
@usableFromInline
781+
func _makeSwiftValue(_ value: Any) -> AnyObject {
782+
_assertSwiftValueFlavorIsConsistent()
783+
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
784+
return foundationType.init(value)
785+
} else {
786+
return _SwiftValue(value)
787+
}
788+
}
789+
790+
/// Bridge an arbitrary value to an Objective-C object.
791+
///
792+
/// - If `T` is a class type, it is always bridged verbatim, the function
793+
/// returns `x`;
794+
///
795+
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`,
796+
/// returns the result of `x._bridgeToObjectiveC()`;
797+
///
798+
/// - otherwise, we use **boxing** to bring the value into Objective-C.
799+
/// The value is wrapped in an instance of a private Objective-C class
800+
/// that is `id`-compatible and dynamically castable back to the type of
801+
/// the boxed value, but is otherwise opaque.
802+
///
803+
/// COMPILER_INTRINSIC
804+
@inlinable // FIXME(sil-serialize-all)
805+
public func _bridgeAnythingToObjectiveC<T>(_ x: T) -> AnyObject {
806+
var done = false
807+
var result: AnyObject!
808+
809+
var source: Any = x
810+
811+
if let dynamicSource = _extractDynamicValue(x) {
812+
result = dynamicSource as AnyObject
813+
done = true
814+
}
815+
816+
if !done, let wrapper = source as? _Unwrappable {
817+
if let value = wrapper.unwrap() {
818+
result = value as AnyObject
819+
} else {
820+
result = _nullPlaceholder
821+
}
822+
823+
done = true
824+
}
825+
826+
if !done {
827+
if type(of: source) as? AnyClass != nil {
828+
result = unsafeBitCast(x, to: AnyObject.self)
829+
} else if let object = _bridgeToObjectiveCUsingProtocolIfPossible(source) {
830+
result = object
831+
} else {
832+
result = _makeSwiftValue(source)
833+
}
834+
}
835+
836+
return result
837+
}
838+
839+
#endif // !_runtime(_ObjC)
840+

stdlib/public/core/Codable.swift.gyb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,7 +1171,7 @@ public enum EncodingError : Error {
11711171
public var _userInfo: AnyObject? {
11721172
// The error dictionary must be returned as an AnyObject. We can do this
11731173
// only on platforms with bridging, unfortunately.
1174-
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
1174+
#if _runtime(_ObjC)
11751175
let context: Context
11761176
switch self {
11771177
case .invalidValue(_, let c): context = c
@@ -1281,7 +1281,7 @@ public enum DecodingError : Error {
12811281
public var _userInfo: AnyObject? {
12821282
// The error dictionary must be returned as an AnyObject. We can do this
12831283
// only on platforms with bridging, unfortunately.
1284-
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
1284+
#if _runtime(_ObjC)
12851285
let context: Context
12861286
switch self {
12871287
case .keyNotFound(_, let c): context = c

0 commit comments

Comments
 (0)