@@ -4150,27 +4150,32 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
4150
4150
}
4151
4151
}
4152
4152
4153
- // Check for casts between specific concrete types that cannot succeed.
4154
- if (auto toElementType = ConstraintSystem::isArrayType (toType)) {
4155
- if (auto fromElementType = ConstraintSystem::isArrayType (fromType)) {
4156
- switch (typeCheckCheckedCast (*fromElementType, *toElementType,
4157
- CheckedCastContextKind::None, dc,
4158
- SourceLoc (), nullptr , SourceRange ())) {
4159
- case CheckedCastKind::Coercion:
4160
- return CheckedCastKind::Coercion;
4153
+ auto checkElementCast = [&](Type fromElt, Type toElt,
4154
+ CheckedCastKind castKind) -> CheckedCastKind {
4155
+ switch (typeCheckCheckedCast (fromElt, toElt, CheckedCastContextKind::None,
4156
+ dc, SourceLoc (), nullptr , SourceRange ())) {
4157
+ case CheckedCastKind::Coercion:
4158
+ return CheckedCastKind::Coercion;
4161
4159
4162
- case CheckedCastKind::BridgingCoercion:
4163
- return CheckedCastKind::BridgingCoercion;
4160
+ case CheckedCastKind::BridgingCoercion:
4161
+ return CheckedCastKind::BridgingCoercion;
4164
4162
4165
- case CheckedCastKind::ArrayDowncast:
4166
- case CheckedCastKind::DictionaryDowncast:
4167
- case CheckedCastKind::SetDowncast:
4168
- case CheckedCastKind::ValueCast:
4169
- return CheckedCastKind::ArrayDowncast ;
4163
+ case CheckedCastKind::ArrayDowncast:
4164
+ case CheckedCastKind::DictionaryDowncast:
4165
+ case CheckedCastKind::SetDowncast:
4166
+ case CheckedCastKind::ValueCast:
4167
+ return castKind ;
4170
4168
4171
- case CheckedCastKind::Unresolved:
4172
- return failed ();
4173
- }
4169
+ case CheckedCastKind::Unresolved:
4170
+ return failed ();
4171
+ }
4172
+ };
4173
+
4174
+ // Check for casts between specific concrete types that cannot succeed.
4175
+ if (auto toElementType = ConstraintSystem::isArrayType (toType)) {
4176
+ if (auto fromElementType = ConstraintSystem::isArrayType (fromType)) {
4177
+ return checkElementCast (*fromElementType, *toElementType,
4178
+ CheckedCastKind::ArrayDowncast);
4174
4179
}
4175
4180
}
4176
4181
@@ -4240,24 +4245,31 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
4240
4245
4241
4246
if (auto toElementType = ConstraintSystem::isSetType (toType)) {
4242
4247
if (auto fromElementType = ConstraintSystem::isSetType (fromType)) {
4243
- switch (typeCheckCheckedCast (*fromElementType, *toElementType,
4244
- CheckedCastContextKind::None, dc,
4245
- SourceLoc (), nullptr , SourceRange ())) {
4246
- case CheckedCastKind::Coercion:
4247
- return CheckedCastKind::Coercion;
4248
-
4249
- case CheckedCastKind::BridgingCoercion:
4250
- return CheckedCastKind::BridgingCoercion;
4251
-
4252
- case CheckedCastKind::ArrayDowncast:
4253
- case CheckedCastKind::DictionaryDowncast:
4254
- case CheckedCastKind::SetDowncast:
4255
- case CheckedCastKind::ValueCast:
4256
- return CheckedCastKind::SetDowncast;
4248
+ return checkElementCast (*fromElementType, *toElementType,
4249
+ CheckedCastKind::SetDowncast);
4250
+ }
4251
+ }
4257
4252
4258
- case CheckedCastKind::Unresolved:
4253
+ if (auto toTuple = toType->getAs <TupleType>()) {
4254
+ if (auto fromTuple = fromType->getAs <TupleType>()) {
4255
+ if (fromTuple->getNumElements () != toTuple->getNumElements ())
4259
4256
return failed ();
4257
+
4258
+ for (unsigned i = 0 , n = toTuple->getNumElements (); i != n; ++i) {
4259
+ const auto &fromElt = fromTuple->getElement (i);
4260
+ const auto &toElt = toTuple->getElement (i);
4261
+
4262
+ if (fromElt.getName () != toElt.getName ())
4263
+ return failed ();
4264
+
4265
+ auto result = checkElementCast (fromElt.getType (), toElt.getType (),
4266
+ CheckedCastKind::ValueCast);
4267
+
4268
+ if (result == CheckedCastKind::Unresolved)
4269
+ return result;
4260
4270
}
4271
+
4272
+ return CheckedCastKind::ValueCast;
4261
4273
}
4262
4274
}
4263
4275
0 commit comments