@@ -4075,27 +4075,32 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
4075
4075
}
4076
4076
}
4077
4077
4078
- // Check for casts between specific concrete types that cannot succeed.
4079
- if (auto toElementType = ConstraintSystem::isArrayType (toType)) {
4080
- if (auto fromElementType = ConstraintSystem::isArrayType (fromType)) {
4081
- switch (typeCheckCheckedCast (*fromElementType, *toElementType,
4082
- CheckedCastContextKind::None, dc,
4083
- SourceLoc (), nullptr , SourceRange ())) {
4084
- case CheckedCastKind::Coercion:
4085
- return CheckedCastKind::Coercion;
4078
+ auto checkElementCast = [&](Type fromElt, Type toElt,
4079
+ CheckedCastKind castKind) -> CheckedCastKind {
4080
+ switch (typeCheckCheckedCast (fromElt, toElt, CheckedCastContextKind::None,
4081
+ dc, SourceLoc (), nullptr , SourceRange ())) {
4082
+ case CheckedCastKind::Coercion:
4083
+ return CheckedCastKind::Coercion;
4086
4084
4087
- case CheckedCastKind::BridgingCoercion:
4088
- return CheckedCastKind::BridgingCoercion;
4085
+ case CheckedCastKind::BridgingCoercion:
4086
+ return CheckedCastKind::BridgingCoercion;
4089
4087
4090
- case CheckedCastKind::ArrayDowncast:
4091
- case CheckedCastKind::DictionaryDowncast:
4092
- case CheckedCastKind::SetDowncast:
4093
- case CheckedCastKind::ValueCast:
4094
- return CheckedCastKind::ArrayDowncast ;
4088
+ case CheckedCastKind::ArrayDowncast:
4089
+ case CheckedCastKind::DictionaryDowncast:
4090
+ case CheckedCastKind::SetDowncast:
4091
+ case CheckedCastKind::ValueCast:
4092
+ return castKind ;
4095
4093
4096
- case CheckedCastKind::Unresolved:
4097
- return failed ();
4098
- }
4094
+ case CheckedCastKind::Unresolved:
4095
+ return failed ();
4096
+ }
4097
+ };
4098
+
4099
+ // Check for casts between specific concrete types that cannot succeed.
4100
+ if (auto toElementType = ConstraintSystem::isArrayType (toType)) {
4101
+ if (auto fromElementType = ConstraintSystem::isArrayType (fromType)) {
4102
+ return checkElementCast (*fromElementType, *toElementType,
4103
+ CheckedCastKind::ArrayDowncast);
4099
4104
}
4100
4105
}
4101
4106
@@ -4165,24 +4170,31 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
4165
4170
4166
4171
if (auto toElementType = ConstraintSystem::isSetType (toType)) {
4167
4172
if (auto fromElementType = ConstraintSystem::isSetType (fromType)) {
4168
- switch (typeCheckCheckedCast (*fromElementType, *toElementType,
4169
- CheckedCastContextKind::None, dc,
4170
- SourceLoc (), nullptr , SourceRange ())) {
4171
- case CheckedCastKind::Coercion:
4172
- return CheckedCastKind::Coercion;
4173
-
4174
- case CheckedCastKind::BridgingCoercion:
4175
- return CheckedCastKind::BridgingCoercion;
4176
-
4177
- case CheckedCastKind::ArrayDowncast:
4178
- case CheckedCastKind::DictionaryDowncast:
4179
- case CheckedCastKind::SetDowncast:
4180
- case CheckedCastKind::ValueCast:
4181
- return CheckedCastKind::SetDowncast;
4173
+ return checkElementCast (*fromElementType, *toElementType,
4174
+ CheckedCastKind::SetDowncast);
4175
+ }
4176
+ }
4182
4177
4183
- case CheckedCastKind::Unresolved:
4178
+ if (auto toTuple = toType->getAs <TupleType>()) {
4179
+ if (auto fromTuple = fromType->getAs <TupleType>()) {
4180
+ if (fromTuple->getNumElements () != toTuple->getNumElements ())
4184
4181
return failed ();
4182
+
4183
+ for (unsigned i = 0 , n = toTuple->getNumElements (); i != n; ++i) {
4184
+ const auto &fromElt = fromTuple->getElement (i);
4185
+ const auto &toElt = toTuple->getElement (i);
4186
+
4187
+ if (fromElt.getName () != toElt.getName ())
4188
+ return failed ();
4189
+
4190
+ auto result = checkElementCast (fromElt.getType (), toElt.getType (),
4191
+ CheckedCastKind::ValueCast);
4192
+
4193
+ if (result == CheckedCastKind::Unresolved)
4194
+ return result;
4185
4195
}
4196
+
4197
+ return CheckedCastKind::ValueCast;
4186
4198
}
4187
4199
}
4188
4200
0 commit comments