Skip to content

Commit 8b1bbeb

Browse files
committed
Merge pull request #16736 from millenomi/LinuxAsBridging_2
Turn on 'as' bridging for Linux (2) (cherry picked from commit 63348bc)
1 parent 0acd02d commit 8b1bbeb

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
@@ -1138,22 +1138,19 @@ bool swift::canUseScalarCheckedCastInstructions(SILModule &M,
11381138
if (!objectType.isAnyClassReferenceType())
11391139
return false;
11401140

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

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

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

lib/Sema/CSApply.cpp

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

36833683
if (!choice) {
3684-
if (tc.Context.LangOpts.EnableObjCInterop)
3685-
choice = solution.getDisjunctionChoice(locator);
3686-
else
3687-
choice = 0;
3684+
choice = solution.getDisjunctionChoice(locator);
36883685
}
36893686

36903687
// 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
@@ -2899,8 +2899,7 @@ bool TypeChecker::isExplicitlyConvertibleTo(Type type1, Type type2,
28992899

29002900
bool TypeChecker::isObjCBridgedTo(Type type1, Type type2, DeclContext *dc,
29012901
bool *unwrappedIUO) {
2902-
return (Context.LangOpts.EnableObjCInterop &&
2903-
typesSatisfyConstraint(type1, type2,
2902+
return (typesSatisfyConstraint(type1, type2,
29042903
/*openArchetypes=*/false,
29052904
ConstraintKind::BridgingConversion,
29062905
dc, unwrappedIUO));
@@ -3412,9 +3411,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
34123411
}
34133412

34143413
// Check for a bridging conversion.
3415-
// Anything bridges to AnyObject in ObjC interop mode.
3416-
if (Context.LangOpts.EnableObjCInterop
3417-
&& toType->isAnyObject())
3414+
// Anything bridges to AnyObject.
3415+
if (toType->isAnyObject())
34183416
return CheckedCastKind::BridgingCoercion;
34193417

34203418
// 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)