More array casting work:

- Continue adding support for checked downcasts of array types (rdar://problem/16535104)
- Fix non-bridged array conversions post-r17868
- Fix rdar://problem/16773693
- Add tests for NSArray coercions to and from Array<T>

Swift SVN r17957
This commit is contained in:
Joe Pamer
2014-05-12 20:49:42 +00:00
parent 9598880928
commit 1e5b9116d4
21 changed files with 175 additions and 26 deletions

View File

@@ -1704,6 +1704,11 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
if (concrete && kind >= TypeMatchKind::Conversion &&
shouldTryUserConversion(*this, type1)) {
conversionsOrFixes.push_back(ConversionRestrictionKind::User);
// Favor array conversions to non-array types (such as NSArray).
if (this->isArrayType(desugar1) && !this->isArrayType(desugar2)) {
this->increaseScore(SK_UserConversion);
}
}
commit_to_conversions:
@@ -1987,7 +1992,9 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint(
///
/// This routine does not attempt to check whether the cast can actually
/// succeed; that's the caller's responsibility.
static CheckedCastKind getCheckedCastKind(Type fromType, Type toType) {
static CheckedCastKind getCheckedCastKind(ConstraintSystem *cs,
Type fromType,
Type toType) {
// Peel off optionals metatypes from the types, because we might cast through
// them.
while (auto toValueType = toType->getAnyOptionalObjectType()) {
@@ -2021,6 +2028,11 @@ static CheckedCastKind getCheckedCastKind(Type fromType, Type toType) {
bool fromArchetype = fromType->is<ArchetypeType>();
bool toExistential = toType->isExistentialType();
bool fromExistential = fromType->isExistentialType();
// Array downcasts are handled specially.
if (cs->isArrayType(fromType) && cs->isArrayType(toType)) {
return CheckedCastKind::ArrayDowncast;
}
// We can only downcast to an existential if the destination protocols are
// objc and the source type is an objc class or an existential bounded by objc
@@ -2093,8 +2105,16 @@ ConstraintSystem::simplifyCheckedCastConstraint(
if (typeVar2)
return SolutionKind::Unsolved;
auto kind = getCheckedCastKind(fromType, toType);
auto kind = getCheckedCastKind(this, fromType, toType);
switch (kind) {
case CheckedCastKind::ArrayDowncast: {
auto fromBaseType = getBaseTypeForArrayType(fromType.getPointer());
auto toBaseType = getBaseTypeForArrayType(toType.getPointer());
addConstraint(ConstraintKind::Subtype, toBaseType, fromBaseType,
getConstraintLocator(locator));
return SolutionKind::Solved;
}
case CheckedCastKind::ArchetypeToArchetype:
case CheckedCastKind::ConcreteToUnrelatedExistential:
case CheckedCastKind::ExistentialToArchetype: