Skip to content

Commit 63348bc

Browse files
authored
Merge pull request #16736 from millenomi/LinuxAsBridging_2
Turn on 'as' bridging for Linux (2)
2 parents db75a67 + f7a28a8 commit 63348bc

File tree

14 files changed

+360
-91
lines changed

14 files changed

+360
-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
@@ -3655,10 +3655,7 @@ namespace {
36553655
auto *locator = cs.getConstraintLocator(expr);
36563656

36573657
if (!choice) {
3658-
if (tc.Context.LangOpts.EnableObjCInterop)
3659-
choice = solution.getDisjunctionChoice(locator);
3660-
else
3661-
choice = 0;
3658+
choice = solution.getDisjunctionChoice(locator);
36623659
}
36633660

36643661
// 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
@@ -3639,11 +3639,6 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
36393639
Type type2,
36403640
TypeMatchOptions flags,
36413641
ConstraintLocatorBuilder locator) {
3642-
// There's no bridging without ObjC interop, so we shouldn't have set up
3643-
// bridging constraints without it.
3644-
assert(TC.Context.LangOpts.EnableObjCInterop
3645-
&& "bridging constraint w/o ObjC interop?!");
3646-
36473642
TypeMatchOptions subflags = getDefaultDecompositionOptions(flags);
36483643

36493644
/// Form an unresolved result.
@@ -5088,14 +5083,11 @@ void ConstraintSystem::addExplicitConversionConstraint(
50885083
coerceConstraint->setFavored();
50895084
constraints.push_back(coerceConstraint);
50905085

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

51005092
if (allowFixes && shouldAttemptFixes()) {
51015093
Constraint *downcastConstraint =
@@ -5106,8 +5098,8 @@ void ConstraintSystem::addExplicitConversionConstraint(
51065098
}
51075099

51085100
addDisjunctionConstraint(constraints, locator,
5109-
getASTContext().LangOpts.EnableObjCInterop && allowFixes ? RememberChoice
5110-
: ForgetChoice);
5101+
allowFixes ? RememberChoice
5102+
: ForgetChoice);
51115103
}
51125104

51135105
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: 181 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,182 @@ 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+
if let foundationType = _foundationSwiftValueType {
729+
return foundationType is T.Type
730+
} else {
731+
return _SwiftValue.self is T.Type
732+
}
733+
}
734+
735+
@_silgen_name("_swift_extractDynamicValue")
736+
public func _extractDynamicValue<T>(_ value: T) -> AnyObject?
737+
738+
@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible")
739+
public func _bridgeToObjectiveCUsingProtocolIfPossible<T>(_ value: T) -> AnyObject?
740+
741+
@usableFromInline
742+
protocol _Unwrappable {
743+
func unwrap() -> Any?
744+
}
745+
746+
extension Optional: _Unwrappable {
747+
func unwrap() -> Any? {
748+
return self
749+
}
750+
}
751+
752+
private let _foundationSwiftValueType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type
753+
754+
@usableFromInline
755+
internal var _nullPlaceholder: AnyObject {
756+
if let foundationType = _foundationSwiftValueType {
757+
return foundationType.null
758+
} else {
759+
return _SwiftValue.null
760+
}
761+
}
762+
763+
@usableFromInline
764+
func _makeSwiftValue(_ value: Any) -> AnyObject {
765+
if let foundationType = _foundationSwiftValueType {
766+
return foundationType.init(value)
767+
} else {
768+
return _SwiftValue(value)
769+
}
770+
}
771+
772+
/// Bridge an arbitrary value to an Objective-C object.
773+
///
774+
/// - If `T` is a class type, it is always bridged verbatim, the function
775+
/// returns `x`;
776+
///
777+
/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`,
778+
/// returns the result of `x._bridgeToObjectiveC()`;
779+
///
780+
/// - otherwise, we use **boxing** to bring the value into Objective-C.
781+
/// The value is wrapped in an instance of a private Objective-C class
782+
/// that is `id`-compatible and dynamically castable back to the type of
783+
/// the boxed value, but is otherwise opaque.
784+
///
785+
/// COMPILER_INTRINSIC
786+
@inlinable // FIXME(sil-serialize-all)
787+
public func _bridgeAnythingToObjectiveC<T>(_ x: T) -> AnyObject {
788+
var done = false
789+
var result: AnyObject!
790+
791+
var source: Any = x
792+
793+
if let dynamicSource = _extractDynamicValue(x) {
794+
result = dynamicSource as AnyObject
795+
done = true
796+
}
797+
798+
if !done, let wrapper = source as? _Unwrappable {
799+
if let value = wrapper.unwrap() {
800+
result = value as AnyObject
801+
} else {
802+
result = _nullPlaceholder
803+
}
804+
805+
done = true
806+
}
807+
808+
if !done {
809+
if type(of: source) as? AnyClass != nil {
810+
result = unsafeBitCast(x, to: AnyObject.self)
811+
} else if let object = _bridgeToObjectiveCUsingProtocolIfPossible(source) {
812+
result = object
813+
} else {
814+
result = _makeSwiftValue(source)
815+
}
816+
}
817+
818+
return result
819+
}
820+
821+
#endif // !_runtime(_ObjC)
822+

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)