@@ -4150,27 +4150,32 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
41504150 }
41514151 }
41524152
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;
41614159
4162- case CheckedCastKind::BridgingCoercion:
4163- return CheckedCastKind::BridgingCoercion;
4160+ case CheckedCastKind::BridgingCoercion:
4161+ return CheckedCastKind::BridgingCoercion;
41644162
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 ;
41704168
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);
41744179 }
41754180 }
41764181
@@ -4240,24 +4245,31 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
42404245
42414246 if (auto toElementType = ConstraintSystem::isSetType (toType)) {
42424247 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+ }
42574252
4258- case CheckedCastKind::Unresolved:
4253+ if (auto toTuple = toType->getAs <TupleType>()) {
4254+ if (auto fromTuple = fromType->getAs <TupleType>()) {
4255+ if (fromTuple->getNumElements () != toTuple->getNumElements ())
42594256 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;
42604270 }
4271+
4272+ return CheckedCastKind::ValueCast;
42614273 }
42624274 }
42634275
0 commit comments