From 8df19d2c87340c05a4dccbe066c20cde509c2b3c Mon Sep 17 00:00:00 2001 From: Pavel Yaskevich Date: Wed, 1 Jul 2020 14:31:51 -0700 Subject: [PATCH] [ConstraintSystem] NFC: Associate transitive binding inference with `PotentialBindings` --- lib/Sema/CSBindings.cpp | 37 +++++++++++++++++++------------------ lib/Sema/ConstraintSystem.h | 33 +++++++++++++++++---------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index d137175ed07..3359cc8e751 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -21,36 +21,37 @@ using namespace swift; using namespace constraints; -void ConstraintSystem::inferTransitiveSupertypeBindings( - const llvm::SmallDenseMap - &inferredBindings, - PotentialBindings &bindings) { - auto *typeVar = bindings.TypeVar; +void ConstraintSystem::PotentialBindings::inferTransitiveBindings( + ConstraintSystem &cs, + const llvm::SmallDenseMap + &inferredBindings) { + using BindingKind = ConstraintSystem::AllowedBindingKind; llvm::SmallVector subtypeOf; // First, let's collect all of the `subtype` constraints associated // with this type variable. - llvm::copy_if(bindings.Sources, std::back_inserter(subtypeOf), + llvm::copy_if(Sources, std::back_inserter(subtypeOf), [&](const Constraint *constraint) -> bool { if (constraint->getKind() != ConstraintKind::Subtype) return false; - auto rhs = simplifyType(constraint->getSecondType()); - return rhs->getAs() == typeVar; + auto rhs = cs.simplifyType(constraint->getSecondType()); + return rhs->getAs() == TypeVar; }); if (subtypeOf.empty()) return; // We need to make sure that there are no duplicate bindings in the - // set, other we'll produce multiple identical solutions. + // set, otherwise solver would produce multiple identical solutions. llvm::SmallPtrSet existingTypes; - for (const auto &binding : bindings.Bindings) + for (const auto &binding : Bindings) existingTypes.insert(binding.BindingType->getCanonicalType()); for (auto *constraint : subtypeOf) { auto *tv = - simplifyType(constraint->getFirstType())->getAs(); + cs.simplifyType(constraint->getFirstType())->getAs(); if (!tv) continue; @@ -63,8 +64,8 @@ void ConstraintSystem::inferTransitiveSupertypeBindings( // 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 != AllowedBindingKind::Exact && - binding.Kind != AllowedBindingKind::Supertypes) + if (binding.Kind != BindingKind::Exact && + binding.Kind != BindingKind::Supertypes) continue; auto type = binding.BindingType; @@ -75,16 +76,16 @@ void ConstraintSystem::inferTransitiveSupertypeBindings( if (!existingTypes.insert(type->getCanonicalType()).second) continue; - if (ConstraintSystem::typeVarOccursInType(typeVar, type)) + if (ConstraintSystem::typeVarOccursInType(TypeVar, type)) continue; - bindings.addPotentialBinding( - binding.withSameSource(type, AllowedBindingKind::Supertypes)); + addPotentialBinding( + binding.withSameSource(type, BindingKind::Supertypes)); } // Infer transitive protocol requirements. for (auto *protocol : relatedBindings->getSecond().Protocols) { - bindings.Protocols.push_back(protocol); + Protocols.push_back(protocol); } } } @@ -113,7 +114,7 @@ ConstraintSystem::determineBestBindings() { auto &bindings = cachedBindings->getSecond(); - inferTransitiveSupertypeBindings(cache, bindings); + bindings.inferTransitiveBindings(*this, cache); if (isDebugMode()) { bindings.dump(typeVar, llvm::errs(), solverState->depth * 2); diff --git a/lib/Sema/ConstraintSystem.h b/lib/Sema/ConstraintSystem.h index 2a318a4eeef..168737ad206 100644 --- a/lib/Sema/ConstraintSystem.h +++ b/lib/Sema/ConstraintSystem.h @@ -4557,6 +4557,23 @@ private: /// if it has only concrete types or would resolve a closure. bool favoredOverDisjunction(Constraint *disjunction) const; + /// Detect `subtype` relationship between two type variables and + /// attempt to infer supertype bindings transitively e.g. + /// + /// Given A <: T1 <: T2 transitively A <: T2 + /// + /// Which gives us a new (superclass A) binding for T2 as well as T1. + /// + /// \param cs The constraint system this type variable is associated with. + /// + /// \param inferredBindings The set of all bindings inferred for type + /// variables in the workset. + void inferTransitiveBindings( + ConstraintSystem &cs, + const llvm::SmallDenseMap + &inferredBindings); + void dump(llvm::raw_ostream &out, unsigned indent = 0) const LLVM_ATTRIBUTE_USED { out.indent(indent); @@ -4625,22 +4642,6 @@ private: bool &addOptionalSupertypeBindings) const; PotentialBindings getPotentialBindings(TypeVariableType *typeVar) const; - /// Detect `subtype` relationship between two type variables and - /// attempt to infer supertype bindings transitively e.g. - /// - /// Given A <: T1 <: T2 transitively A <: T2 - /// - /// Which gives us a new (superclass A) binding for T2 as well as T1. - /// - /// \param inferredBindings The set of all bindings inferred for type - /// variables in the workset. - /// \param bindings The type variable we aim to infer new supertype - /// bindings for. - void inferTransitiveSupertypeBindings( - const llvm::SmallDenseMap - &inferredBindings, - PotentialBindings &bindings); - private: /// Add a constraint to the constraint system. SolutionKind addConstraintImpl(ConstraintKind kind, Type first, Type second,