mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Revert "Turn on ‘as’ bridging on Linux."
This commit is contained in:
@@ -1134,19 +1134,22 @@ 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 (M.getASTContext().LangOpts.EnableObjCInterop) {
|
||||
if (auto nserror = M.Types.getNSErrorType())
|
||||
return !super->isEqual(nserror);
|
||||
// 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();
|
||||
}
|
||||
|
||||
// If NSError wasn't loaded, any base class constraint must not be NSError.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (M.getASTContext().LangOpts.EnableObjCInterop
|
||||
|
||||
@@ -3686,7 +3686,10 @@ namespace {
|
||||
auto *locator = cs.getConstraintLocator(expr);
|
||||
|
||||
if (!choice) {
|
||||
choice = solution.getDisjunctionChoice(locator);
|
||||
if (tc.Context.LangOpts.EnableObjCInterop)
|
||||
choice = solution.getDisjunctionChoice(locator);
|
||||
else
|
||||
choice = 0;
|
||||
}
|
||||
|
||||
// Handle the coercion/bridging of the underlying subexpression, where
|
||||
|
||||
@@ -3627,6 +3627,11 @@ 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.
|
||||
@@ -5071,11 +5076,14 @@ void ConstraintSystem::addExplicitConversionConstraint(
|
||||
coerceConstraint->setFavored();
|
||||
constraints.push_back(coerceConstraint);
|
||||
|
||||
// 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);
|
||||
// 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);
|
||||
}
|
||||
|
||||
if (allowFixes && shouldAttemptFixes()) {
|
||||
Constraint *downcastConstraint =
|
||||
@@ -5086,8 +5094,8 @@ void ConstraintSystem::addExplicitConversionConstraint(
|
||||
}
|
||||
|
||||
addDisjunctionConstraint(constraints, locator,
|
||||
allowFixes ? RememberChoice
|
||||
: ForgetChoice);
|
||||
getASTContext().LangOpts.EnableObjCInterop && allowFixes ? RememberChoice
|
||||
: ForgetChoice);
|
||||
}
|
||||
|
||||
ConstraintSystem::SolutionKind
|
||||
|
||||
@@ -612,6 +612,10 @@ Constraint *Constraint::create(ConstraintSystem &cs, ConstraintKind kind,
|
||||
assert((kind != ConstraintKind::LiteralConformsTo) ||
|
||||
second->is<ProtocolType>());
|
||||
|
||||
// Bridging constraints require bridging to be enabled.
|
||||
assert(kind != ConstraintKind::BridgingConversion
|
||||
|| cs.TC.Context.LangOpts.EnableObjCInterop);
|
||||
|
||||
// Create the constraint.
|
||||
unsigned size = totalSizeToAlloc<TypeVariableType*>(typeVars.size());
|
||||
void *mem = cs.getAllocator().Allocate(size, alignof(Constraint));
|
||||
|
||||
@@ -2881,7 +2881,8 @@ bool TypeChecker::isExplicitlyConvertibleTo(Type type1, Type type2,
|
||||
|
||||
bool TypeChecker::isObjCBridgedTo(Type type1, Type type2, DeclContext *dc,
|
||||
bool *unwrappedIUO) {
|
||||
return (typesSatisfyConstraint(type1, type2,
|
||||
return (Context.LangOpts.EnableObjCInterop &&
|
||||
typesSatisfyConstraint(type1, type2,
|
||||
/*openArchetypes=*/false,
|
||||
ConstraintKind::BridgingConversion,
|
||||
dc, unwrappedIUO));
|
||||
@@ -3393,8 +3394,9 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
|
||||
}
|
||||
|
||||
// Check for a bridging conversion.
|
||||
// Anything bridges to AnyObject.
|
||||
if (toType->isAnyObject())
|
||||
// Anything bridges to AnyObject in ObjC interop mode.
|
||||
if (Context.LangOpts.EnableObjCInterop
|
||||
&& toType->isAnyObject())
|
||||
return CheckedCastKind::BridgingCoercion;
|
||||
|
||||
// Do this check later in Swift 3 mode so that we check for NSNumber and
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if _runtime(_ObjC)
|
||||
|
||||
@_exported
|
||||
import ObjectiveC
|
||||
import _SwiftObjectiveCOverlayShims
|
||||
@@ -227,5 +225,3 @@ extension NSObject : CVarArg {
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#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
|
||||
@@ -82,8 +83,6 @@ public protocol _ObjectiveCBridgeable {
|
||||
-> Self
|
||||
}
|
||||
|
||||
#if _runtime(_ObjC)
|
||||
|
||||
//===--- Bridging for metatypes -------------------------------------------===//
|
||||
|
||||
/// A stand-in for a value of metatype type.
|
||||
@@ -641,200 +640,3 @@ public func _getObjCTypeEncoding<T>(_ type: T.Type) -> UnsafePointer<Int8> {
|
||||
}
|
||||
|
||||
#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<T:_ObjectiveCBridgeable> (
|
||||
_ 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<T:_ObjectiveCBridgeable>(
|
||||
_ 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<Any>.none as Any)
|
||||
}
|
||||
|
||||
/// COMPILER_INTRISIC
|
||||
@_silgen_name("swift_unboxFromSwiftValueWithType")
|
||||
public func swift_unboxFromSwiftValueWithType<T>(
|
||||
_ source: inout AnyObject,
|
||||
_ result: UnsafeMutablePointer<T>
|
||||
) -> Bool {
|
||||
|
||||
if source === _nullPlaceholder {
|
||||
if let unpacked = Optional<Any>.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
|
||||
}
|
||||
|
||||
@_silgen_name("_swift_extractDynamicValue")
|
||||
public func _extractDynamicValue<T>(_ value: T) -> AnyObject?
|
||||
|
||||
@_silgen_name("_swift_bridgeToObjectiveCUsingProtocolIfPossible")
|
||||
public func _bridgeToObjectiveCUsingProtocolIfPossible<T>(_ value: T) -> AnyObject?
|
||||
|
||||
@usableFromInline
|
||||
protocol _Unwrappable {
|
||||
func unwrap() -> Any?
|
||||
}
|
||||
|
||||
extension Optional: _Unwrappable {
|
||||
func unwrap() -> Any? {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
// This is a best-effort tripmine for detecting the situation
|
||||
// (which should never happen) of Swift._SwiftValue and
|
||||
// Foundation._SwiftValue/Foundation.NSNull being used
|
||||
// in the same process.
|
||||
|
||||
@usableFromInline
|
||||
internal enum _SwiftValueFlavor: Equatable {
|
||||
case stdlib
|
||||
case foundation
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
func _currentSwiftValueFlavor() -> _SwiftValueFlavor {
|
||||
if _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type != nil {
|
||||
return .foundation
|
||||
} else {
|
||||
return .stdlib
|
||||
}
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
internal var _selectedSwiftValueFlavor: _SwiftValueFlavor = _currentSwiftValueFlavor()
|
||||
|
||||
@usableFromInline
|
||||
internal func _assertSwiftValueFlavorIsConsistent() {
|
||||
assert(_selectedSwiftValueFlavor == _currentSwiftValueFlavor())
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
internal var _nullPlaceholder: AnyObject {
|
||||
_assertSwiftValueFlavorIsConsistent()
|
||||
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
|
||||
return foundationType.null
|
||||
} else {
|
||||
return _SwiftValue.null
|
||||
}
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
func _makeSwiftValue(_ value: Any) -> AnyObject {
|
||||
_assertSwiftValueFlavorIsConsistent()
|
||||
if let foundationType = _typeByName("Foundation._SwiftValue") as? _NSSwiftValue.Type {
|
||||
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<T>(_ 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)
|
||||
|
||||
|
||||
@@ -1171,7 +1171,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 _runtime(_ObjC)
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let context: Context
|
||||
switch self {
|
||||
case .invalidValue(_, let c): context = c
|
||||
@@ -1281,7 +1281,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 _runtime(_ObjC)
|
||||
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
|
||||
let context: Context
|
||||
switch self {
|
||||
case .keyNotFound(_, let c): context = c
|
||||
|
||||
@@ -196,6 +196,7 @@ swift::swift_dynamicCastFailure(const Metadata *sourceType,
|
||||
targetType, targetName.c_str(), message);
|
||||
}
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// Objective-C bridging helpers.
|
||||
namespace {
|
||||
struct _ObjectiveCBridgeableWitnessTable;
|
||||
@@ -226,6 +227,7 @@ 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,
|
||||
@@ -798,7 +800,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
|
||||
// A fallback to use if we don't have a more specialized approach
|
||||
// for a non-class type.
|
||||
auto fallbackForNonClass = [&] {
|
||||
#if SWIFT_OBJC_INTEROP // TODO
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If the destination type is a set of protocols that SwiftValue
|
||||
// implements, we're fine.
|
||||
if (findSwiftValueConformances(targetType,
|
||||
@@ -858,6 +860,7 @@ 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(
|
||||
@@ -870,6 +873,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
|
||||
maybeDeallocateSource(success);
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
LLVM_FALLTHROUGH;
|
||||
|
||||
case MetadataKind::Function:
|
||||
@@ -1327,6 +1331,7 @@ 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,
|
||||
@@ -1339,6 +1344,7 @@ static void *_dynamicCastUnknownClass(void *object,
|
||||
|
||||
return const_cast<void*>(swift_dynamicCastUnknownClass(object, targetType));
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool _dynamicCastUnknownClassIndirect(OpaqueValue *dest,
|
||||
void *object,
|
||||
@@ -2047,13 +2053,7 @@ checkDynamicCastFromOptional(OpaqueValue *dest,
|
||||
/**************************** Bridging _SwiftValue ****************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
/// Try to unbox a _SwiftValue box to perform a dynamic cast.
|
||||
static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
|
||||
OpaqueValue *src,
|
||||
@@ -2071,14 +2071,6 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !SWIFT_OBJC_INTEROP // _SwiftValue is a native class:
|
||||
// TODO: memory management?
|
||||
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));
|
||||
|
||||
@@ -2118,10 +2110,10 @@ static bool tryDynamicCastBoxedSwiftValue(OpaqueValue *dest,
|
||||
objc_release((id)srcSwiftValue);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
/******************************** Collections *********************************/
|
||||
@@ -2416,6 +2408,7 @@ 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
|
||||
@@ -2430,6 +2423,7 @@ 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.
|
||||
@@ -2438,6 +2432,7 @@ 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<ExistentialTypeMetadata>(srcType)) {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
// If coming from AnyObject, we may want to bridge.
|
||||
if (isAnyObjectExistentialType(srcExistentialType)) {
|
||||
if (auto targetBridgeWitness = findBridgeWitness(targetType)) {
|
||||
@@ -2447,6 +2442,7 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src,
|
||||
flags);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return _dynamicCastFromExistential(dest, src, srcExistentialType,
|
||||
targetType, flags);
|
||||
}
|
||||
@@ -2511,6 +2507,7 @@ 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,
|
||||
@@ -2518,6 +2515,7 @@ static bool swift_dynamicCastImpl(OpaqueValue *dest, OpaqueValue *src,
|
||||
srcBridgeWitness,
|
||||
flags);
|
||||
}
|
||||
#endif
|
||||
return _fail(src, srcType, targetType, flags);
|
||||
}
|
||||
|
||||
@@ -2566,6 +2564,7 @@ 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,
|
||||
@@ -2574,7 +2573,6 @@ 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)) {
|
||||
@@ -2673,6 +2671,7 @@ static inline bool swift_isClassOrObjCExistentialTypeImpl(const Metadata *T) {
|
||||
/********************************** Bridging **********************************/
|
||||
/******************************************************************************/
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Bridging to and from Objective-C
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -2893,13 +2892,6 @@ 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) {
|
||||
@@ -3000,7 +2992,6 @@ 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
|
||||
@@ -3008,12 +2999,10 @@ 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) {
|
||||
@@ -3026,20 +3015,16 @@ 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<const MetatypeMetadata *>(T);
|
||||
if (metaTy->InstanceType->isAnyClass())
|
||||
return &BRIDGING_CONFORMANCE_SYM;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case MetadataKind::ExistentialMetatype: {
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
auto existentialMetaTy =
|
||||
static_cast<const ExistentialMetatypeMetadata *>(T);
|
||||
if (existentialMetaTy->isObjC())
|
||||
return &BRIDGING_CONFORMANCE_SYM;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3081,8 +3066,6 @@ const Metadata *_getBridgedNonVerbatimObjectiveCType(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
|
||||
// @_silgen_name("_bridgeNonVerbatimFromObjectiveCToAny")
|
||||
// func _bridgeNonVerbatimFromObjectiveCToAny(
|
||||
// x: AnyObject,
|
||||
@@ -3119,6 +3102,7 @@ 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;
|
||||
@@ -3150,7 +3134,6 @@ _bridgeNonVerbatimFromObjectiveC(
|
||||
OpaqueValue *destValue,
|
||||
const Metadata *nativeType_
|
||||
) {
|
||||
|
||||
if (tryBridgeNonVerbatimFromObjectiveCUniversal(sourceValue, nativeType,
|
||||
destValue))
|
||||
return;
|
||||
@@ -3228,8 +3211,6 @@ _bridgeNonVerbatimFromObjectiveCConditional(
|
||||
destValue, nativeType, nativeType, bridgeWitness);
|
||||
}
|
||||
|
||||
#endif // SWIFT_OBJC_INTEROP
|
||||
|
||||
// func _isBridgedNonVerbatimToObjectiveC<T>(_: T.Type) -> Bool
|
||||
// Called by inlined stdlib code.
|
||||
#define _isBridgedNonVerbatimToObjectiveC \
|
||||
@@ -3242,6 +3223,7 @@ bool _isBridgedNonVerbatimToObjectiveC(const Metadata *value,
|
||||
auto bridgeWitness = findBridgeWitness(T);
|
||||
return (bool)bridgeWitness;
|
||||
}
|
||||
#endif
|
||||
|
||||
// func _isClassOrObjCExistential<T>(x: T.Type) -> Bool
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERFACE
|
||||
@@ -3270,55 +3252,6 @@ 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<HeapObject**>(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"
|
||||
|
||||
|
||||
5
test/Constraints/bridging_nonobjc.swift
Normal file
5
test/Constraints/bridging_nonobjc.swift
Normal file
@@ -0,0 +1,5 @@
|
||||
// RUN: %target-swift-frontend -typecheck -verify %s -disable-objc-interop
|
||||
|
||||
|
||||
var x: Any = 1
|
||||
var y = x as AnyObject // expected-error{{not convertible}}
|
||||
@@ -158,6 +158,16 @@ print(allToAll(type(of: C()), AnyObject.self)) // CHECK-NEXT: true
|
||||
// Bridging
|
||||
print(allToAll(0, AnyObject.self)) // CHECK-NEXT: 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
|
||||
|
||||
// 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
|
||||
|
||||
//
|
||||
// rdar://problem/19482567
|
||||
//
|
||||
|
||||
@@ -59,9 +59,11 @@ func class_archetype_to_class_archetype
|
||||
<T:ClassBound, U:ClassBound>(_ t:T) -> U {
|
||||
return t as! U
|
||||
// Error bridging can change the identity of class-constrained archetypes.
|
||||
// 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-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-LABEL: sil hidden @$S13generic_casts019class_archetype_is_c1_D0{{[_0-9a-zA-Z]*}}F
|
||||
@@ -69,7 +71,8 @@ func class_archetype_is_class_archetype
|
||||
<T:ClassBound, U:ClassBound>(_ t:T, u:U.Type) -> Bool {
|
||||
return t is U
|
||||
// Error bridging can change the identity of class-constrained archetypes.
|
||||
// CHECK: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
|
||||
// CHECK-objc: checked_cast_addr_br {{.*}} T in {{%.*}} : $*T to U in {{%.*}} : $*U
|
||||
// CHECK-native: checked_cast_br {{.*}} : $T to $U
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$S13generic_casts38opaque_archetype_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F
|
||||
@@ -158,16 +161,19 @@ func opaque_existential_is_class_archetype
|
||||
func class_existential_to_class_archetype
|
||||
<T:ClassBound>(_ p:ClassBound) -> T {
|
||||
return p as! 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-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-LABEL: sil hidden @$S13generic_casts021class_existential_is_C10_archetype{{[_0-9a-zA-Z]*}}F
|
||||
func class_existential_is_class_archetype
|
||||
<T:ClassBound>(_ p:ClassBound, _: T) -> Bool {
|
||||
return p is T
|
||||
// CHECK: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
|
||||
// CHECK-objc: checked_cast_addr_br {{.*}} ClassBound in {{%.*}} : $*ClassBound to T in {{%.*}} : $*T
|
||||
// CHECK-native: checked_cast_br {{.*}} : $ClassBound to $T
|
||||
}
|
||||
|
||||
// CHECK-LABEL: sil hidden @$S13generic_casts40opaque_existential_to_addr_only_concrete{{[_0-9a-zA-Z]*}}F
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
// XFAIL: linux
|
||||
|
||||
// FIXME: Should go into the standard library.
|
||||
public extension _ObjectiveCBridgeable {
|
||||
static func _unconditionallyBridgeFromObjectiveC(_ source: _ObjectiveCType?)
|
||||
|
||||
18
test/stmt/errors_nonobjc.swift
Normal file
18
test/stmt/errors_nonobjc.swift
Normal file
@@ -0,0 +1,18 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: %target-swift-frontend -emit-module -module-name Foundation -o %t/Foundation.swiftmodule %S/Inputs/Foundation-with-NSError.swift
|
||||
// RUN: %target-swift-frontend -I %t -typecheck -verify %s
|
||||
// UNSUPPORTED: objc_interop
|
||||
|
||||
import Foundation
|
||||
|
||||
// Catching `as NSError` ought *not* to be exhaustive when ObjC interop is
|
||||
// disabled. It's just another error type.
|
||||
|
||||
func bar() throws {}
|
||||
|
||||
func foo() {
|
||||
do {
|
||||
try bar() // expected-error{{enclosing catch is not exhaustive}}
|
||||
} catch _ as NSError {
|
||||
}
|
||||
}
|
||||
@@ -135,12 +135,7 @@ void _bridgeNonVerbatimFromObjectiveCToAny(HeapObject *sourceValue,
|
||||
abort();
|
||||
}
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
bool swift_unboxFromSwiftValueWithType(OpaqueValue *source,
|
||||
OpaqueValue *result,
|
||||
const Metadata *destinationType) {
|
||||
abort();
|
||||
}
|
||||
|
||||
// ErrorObject
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_STDLIB_INTERNAL
|
||||
|
||||
Reference in New Issue
Block a user