diff --git a/lib/SIL/DynamicCasts.cpp b/lib/SIL/DynamicCasts.cpp index 1604f8dda5360..8bbb6c031485e 100644 --- a/lib/SIL/DynamicCasts.cpp +++ b/lib/SIL/DynamicCasts.cpp @@ -1139,22 +1139,19 @@ bool swift::canUseScalarCheckedCastInstructions(SILModule &M, if (!objectType.isAnyClassReferenceType()) return false; - if (M.getASTContext().LangOpts.EnableObjCInterop) { auto super = archetype->getSuperclass(); if (super.isNull()) return false; - // A base class constraint that isn't NSError rules out the archetype being - // bound to NSError. - if (auto nserror = M.Types.getNSErrorType()) - return !super->isEqual(nserror); - // If NSError wasn't loaded, any base class constraint must not be NSError. - return true; - } else { - // If ObjC bridging isn't enabled, we can do a scalar cast from any - // reference type to any class-constrained archetype. - return archetype->requiresClass(); + // A base class constraint that isn't NSError rules out the archetype being + // bound to NSError. + if (M.getASTContext().LangOpts.EnableObjCInterop) { + if (auto nserror = M.Types.getNSErrorType()) + return !super->isEqual(nserror); } + + // If NSError wasn't loaded, any base class constraint must not be NSError. + return true; } if (M.getASTContext().LangOpts.EnableObjCInterop diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 38181460877dc..efb4dab554281 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -3660,10 +3660,7 @@ namespace { auto *locator = cs.getConstraintLocator(expr); if (!choice) { - if (tc.Context.LangOpts.EnableObjCInterop) - choice = solution.getDisjunctionChoice(locator); - else - choice = 0; + choice = solution.getDisjunctionChoice(locator); } // Handle the coercion/bridging of the underlying subexpression, where diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index 517741ff7cf90..367db6a5c47bc 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3637,11 +3637,6 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1, Type type2, TypeMatchOptions flags, ConstraintLocatorBuilder locator) { - // There's no bridging without ObjC interop, so we shouldn't have set up - // bridging constraints without it. - assert(TC.Context.LangOpts.EnableObjCInterop - && "bridging constraint w/o ObjC interop?!"); - TypeMatchOptions subflags = getDefaultDecompositionOptions(flags); /// Form an unresolved result. @@ -5086,14 +5081,11 @@ void ConstraintSystem::addExplicitConversionConstraint( coerceConstraint->setFavored(); constraints.push_back(coerceConstraint); - // Bridging. - if (getASTContext().LangOpts.EnableObjCInterop) { - // The source type can be explicitly converted to the destination type. - Constraint *bridgingConstraint = - Constraint::create(*this, ConstraintKind::BridgingConversion, - fromType, toType, locatorPtr); - constraints.push_back(bridgingConstraint); - } + // The source type can be explicitly converted to the destination type. + Constraint *bridgingConstraint = + Constraint::create(*this, ConstraintKind::BridgingConversion, + fromType, toType, locatorPtr); + constraints.push_back(bridgingConstraint); if (allowFixes && shouldAttemptFixes()) { Constraint *downcastConstraint = @@ -5104,8 +5096,8 @@ void ConstraintSystem::addExplicitConversionConstraint( } addDisjunctionConstraint(constraints, locator, - getASTContext().LangOpts.EnableObjCInterop && allowFixes ? RememberChoice - : ForgetChoice); + allowFixes ? RememberChoice + : ForgetChoice); } ConstraintSystem::SolutionKind diff --git a/lib/Sema/Constraint.cpp b/lib/Sema/Constraint.cpp index 68a7545c403e9..622cfb1275d74 100644 --- a/lib/Sema/Constraint.cpp +++ b/lib/Sema/Constraint.cpp @@ -612,10 +612,6 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind, assert((kind != ConstraintKind::LiteralConformsTo) || second->is()); - // Bridging constraints require bridging to be enabled. - assert(kind != ConstraintKind::BridgingConversion - || cs.TC.Context.LangOpts.EnableObjCInterop); - // Create the constraint. unsigned size = totalSizeToAlloc(typeVars.size()); void *mem = cs.getAllocator().Allocate(size, alignof(Constraint)); diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index eefdc0c0dce31..3feb385331904 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -2878,8 +2878,7 @@ bool TypeChecker::isExplicitlyConvertibleTo(Type type1, Type type2, bool TypeChecker::isObjCBridgedTo(Type type1, Type type2, DeclContext *dc, bool *unwrappedIUO) { - return (Context.LangOpts.EnableObjCInterop && - typesSatisfyConstraint(type1, type2, + return (typesSatisfyConstraint(type1, type2, /*openArchetypes=*/false, ConstraintKind::BridgingConversion, dc, unwrappedIUO)); @@ -3391,9 +3390,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType, } // Check for a bridging conversion. - // Anything bridges to AnyObject in ObjC interop mode. - if (Context.LangOpts.EnableObjCInterop - && toType->isAnyObject()) + // Anything bridges to AnyObject. + if (toType->isAnyObject()) return CheckedCastKind::BridgingCoercion; // Do this check later in Swift 3 mode so that we check for NSNumber and diff --git a/stdlib/public/core/BridgeObjectiveC.swift b/stdlib/public/core/BridgeObjectiveC.swift index b26c720f31833..e2243c1f67c7b 100644 --- a/stdlib/public/core/BridgeObjectiveC.swift +++ b/stdlib/public/core/BridgeObjectiveC.swift @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#if _runtime(_ObjC) /// A Swift Array or Dictionary of types conforming to /// `_ObjectiveCBridgeable` can be passed to Objective-C as an NSArray or /// NSDictionary, respectively. The elements of the resulting NSArray @@ -83,6 +82,8 @@ public protocol _ObjectiveCBridgeable { -> Self } +#if _runtime(_ObjC) + //===--- Bridging for metatypes -------------------------------------------===// /// A stand-in for a value of metatype type. @@ -640,3 +641,182 @@ public func _getObjCTypeEncoding(_ type: T.Type) -> UnsafePointer { } #endif + +//===--- Bridging without the ObjC runtime --------------------------------===// + +#if !_runtime(_ObjC) + +/// Convert `x` from its Objective-C representation to its Swift +/// representation. +/// COMPILER_INTRINSIC +@_inlineable // FIXME(sil-serialize-all) +public func _forceBridgeFromObjectiveC_bridgeable ( + _ x: T._ObjectiveCType, + _: T.Type +) -> T { + var result: T? + T._forceBridgeFromObjectiveC(x, result: &result) + return result! +} + +/// Attempt to convert `x` from its Objective-C representation to its Swift +/// representation. +/// COMPILER_INTRINSIC +@_inlineable // FIXME(sil-serialize-all) +public func _conditionallyBridgeFromObjectiveC_bridgeable( + _ x: T._ObjectiveCType, + _: T.Type +) -> T? { + var result: T? + T._conditionallyBridgeFromObjectiveC (x, result: &result) + return result +} + +public // SPI(Foundation) +protocol _NSSwiftValue: class { + init(_ value: Any) + var value: Any { get } + static var null: AnyObject { get } +} + +@usableFromInline +internal class _SwiftValue { + @usableFromInline + let value: Any + + @usableFromInline + init(_ value: Any) { + self.value = value + } + + @usableFromInline + static let null = _SwiftValue(Optional.none as Any) +} + +// Internal stdlib SPI +@_silgen_name("swift_unboxFromSwiftValueWithType") +public func swift_unboxFromSwiftValueWithType( + _ source: inout AnyObject, + _ result: UnsafeMutablePointer + ) -> Bool { + + if source === _nullPlaceholder { + if let unpacked = Optional.none as? T { + result.initialize(to: unpacked) + return true + } + } + + if let box = source as? _SwiftValue { + if let value = box.value as? T { + result.initialize(to: value) + return true + } + } else if let box = source as? _NSSwiftValue { + if let value = box.value as? T { + result.initialize(to: value) + return true + } + } + + return false +} + +// Internal stdlib SPI +@_silgen_name("swift_swiftValueConformsTo") +public func _swiftValueConformsTo(_ type: T.Type) -> Bool { + if let foundationType = _foundationSwiftValueType { + return foundationType is T.Type + } else { + return _SwiftValue.self is T.Type + } +} + +@_silgen_name("_swift_extractDynamicValue") +public func _extractDynamicValue(_ value: T) -> AnyObject? + +@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible") +public func _bridgeToObjectiveCUsingProtocolIfPossible(_ value: T) -> AnyObject? + +@usableFromInline +protocol _Unwrappable { + func unwrap() -> Any? +} + +extension Optional: _Unwrappable { + func unwrap() -> Any? { + return self + } +} + +private let _foundationSwiftValueType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type + +@usableFromInline +internal var _nullPlaceholder: AnyObject { + if let foundationType = _foundationSwiftValueType { + return foundationType.null + } else { + return _SwiftValue.null + } +} + +@usableFromInline +func _makeSwiftValue(_ value: Any) -> AnyObject { + if let foundationType = _foundationSwiftValueType { + return foundationType.init(value) + } else { + return _SwiftValue(value) + } +} + +/// Bridge an arbitrary value to an Objective-C object. +/// +/// - If `T` is a class type, it is always bridged verbatim, the function +/// returns `x`; +/// +/// - otherwise, if `T` conforms to `_ObjectiveCBridgeable`, +/// returns the result of `x._bridgeToObjectiveC()`; +/// +/// - otherwise, we use **boxing** to bring the value into Objective-C. +/// The value is wrapped in an instance of a private Objective-C class +/// that is `id`-compatible and dynamically castable back to the type of +/// the boxed value, but is otherwise opaque. +/// +/// COMPILER_INTRINSIC +@inlinable // FIXME(sil-serialize-all) +public func _bridgeAnythingToObjectiveC(_ x: T) -> AnyObject { + var done = false + var result: AnyObject! + + var source: Any = x + + if let dynamicSource = _extractDynamicValue(x) { + result = dynamicSource as AnyObject + done = true + } + + if !done, let wrapper = source as? _Unwrappable { + if let value = wrapper.unwrap() { + result = value as AnyObject + } else { + result = _nullPlaceholder + } + + done = true + } + + if !done { + if type(of: source) as? AnyClass != nil { + result = unsafeBitCast(x, to: AnyObject.self) + } else if let object = _bridgeToObjectiveCUsingProtocolIfPossible(source) { + result = object + } else { + result = _makeSwiftValue(source) + } + } + + return result +} + +#endif // !_runtime(_ObjC) + diff --git a/stdlib/public/core/Codable.swift.gyb b/stdlib/public/core/Codable.swift.gyb index cd4a2847c100f..5a19c3be0020b 100644 --- a/stdlib/public/core/Codable.swift.gyb +++ b/stdlib/public/core/Codable.swift.gyb @@ -1180,7 +1180,7 @@ public enum EncodingError : Error { public var _userInfo: AnyObject? { // The error dictionary must be returned as an AnyObject. We can do this // only on platforms with bridging, unfortunately. - #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + #if _runtime(_ObjC) let context: Context switch self { case .invalidValue(_, let c): context = c @@ -1290,7 +1290,7 @@ public enum DecodingError : Error { public var _userInfo: AnyObject? { // The error dictionary must be returned as an AnyObject. We can do this // only on platforms with bridging, unfortunately. - #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS) + #if _runtime(_ObjC) let context: Context switch self { case .keyNotFound(_, let c): context = c diff --git a/stdlib/public/runtime/Casting.cpp b/stdlib/public/runtime/Casting.cpp index 98634688c84ab..eb0676a7b8f34 100644 --- a/stdlib/public/runtime/Casting.cpp +++ b/stdlib/public/runtime/Casting.cpp @@ -196,7 +196,6 @@ swift::swift_dynamicCastFailure(const Metadata *sourceType, targetType, targetName.c_str(), message); } -#if SWIFT_OBJC_INTEROP // Objective-C bridging helpers. namespace { struct _ObjectiveCBridgeableWitnessTable; @@ -227,7 +226,6 @@ static bool _dynamicCastClassToValueViaObjCBridgeable( const Metadata *targetType, const _ObjectiveCBridgeableWitnessTable *targetBridgeWitness, DynamicCastFlags flags); -#endif /// A convenient method for failing out of a dynamic cast. static bool _fail(OpaqueValue *srcValue, const Metadata *srcType, @@ -663,6 +661,16 @@ static bool _dynamicCastFromAnyHashable(OpaqueValue *destination, /******************************** Existentials ********************************/ /******************************************************************************/ +#if !SWIFT_OBJC_INTEROP // _SwiftValue is a native class +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_swiftValueConformsTo(const Metadata *destinationType); + +#define _bridgeAnythingToObjectiveC \ + MANGLE_SYM(s27_bridgeAnythingToObjectiveCyyXlxlF) +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API +HeapObject *_bridgeAnythingToObjectiveC(OpaqueValue *src, const Metadata *srcType); +#endif + /// Perform a dynamic cast to an existential type. static bool _dynamicCastToExistential(OpaqueValue *dest, OpaqueValue *src, @@ -757,6 +765,15 @@ static bool _dynamicCastToExistential(OpaqueValue *dest, maybeDeallocateSource(true); return true; } +#else // !SWIFT_OBJC_INTEROP -- _SwiftValue is a native class + bool isMetatype = kind == MetadataKind::ExistentialMetatype || kind == MetadataKind::Metatype; + if (!isMetatype && (isTargetTypeAnyObject || swift_swiftValueConformsTo(targetType))) { + auto object = _bridgeAnythingToObjectiveC(src, srcType); + swift_retain(object); + destExistential->Value = object; + maybeDeallocateSource(true); + return true; + } #endif return _fail(src, srcType, targetType, flags); @@ -805,7 +822,6 @@ static bool _dynamicCastToExistential(OpaqueValue *dest, case MetadataKind::Enum: case MetadataKind::Optional: -#if SWIFT_OBJC_INTEROP // If the source type is bridged to Objective-C, try to bridge. if (auto srcBridgeWitness = findBridgeWitness(srcDynamicType)) { bool success = _dynamicCastValueToClassExistentialViaObjCBridgeable( @@ -818,7 +834,6 @@ static bool _dynamicCastToExistential(OpaqueValue *dest, maybeDeallocateSource(success); return success; } -#endif LLVM_FALLTHROUGH; default: @@ -1181,7 +1196,6 @@ swift_dynamicCastMetatypeUnconditionalImpl(const Metadata *sourceType, /********************************** Classes ***********************************/ /******************************************************************************/ -#if SWIFT_OBJC_INTEROP /// Do a dynamic cast to the target class. static void *_dynamicCastUnknownClass(void *object, const Metadata *targetType, @@ -1194,7 +1208,6 @@ static void *_dynamicCastUnknownClass(void *object, return const_cast(swift_dynamicCastUnknownClass(object, targetType)); } -#endif static bool _dynamicCastUnknownClassIndirect(OpaqueValue *dest, void *object, @@ -1873,7 +1886,13 @@ checkDynamicCastFromOptional(OpaqueValue *dest, /**************************** Bridging _SwiftValue ****************************/ /******************************************************************************/ -#if SWIFT_OBJC_INTEROP +#if !SWIFT_OBJC_INTEROP // _SwiftValue is a native class +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_unboxFromSwiftValueWithType(OpaqueValue *source, + OpaqueValue *result, + const Metadata *destinationType); +#endif + /// Try to unbox a _SwiftValue box to perform a dynamic cast. static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest, OpaqueValue *src, @@ -1891,6 +1910,13 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest, return false; } +#if !SWIFT_OBJC_INTEROP // _SwiftValue is a native class: + if (swift_unboxFromSwiftValueWithType(src, dest, targetType)) { + return true; + } +#endif + +#if SWIFT_OBJC_INTEROP // _SwiftValue is an ObjC class: id srcObject; memcpy(&srcObject, src, sizeof(id)); @@ -1930,10 +1956,10 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest, objc_release((id)srcSwiftValue); return true; } +#endif return false; } -#endif /******************************************************************************/ /******************************** Collections *********************************/ @@ -2228,7 +2254,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, if (!srcType) return unwrapResult.success; -#if SWIFT_OBJC_INTEROP // A class or AnyObject reference may point to a _SwiftValue box. { auto innerFlags = flags - DynamicCastFlags::Unconditional @@ -2243,7 +2268,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, // (for example, casting _SwiftValue to NSObject will be successful) } } -#endif switch (targetType->getKind()) { // Handle wrapping an Optional target. @@ -2252,7 +2276,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, // unwrapping the target. This handles an optional source wrapped within an // existential that Optional conforms to (Any). if (auto srcExistentialType = dyn_cast(srcType)) { -#if SWIFT_OBJC_INTEROP // If coming from AnyObject, we may want to bridge. if (isAnyObjectExistentialType(srcExistentialType)) { if (auto targetBridgeWitness = findBridgeWitness(targetType)) { @@ -2262,7 +2285,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, flags); } } -#endif return _dynamicCastFromExistential(dest, src, srcExistentialType, targetType, flags); } @@ -2327,7 +2349,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, case MetadataKind::Enum: case MetadataKind::Optional: { -#if SWIFT_OBJC_INTEROP // If the source type is bridged to Objective-C, try to bridge. if (auto srcBridgeWitness = findBridgeWitness(srcType)) { return _dynamicCastValueToClassViaObjCBridgeable(dest, src, srcType, @@ -2335,7 +2356,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, srcBridgeWitness, flags); } -#endif return _fail(src, srcType, targetType, flags); } @@ -2377,7 +2397,6 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, return _dynamicCastToAnyHashable(dest, src, srcType, targetType, flags); } -#if SWIFT_OBJC_INTEROP // If the target type is bridged to Objective-C, try to bridge. if (auto targetBridgeWitness = findBridgeWitness(targetType)) { return _dynamicCastClassToValueViaObjCBridgeable(dest, src, srcType, @@ -2386,6 +2405,7 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src, flags); } +#if SWIFT_OBJC_INTEROP // If the source is an NSError, and the target is a bridgeable // Error, try to bridge. if (tryDynamicCastNSErrorToValue(dest, src, srcType, targetType, flags)) { @@ -2471,7 +2491,6 @@ static inline bool swift_isClassOrObjCExistentialTypeImpl(const Metadata *T) { /********************************** Bridging **********************************/ /******************************************************************************/ -#if SWIFT_OBJC_INTEROP //===----------------------------------------------------------------------===// // Bridging to and from Objective-C //===----------------------------------------------------------------------===// @@ -2648,7 +2667,7 @@ static bool _dynamicCastClassToValueViaObjCBridgeable( // Allocate a buffer to store the T? returned by bridging. // The extra byte is for the tag. const std::size_t inlineValueSize = 3 * sizeof(void*); - alignas(std::max_align_t) char inlineBuffer[inlineValueSize + 1]; + alignas(max_align_t) char inlineBuffer[inlineValueSize + 1]; void *optDestBuffer; if (targetType->getValueWitnesses()->getStride() <= inlineValueSize) { // Use the inline buffer. @@ -2692,6 +2711,13 @@ static bool _dynamicCastClassToValueViaObjCBridgeable( return success; } +#if !SWIFT_OBJC_INTEROP // _SwiftValue is a native class: + + + +#endif // !_SWIFT_OBJC_INTEROP + +#if SWIFT_OBJC_INTEROP static id bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src, const Metadata *srcType, bool consume) { @@ -2792,6 +2818,7 @@ id _bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src, return bridgeAnythingNonVerbatimToObjectiveC(src, srcType, /*consume*/shouldConsume); } +#endif //===--- Bridging helpers for the Swift stdlib ----------------------------===// // Functions that must discover and possibly use an arbitrary type's @@ -2799,10 +2826,12 @@ id _bridgeAnythingNonVerbatimToObjectiveC(OpaqueValue *src, // documentation. //===----------------------------------------------------------------------===// +#if SWIFT_OBJC_INTEROP #define BRIDGING_CONFORMANCE_SYM \ MANGLE_SYM(s19_BridgeableMetatypeVs21_ObjectiveCBridgeablesWP) extern "C" const _ObjectiveCBridgeableWitnessTable BRIDGING_CONFORMANCE_SYM; +#endif static const _ObjectiveCBridgeableWitnessTable * findBridgeWitness(const Metadata *T) { @@ -2815,16 +2844,20 @@ findBridgeWitness(const Metadata *T) { // that looks like a metatype value if the metatype can be bridged. switch (T->getKind()) { case MetadataKind::Metatype: { +#if SWIFT_OBJC_INTEROP auto metaTy = static_cast(T); if (metaTy->InstanceType->isAnyClass()) return &BRIDGING_CONFORMANCE_SYM; +#endif break; } case MetadataKind::ExistentialMetatype: { +#if SWIFT_OBJC_INTEROP auto existentialMetaTy = static_cast(T); if (existentialMetaTy->isObjC()) return &BRIDGING_CONFORMANCE_SYM; +#endif break; } @@ -2854,6 +2887,8 @@ const Metadata *_getBridgedNonVerbatimObjectiveCType( return nullptr; } +#if SWIFT_OBJC_INTEROP + // @_silgen_name("_bridgeNonVerbatimFromObjectiveCToAny") // func _bridgeNonVerbatimFromObjectiveCToAny( // x: AnyObject, @@ -2890,7 +2925,6 @@ static bool tryBridgeNonVerbatimFromObjectiveCUniversal( return true; } } - // Check if the value is a box containing a value of the desired type. if (auto srcBox = getAsSwiftValue((id)sourceValue)) { const Metadata *sourceType; @@ -2922,6 +2956,7 @@ _bridgeNonVerbatimFromObjectiveC( OpaqueValue *destValue, const Metadata *nativeType_ ) { + if (tryBridgeNonVerbatimFromObjectiveCUniversal(sourceValue, nativeType, destValue)) return; @@ -2999,6 +3034,8 @@ _bridgeNonVerbatimFromObjectiveCConditional( destValue, nativeType, nativeType, bridgeWitness); } +#endif // SWIFT_OBJC_INTEROP + // func _isBridgedNonVerbatimToObjectiveC(_: T.Type) -> Bool // Called by inlined stdlib code. #define _isBridgedNonVerbatimToObjectiveC \ @@ -3011,7 +3048,6 @@ bool _isBridgedNonVerbatimToObjectiveC(const Metadata *value, auto bridgeWitness = findBridgeWitness(T); return (bool)bridgeWitness; } -#endif // func _isClassOrObjCExistential(x: T.Type) -> Bool SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE @@ -3040,6 +3076,55 @@ bool swift_isOptionalType(const Metadata *type) { return type->getKind() == MetadataKind::Optional; } +#if !SWIFT_OBJC_INTEROP +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool _swift_isOptional(OpaqueValue *src, const Metadata *type) { + return swift_isOptionalType(type); +} + +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +HeapObject *_swift_extractDynamicValue(OpaqueValue *value, const Metadata *self) { + OpaqueValue *outValue; + const Metadata *outType; + bool canTake = false; + + findDynamicValueAndType(value, self, outValue, outType, canTake, + /*isAnyObject*/ true, + /*isExistentialMetatype*/ true); + + if (!outType || (outType != self && outType->isAnyClass())) { + HeapObject *object = *(reinterpret_cast(outValue)); + swift_retain(object); + return object; + } + + return nullptr; +} + +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +HeapObject *_swift_bridgeToObjectiveCUsingProtocolIfPossible( + OpaqueValue *src, const Metadata *srcType) { + assert(!swift_isClassOrObjCExistentialTypeImpl(srcType)); + + OpaqueValue *outValue; + const Metadata *outType; + bool canTake = false; + + findDynamicValueAndType(src, srcType, outValue, outType, canTake, + /*isAnyObject*/ false, + /*isExistentialMetatype*/ true); + + auto bridgeWitness = findBridgeWitness(outType); + if (bridgeWitness) { + auto bridgedObject = + bridgeWitness->bridgeToObjectiveC(outValue, outType, bridgeWitness); + return bridgedObject; + } else { + return nullptr; + } +} +#endif + #define OVERRIDE_CASTING COMPATIBILITY_OVERRIDE #include "CompatibilityOverride.def" diff --git a/test/Constraints/bridging_nonobjc.swift b/test/Constraints/bridging_nonobjc.swift index f2c06ee9e168b..df05f59d89e24 100644 --- a/test/Constraints/bridging_nonobjc.swift +++ b/test/Constraints/bridging_nonobjc.swift @@ -2,4 +2,4 @@ var x: Any = 1 -var y = x as AnyObject // expected-error{{not convertible}} +var y = x as AnyObject diff --git a/test/Interpreter/generic_casts.swift b/test/Interpreter/generic_casts.swift index 0705141eaacac..262fdc0f2916b 100644 --- a/test/Interpreter/generic_casts.swift +++ b/test/Interpreter/generic_casts.swift @@ -4,9 +4,10 @@ // REQUIRES: executable_test // FIXME: rdar://problem/19648117 Needs splitting objc parts out -// XFAIL: linux +#if canImport(Foundation) import Foundation +#endif func allToInt(_ x: T) -> Int { return x as! Int @@ -153,21 +154,35 @@ print(u is Int.Type) // CHECK: false // FIXME: Can't spell AnyObject.Protocol // CHECK-LABEL: AnyObject casts: print("AnyObject casts:") -print(allToAll(C(), AnyObject.self)) // CHECK-NEXT: true -print(allToAll(type(of: C()), AnyObject.self)) // CHECK-NEXT: true +print(allToAll(C(), AnyObject.self)) // CHECK: true + +// On Darwin, the object will be the ObjC-runtime-class object; +// out of Darwin, this should not succeed. +print(allToAll(type(of: C()), AnyObject.self)) +// CHECK-objc: true +// CHECK-native: false + // Bridging -print(allToAll(0, AnyObject.self)) // CHECK-NEXT: true +// NSNumber on Darwin, _SwiftValue on Linux. +print(allToAll(0, AnyObject.self)) // CHECK: true // This will get bridged using _SwiftValue. struct NotBridged { var x: Int } -print(allToAll(NotBridged(x: 0), AnyObject.self)) // CHECK-NEXT: true -print(allToAll(NotBridged(x: 0), NSCopying.self)) // CHECK-NEXT: true +print(allToAll(NotBridged(x: 0), AnyObject.self)) // CHECK: true + +#if canImport(Foundation) +// This requires Foundation (for NSCopying): +print(allToAll(NotBridged(x: 0), NSCopying.self)) // CHECK-objc: true +#endif -// These casts fail (intentionally) even though _SwiftValue does +// On Darwin, these casts fail (intentionally) even though _SwiftValue does // technically conform to these protocols through NSObject. -print(allToAll(NotBridged(x: 0), CustomStringConvertible.self)) // CHECK-NEXT: false -print(allToAll(NotBridged(x: 0), (AnyObject & CustomStringConvertible).self)) // CHECK-NEXT: false +// Off Darwin, it should not conform at all. +print(allToAll(NotBridged(x: 0), CustomStringConvertible.self)) // CHECK: false +print(allToAll(NotBridged(x: 0), (AnyObject & CustomStringConvertible).self)) // CHECK: false +#if canImport(Foundation) +// This requires Foundation (for NSArray): // // rdar://problem/19482567 // @@ -183,4 +198,5 @@ func swiftOptimizesThisFunctionIncorrectly() -> Bool { } let result = swiftOptimizesThisFunctionIncorrectly() -print("Bridge cast result: \(result)") // CHECK-NEXT: Bridge cast result: true +print("Bridge cast result: \(result)") // CHECK-NEXT-objc: Bridge cast result: true +#endif diff --git a/test/SILGen/generic_casts.swift b/test/SILGen/generic_casts.swift index 3a8e7fc066f43..74aace8820469 100644 --- a/test/SILGen/generic_casts.swift +++ b/test/SILGen/generic_casts.swift @@ -59,11 +59,9 @@ func class_archetype_to_class_archetype (_ t:T) -> U { return t as! U // Error bridging can change the identity of class-constrained archetypes. - // CHECK-objc: unconditional_checked_cast_addr T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U - // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] - // CHECK-objc: return [[DOWNCAST]] : $U - - // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $T to $U + // CHECK: unconditional_checked_cast_addr T in {{%.*}} : $*T to U in [[DOWNCAST_ADDR:%.*]] : $*U + // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] + // CHECK: return [[DOWNCAST]] : $U } // CHECK-LABEL: sil hidden @$S13generic_casts019class_archetype_is_c1_D0{{[_0-9a-zA-Z]*}}F @@ -71,8 +69,7 @@ func class_archetype_is_class_archetype (_ t:T, u:U.Type) -> Bool { return t is U // Error bridging can change the identity of class-constrained archetypes. - // CHECK-objc: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U - // CHECK-native: checked_cast_br {{.*}} : $T to $U + // CHECK: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U } // CHECK-LABEL: sil hidden @$S13generic_casts38opaque_archetype_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F @@ -161,19 +158,16 @@ func opaque_existential_is_class_archetype func class_existential_to_class_archetype (_ p:ClassBound) -> T { return p as! T - // CHECK-objc: unconditional_checked_cast_addr ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T - // CHECK-objc: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] - // CHECK-objc: return [[DOWNCAST]] : $T - - // CHECK-native: [[DOWNCAST:%.*]] = unconditional_checked_cast {{.*}} : $ClassBound to $T + // CHECK: unconditional_checked_cast_addr ClassBound in {{%.*}} : $*ClassBound to T in [[DOWNCAST_ADDR:%.*]] : $*T + // CHECK: [[DOWNCAST:%.*]] = load [take] [[DOWNCAST_ADDR]] + // CHECK: return [[DOWNCAST]] : $T } // CHECK-LABEL: sil hidden @$S13generic_casts021class_existential_is_C10_archetype{{[_0-9a-zA-Z]*}}F func class_existential_is_class_archetype (_ p:ClassBound, _: T) -> Bool { return p is T - // CHECK-objc: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T - // CHECK-native: checked_cast_br {{.*}} : $ClassBound to $T + // CHECK: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T } // CHECK-LABEL: sil hidden @$S13generic_casts40opaque_existential_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F diff --git a/test/expr/cast/array_downcast.swift b/test/expr/cast/array_downcast.swift index 475036de10fe9..fddea8a4742fd 100644 --- a/test/expr/cast/array_downcast.swift +++ b/test/expr/cast/array_downcast.swift @@ -1,7 +1,5 @@ // RUN: %target-typecheck-verify-swift -// XFAIL: linux - // FIXME: Should go into the standard library. public extension _ObjectiveCBridgeable { static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?) diff --git a/test/stmt/errors_nonobjc.swift b/test/stmt/errors_nonobjc.swift index 7f710f7bcb07c..5d09db24c6569 100644 --- a/test/stmt/errors_nonobjc.swift +++ b/test/stmt/errors_nonobjc.swift @@ -5,14 +5,13 @@ import Foundation -// Catching `as NSError` ought *not* to be exhaustive when ObjC interop is -// disabled. It's just another error type. +// Since we enabled bridging on non-ObjC platforms, NSError ought to be treated as exhaustive. func bar() throws {} func foo() { do { - try bar() // expected-error{{enclosing catch is not exhaustive}} + try bar() } catch _ as NSError { } } diff --git a/unittests/runtime/Stdlib.cpp b/unittests/runtime/Stdlib.cpp index 649513372085d..7f7003611ab6b 100644 --- a/unittests/runtime/Stdlib.cpp +++ b/unittests/runtime/Stdlib.cpp @@ -11,6 +11,7 @@ //===----------------------------------------------------------------------===// #include "swift/Runtime/Metadata.h" +#include "swift/Demangling/ManglingMacros.h" using namespace swift; @@ -135,6 +136,22 @@ void _bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue, abort(); } +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_unboxFromSwiftValueWithType(OpaqueValue *source, + OpaqueValue *result, + const Metadata *destinationType) { + abort(); +} + +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL +bool swift_swiftValueConformsTo(const Metadata *destinationType) { + abort(); +} + +SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_API +HeapObject *$Ss27_bridgeAnythingToObjectiveCyyXlxlF(OpaqueValue *src, const Metadata *srcType) { + abort(); +} // ErrorObject