@@ -247,6 +247,7 @@ static void _buildNameForMetadata(const Metadata *type,
247247 result);
248248 }
249249 case MetadataKind::Enum:
250+ case MetadataKind::Optional:
250251 case MetadataKind::Struct: {
251252 auto structType = static_cast <const StructMetadata *>(type);
252253 return _buildNominalTypeName (structType->Description ,
@@ -574,6 +575,7 @@ static bool _conformsToProtocol(const OpaqueValue *value,
574575 case MetadataKind::HeapGenericLocalVariable:
575576 case MetadataKind::ErrorObject:
576577 case MetadataKind::Enum:
578+ case MetadataKind::Optional:
577579 case MetadataKind::Opaque:
578580 case MetadataKind::Struct:
579581 case MetadataKind::Tuple:
@@ -634,6 +636,7 @@ static bool _conformsToProtocol(const OpaqueValue *value,
634636 case MetadataKind::ErrorObject:
635637 case MetadataKind::Metatype:
636638 case MetadataKind::Enum:
639+ case MetadataKind::Optional:
637640 case MetadataKind::Opaque:
638641 case MetadataKind::Struct:
639642 case MetadataKind::Tuple:
@@ -736,6 +739,7 @@ static void findDynamicValueAndType(OpaqueValue *value, const Metadata *type,
736739 case MetadataKind::HeapGenericLocalVariable:
737740 case MetadataKind::ErrorObject:
738741 case MetadataKind::Enum:
742+ case MetadataKind::Optional:
739743 case MetadataKind::Opaque:
740744 case MetadataKind::Struct:
741745 case MetadataKind::Tuple:
@@ -797,6 +801,7 @@ static void deallocateDynamicValue(OpaqueValue *value, const Metadata *type) {
797801 case MetadataKind::HeapGenericLocalVariable:
798802 case MetadataKind::ErrorObject:
799803 case MetadataKind::Enum:
804+ case MetadataKind::Optional:
800805 case MetadataKind::Opaque:
801806 case MetadataKind::Struct:
802807 case MetadataKind::Tuple:
@@ -822,6 +827,7 @@ swift_dynamicCastMetatypeToObjectConditional(const Metadata *metatype) {
822827 // Other kinds of metadata don't cast to AnyObject.
823828 case MetadataKind::Struct:
824829 case MetadataKind::Enum:
830+ case MetadataKind::Optional:
825831 case MetadataKind::Opaque:
826832 case MetadataKind::Tuple:
827833 case MetadataKind::Function:
@@ -852,6 +858,7 @@ swift_dynamicCastMetatypeToObjectUnconditional(const Metadata *metatype) {
852858 // Other kinds of metadata don't cast to AnyObject.
853859 case MetadataKind::Struct:
854860 case MetadataKind::Enum:
861+ case MetadataKind::Optional:
855862 case MetadataKind::Opaque:
856863 case MetadataKind::Tuple:
857864 case MetadataKind::Function:
@@ -939,6 +946,7 @@ static bool _dynamicCastToExistential(OpaqueValue *dest,
939946
940947 case MetadataKind::Struct:
941948 case MetadataKind::Enum:
949+ case MetadataKind::Optional:
942950#if SWIFT_OBJC_INTEROP
943951 // If the source type is bridged to Objective-C, try to bridge.
944952 if (auto srcBridgeWitness = findBridgeWitness (srcDynamicType)) {
@@ -1111,6 +1119,7 @@ swift::swift_dynamicCastUnknownClass(const void *object,
11111119 case MetadataKind::ErrorObject:
11121120 case MetadataKind::Metatype:
11131121 case MetadataKind::Enum:
1122+ case MetadataKind::Optional:
11141123 case MetadataKind::Opaque:
11151124 case MetadataKind::Struct:
11161125 case MetadataKind::Tuple:
@@ -1166,6 +1175,7 @@ swift::swift_dynamicCastUnknownClassUnconditional(const void *object,
11661175 case MetadataKind::ErrorObject:
11671176 case MetadataKind::Metatype:
11681177 case MetadataKind::Enum:
1178+ case MetadataKind::Optional:
11691179 case MetadataKind::Opaque:
11701180 case MetadataKind::Struct:
11711181 case MetadataKind::Tuple:
@@ -1225,6 +1235,7 @@ swift::swift_dynamicCastMetatype(const Metadata *sourceType,
12251235 case MetadataKind::ErrorObject:
12261236 case MetadataKind::Metatype:
12271237 case MetadataKind::Enum:
1238+ case MetadataKind::Optional:
12281239 case MetadataKind::Opaque:
12291240 case MetadataKind::Struct:
12301241 case MetadataKind::Tuple:
@@ -1255,6 +1266,7 @@ swift::swift_dynamicCastMetatype(const Metadata *sourceType,
12551266 case MetadataKind::ErrorObject:
12561267 case MetadataKind::Metatype:
12571268 case MetadataKind::Enum:
1269+ case MetadataKind::Optional:
12581270 case MetadataKind::Opaque:
12591271 case MetadataKind::Struct:
12601272 case MetadataKind::Tuple:
@@ -1270,6 +1282,7 @@ swift::swift_dynamicCastMetatype(const Metadata *sourceType,
12701282 case MetadataKind::ErrorObject:
12711283 case MetadataKind::Metatype:
12721284 case MetadataKind::Enum:
1285+ case MetadataKind::Optional:
12731286 case MetadataKind::Opaque:
12741287 case MetadataKind::Struct:
12751288 case MetadataKind::Tuple:
@@ -1332,6 +1345,7 @@ swift::swift_dynamicCastMetatypeUnconditional(const Metadata *sourceType,
13321345 case MetadataKind::ErrorObject:
13331346 case MetadataKind::Metatype:
13341347 case MetadataKind::Enum:
1348+ case MetadataKind::Optional:
13351349 case MetadataKind::Opaque:
13361350 case MetadataKind::Struct:
13371351 case MetadataKind::Tuple:
@@ -1363,6 +1377,7 @@ swift::swift_dynamicCastMetatypeUnconditional(const Metadata *sourceType,
13631377 case MetadataKind::ErrorObject:
13641378 case MetadataKind::Metatype:
13651379 case MetadataKind::Enum:
1380+ case MetadataKind::Optional:
13661381 case MetadataKind::Opaque:
13671382 case MetadataKind::Struct:
13681383 case MetadataKind::Tuple:
@@ -1377,6 +1392,7 @@ swift::swift_dynamicCastMetatypeUnconditional(const Metadata *sourceType,
13771392 case MetadataKind::ErrorObject:
13781393 case MetadataKind::Metatype:
13791394 case MetadataKind::Enum:
1395+ case MetadataKind::Optional:
13801396 case MetadataKind::Opaque:
13811397 case MetadataKind::Struct:
13821398 case MetadataKind::Tuple:
@@ -1715,6 +1731,7 @@ static bool _dynamicCastToMetatype(OpaqueValue *dest,
17151731 case MetadataKind::HeapGenericLocalVariable:
17161732 case MetadataKind::ErrorObject:
17171733 case MetadataKind::Enum:
1734+ case MetadataKind::Optional:
17181735 case MetadataKind::Opaque:
17191736 case MetadataKind::Struct:
17201737 case MetadataKind::Tuple:
@@ -1885,6 +1902,7 @@ static bool _dynamicCastToExistentialMetatype(OpaqueValue *dest,
18851902 case MetadataKind::HeapGenericLocalVariable:
18861903 case MetadataKind::ErrorObject:
18871904 case MetadataKind::Enum:
1905+ case MetadataKind::Optional:
18881906 case MetadataKind::Opaque:
18891907 case MetadataKind::Struct:
18901908 case MetadataKind::Tuple:
@@ -1947,6 +1965,7 @@ static bool _dynamicCastToFunction(OpaqueValue *dest,
19471965 case MetadataKind::Class:
19481966 case MetadataKind::Struct:
19491967 case MetadataKind::Enum:
1968+ case MetadataKind::Optional:
19501969 case MetadataKind::ObjCClassWrapper:
19511970 case MetadataKind::ForeignClass:
19521971 case MetadataKind::ExistentialMetatype:
@@ -1971,13 +1990,59 @@ static id dynamicCastValueToNSError(OpaqueValue *src,
19711990}
19721991#endif
19731992
1993+ static bool canCastToExistential (OpaqueValue *dest, OpaqueValue *src,
1994+ const Metadata *srcType,
1995+ const Metadata *targetType) {
1996+ if (targetType->getKind () != MetadataKind::Existential)
1997+ return false ;
1998+
1999+ return _dynamicCastToExistential (dest, src, srcType,
2000+ cast<ExistentialTypeMetadata>(targetType),
2001+ DynamicCastFlags::Default);
2002+ }
2003+
19742004// / Perform a dynamic cast to an arbitrary type.
19752005bool swift::swift_dynamicCast (OpaqueValue *dest,
19762006 OpaqueValue *src,
19772007 const Metadata *srcType,
19782008 const Metadata *targetType,
19792009 DynamicCastFlags flags) {
2010+ // Check if the cast source is Optional and the target is not an existential
2011+ // that Optional conforms to. Unwrap one level of Optional and continue.
2012+ if (srcType->getKind () == MetadataKind::Optional
2013+ && !canCastToExistential (dest, src, srcType, targetType)) {
2014+ const Metadata *payloadType =
2015+ cast<EnumMetadata>(srcType)->getGenericArgs ()[0 ];
2016+ int enumCase =
2017+ swift_getEnumCaseSinglePayload (src, payloadType, 1 /* emptyCases=*/ );
2018+ if (enumCase != -1 ) {
2019+ // Allow Optional<T>.None -> Optional<U>.None
2020+ if (targetType->getKind () != MetadataKind::Optional)
2021+ return _fail (src, srcType, targetType, flags);
2022+ // Inject the .None tag
2023+ swift_storeEnumTagSinglePayload (dest, payloadType, enumCase,
2024+ 1 /* emptyCases=*/ );
2025+ return _succeed (dest, src, srcType, flags);
2026+ }
2027+ // .Some
2028+ // Single payload enums are guaranteed layout compatible with their
2029+ // payload. Only the source's payload needs to be taken or destroyed.
2030+ srcType = payloadType;
2031+ }
2032+
19802033 switch (targetType->getKind ()) {
2034+ // Handle wrapping an Optional target.
2035+ case MetadataKind::Optional: {
2036+ // Recursively cast into the layout compatible payload area.
2037+ const Metadata *payloadType =
2038+ cast<EnumMetadata>(targetType)->getGenericArgs ()[0 ];
2039+ if (swift_dynamicCast (dest, src, srcType, payloadType, flags)) {
2040+ swift_storeEnumTagSinglePayload (dest, payloadType, -1 /* case*/ ,
2041+ 1 /* emptyCases*/ );
2042+ return true ;
2043+ }
2044+ return false ;
2045+ }
19812046
19822047 // Casts to class type.
19832048 case MetadataKind::Class:
@@ -2020,6 +2085,7 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
20202085 }
20212086
20222087 case MetadataKind::Enum:
2088+ case MetadataKind::Optional:
20232089 case MetadataKind::Struct: {
20242090#if SWIFT_OBJC_INTEROP
20252091 // If the source type is bridged to Objective-C, try to bridge.
@@ -2092,6 +2158,7 @@ bool swift::swift_dynamicCast(OpaqueValue *dest,
20922158 }
20932159
20942160 case MetadataKind::Enum:
2161+ case MetadataKind::Optional:
20952162 case MetadataKind::Existential:
20962163 case MetadataKind::ExistentialMetatype:
20972164 case MetadataKind::Function:
@@ -2970,6 +3037,7 @@ findBridgeWitness(const Metadata *T) {
29703037 case MetadataKind::Class:
29713038 case MetadataKind::Struct:
29723039 case MetadataKind::Enum:
3040+ case MetadataKind::Optional:
29733041 case MetadataKind::Opaque:
29743042 case MetadataKind::Tuple:
29753043 case MetadataKind::Function:
@@ -3149,3 +3217,7 @@ extern "C" const Metadata *_swift_getSuperclass_nonNull(
31493217extern " C" bool swift_isClassType (const Metadata *type) {
31503218 return Metadata::isAnyKindOfClass (type->getKind ());
31513219}
3220+
3221+ extern " C" bool swift_isOptionalType (const Metadata *type) {
3222+ return type->getKind () == MetadataKind::Optional;
3223+ }
0 commit comments