//===--- CSBindings.cpp - Constraint Solver -------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements selection of bindings for type variables. // //===----------------------------------------------------------------------===// #include "TypeChecker.h" #include "swift/Sema/ConstraintGraph.h" #include "swift/Sema/ConstraintSystem.h" #include "llvm/ADT/SetVector.h" #include using namespace swift; using namespace constraints; bool ConstraintSystem::PotentialBinding::isViableForJoin() const { return Kind == AllowedBindingKind::Supertypes && !BindingType->hasLValueType() && !BindingType->hasUnresolvedType() && !BindingType->hasTypeVariable() && !BindingType->hasHole() && !BindingType->hasUnboundGenericType() && !hasDefaultedLiteralProtocol() && !isDefaultableBinding(); } bool ConstraintSystem::PotentialBindings::isDelayed() const { if (!DelayedBy.empty()) return true; if (isHole()) { auto *locator = TypeVar->getImpl().getLocator(); assert(locator && "a hole without locator?"); // Delay resolution of the code completion expression until // the very end to give it a chance to be bound to some // contextual type even if it's a hole. if (locator->directlyAt()) return true; // Delay resolution of the `nil` literal to a hole until // the very end to give it a change to be bound to some // other type, just like code completion expression which // relies solely on contextual information. if (locator->directlyAt()) return true; } return false; } bool ConstraintSystem::PotentialBindings::involvesTypeVariables() const { // This is effectively O(1) right now since bindings are re-computed // on each step of the solver, but once bindings are computed // incrementally it becomes more important to double-check that // any adjacent type variables found previously are still unresolved. return llvm::any_of(AdjacentVars, [](TypeVariableType *typeVar) { return !typeVar->getImpl().getFixedType(/*record=*/nullptr); }); } bool ConstraintSystem::PotentialBindings::isPotentiallyIncomplete() const { // Generic parameters are always potentially incomplete. if (isGenericParameter()) return true; // If current type variable is associated with a code completion token // it's possible that it doesn't have enough contextual information // to be resolved to anything so let's delay considering it until everything // else is resolved. if (AssociatedCodeCompletionToken) return true; auto *locator = TypeVar->getImpl().getLocator(); if (!locator) return false; if (locator->isLastElement()) { // If subtyping is allowed and this is a result of an implicit member chain, // let's delay binding it to an optional until its object type resolved too or // it has been determined that there is no possibility to resolve it. Otherwise // we might end up missing solutions since it's allowed to implicitly unwrap // base type of the chain but it can't be done early - type variable // representing chain's result type has a different l-valueness comparing // to generic parameter of the optional. if (llvm::any_of(Bindings, [&](const PotentialBinding &binding) { if (binding.Kind != AllowedBindingKind::Subtypes) return false; auto objectType = binding.BindingType->getOptionalObjectType(); return objectType && objectType->isTypeVariableOrMember(); })) return true; } if (isHole()) { // If the base of the unresolved member reference like `.foo` // couldn't be resolved we'd want to bind it to a hole at the // very last moment possible, just like generic parameters. if (locator->isLastElement()) return true; // Delay resolution of the code completion expression until // the very end to give it a chance to be bound to some // contextual type even if it's a hole. if (locator->directlyAt()) return true; // Delay resolution of the `nil` literal to a hole until // the very end to give it a change to be bound to some // other type, just like code completion expression which // relies solely on contextual information. if (locator->directlyAt()) return true; } // If there is a `bind param` constraint associated with // current type variable, result should be aware of that // fact. Binding set might be incomplete until // this constraint is resolved, because we currently don't // look-through constraints expect to `subtype` to try and // find related bindings. // This only affects type variable that appears one the // right-hand side of the `bind param` constraint and // represents result type of the closure body, because // left-hand side gets types from overload choices. if (llvm::any_of( EquivalentTo, [&](const std::pair &equivalence) { auto *constraint = equivalence.second; return constraint->getKind() == ConstraintKind::BindParam && constraint->getSecondType()->isEqual(TypeVar); })) return true; return false; } void ConstraintSystem::PotentialBindings::inferTransitiveProtocolRequirements( const ConstraintSystem &cs, llvm::SmallDenseMap &inferredBindings) { if (TransitiveProtocols) return; llvm::SmallVector, 4> workList; llvm::SmallPtrSet visitedRelations; llvm::SmallDenseMap, 4> protocols; auto addToWorkList = [&](TypeVariableType *parent, TypeVariableType *typeVar) { if (visitedRelations.insert(typeVar).second) workList.push_back({parent, typeVar}); }; auto propagateProtocolsTo = [&protocols](TypeVariableType *dstVar, const SmallVectorImpl &direct, const SmallPtrSetImpl &transitive) { auto &destination = protocols[dstVar]; for (auto *protocol : direct) destination.insert(protocol); for (auto *protocol : transitive) destination.insert(protocol); }; addToWorkList(nullptr, TypeVar); do { auto *currentVar = workList.back().second; auto cachedBindings = inferredBindings.find(currentVar); if (cachedBindings == inferredBindings.end()) { workList.pop_back(); continue; } auto &bindings = cachedBindings->getSecond(); // If current variable already has transitive protocol // conformances inferred, there is no need to look deeper // into subtype/equivalence chain. if (bindings.TransitiveProtocols) { TypeVariableType *parent = nullptr; std::tie(parent, currentVar) = workList.pop_back_val(); assert(parent); propagateProtocolsTo(parent, bindings.Protocols, *bindings.TransitiveProtocols); continue; } for (const auto &entry : bindings.SubtypeOf) addToWorkList(currentVar, entry.first); // If current type variable is part of an equivalence // class, make it a "representative" and let's it infer // supertypes and direct protocol requirements from // other members. for (const auto &entry : bindings.EquivalentTo) { auto eqBindings = inferredBindings.find(entry.first); if (eqBindings != inferredBindings.end()) { const auto &bindings = eqBindings->getSecond(); llvm::SmallPtrSet placeholder; // Add any direct protocols from members of the // equivalence class, so they could be propagated // to all of the members. propagateProtocolsTo(currentVar, bindings.Protocols, placeholder); // Since type variables are equal, current type variable // becomes a subtype to any supertype found in the current // equivalence class. for (const auto &eqEntry : bindings.SubtypeOf) addToWorkList(currentVar, eqEntry.first); } } // More subtype/equivalences relations have been added. if (workList.back().second != currentVar) continue; TypeVariableType *parent = nullptr; std::tie(parent, currentVar) = workList.pop_back_val(); // At all of the protocols associated with current type variable // are transitive to its parent, propogate them down the subtype/equivalence // chain. if (parent) { propagateProtocolsTo(parent, bindings.Protocols, protocols[currentVar]); } auto inferredProtocols = std::move(protocols[currentVar]); llvm::SmallPtrSet protocolsForEquivalence; // Equivalence class should contain both: // - direct protocol requirements of the current type // variable; // - all of the transitive protocols inferred through // the members of the equivalence class. { protocolsForEquivalence.insert(bindings.Protocols.begin(), bindings.Protocols.end()); protocolsForEquivalence.insert(inferredProtocols.begin(), inferredProtocols.end()); } // Propogate inferred protocols to all of the members of the // equivalence class. for (const auto &equivalence : bindings.EquivalentTo) { auto eqBindings = inferredBindings.find(equivalence.first); if (eqBindings != inferredBindings.end()) { auto &bindings = eqBindings->getSecond(); bindings.TransitiveProtocols.emplace(protocolsForEquivalence); } } // Update the bindings associated with current type variable, // to avoid repeating this inference process. bindings.TransitiveProtocols.emplace(std::move(inferredProtocols)); } while (!workList.empty()); } void ConstraintSystem::PotentialBindings::inferTransitiveBindings( ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes, const llvm::SmallDenseMap &inferredBindings) { using BindingKind = ConstraintSystem::AllowedBindingKind; for (const auto &entry : SupertypeOf) { auto relatedBindings = inferredBindings.find(entry.first); if (relatedBindings == inferredBindings.end()) continue; auto &bindings = relatedBindings->getSecond(); // FIXME: This is a workaround necessary because solver doesn't filter // bindings based on protocol requirements placed on a type variable. // // Forward propagate (subtype -> supertype) only literal conformance // requirements since that helps solver to infer more types at // parameter positions. // // \code // func foo(_: String, _: T) -> T { // fatalError() // } // // func bar(_: Any?) {} // // func test() { // bar(foo("", "")) // } // \endcode // // If one of the literal arguments doesn't propagate its // `ExpressibleByStringLiteral` conformance, we'd end up picking // `T` with only one type `Any?` which is incorrect. llvm::copy_if(bindings.Protocols, std::back_inserter(Protocols), [](const Constraint *protocol) { return protocol->getKind() == ConstraintKind::LiteralConformsTo; }); // Infer transitive defaults. for (const auto &def : bindings.Defaults) addDefault(def.second); // TODO: We shouldn't need this in the future. if (entry.second->getKind() != ConstraintKind::Subtype) continue; for (auto &binding : bindings.Bindings) { // We need the binding kind for the potential binding to // either be Exact or Supertypes in order for it to make sense // to add Supertype bindings based on the relationship between // our type variables. if (binding.Kind != BindingKind::Exact && binding.Kind != BindingKind::Supertypes) continue; auto type = binding.BindingType; if (type->isHole()) continue; if (!existingTypes.insert(type->getCanonicalType()).second) continue; if (ConstraintSystem::typeVarOccursInType(TypeVar, type)) continue; addPotentialBinding( binding.withSameSource(type, BindingKind::Supertypes)); } } } static bool isUnviableDefaultType(Type defaultType, llvm::SmallPtrSetImpl &existingTypes) { auto canType = defaultType->getCanonicalType(); if (!defaultType->hasUnboundGenericType()) return !existingTypes.insert(canType).second; // For generic literal types, check whether we already have a // specialization of this generic within our list. // FIXME: This assumes that, e.g., the default literal // int/float/char/string types are never generic. auto nominal = defaultType->getAnyNominal(); if (!nominal) return true; if (llvm::any_of(existingTypes, [&nominal](CanType existingType) { // FIXME: Check parents? return nominal == existingType->getAnyNominal(); })) return true; existingTypes.insert(canType); return false; } void ConstraintSystem::PotentialBindings::inferDefaultTypes( ConstraintSystem &cs, llvm::SmallPtrSetImpl &existingTypes) { auto isDirectRequirement = [&](Constraint *constraint) -> bool { if (auto *typeVar = constraint->getFirstType()->getAs()) { auto *repr = cs.getRepresentative(typeVar); return repr == TypeVar; } return false; }; // If we have any literal constraints, check whether there is already a // binding that provides a type that conforms to that literal protocol. In // such cases, don't add the default binding suggestion because the existing // suggestion is better. // // Note that ordering is important when it comes to bindings, we'd like to // add any "direct" default types first to attempt them before transitive // ones. // // Key is a literal protocol requirement, Value indicates whether (first) // given protocol is a direct requirement, and (second) whether it has been // covered by an existing binding. bool canBeNil = false; llvm::SmallMapVector, 4> literalProtocols; for (auto *constraint : Protocols) { if (constraint->getKind() != ConstraintKind::LiteralConformsTo) continue; auto *protocol = constraint->getProtocol(); // No reason to add `ExpressibleByNilLiteral` into the set // because it doesn't have a default type. if (protocol->isSpecificProtocol( KnownProtocolKind::ExpressibleByNilLiteral)) { canBeNil = true; continue; } // Let's try to coalesce integer and floating point literal protocols // if they appear together because the only possible default type that // could satisfy both requirements is `Double`. { if (protocol->isSpecificProtocol( KnownProtocolKind::ExpressibleByIntegerLiteral)) { auto *floatLiteral = CS.getASTContext().getProtocol( KnownProtocolKind::ExpressibleByFloatLiteral); if (literalProtocols.count(floatLiteral)) continue; } if (protocol->isSpecificProtocol( KnownProtocolKind::ExpressibleByFloatLiteral)) { auto *intLiteral = CS.getASTContext().getProtocol( KnownProtocolKind::ExpressibleByIntegerLiteral); literalProtocols.erase(intLiteral); } } literalProtocols.insert( {protocol, {isDirectRequirement(constraint), false}}); } for (auto &binding : Bindings) { Type type; switch (binding.Kind) { case AllowedBindingKind::Exact: type = binding.BindingType; break; case AllowedBindingKind::Subtypes: case AllowedBindingKind::Supertypes: type = binding.BindingType->getRValueType(); break; } if (type->isTypeVariableOrMember() || type->isHole()) continue; bool requiresUnwrap = false; for (auto &entry : literalProtocols) { auto *protocol = entry.first; bool isDirectRequirement = entry.second.first; bool &isCovered = entry.second.second; if (isCovered) continue; do { // If the type conforms to this protocol, we're covered. if (TypeChecker::conformsToProtocol(type, protocol, cs.DC)) { isCovered = true; break; } // Can't unwrap optionals if there is `ExpressibleByNilLiteral` // conformance requirement placed on the type variable. if (canBeNil) break; // If this literal protocol is not a direct requirement it // would be possible to change optionality while inferring // bindings for a supertype, so this hack doesn't apply. if (!isDirectRequirement) break; // If we're allowed to bind to subtypes, look through optionals. // FIXME: This is really crappy special case of computing a reasonable // result based on the given constraints. if (binding.Kind == AllowedBindingKind::Subtypes) { if (auto objTy = type->getOptionalObjectType()) { requiresUnwrap = true; type = objTy; continue; } } requiresUnwrap = false; break; } while (true); } if (requiresUnwrap) binding.BindingType = type; } // If this is not a literal protocol or it has been "covered" by an existing // binding it can't provide a default type. auto isUnviableForDefaulting = [&literalProtocols](ProtocolDecl *protocol) { auto literal = literalProtocols.find(protocol); return literal == literalProtocols.end() || literal->second.second; }; for (auto *constraint : Protocols) { auto *protocol = constraint->getProtocol(); if (isUnviableForDefaulting(protocol)) continue; auto defaultType = TypeChecker::getDefaultType(protocol, cs.DC); if (!defaultType) continue; if (isUnviableDefaultType(defaultType, existingTypes)) continue; // We need to figure out whether this is a direct conformance // requirement or inferred transitive one to identify binding // kind correctly. addPotentialBinding({defaultType, isDirectRequirement(constraint) ? AllowedBindingKind::Subtypes : AllowedBindingKind::Supertypes, constraint}); } } void ConstraintSystem::PotentialBindings::finalize( ConstraintSystem &cs, llvm::SmallDenseMap &inferredBindings) { // We need to make sure that there are no duplicate bindings in the // set, otherwise solver would produce multiple identical solutions. llvm::SmallPtrSet existingTypes; for (const auto &binding : Bindings) existingTypes.insert(binding.BindingType->getCanonicalType()); inferTransitiveProtocolRequirements(cs, inferredBindings); inferTransitiveBindings(cs, existingTypes, inferredBindings); inferDefaultTypes(cs, existingTypes); } Optional ConstraintSystem::determineBestBindings() { // Look for potential type variable bindings. Optional bestBindings; llvm::SmallDenseMap cache; // First, let's collect all of the possible bindings. for (auto *typeVar : getTypeVariables()) { if (!typeVar->getImpl().hasRepresentativeOrFixed()) cache.insert({typeVar, inferBindingsFor(typeVar, /*finalize=*/false)}); } // Determine whether given type variable with its set of bindings is // viable to be attempted on the next step of the solver. If type variable // has no "direct" bindings of any kind e.g. direct bindings to concrete // types, default types from "defaultable" constraints or literal // conformances, such type variable is not viable to be evaluated to be // attempted next. auto isViableForRanking = [this](const ConstraintSystem::PotentialBindings &bindings) -> bool { auto *typeVar = bindings.TypeVar; // If type variable is marked as a potential hole there is always going // to be at least one binding available for it. if (shouldAttemptFixes() && typeVar->getImpl().canBindToHole()) return true; return bindings || llvm::any_of(bindings.Protocols, [&](Constraint *constraint) { return bool( TypeChecker::getDefaultType(constraint->getProtocol(), DC)); }); }; // Now let's see if we could infer something for related type // variables based on other bindings. for (auto *typeVar : getTypeVariables()) { auto cachedBindings = cache.find(typeVar); if (cachedBindings == cache.end()) continue; auto &bindings = cachedBindings->getSecond(); // Before attempting to infer transitive bindings let's check // whether there are any viable "direct" bindings associated with // current type variable, if there are none - it means that this type // variable could only be used to transitively infer bindings for // other type variables and can't participate in ranking. // // Viable bindings include - any types inferred from constraints // associated with given type variable, any default constraints, // or any conformance requirements to literal protocols with can // produce a default type. bool isViable = isViableForRanking(bindings); bindings.finalize(*this, cache); if (!bindings || !isViable) continue; if (isDebugMode()) { bindings.dump(typeVar, llvm::errs(), solverState->depth * 2); } // If these are the first bindings, or they are better than what // we saw before, use them instead. if (!bestBindings || bindings < *bestBindings) bestBindings.emplace(bindings); } return bestBindings; } /// Find the set of type variables that are inferable from the given type. /// /// \param type The type to search. /// \param typeVars Collects the type variables that are inferable from the /// given type. This set is not cleared, so that multiple types can be explored /// and introduce their results into the same set. static void findInferableTypeVars(Type type, SmallPtrSetImpl &typeVars) { type = type->getCanonicalType(); if (!type->hasTypeVariable()) return; class Walker : public TypeWalker { SmallPtrSetImpl &typeVars; public: explicit Walker(SmallPtrSetImpl &typeVars) : typeVars(typeVars) {} Action walkToTypePre(Type ty) override { if (ty->is()) return Action::SkipChildren; if (auto typeVar = ty->getAs()) typeVars.insert(typeVar); return Action::Continue; } }; type.walk(Walker(typeVars)); } void ConstraintSystem::PotentialBindings::addDefault(Constraint *constraint) { auto defaultTy = constraint->getSecondType(); Defaults.insert({defaultTy->getCanonicalType(), constraint}); } void ConstraintSystem::PotentialBindings::addPotentialBinding( PotentialBinding binding, bool allowJoinMeet) { assert(!binding.BindingType->is()); // If this is a non-defaulted supertype binding, // check whether we can combine it with another // supertype binding by computing the 'join' of the types. if (binding.isViableForJoin() && allowJoinMeet) { bool joined = false; auto isAcceptableJoin = [](Type type) { return !type->isAny() && (!type->getOptionalObjectType() || !type->getOptionalObjectType()->isAny()); }; for (auto &existingBinding : Bindings) { if (!existingBinding.isViableForJoin()) continue; auto join = Type::join(existingBinding.BindingType, binding.BindingType); if (join && isAcceptableJoin(*join)) { existingBinding.BindingType = *join; joined = true; } } // If new binding has been joined with at least one of existing // bindings, there is no reason to include it into the set. if (joined) return; } if (auto *literalProtocol = binding.getDefaultedLiteralProtocol()) foundLiteralBinding(literalProtocol); // If the type variable can't bind to an lvalue, make sure the // type we pick isn't an lvalue. if (!TypeVar->getImpl().canBindToLValue() && binding.BindingType->hasLValueType()) { binding = binding.withType(binding.BindingType->getRValueType()); } if (!isViable(binding)) return; Bindings.push_back(std::move(binding)); } bool ConstraintSystem::PotentialBindings::isViable( PotentialBinding &binding) const { // Prevent against checking against the same opened nominal type // over and over again. Doing so means redundant work in the best // case. In the worst case, we'll produce lots of duplicate solutions // for this constraint system, which is problematic for overload // resolution. auto type = binding.BindingType; if (type->hasTypeVariable()) { auto *NTD = type->getAnyNominal(); if (!NTD) return true; for (auto &existing : Bindings) { auto *existingNTD = existing.BindingType->getAnyNominal(); if (existingNTD && NTD == existingNTD) return false; } } return true; } bool ConstraintSystem::PotentialBindings::favoredOverDisjunction( Constraint *disjunction) const { if (isHole() || isDelayed()) return false; // If this bindings are for a closure and there are no holes, // it shouldn't matter whether it there are any type variables // or not because e.g. parameter type can have type variables, // but we still want to resolve closure body early (instead of // attempting any disjunction) to gain additional contextual // information. if (TypeVar->getImpl().isClosureType()) { auto boundType = disjunction->getNestedConstraints()[0]->getFirstType(); // If disjunction is attempting to bind a type variable, let's // favor closure because it would add additional context, otherwise // if it's something like a collection (where it has to pick // between a conversion and bridging conversion) or concrete // type let's prefer the disjunction. // // We are looking through optionals here because it could be // a situation where disjunction is formed to match optionals // either as deep equality or optional-to-optional conversion. // Such type variables might be connected to closure as well // e.g. when result type is optional, so it makes sense to // open closure before attempting such disjunction. return boundType->lookThroughAllOptionalTypes()->is(); } return !involvesTypeVariables(); } ConstraintSystem::PotentialBindings ConstraintSystem::inferBindingsFor(TypeVariableType *typeVar, bool finalize) { assert(typeVar->getImpl().getRepresentative(nullptr) == typeVar && "not a representative"); assert(!typeVar->getImpl().getFixedType(nullptr) && "has a fixed type"); PotentialBindings bindings(*this, typeVar); // Gather the constraints associated with this type variable. auto constraints = CG.gatherConstraints( typeVar, ConstraintGraph::GatheringKind::EquivalenceClass); llvm::SmallPtrSet exactTypes; for (auto *constraint : constraints) { bool failed = bindings.infer(*this, exactTypes, constraint); // Upon inference failure let's produce an empty set of bindings. if (failed) return {*this, typeVar}; } if (finalize) { llvm::SmallDenseMap inferred; bindings.finalize(*this, inferred); } return bindings; } Optional ConstraintSystem::getPotentialBindingForRelationalConstraint( PotentialBindings &result, Constraint *constraint) const { assert(constraint->getClassification() == ConstraintClassification::Relational && "only relational constraints handled here"); auto *typeVar = result.TypeVar; auto first = simplifyType(constraint->getFirstType()); auto second = simplifyType(constraint->getSecondType()); if (first->is() && first->isEqual(second)) return None; Type type; AllowedBindingKind kind; if (first->getAs() == typeVar) { // Upper bound for this type variable. type = second; kind = AllowedBindingKind::Subtypes; } else if (second->getAs() == typeVar) { // Lower bound for this type variable. type = first; kind = AllowedBindingKind::Supertypes; } else { // If the left-hand side of a relational constraint is a // type variable representing a closure type, let's delay // attempting any bindings related to any type variables // on the other side since it could only be either a closure // parameter or a result type, and we can't get a full set // of bindings for them until closure's body is opened. if (auto *typeVar = first->getAs()) { if (typeVar->getImpl().isClosureType()) { result.DelayedBy.push_back(constraint); return None; } } // Check whether both this type and another type variable are // inferable. SmallPtrSet typeVars; findInferableTypeVars(first, typeVars); findInferableTypeVars(second, typeVars); if (typeVars.erase(typeVar)) { result.AdjacentVars.insert(typeVars.begin(), typeVars.end()); } return None; } // Do not attempt to bind to ErrorType. if (type->hasError()) return None; if (auto *locator = typeVar->getImpl().getLocator()) { if (locator->isKeyPathType()) { auto *BGT = type->lookThroughAllOptionalTypes()->getAs(); if (!BGT || !isKnownKeyPathDecl(getASTContext(), BGT->getDecl())) return None; } } // If the source of the binding is 'OptionalObject' constraint // and type variable is on the left-hand side, that means // that it _has_ to be of optional type, since the right-hand // side of the constraint is object type of the optional. if (constraint->getKind() == ConstraintKind::OptionalObject && kind == AllowedBindingKind::Subtypes) { type = OptionalType::get(type); } // If the type we'd be binding to is a dependent member, don't try to // resolve this type variable yet. if (type->getWithoutSpecifierType() ->lookThroughAllOptionalTypes() ->is()) { SmallVector referencedVars; type->getTypeVariables(referencedVars); bool containsSelf = false; for (auto *var : referencedVars) { // Add all type variables encountered in the type except // to the current type variable. if (var != typeVar) { result.AdjacentVars.insert(var); continue; } containsSelf = true; } // If inferred type doesn't contain the current type variable, // let's mark bindings as delayed until dependent member type // is resolved. if (!containsSelf) result.DelayedBy.push_back(constraint); return None; } // If our binding choice is a function type and we're attempting // to bind to a type variable that is the result of opening a // generic parameter, strip the noescape bit so that we only allow // bindings of escaping functions in this position. We do this // because within the generic function we have no indication of // whether the parameter is a function type and if so whether it // should be allowed to escape. As a result we allow anything // passed in to escape. if (auto *fnTy = type->getAs()) if (typeVar->getImpl().getGenericParameter() && !shouldAttemptFixes()) type = fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape(false)); // Check whether we can perform this binding. // FIXME: this has a super-inefficient extraneous simplifyType() in it. if (auto boundType = checkTypeOfBinding(typeVar, type)) { type = *boundType; if (type->hasTypeVariable()) { SmallVector referencedVars; type->getTypeVariables(referencedVars); result.AdjacentVars.insert(referencedVars.begin(), referencedVars.end()); } } else { auto *bindingTypeVar = type->getRValueType()->getAs(); if (!bindingTypeVar) return None; result.AdjacentVars.insert(bindingTypeVar); // If current type variable is associated with a code completion token // it's possible that it doesn't have enough contextual information // to be resolved to anything, so let's note that fact in the potential // bindings and use it when forming a hole if there are no other bindings // available. if (auto *locator = bindingTypeVar->getImpl().getLocator()) { if (locator->directlyAt()) result.AssociatedCodeCompletionToken = locator->getAnchor(); } switch (constraint->getKind()) { case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ArgumentConversion: case ConstraintKind::OperatorArgumentConversion: { if (kind == AllowedBindingKind::Subtypes) { result.SubtypeOf.insert({bindingTypeVar, constraint}); } else { assert(kind == AllowedBindingKind::Supertypes); result.SupertypeOf.insert({bindingTypeVar, constraint}); } break; } case ConstraintKind::Bind: case ConstraintKind::BindParam: case ConstraintKind::Equal: { result.EquivalentTo.insert({bindingTypeVar, constraint}); break; } default: break; } return None; } // Make sure we aren't trying to equate type variables with different // lvalue-binding rules. if (auto otherTypeVar = type->getAs()) { if (typeVar->getImpl().canBindToLValue() != otherTypeVar->getImpl().canBindToLValue()) return None; } if (type->is() && !typeVar->getImpl().canBindToInOut()) type = LValueType::get(type->getInOutObjectType()); if (type->is() && !typeVar->getImpl().canBindToLValue()) type = type->getRValueType(); // BindParam constraints are not reflexive and must be treated specially. if (constraint->getKind() == ConstraintKind::BindParam) { if (kind == AllowedBindingKind::Subtypes) { if (auto *lvt = type->getAs()) { type = InOutType::get(lvt->getObjectType()); } } else if (kind == AllowedBindingKind::Supertypes) { if (auto *iot = type->getAs()) { type = LValueType::get(iot->getObjectType()); } } kind = AllowedBindingKind::Exact; } return PotentialBinding{type, kind, constraint}; } /// Retrieve the set of potential type bindings for the given /// representative type variable, along with flags indicating whether /// those types should be opened. bool ConstraintSystem::PotentialBindings::infer( ConstraintSystem &cs, llvm::SmallPtrSetImpl &exactTypes, Constraint *constraint) { switch (constraint->getKind()) { case ConstraintKind::Bind: case ConstraintKind::Equal: case ConstraintKind::BindParam: case ConstraintKind::BindToPointerType: case ConstraintKind::Subtype: case ConstraintKind::Conversion: case ConstraintKind::ArgumentConversion: case ConstraintKind::OperatorArgumentConversion: case ConstraintKind::OptionalObject: { auto binding = cs.getPotentialBindingForRelationalConstraint(*this, constraint); if (!binding) break; auto type = binding->BindingType; if (exactTypes.insert(type->getCanonicalType()).second) { addPotentialBinding(*binding); // Determines whether this type variable represents an object // of the optional type extracted by force unwrap. if (auto *locator = TypeVar->getImpl().getLocator()) { auto anchor = locator->getAnchor(); // Result of force unwrap is always connected to its base // optional type via `OptionalObject` constraint which // preserves l-valueness, so in case where object type got // inferred before optional type (because it got the // type from context e.g. parameter type of a function call), // we need to test type with and without l-value after // delaying bindings for as long as possible. if (isExpr(anchor) && TypeVar->getImpl().canBindToLValue() && !type->is()) { addPotentialBinding(binding->withType(LValueType::get(type))); DelayedBy.push_back(constraint); } // If this is a type variable representing closure result, // which is on the right-side of some relational constraint // let's have it try `Void` as well because there is an // implicit conversion `() -> T` to `() -> Void` and this // helps to avoid creating a thunk to support it. auto voidType = cs.getASTContext().TheEmptyTupleType; if (locator->isLastElement() && binding->Kind == AllowedBindingKind::Supertypes && exactTypes.insert(voidType).second) { addPotentialBinding({voidType, binding->Kind, constraint}, /*allowJoinMeet=*/false); } } } break; } case ConstraintKind::KeyPathApplication: { // If this variable is in the application projected result type, mark the // result as `FullyBound` to ensure we delay binding until we've bound // other type variables in the KeyPathApplication constraint. This ensures // we try to bind the key path type first, which can allow us to discover // additional bindings for the result type. SmallPtrSet typeVars; findInferableTypeVars(cs.simplifyType(constraint->getThirdType()), typeVars); if (typeVars.count(TypeVar)) { DelayedBy.push_back(constraint); } break; } case ConstraintKind::BridgingConversion: case ConstraintKind::CheckedCast: case ConstraintKind::EscapableFunctionOf: case ConstraintKind::OpenedExistentialOf: case ConstraintKind::KeyPath: case ConstraintKind::FunctionInput: case ConstraintKind::FunctionResult: case ConstraintKind::OpaqueUnderlyingType: // Constraints from which we can't do anything. break; case ConstraintKind::DynamicTypeOf: { // Direct binding of the left-hand side could result // in `DynamicTypeOf` failure if right-hand side is // bound (because 'Bind' requires equal types to // succeed), or left is bound to Any which is not an // [existential] metatype. auto dynamicType = constraint->getFirstType(); if (auto *tv = dynamicType->getAs()) { if (tv->getImpl().getRepresentative(nullptr) == TypeVar) return true; } // This is right-hand side, let's continue. break; } case ConstraintKind::Defaultable: case ConstraintKind::DefaultClosureType: // Do these in a separate pass. if (cs.getFixedTypeRecursive(constraint->getFirstType(), true) ->getAs() == TypeVar) { addDefault(constraint); } break; case ConstraintKind::Disjunction: // If there is additional context available via disjunction // associated with closure literal (e.g. coercion to some other // type) let's delay resolving the closure until the disjunction // is attempted. if (TypeVar->getImpl().isClosureType()) return true; DelayedBy.push_back(constraint); break; case ConstraintKind::ConformsTo: case ConstraintKind::SelfObjectOfProtocol: { auto protocolTy = constraint->getSecondType(); if (!protocolTy->is()) return false; LLVM_FALLTHROUGH; } case ConstraintKind::LiteralConformsTo: { // Record constraint where protocol requirement originated // this is useful to use for the binding later. Protocols.push_back(constraint); break; } case ConstraintKind::ApplicableFunction: case ConstraintKind::DynamicCallableApplicableFunction: case ConstraintKind::BindOverload: { // It's possible that type of member couldn't be determined, // and if so it would be beneficial to bind member to a hole // early to propagate that information down to arguments, // result type of a call that references such a member. if (cs.shouldAttemptFixes() && TypeVar->getImpl().canBindToHole()) { if (ConstraintSystem::typeVarOccursInType( TypeVar, cs.simplifyType(constraint->getSecondType()))) break; } DelayedBy.push_back(constraint); break; } case ConstraintKind::ValueMember: case ConstraintKind::UnresolvedValueMember: case ConstraintKind::ValueWitness: { // If current type variable represents a member type of some reference, // it would be bound once member is resolved either to a actual member // type or to a hole if member couldn't be found. auto memberTy = constraint->getSecondType()->castTo(); if (memberTy->getImpl().hasRepresentativeOrFixed()) { if (auto type = memberTy->getImpl().getFixedType(/*record=*/nullptr)) { // It's possible that member has been bound to some other type variable // instead of merged with it because it's wrapped in an l-value type. if (type->getWithoutSpecifierType()->isEqual(TypeVar)) { DelayedBy.push_back(constraint); break; } } else { memberTy = memberTy->getImpl().getRepresentative(/*record=*/nullptr); } } if (memberTy == TypeVar) DelayedBy.push_back(constraint); break; } case ConstraintKind::OneWayEqual: case ConstraintKind::OneWayBindParam: { // Don't produce any bindings if this type variable is on the left-hand // side of a one-way binding. auto firstType = constraint->getFirstType(); if (auto *tv = firstType->getAs()) { if (tv->getImpl().getRepresentative(nullptr) == TypeVar) return true; } break; } } return false; } /// Check whether the given type can be used as a binding for the given /// type variable. /// /// \returns the type to bind to, if the binding is okay. Optional ConstraintSystem::checkTypeOfBinding(TypeVariableType *typeVar, Type type) const { // Simplify the type. type = simplifyType(type); // If the type references the type variable, don't permit the binding. SmallVector referencedTypeVars; type->getTypeVariables(referencedTypeVars); if (count(referencedTypeVars, typeVar)) return None; // If type variable is not allowed to bind to `lvalue`, // let's check if type of potential binding has any // type variables, which are allowed to bind to `lvalue`, // and postpone such type from consideration. if (!typeVar->getImpl().canBindToLValue()) { for (auto *typeVar : referencedTypeVars) { if (typeVar->getImpl().canBindToLValue()) return None; } } { auto objType = type->getWithoutSpecifierType(); // If the type is a type variable itself, don't permit the binding. if (objType->is()) return None; // Don't bind to a dependent member type, even if it's currently // wrapped in any number of optionals, because binding producer // might unwrap and try to attempt it directly later. if (objType->lookThroughAllOptionalTypes()->is()) return None; } // Okay, allow the binding (with the simplified type). return type; } // Given a possibly-Optional type, return the direct superclass of the // (underlying) type wrapped in the same number of optional levels as // type. static Type getOptionalSuperclass(Type type) { int optionalLevels = 0; while (auto underlying = type->getOptionalObjectType()) { ++optionalLevels; type = underlying; } if (!type->mayHaveSuperclass()) return Type(); auto superclass = type->getSuperclass(); if (!superclass) return Type(); while (optionalLevels--) superclass = OptionalType::get(superclass); return superclass; } /// Enumerates all of the 'direct' supertypes of the given type. /// /// The direct supertype S of a type T is a supertype of T (e.g., T < S) /// such that there is no type U where T < U and U < S. static SmallVector enumerateDirectSupertypes(Type type) { SmallVector result; if (type->is() || type->is()) { type = type->getWithoutSpecifierType(); result.push_back(type); } if (auto superclass = getOptionalSuperclass(type)) { // FIXME: Can also weaken to the set of protocol constraints, but only // if there are any protocols that the type conforms to but the superclass // does not. result.push_back(superclass); } // FIXME: lots of other cases to consider! return result; } bool TypeVarBindingProducer::computeNext() { SmallVector newBindings; auto addNewBinding = [&](Binding binding) { auto type = binding.BindingType; // If we've already tried this binding, move on. if (!BoundTypes.insert(type.getPointer()).second) return; if (!ExploredTypes.insert(type->getCanonicalType()).second) return; newBindings.push_back(std::move(binding)); }; for (auto &binding : Bindings) { const auto type = binding.BindingType; assert(!type->hasError()); // After our first pass, note that we've explored these types. if (NumTries == 0) ExploredTypes.insert(type->getCanonicalType()); // If we have a protocol with a default type, look for alternative // types to the default. if (NumTries == 0 && binding.hasDefaultedLiteralProtocol()) { auto knownKind = *(binding.getDefaultedLiteralProtocol()->getKnownProtocolKind()); for (auto altType : CS.getAlternativeLiteralTypes(knownKind)) { addNewBinding(binding.withSameSource(altType, BindingKind::Subtypes)); } } // Allow solving for T even for a binding kind where that's invalid // if fixes are allowed, because that gives us the opportunity to // match T? values to the T binding by adding an unwrap fix. if (binding.Kind == BindingKind::Subtypes || CS.shouldAttemptFixes()) { // If we were unsuccessful solving for T?, try solving for T. if (auto objTy = type->getOptionalObjectType()) { // If T is a type variable, only attempt this if both the // type variable we are trying bindings for, and the type // variable we will attempt to bind, both have the same // polarity with respect to being able to bind lvalues. if (auto otherTypeVar = objTy->getAs()) { if (TypeVar->getImpl().canBindToLValue() == otherTypeVar->getImpl().canBindToLValue()) { addNewBinding(binding.withSameSource(objTy, binding.Kind)); } } else { addNewBinding(binding.withSameSource(objTy, binding.Kind)); } } } auto srcLocator = binding.getLocator(); if (srcLocator && (srcLocator->isLastElement() || srcLocator->isLastElement()) && !type->hasTypeVariable() && type->isKnownStdlibCollectionType()) { // If the type binding comes from the argument conversion, let's // instead of binding collection types directly, try to bind // using temporary type variables substituted for element // types, that's going to ensure that subtype relationship is // always preserved. auto *BGT = type->castTo(); auto dstLocator = TypeVar->getImpl().getLocator(); auto newType = CS.openUnboundGenericType(BGT->getDecl(), BGT->getParent(), dstLocator) ->reconstituteSugar(/*recursive=*/false); addNewBinding(binding.withType(newType)); } if (binding.Kind == BindingKind::Supertypes) { for (auto supertype : enumerateDirectSupertypes(type)) { // If we're not allowed to try this binding, skip it. if (auto simplifiedSuper = CS.checkTypeOfBinding(TypeVar, supertype)) addNewBinding(binding.withType(*simplifiedSuper)); } } } if (NumTries == 0) { // Add defaultable constraints (if any). for (auto *constraint : DelayedDefaults) { if (constraint->getKind() == ConstraintKind::DefaultClosureType) { // If there are no other possible bindings for this closure // let's default it to the type inferred from its parameters/body, // otherwise we should only attempt contextual types as a // top-level closure type. if (!ExploredTypes.empty()) continue; } addNewBinding(getDefaultBinding(constraint)); } } if (newBindings.empty()) return false; Index = 0; ++NumTries; Bindings = std::move(newBindings); return true; } Optional> TypeVariableBinding::fixForHole(ConstraintSystem &cs) const { auto *dstLocator = TypeVar->getImpl().getLocator(); auto *srcLocator = Binding.getLocator(); // FIXME: This check could be turned into an assert once // all code completion kinds are ported to use // `TypeChecker::typeCheckForCodeCompletion` API. if (cs.isForCodeCompletion()) { // If the hole is originated from code completion expression // let's not try to fix this, anything connected to a // code completion is allowed to be a hole because presence // of a code completion token makes constraint system // under-constrained due to e.g. lack of expressions on the // right-hand side of the token, which are required for a // regular type-check. if (dstLocator->directlyAt() || srcLocator->directlyAt()) return None; } unsigned defaultImpact = 1; if (auto *GP = TypeVar->getImpl().getGenericParameter()) { // If it is represetative for a key path root, let's emit a more // specific diagnostic. auto *keyPathRoot = cs.isRepresentativeFor(TypeVar, ConstraintLocator::KeyPathRoot); if (keyPathRoot) { ConstraintFix *fix = SpecifyKeyPathRootType::create( cs, keyPathRoot->getImpl().getLocator()); return std::make_pair(fix, defaultImpact); } else { auto path = dstLocator->getPath(); // Drop `generic parameter` locator element so that all missing // generic parameters related to the same path can be coalesced later. ConstraintFix *fix = DefaultGenericArgument::create( cs, GP, cs.getConstraintLocator(dstLocator->getAnchor(), path.drop_back())); return std::make_pair(fix, defaultImpact); } } if (TypeVar->getImpl().isClosureParameterType()) { ConstraintFix *fix = SpecifyClosureParameterType::create(cs, dstLocator); return std::make_pair(fix, defaultImpact); } if (TypeVar->getImpl().isClosureResultType()) { auto *closure = castToExpr(dstLocator->getAnchor()); // If the whole body is being ignored due to a pre-check failure, // let's not record a fix about result type since there is // just not enough context to infer it without a body. if (cs.hasFixFor(cs.getConstraintLocator(closure), FixKind::IgnoreInvalidResultBuilderBody)) return None; ConstraintFix *fix = SpecifyClosureReturnType::create(cs, dstLocator); return std::make_pair(fix, defaultImpact); } if (srcLocator->directlyAt()) { ConstraintFix *fix = SpecifyObjectLiteralTypeImport::create(cs, dstLocator); return std::make_pair(fix, defaultImpact); } if (srcLocator->isKeyPathRoot()) { // If we recorded an invalid key path fix, let's skip this specify root // type fix because it wouldn't produce a useful diagnostic. auto *kpLocator = cs.getConstraintLocator(srcLocator->getAnchor()); if (cs.hasFixFor(kpLocator, FixKind::AllowKeyPathWithoutComponents)) return None; ConstraintFix *fix = SpecifyKeyPathRootType::create(cs, dstLocator); return std::make_pair(fix, defaultImpact); } if (dstLocator->directlyAt()) { // This is a dramatic event, it means that there is absolutely // no contextual information to resolve type of `nil`. ConstraintFix *fix = SpecifyContextualTypeForNil::create(cs, dstLocator); return std::make_pair(fix, /*impact=*/(unsigned)10); } return None; } bool TypeVariableBinding::attempt(ConstraintSystem &cs) const { auto type = Binding.BindingType; auto *srcLocator = Binding.getLocator(); auto *dstLocator = TypeVar->getImpl().getLocator(); if (Binding.hasDefaultedLiteralProtocol()) { type = cs.openUnboundGenericTypes(type, dstLocator); type = type->reconstituteSugar(/*recursive=*/false); } cs.addConstraint(ConstraintKind::Bind, TypeVar, type, srcLocator); // If this was from a defaultable binding note that. if (Binding.isDefaultableBinding()) { cs.DefaultedConstraints.push_back(srcLocator); if (type->isHole()) { // Reflect in the score that this type variable couldn't be // resolved and had to be bound to a placeholder "hole" type. cs.increaseScore(SK_Hole); if (auto fix = fixForHole(cs)) { if (cs.recordFix(/*fix=*/fix->first, /*impact=*/fix->second)) return true; } } } return !cs.failedConstraint && !cs.simplify(); }