Factor our the selection of "alternative" literal type suggestions.

Swift SVN r11035
This commit is contained in:
Doug Gregor
2013-12-09 19:19:21 +00:00
parent 00e4a84b74
commit 3040f2195b
4 changed files with 73 additions and 8 deletions

View File

@@ -859,13 +859,7 @@ static bool tryTypeVariableBindings(
continue;
KnownProtocolKind knownKind = *proto->getKnownProtocolKind();
for (auto decl : tc.Context.getTypesThatConformTo(knownKind)) {
Type type;
if (auto nominal = dyn_cast<NominalTypeDecl>(decl))
type = nominal->getDeclaredTypeOfContext();
else
type = cast<ExtensionDecl>(decl)->getDeclaredTypeOfContext();
for (auto type : cs.getAlternativeLiteralTypes(knownKind)) {
if (exploredTypes.insert(type->getCanonicalType()))
newBindings.push_back({type, true});
}

View File

@@ -221,6 +221,65 @@ LookupResult &ConstraintSystem::lookupMember(Type base, Identifier name) {
return *result;
}
ArrayRef<Type> ConstraintSystem::getAlternativeLiteralTypes(
KnownProtocolKind kind) {
unsigned index;
switch (kind) {
#define PROTOCOL(Protocol) \
case KnownProtocolKind::Protocol: llvm_unreachable("Not a literal protocol");
#define LITERAL_CONVERTIBLE_PROTOCOL(Protocol)
#include "swift/AST/KnownProtocols.def"
case KnownProtocolKind::ArrayLiteralConvertible:
index = 0;
break;
case KnownProtocolKind::CharacterLiteralConvertible:
index = 1;
break;
case KnownProtocolKind::DictionaryLiteralConvertible:
index = 2;
break;
case KnownProtocolKind::FloatLiteralConvertible:
index = 3;
break;
case KnownProtocolKind::IntegerLiteralConvertible:
index = 4;
break;
case KnownProtocolKind::StringInterpolationConvertible:
index = 5;
break;
case KnownProtocolKind::StringLiteralConvertible:
index = 6;
break;
}
// If we already looked for alternative literal types, return those results.
if (AlternativeLiteralTypes[index])
return *AlternativeLiteralTypes[index];
// Collect all of the types that conform to the given literal protocol.
SmallVector<Type, 4> types;
for (auto decl : TC.Context.getTypesThatConformTo(kind)) {
Type type;
if (auto nominal = dyn_cast<NominalTypeDecl>(decl))
type = nominal->getDeclaredTypeOfContext();
else
type = cast<ExtensionDecl>(decl)->getDeclaredTypeOfContext();
types.push_back(type);
}
AlternativeLiteralTypes[index] = allocateCopy(types);
return *AlternativeLiteralTypes[index];
}
ConstraintLocator *ConstraintSystem::getConstraintLocator(
Expr *anchor,
ArrayRef<ConstraintLocator::PathElement> path) {

View File

@@ -968,6 +968,9 @@ private:
llvm::DenseMap<std::pair<Type, Identifier>, Optional<LookupResult>>
MemberLookups;
/// Cached sets of "alternative" literal types.
Optional<ArrayRef<Type>> AlternativeLiteralTypes[7];
/// \brief Folding set containing all of the locators used in this
/// constraint system.
llvm::FoldingSet<ConstraintLocator> ConstraintLocators;
@@ -1171,6 +1174,10 @@ public:
/// \returns A reference to the member-lookup result.
LookupResult &lookupMember(Type base, Identifier name);
/// Retrieve the set of "alternative" literal types that we'll explore
/// for a given literal protocol kind.
ArrayRef<Type> getAlternativeLiteralTypes(KnownProtocolKind kind);
/// \brief Create a new type variable.
TypeVariableType *createTypeVariable(ConstraintLocator *locator,
unsigned options) {
@@ -1545,6 +1552,11 @@ public:
return allocateCopy(array.begin(), array.end());
}
template<typename T>
ArrayRef<T> allocateCopy(SmallVectorImpl<T> &vec) {
return allocateCopy(vec.begin(), vec.end());
}
/// \brief Generate constraints for the given (unchecked) expression.
///
/// \returns a possibly-sanitized expression, or null if an error occurred.