Skip to content

Revert "Remove stdlib and runtime dependencies on Foundation and CF" #26849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions include/swift/Runtime/ObjCBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,6 @@ namespace swift {
SWIFT_RUNTIME_EXPORT
void swift_rootObjCDealloc(HeapObject *self);

// Uses Swift bridging to box a C string into an NSString without introducing
// a link-time dependency on NSString.
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API
id swift_stdlib_NSStringFromUTF8(const char *cstr, int len);

}

#endif // SWIFT_OBJC_INTEROP
Expand Down
16 changes: 0 additions & 16 deletions stdlib/public/core/BridgeObjectiveC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,22 +85,6 @@ public protocol _ObjectiveCBridgeable {

#if _runtime(_ObjC)

@_silgen_name("swift_stdlib_connectNSBaseClasses")
internal func _connectNSBaseClasses() -> Bool


private let _bridgeInitializedSuccessfully = _connectNSBaseClasses()
internal var _orphanedFoundationSubclassesReparented: Bool = false

/// Reparents the SwiftNativeNS*Base classes to be subclasses of their respective
/// Foundation types, or is false if they couldn't be reparented. Must be run
/// in order to bridge Swift Strings, Arrays, Dictionarys, Sets, or Enumerators to ObjC.
internal func _connectOrphanedFoundationSubclassesIfNeeded() -> Void {
let bridgeWorks = _bridgeInitializedSuccessfully
_debugPrecondition(bridgeWorks)
_orphanedFoundationSubclassesReparented = true
}

//===--- Bridging for metatypes -------------------------------------------===//

/// A stand-in for a value of metatype type.
Expand Down
2 changes: 2 additions & 0 deletions stdlib/public/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ set(swift_core_private_link_libraries)
set(swift_stdlib_compile_flags "${SWIFT_RUNTIME_SWIFT_COMPILE_FLAGS}")
if(SWIFT_PRIMARY_VARIANT_SDK IN_LIST SWIFT_APPLE_PLATFORMS)
list(APPEND swift_core_link_flags "-all_load")
list(APPEND swift_core_framework_depends Foundation)
list(APPEND swift_core_framework_depends CoreFoundation)
list(APPEND swift_core_private_link_libraries icucore)
else()
# With the GNU linker the equivalent of -all_load is to tell the linker
Expand Down
16 changes: 1 addition & 15 deletions stdlib/public/core/ContiguousArrayBuffer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -417,27 +417,13 @@ internal struct _ContiguousArrayBuffer<Element>: _ArrayBufferProtocol {
}

#if _runtime(_ObjC)

/// Convert to an NSArray.
///
/// - Precondition: `Element` is bridged to Objective-C.
///
/// - Complexity: O(1).
@usableFromInline
@inlinable
internal __consuming func _asCocoaArray() -> AnyObject {
// _asCocoaArray was @inlinable in Swift 5.0 and 5.1, which means that there
// are existing apps out there that effectively have the old implementation
// Be careful with future changes to this function. Here be dragons!
// The old implementation was
// if count == 0 {
// return _emptyArrayStorage
// }
// if _isBridgedVerbatimToObjectiveC(Element.self) {
// return _storage
// }
// return __SwiftDeferredNSArray(_nativeStorage: _storage)

_connectOrphanedFoundationSubclassesIfNeeded()
if count == 0 {
return _emptyArrayStorage
}
Expand Down
3 changes: 0 additions & 3 deletions stdlib/public/core/DictionaryBridging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ internal func _stdlib_NSDictionary_allKeys(
extension _NativeDictionary { // Bridging
@usableFromInline
__consuming internal func bridged() -> AnyObject {
_connectOrphanedFoundationSubclassesIfNeeded()
// We can zero-cost bridge if our keys are verbatim
// or if we're the empty singleton.

Expand Down Expand Up @@ -68,7 +67,6 @@ final internal class _SwiftDictionaryNSEnumerator<Key: Hashable, Value>

internal init(_ base: __owned _NativeDictionary<Key, Value>) {
_internalInvariant(_isBridgedVerbatimToObjectiveC(Key.self))
_internalInvariant(_orphanedFoundationSubclassesReparented)
self.base = base
self.bridgedKeys = nil
self.nextBucket = base.hashTable.startBucket
Expand All @@ -79,7 +77,6 @@ final internal class _SwiftDictionaryNSEnumerator<Key: Hashable, Value>
@nonobjc
internal init(_ deferred: __owned _SwiftDeferredNSDictionary<Key, Value>) {
_internalInvariant(!_isBridgedVerbatimToObjectiveC(Key.self))
_internalInvariant(_orphanedFoundationSubclassesReparented)
self.base = deferred.native
self.bridgedKeys = deferred.bridgeKeys()
self.nextBucket = base.hashTable.startBucket
Expand Down
5 changes: 1 addition & 4 deletions stdlib/public/core/Hashing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,7 @@ internal struct _UnmanagedAnyObjectArray {
// renamed. The old name must not be used in the new runtime.
final internal class __SwiftEmptyNSEnumerator
: __SwiftNativeNSEnumerator, _NSEnumerator {
internal override required init() {
super.init()
_internalInvariant(_orphanedFoundationSubclassesReparented)
}
internal override required init() { super.init() }

@objc
internal func nextObject() -> AnyObject? {
Expand Down
6 changes: 2 additions & 4 deletions stdlib/public/core/ReflectionMirror.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,10 @@ internal func getChild<T>(of value: T, type: Any.Type, index: Int) -> (label: St
internal func _getQuickLookObject<T>(_: T) -> AnyObject?

@_silgen_name("_swift_stdlib_NSObject_isKindOfClass")
internal func _isImpl(_ object: AnyObject, kindOf: UnsafePointer<CChar>) -> Bool
internal func _isImpl(_ object: AnyObject, kindOf: AnyObject) -> Bool

internal func _is(_ object: AnyObject, kindOf `class`: String) -> Bool {
return `class`.withCString {
return _isImpl(object, kindOf: $0)
}
return _isImpl(object, kindOf: `class` as AnyObject)
}

internal func _getClassPlaygroundQuickLook(
Expand Down
15 changes: 8 additions & 7 deletions stdlib/public/core/SetBridging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,24 @@

import SwiftShims

@_silgen_name("swift_stdlib_CFSetGetValues")
internal
func _stdlib_CFSetGetValues(
_ nss: AnyObject,
_: UnsafeMutablePointer<AnyObject>)

/// Equivalent to `NSSet.allObjects`, but does not leave objects on the
/// autorelease pool.
internal func _stdlib_NSSet_allObjects(_ object: AnyObject) -> _BridgingBuffer {
let nss = unsafeBitCast(object, to: _NSSet.self)
let count = nss.count
let storage = _BridgingBuffer(count)
nss.getObjects(storage.baseAddress, count: count)
let storage = _BridgingBuffer(nss.count)
_stdlib_CFSetGetValues(nss, storage.baseAddress)
return storage
}

extension _NativeSet { // Bridging
@usableFromInline
internal __consuming func bridged() -> AnyObject {
_connectOrphanedFoundationSubclassesIfNeeded()

// We can zero-cost bridge if our keys are verbatim
// or if we're the empty singleton.

Expand Down Expand Up @@ -67,7 +70,6 @@ final internal class _SwiftSetNSEnumerator<Element: Hashable>

internal init(_ base: __owned _NativeSet<Element>) {
_internalInvariant(_isBridgedVerbatimToObjectiveC(Element.self))
_internalInvariant(_orphanedFoundationSubclassesReparented)
self.base = base
self.bridgedElements = nil
self.nextBucket = base.hashTable.startBucket
Expand All @@ -78,7 +80,6 @@ final internal class _SwiftSetNSEnumerator<Element: Hashable>
@nonobjc
internal init(_ deferred: __owned _SwiftDeferredNSSet<Element>) {
_internalInvariant(!_isBridgedVerbatimToObjectiveC(Element.self))
_internalInvariant(_orphanedFoundationSubclassesReparented)
self.base = deferred.native
self.bridgedElements = deferred.bridgeElements()
self.nextBucket = base.hashTable.startBucket
Expand Down
4 changes: 0 additions & 4 deletions stdlib/public/core/ShadowProtocols.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,6 @@ internal protocol _NSSetCore: _NSCopying, _NSFastEnumeration {
/// supplies.
@unsafe_no_objc_tagged_pointer @objc
internal protocol _NSSet: _NSSetCore {
@objc(getObjects:count:) func getObjects(
_ buffer: UnsafeMutablePointer<AnyObject>,
count: Int
)
}

/// A shadow for the API of NSNumber we will use in the core
Expand Down
15 changes: 0 additions & 15 deletions stdlib/public/core/StringBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -442,9 +442,6 @@ extension String {
@_effects(releasenone)
public // SPI(Foundation)
func _bridgeToObjectiveCImpl() -> AnyObject {

_connectOrphanedFoundationSubclassesIfNeeded()

// Smol ASCII a) may bridge to tagged pointers, b) can't contain a BOM
if _guts.isSmallASCII {
let maybeTagged = _guts.asSmall.withUTF8 { bufPtr in
Expand All @@ -456,7 +453,6 @@ extension String {
}
if let tagged = maybeTagged { return tagged }
}

if _guts.isSmall {
// We can't form a tagged pointer String, so grow to a non-small String,
// and bridge that instead. Also avoids CF deleting any BOM that may be
Expand Down Expand Up @@ -501,17 +497,6 @@ public func _getDescription<T>(_ x: T) -> AnyObject {
return String(reflecting: x)._bridgeToObjectiveCImpl()
}

@_silgen_name("swift_stdlib_NSStringFromUTF8")
@usableFromInline //this makes the symbol available to the runtime :(
@available(macOS 9999, iOS 9999, tvOS 9999, watchOS 9999, *)
internal func _NSStringFromUTF8(_ s: UnsafePointer<UInt8>, _ len: Int)
-> AnyObject {
return String(
decoding: UnsafeBufferPointer(start: s, count: len),
as: UTF8.self
)._bridgeToObjectiveCImpl()
}

#else // !_runtime(_ObjC)

internal class __SwiftNativeNSString {
Expand Down
67 changes: 20 additions & 47 deletions stdlib/public/runtime/ErrorObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,14 @@
using namespace swift;
using namespace swift::hashable_support;

// Mimic the memory layout of NSError so things don't go haywire when we
// switch superclasses to the real thing.
@interface __SwiftNSErrorLayoutStandin : NSObject {
@private
void *_reserved;
NSInteger _code;
id _domain;
id _userInfo;
}
@end

@implementation __SwiftNSErrorLayoutStandin
@end

/// A subclass of NSError used to represent bridged native Swift errors.
/// This type cannot be subclassed, and should not ever be instantiated
/// except by the Swift runtime.
///
/// NOTE: older runtimes called this _SwiftNativeNSError. The two must
/// coexist, so it was renamed. The old name must not be used in the new
/// runtime.
@interface __SwiftNativeNSError : __SwiftNSErrorLayoutStandin
@interface __SwiftNativeNSError : NSError
@end

@implementation __SwiftNativeNSError
Expand All @@ -85,29 +71,29 @@ - (void)dealloc {
// layout. This gives us a buffer in case NSError decides to change its stored
// property order.

- (id /* NSString */)domain {
- (NSString*)domain {
auto error = (const SwiftError*)self;
// The domain string should not be nil; if it is, then this error box hasn't
// been initialized yet as an NSError.
auto domain = error->domain.load(SWIFT_MEMORY_ORDER_CONSUME);
assert(domain
&& "Error box used as NSError before initialization");
// Don't need to .retain.autorelease since it's immutable.
return cf_const_cast<id>(domain);
return cf_const_cast<NSString*>(domain);
}

- (NSInteger)code {
auto error = (const SwiftError*)self;
return error->code.load(SWIFT_MEMORY_ORDER_CONSUME);
}

- (id /* NSDictionary */)userInfo {
- (NSDictionary*)userInfo {
auto error = (const SwiftError*)self;
auto userInfo = error->userInfo.load(SWIFT_MEMORY_ORDER_CONSUME);
assert(userInfo
&& "Error box used as NSError before initialization");
// Don't need to .retain.autorelease since it's immutable.
return cf_const_cast<id>(userInfo);
return cf_const_cast<NSDictionary*>(userInfo);
}

- (id)copyWithZone:(NSZone *)zone {
Expand Down Expand Up @@ -167,29 +153,16 @@ - (BOOL)isEqual:(id)other {
@end

Class swift::getNSErrorClass() {
return SWIFT_LAZY_CONSTANT(objc_lookUpClass("NSError"));
return SWIFT_LAZY_CONSTANT([NSError class]);
}

const Metadata *swift::getNSErrorMetadata() {
return SWIFT_LAZY_CONSTANT(
swift_getObjCClassMetadata((const ClassMetadata *)getNSErrorClass()));
}

static Class getAndBridgeSwiftNativeNSErrorClass() {
Class nsErrorClass = swift::getNSErrorClass();
Class ourClass = [__SwiftNativeNSError class];
// We want "err as AnyObject" to do *something* even without Foundation
if (nsErrorClass) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
class_setSuperclass(ourClass, nsErrorClass);
#pragma clang diagnostic pop
}
return ourClass;
}

static Class getSwiftNativeNSErrorClass() {
return SWIFT_LAZY_CONSTANT(getAndBridgeSwiftNativeNSErrorClass());
return SWIFT_LAZY_CONSTANT([__SwiftNativeNSError class]);
}

/// Allocate a catchable error object.
Expand Down Expand Up @@ -301,7 +274,7 @@ static ErrorBridgingInfo getErrorBridgingInfo() {

const Metadata *SwiftError::getType() const {
if (isPureNSError()) {
id asError = reinterpret_cast<id>(const_cast<SwiftError *>(this));
auto asError = reinterpret_cast<NSError *>(const_cast<SwiftError *>(this));
return swift_getObjCClassMetadata((ClassMetadata*)[asError class]);
}
return type;
Expand Down Expand Up @@ -390,9 +363,9 @@ static ErrorBridgingInfo getErrorBridgingInfo() {
#define getErrorDomainNSString \
MANGLE_SYM(s23_getErrorDomainNSStringyyXlSPyxGs0B0RzlF)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
id getErrorDomainNSString(const OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error);
NSString *getErrorDomainNSString(const OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error);

// internal func _getErrorCode<T : Error>(_ x: UnsafePointer<T>) -> Int
#define getErrorCode \
Expand All @@ -406,17 +379,17 @@ NSInteger getErrorCode(const OpaqueValue *error,
#define getErrorUserInfoNSDictionary \
MANGLE_SYM(s29_getErrorUserInfoNSDictionaryyyXlSgSPyxGs0B0RzlF)
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
id getErrorUserInfoNSDictionary(
NSDictionary *getErrorUserInfoNSDictionary(
const OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error);

// @_silgen_name("_swift_stdlib_getErrorDefaultUserInfo")
// internal func _getErrorDefaultUserInfo<T : Error>(_ x: T) -> AnyObject
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
id _swift_stdlib_getErrorDefaultUserInfo(OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error) {
NSDictionary *_swift_stdlib_getErrorDefaultUserInfo(OpaqueValue *error,
const Metadata *T,
const WitnessTable *Error) {
// public func Foundation._getErrorDefaultUserInfo<T: Error>(_ error: T)
// -> AnyObject?
auto foundationGetDefaultUserInfo = getErrorBridgingInfo().GetErrorDefaultUserInfo;
Expand All @@ -434,7 +407,7 @@ id _swift_stdlib_getErrorDefaultUserInfo(OpaqueValue *error,
/// at +1.
id
swift::_swift_stdlib_bridgeErrorToNSError(SwiftError *errorObject) {
id ns = reinterpret_cast<id>(errorObject);
auto ns = reinterpret_cast<NSError *>(errorObject);

// If we already have a domain set, then we've already initialized.
// If this is a real NSError, then Cocoa and Core Foundation's initializers
Expand All @@ -458,9 +431,9 @@ id _swift_stdlib_getErrorDefaultUserInfo(OpaqueValue *error,
auto type = errorObject->getType();
auto witness = errorObject->getErrorConformance();

id domain = getErrorDomainNSString(value, type, witness);
NSString *domain = getErrorDomainNSString(value, type, witness);
NSInteger code = getErrorCode(value, type, witness);
id userInfo = getErrorUserInfoNSDictionary(value, type, witness);
NSDictionary *userInfo = getErrorUserInfoNSDictionary(value, type, witness);

// Never produce an empty userInfo dictionary.
if (!userInfo)
Expand Down Expand Up @@ -507,7 +480,7 @@ id _swift_stdlib_getErrorDefaultUserInfo(OpaqueValue *error,
if (![reinterpret_cast<id>(object) isKindOfClass: NSErrorClass])
return false;

id srcInstance = reinterpret_cast<id>(object);
NSError *srcInstance = reinterpret_cast<NSError *>(object);

// A __SwiftNativeNSError box can always be unwrapped to cast the value back
// out as an Error existential.
Expand Down Expand Up @@ -550,7 +523,7 @@ ProtocolDescriptorRef theErrorProtocol(&PROTOCOL_DESCR_SYM(s5Error),
auto *destTypeExistential = dyn_cast<ExistentialTypeMetadata>(destType);
if (destTypeExistential &&
destTypeExistential->getRepresentation() == ExistentialTypeRepresentation::Error) {
auto destBoxAddr = reinterpret_cast<id*>(dest);
auto destBoxAddr = reinterpret_cast<NSError**>(dest);
*destBoxAddr = objc_retain(srcInstance);
return true;
}
Expand Down
Loading