mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
SR-14635: __SwiftValue should be transparent to casting
This PR changes the casting machinery to avoid casting `__SwiftValue` boxes directly. This forces the caster to instead unwrap `__SwiftValue` boxes and retry with the inner content. This results in boxed values being cast like the inner content. This fixes the behavior in situations like the following: ``` let t = ... let s = t as Any as! AnyObject // `s` is now a `__SwiftValue` box // Next line should be true iff t conforms to NSCopying // Prior to this change, it always succeeds s is NSCopying ``` After this change, the above cast succeeds only if `t` actually conforms to `NSCopying`. This is a follow-on to PR#37683. Related to: SR-14635
This commit is contained in:
@@ -425,6 +425,29 @@ tryCastUnwrappingObjCSwiftValueSource(
|
||||
destFailureType, srcFailureType,
|
||||
/*takeOnSuccess=*/ false, mayDeferChecks);
|
||||
}
|
||||
#else
|
||||
static DynamicCastResult
|
||||
tryCastUnwrappingSwiftValueSource(
|
||||
OpaqueValue *destLocation, const Metadata *destType,
|
||||
OpaqueValue *srcValue, const Metadata *srcType,
|
||||
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
||||
bool takeOnSuccess, bool mayDeferChecks)
|
||||
{
|
||||
const Metadata *srcInnerType;
|
||||
const OpaqueValue *srcInnerValue;
|
||||
if (swift_unboxFromSwiftValueWithType(srcValue, &srcInnerValue, &srcInnerType)) {
|
||||
return DynamicCastResult::SuccessViaCopy;
|
||||
}
|
||||
|
||||
// Note: We never `take` the contents from a SwiftValue box as
|
||||
// it might have other references. Instead, let our caller
|
||||
// destroy the reference if necessary.
|
||||
return tryCast(
|
||||
destLocation, destType,
|
||||
const_cast<OpaqueValue *>(srcInnerValue), srcInnerType,
|
||||
destFailureType, srcFailureType,
|
||||
/*takeOnSuccess=*/ false, mayDeferChecks);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -1474,6 +1497,16 @@ tryCastToClassExistential(
|
||||
}
|
||||
|
||||
case MetadataKind::ObjCClassWrapper:
|
||||
#if SWIFT_OBJC_INTEROP
|
||||
id srcObject;
|
||||
memcpy(&srcObject, srcValue, sizeof(id));
|
||||
if (getAsSwiftValue(srcObject) != nullptr) {
|
||||
// Do not directly cast a `__SwiftValue` box
|
||||
// Return failure so our caller will unwrap and try again
|
||||
return DynamicCastResult::Failure;
|
||||
}
|
||||
#endif
|
||||
SWIFT_FALLTHROUGH;
|
||||
case MetadataKind::Class:
|
||||
case MetadataKind::ForeignClass: {
|
||||
auto srcObject = getNonNullSrcObject(srcValue, srcType, destType);
|
||||
@@ -2285,8 +2318,11 @@ tryCast(
|
||||
case MetadataKind::Class: {
|
||||
#if !SWIFT_OBJC_INTEROP
|
||||
// Try unwrapping native __SwiftValue implementation
|
||||
if (swift_unboxFromSwiftValueWithType(srcValue, destLocation, destType)) {
|
||||
return DynamicCastResult::SuccessViaCopy;
|
||||
auto subcastResult = tryCastUnwrappingSwiftValueSource(
|
||||
destLocation, destType, srcValue, srcType,
|
||||
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
||||
if (isSuccess(subcastResult)) {
|
||||
return subcastResult;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user