|
|
|
|
@@ -87,7 +87,7 @@ typedef DynamicCastResult (tryCastFunctionType)(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Forward-declare the main top-level `tryCast()` function
|
|
|
|
|
@@ -401,7 +401,7 @@ tryCastUnwrappingObjCSwiftValueSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
id srcObject;
|
|
|
|
|
memcpy(&srcObject, srcValue, sizeof(id));
|
|
|
|
|
@@ -422,7 +422,7 @@ tryCastUnwrappingObjCSwiftValueSource(
|
|
|
|
|
destLocation, destType,
|
|
|
|
|
const_cast<OpaqueValue *>(srcInnerValue), srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
/*takeOnSuccess=*/ false, mayDeferChecks);
|
|
|
|
|
/*takeOnSuccess=*/ false, mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
static DynamicCastResult
|
|
|
|
|
@@ -430,7 +430,7 @@ tryCastUnwrappingSwiftValueSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::Class);
|
|
|
|
|
|
|
|
|
|
@@ -452,7 +452,7 @@ tryCastToSwiftClass(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Class);
|
|
|
|
|
@@ -496,7 +496,7 @@ tryCastToObjectiveCClass(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::ObjCClassWrapper);
|
|
|
|
|
@@ -546,7 +546,7 @@ tryCastToForeignClass(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
#if SWIFT_OBJC_INTEROP
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
@@ -594,7 +594,8 @@ tryCastToForeignClass(
|
|
|
|
|
static DynamicCastResult tryCastToForeignReferenceType(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
|
|
|
|
|
const Metadata *srcType, const Metadata *&destFailureType,
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks,
|
|
|
|
|
bool prohibitIsolatedConformances) {
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::ForeignReferenceType);
|
|
|
|
|
|
|
|
|
|
@@ -610,7 +611,7 @@ tryCastToEnum(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
// Note: Optional is handled elsewhere
|
|
|
|
|
@@ -783,7 +784,7 @@ tryCastToAnyHashable(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -859,7 +860,7 @@ tryCastToArray(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -899,7 +900,7 @@ tryCastToDictionary(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -940,7 +941,7 @@ tryCastToSet(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -982,7 +983,7 @@ tryCastToString(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -1013,7 +1014,7 @@ tryCastToStruct(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Struct);
|
|
|
|
|
@@ -1036,7 +1037,7 @@ tryCastToOptional(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Optional);
|
|
|
|
|
@@ -1110,7 +1111,7 @@ tryCastUnwrappingOptionalBoth(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Optional);
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::Optional);
|
|
|
|
|
@@ -1134,7 +1135,8 @@ tryCastUnwrappingOptionalBoth(
|
|
|
|
|
auto destInnerLocation = destLocation; // Single-payload enum layout
|
|
|
|
|
auto subcastResult = tryCast(
|
|
|
|
|
destInnerLocation, destInnerType, srcValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
destInnerType->vw_storeEnumTagSinglePayload(
|
|
|
|
|
destLocation, /*case*/ 0, /*emptyCases*/ 1);
|
|
|
|
|
@@ -1153,7 +1155,7 @@ tryCastUnwrappingOptionalDestination(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Optional);
|
|
|
|
|
|
|
|
|
|
@@ -1162,7 +1164,8 @@ tryCastUnwrappingOptionalDestination(
|
|
|
|
|
auto destInnerLocation = destLocation; // Single-payload enum layout
|
|
|
|
|
auto subcastResult = tryCast(
|
|
|
|
|
destInnerLocation, destInnerType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
destInnerType->vw_storeEnumTagSinglePayload(
|
|
|
|
|
destLocation, /*case*/ 0, /*emptyCases*/ 1);
|
|
|
|
|
@@ -1179,7 +1182,7 @@ tryCastUnwrappingOptionalSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::Optional);
|
|
|
|
|
|
|
|
|
|
@@ -1190,7 +1193,8 @@ tryCastUnwrappingOptionalSource(
|
|
|
|
|
if (nonNil) {
|
|
|
|
|
// Recurse with unwrapped source
|
|
|
|
|
return tryCast(destLocation, destType, srcValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
}
|
|
|
|
|
@@ -1208,7 +1212,7 @@ tryCastToTuple(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Tuple);
|
|
|
|
|
@@ -1284,7 +1288,8 @@ tryCastToTuple(
|
|
|
|
|
auto subcastResult = tryCast(destElt.findIn(destLocation), destElt.Type,
|
|
|
|
|
srcElt.findIn(srcValue), srcElt.Type,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
false, mayDeferChecks);
|
|
|
|
|
false, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (subcastResult == DynamicCastResult::Failure) {
|
|
|
|
|
for (unsigned k = 0; k != j; ++k) {
|
|
|
|
|
const auto &elt = destTupleType->getElement(k);
|
|
|
|
|
@@ -1310,7 +1315,7 @@ tryCastToFunction(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Function);
|
|
|
|
|
@@ -1372,7 +1377,8 @@ tryCastToFunction(
|
|
|
|
|
static bool _conformsToProtocols(const OpaqueValue *value,
|
|
|
|
|
const Metadata *type,
|
|
|
|
|
const ExistentialTypeMetadata *existentialType,
|
|
|
|
|
const WitnessTable **conformances) {
|
|
|
|
|
const WitnessTable **conformances,
|
|
|
|
|
bool prohibitIsolatedConformances) {
|
|
|
|
|
if (auto *superclass = existentialType->getSuperclassConstraint()) {
|
|
|
|
|
if (!swift_dynamicCastMetatype(type, superclass))
|
|
|
|
|
return false;
|
|
|
|
|
@@ -1385,7 +1391,7 @@ static bool _conformsToProtocols(const OpaqueValue *value,
|
|
|
|
|
|
|
|
|
|
for (auto protocol : existentialType->getProtocols()) {
|
|
|
|
|
if (!swift::_conformsToProtocolInContext(
|
|
|
|
|
value, type, protocol, conformances))
|
|
|
|
|
value, type, protocol, conformances, prohibitIsolatedConformances))
|
|
|
|
|
return false;
|
|
|
|
|
if (conformances != nullptr && protocol.needsWitnessTable()) {
|
|
|
|
|
assert(*conformances != nullptr);
|
|
|
|
|
@@ -1402,7 +1408,7 @@ tryCastToUnconstrainedOpaqueExistential(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Existential);
|
|
|
|
|
@@ -1429,7 +1435,7 @@ tryCastToConstrainedOpaqueExistential(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Existential);
|
|
|
|
|
@@ -1443,10 +1449,12 @@ tryCastToConstrainedOpaqueExistential(
|
|
|
|
|
// TODO (rdar://17033499) If the source is an existential, we should
|
|
|
|
|
// be able to compare the protocol constraints more efficiently than this.
|
|
|
|
|
if (_conformsToProtocols(srcValue, srcType, destExistentialType,
|
|
|
|
|
destExistential->getWitnessTables())) {
|
|
|
|
|
destExistential->getWitnessTables(),
|
|
|
|
|
prohibitIsolatedConformances)) {
|
|
|
|
|
return tryCastToUnconstrainedOpaqueExistential(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
} else {
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
}
|
|
|
|
|
@@ -1457,7 +1465,7 @@ tryCastToClassExistential(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Existential);
|
|
|
|
|
@@ -1480,7 +1488,8 @@ tryCastToClassExistential(
|
|
|
|
|
auto value = reinterpret_cast<OpaqueValue *>(&tmp);
|
|
|
|
|
auto type = reinterpret_cast<const Metadata *>(tmp);
|
|
|
|
|
if (_conformsToProtocols(value, type, destExistentialType,
|
|
|
|
|
destExistentialLocation->getWitnessTables())) {
|
|
|
|
|
destExistentialLocation->getWitnessTables(),
|
|
|
|
|
prohibitIsolatedConformances)) {
|
|
|
|
|
auto object = *(reinterpret_cast<HeapObject **>(value));
|
|
|
|
|
destExistentialLocation->Value = object;
|
|
|
|
|
if (takeOnSuccess) {
|
|
|
|
|
@@ -1529,7 +1538,8 @@ tryCastToClassExistential(
|
|
|
|
|
}
|
|
|
|
|
if (_conformsToProtocols(srcValue, srcType,
|
|
|
|
|
destExistentialType,
|
|
|
|
|
destExistentialLocation->getWitnessTables())) {
|
|
|
|
|
destExistentialLocation->getWitnessTables(),
|
|
|
|
|
prohibitIsolatedConformances)) {
|
|
|
|
|
destExistentialLocation->Value = srcObject;
|
|
|
|
|
if (takeOnSuccess) {
|
|
|
|
|
return DynamicCastResult::SuccessViaTake;
|
|
|
|
|
@@ -1646,7 +1656,7 @@ tryCastToErrorExistential(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Existential);
|
|
|
|
|
@@ -1665,7 +1675,8 @@ tryCastToErrorExistential(
|
|
|
|
|
assert(destExistentialType->NumProtocols == 1);
|
|
|
|
|
const WitnessTable *errorWitness;
|
|
|
|
|
if (_conformsToProtocols(
|
|
|
|
|
srcValue, srcType, destExistentialType, &errorWitness)) {
|
|
|
|
|
srcValue, srcType, destExistentialType, &errorWitness,
|
|
|
|
|
prohibitIsolatedConformances)) {
|
|
|
|
|
#if SWIFT_OBJC_INTEROP
|
|
|
|
|
// If it already holds an NSError, just use that.
|
|
|
|
|
if (auto embedded = getErrorEmbeddedNSErrorIndirect(
|
|
|
|
|
@@ -1697,7 +1708,7 @@ tryCastUnwrappingExistentialSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::Existential);
|
|
|
|
|
@@ -1738,13 +1749,14 @@ tryCastUnwrappingExistentialSource(
|
|
|
|
|
srcInnerValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
takeOnSuccess && (srcInnerValue == srcValue),
|
|
|
|
|
mayDeferChecks);
|
|
|
|
|
mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DynamicCastResult tryCastUnwrappingExtendedExistentialSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
|
|
|
|
|
const Metadata *srcType, const Metadata *&destFailureType,
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks,
|
|
|
|
|
bool prohibitIsolatedConformances) {
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::ExtendedExistential);
|
|
|
|
|
|
|
|
|
|
@@ -1784,7 +1796,8 @@ static DynamicCastResult tryCastUnwrappingExtendedExistentialSource(
|
|
|
|
|
srcFailureType = srcInnerType;
|
|
|
|
|
return tryCast(destLocation, destType, srcInnerValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
takeOnSuccess && (srcInnerValue == srcValue), mayDeferChecks);
|
|
|
|
|
takeOnSuccess && (srcInnerValue == srcValue), mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static DynamicCastResult
|
|
|
|
|
@@ -1792,7 +1805,7 @@ tryCastUnwrappingExistentialMetatypeSource(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(srcType->getKind() == MetadataKind::ExistentialMetatype);
|
|
|
|
|
@@ -1807,14 +1820,15 @@ tryCastUnwrappingExistentialMetatypeSource(
|
|
|
|
|
srcInnerValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
takeOnSuccess && (srcInnerValue == srcValue),
|
|
|
|
|
mayDeferChecks);
|
|
|
|
|
mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static DynamicCastResult tryCastToExtendedExistential(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType, OpaqueValue *srcValue,
|
|
|
|
|
const Metadata *srcType, const Metadata *&destFailureType,
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks) {
|
|
|
|
|
const Metadata *&srcFailureType, bool takeOnSuccess, bool mayDeferChecks,
|
|
|
|
|
bool prohibitIsolatedConformances) {
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::ExtendedExistential);
|
|
|
|
|
|
|
|
|
|
@@ -1886,6 +1900,10 @@ static DynamicCastResult tryCastToExtendedExistential(
|
|
|
|
|
if (error)
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
|
|
|
|
|
if (prohibitIsolatedConformances &&
|
|
|
|
|
context.globalActorIsolationType)
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
|
|
|
|
|
if (!swift_isInConformanceExecutionContext(selfType, &context))
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
}
|
|
|
|
|
@@ -1951,7 +1969,7 @@ tryCastToOpaque(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Opaque);
|
|
|
|
|
@@ -1990,7 +2008,7 @@ tryCastToMetatype(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::Metatype);
|
|
|
|
|
@@ -2023,7 +2041,8 @@ tryCastToMetatype(
|
|
|
|
|
auto srcInnerValue = reinterpret_cast<OpaqueValue *>(&metatype);
|
|
|
|
|
auto srcInnerType = swift_getMetatypeMetadata(metatype);
|
|
|
|
|
return tryCast(destLocation, destType, srcInnerValue, srcInnerType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
@@ -2040,7 +2059,7 @@ _dynamicCastMetatypeToExistentialMetatype(
|
|
|
|
|
OpaqueValue *destLocation, const ExistentialMetatypeMetadata *destType,
|
|
|
|
|
const Metadata *srcMetatype,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
// The instance type of an existential metatype must be either an
|
|
|
|
|
// existential or an existential metatype.
|
|
|
|
|
@@ -2057,7 +2076,7 @@ _dynamicCastMetatypeToExistentialMetatype(
|
|
|
|
|
= destMetatype ? destMetatype->getWitnessTables() : nullptr;
|
|
|
|
|
if (!_conformsToProtocols(nullptr, srcMetatype,
|
|
|
|
|
targetInstanceTypeAsExistential,
|
|
|
|
|
conformance)) {
|
|
|
|
|
conformance, prohibitIsolatedConformances)) {
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -2096,7 +2115,7 @@ _dynamicCastMetatypeToExistentialMetatype(
|
|
|
|
|
srcInstanceType,
|
|
|
|
|
destFailureType,
|
|
|
|
|
srcFailureType,
|
|
|
|
|
takeOnSuccess, mayDeferChecks);
|
|
|
|
|
takeOnSuccess, mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// "ExistentialMetatype" is the metatype for an existential type.
|
|
|
|
|
@@ -2105,7 +2124,7 @@ tryCastToExistentialMetatype(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
assert(srcType != destType);
|
|
|
|
|
assert(destType->getKind() == MetadataKind::ExistentialMetatype);
|
|
|
|
|
@@ -2122,7 +2141,7 @@ tryCastToExistentialMetatype(
|
|
|
|
|
srcMetatype,
|
|
|
|
|
destFailureType,
|
|
|
|
|
srcFailureType,
|
|
|
|
|
takeOnSuccess, mayDeferChecks);
|
|
|
|
|
takeOnSuccess, mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case MetadataKind::ObjCClassWrapper: {
|
|
|
|
|
@@ -2142,7 +2161,7 @@ tryCastToExistentialMetatype(
|
|
|
|
|
metatype,
|
|
|
|
|
destFailureType,
|
|
|
|
|
srcFailureType,
|
|
|
|
|
takeOnSuccess, mayDeferChecks);
|
|
|
|
|
takeOnSuccess, mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
@@ -2262,7 +2281,7 @@ tryCast(
|
|
|
|
|
OpaqueValue *destLocation, const Metadata *destType,
|
|
|
|
|
OpaqueValue *srcValue, const Metadata *srcType,
|
|
|
|
|
const Metadata *&destFailureType, const Metadata *&srcFailureType,
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks)
|
|
|
|
|
bool takeOnSuccess, bool mayDeferChecks, bool prohibitIsolatedConformances)
|
|
|
|
|
{
|
|
|
|
|
destFailureType = destType;
|
|
|
|
|
srcFailureType = srcType;
|
|
|
|
|
@@ -2295,7 +2314,8 @@ tryCast(
|
|
|
|
|
return DynamicCastResult::Failure;
|
|
|
|
|
}
|
|
|
|
|
auto castResult = tryCastToDestType(destLocation, destType, srcValue,
|
|
|
|
|
srcType, destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
srcType, destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(castResult)) {
|
|
|
|
|
return castResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2312,7 +2332,8 @@ tryCast(
|
|
|
|
|
srcFailureType = srcDynamicType;
|
|
|
|
|
auto castResult = tryCastToDestType(
|
|
|
|
|
destLocation, destType, srcValue, srcDynamicType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(castResult)) {
|
|
|
|
|
return castResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2345,7 +2366,8 @@ tryCast(
|
|
|
|
|
// Try unwrapping Obj-C __SwiftValue implementation
|
|
|
|
|
auto subcastResult = tryCastUnwrappingObjCSwiftValueSource(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2379,7 +2401,8 @@ tryCast(
|
|
|
|
|
case MetadataKind::Existential: {
|
|
|
|
|
auto subcastResult = tryCastUnwrappingExistentialSource(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2389,7 +2412,8 @@ tryCast(
|
|
|
|
|
case MetadataKind::ExistentialMetatype: {
|
|
|
|
|
auto subcastResult = tryCastUnwrappingExistentialMetatypeSource(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2399,7 +2423,8 @@ tryCast(
|
|
|
|
|
case MetadataKind::ExtendedExistential: {
|
|
|
|
|
auto subcastResult = tryCastUnwrappingExtendedExistentialSource(
|
|
|
|
|
destLocation, destType, srcValue, srcType, destFailureType,
|
|
|
|
|
srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2423,14 +2448,16 @@ tryCast(
|
|
|
|
|
if (srcKind == MetadataKind::Optional) {
|
|
|
|
|
auto subcastResult = tryCastUnwrappingOptionalBoth(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
auto subcastResult = tryCastUnwrappingOptionalDestination(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2439,7 +2466,8 @@ tryCast(
|
|
|
|
|
if (srcKind == MetadataKind::Optional) {
|
|
|
|
|
auto subcastResult = tryCastUnwrappingOptionalSource(
|
|
|
|
|
destLocation, destType, srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks);
|
|
|
|
|
destFailureType, srcFailureType, takeOnSuccess, mayDeferChecks,
|
|
|
|
|
prohibitIsolatedConformances);
|
|
|
|
|
if (isSuccess(subcastResult)) {
|
|
|
|
|
return subcastResult;
|
|
|
|
|
}
|
|
|
|
|
@@ -2583,6 +2611,11 @@ swift_dynamicCastImpl(OpaqueValue *destLocation,
|
|
|
|
|
// actually accessed.
|
|
|
|
|
bool mayDeferChecks = flags & DynamicCastFlags::Unconditional;
|
|
|
|
|
|
|
|
|
|
// Whether the compiler told us that we aren't allowed to use *any* isolated
|
|
|
|
|
// conformances, regardless of whether we are in that isolation domain.
|
|
|
|
|
bool prohibitIsolatedConformances =
|
|
|
|
|
flags & DynamicCastFlags::ProhibitIsolatedConformances;
|
|
|
|
|
|
|
|
|
|
// Attempt the cast...
|
|
|
|
|
const Metadata *destFailureType = destType;
|
|
|
|
|
const Metadata *srcFailureType = srcType;
|
|
|
|
|
@@ -2590,7 +2623,7 @@ swift_dynamicCastImpl(OpaqueValue *destLocation,
|
|
|
|
|
destLocation, destType,
|
|
|
|
|
srcValue, srcType,
|
|
|
|
|
destFailureType, srcFailureType,
|
|
|
|
|
takeOnSuccess, mayDeferChecks);
|
|
|
|
|
takeOnSuccess, mayDeferChecks, prohibitIsolatedConformances);
|
|
|
|
|
|
|
|
|
|
switch (result) {
|
|
|
|
|
case DynamicCastResult::Failure:
|
|
|
|
|
|