mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[ConstraintSystem] NFC: Associate transitive binding inference with PotentialBindings
This commit is contained in:
@@ -21,36 +21,37 @@
|
|||||||
using namespace swift;
|
using namespace swift;
|
||||||
using namespace constraints;
|
using namespace constraints;
|
||||||
|
|
||||||
void ConstraintSystem::inferTransitiveSupertypeBindings(
|
void ConstraintSystem::PotentialBindings::inferTransitiveBindings(
|
||||||
const llvm::SmallDenseMap<TypeVariableType *, PotentialBindings>
|
ConstraintSystem &cs,
|
||||||
&inferredBindings,
|
const llvm::SmallDenseMap<TypeVariableType *,
|
||||||
PotentialBindings &bindings) {
|
ConstraintSystem::PotentialBindings>
|
||||||
auto *typeVar = bindings.TypeVar;
|
&inferredBindings) {
|
||||||
|
using BindingKind = ConstraintSystem::AllowedBindingKind;
|
||||||
|
|
||||||
llvm::SmallVector<Constraint *, 4> subtypeOf;
|
llvm::SmallVector<Constraint *, 4> subtypeOf;
|
||||||
// First, let's collect all of the `subtype` constraints associated
|
// First, let's collect all of the `subtype` constraints associated
|
||||||
// with this type variable.
|
// 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 {
|
[&](const Constraint *constraint) -> bool {
|
||||||
if (constraint->getKind() != ConstraintKind::Subtype)
|
if (constraint->getKind() != ConstraintKind::Subtype)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto rhs = simplifyType(constraint->getSecondType());
|
auto rhs = cs.simplifyType(constraint->getSecondType());
|
||||||
return rhs->getAs<TypeVariableType>() == typeVar;
|
return rhs->getAs<TypeVariableType>() == TypeVar;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (subtypeOf.empty())
|
if (subtypeOf.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// We need to make sure that there are no duplicate bindings in the
|
// 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<CanType, 4> existingTypes;
|
llvm::SmallPtrSet<CanType, 4> existingTypes;
|
||||||
for (const auto &binding : bindings.Bindings)
|
for (const auto &binding : Bindings)
|
||||||
existingTypes.insert(binding.BindingType->getCanonicalType());
|
existingTypes.insert(binding.BindingType->getCanonicalType());
|
||||||
|
|
||||||
for (auto *constraint : subtypeOf) {
|
for (auto *constraint : subtypeOf) {
|
||||||
auto *tv =
|
auto *tv =
|
||||||
simplifyType(constraint->getFirstType())->getAs<TypeVariableType>();
|
cs.simplifyType(constraint->getFirstType())->getAs<TypeVariableType>();
|
||||||
if (!tv)
|
if (!tv)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -63,8 +64,8 @@ void ConstraintSystem::inferTransitiveSupertypeBindings(
|
|||||||
// either be Exact or Supertypes in order for it to make sense
|
// either be Exact or Supertypes in order for it to make sense
|
||||||
// to add Supertype bindings based on the relationship between
|
// to add Supertype bindings based on the relationship between
|
||||||
// our type variables.
|
// our type variables.
|
||||||
if (binding.Kind != AllowedBindingKind::Exact &&
|
if (binding.Kind != BindingKind::Exact &&
|
||||||
binding.Kind != AllowedBindingKind::Supertypes)
|
binding.Kind != BindingKind::Supertypes)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto type = binding.BindingType;
|
auto type = binding.BindingType;
|
||||||
@@ -75,16 +76,16 @@ void ConstraintSystem::inferTransitiveSupertypeBindings(
|
|||||||
if (!existingTypes.insert(type->getCanonicalType()).second)
|
if (!existingTypes.insert(type->getCanonicalType()).second)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (ConstraintSystem::typeVarOccursInType(typeVar, type))
|
if (ConstraintSystem::typeVarOccursInType(TypeVar, type))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
bindings.addPotentialBinding(
|
addPotentialBinding(
|
||||||
binding.withSameSource(type, AllowedBindingKind::Supertypes));
|
binding.withSameSource(type, BindingKind::Supertypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infer transitive protocol requirements.
|
// Infer transitive protocol requirements.
|
||||||
for (auto *protocol : relatedBindings->getSecond().Protocols) {
|
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();
|
auto &bindings = cachedBindings->getSecond();
|
||||||
|
|
||||||
inferTransitiveSupertypeBindings(cache, bindings);
|
bindings.inferTransitiveBindings(*this, cache);
|
||||||
|
|
||||||
if (isDebugMode()) {
|
if (isDebugMode()) {
|
||||||
bindings.dump(typeVar, llvm::errs(), solverState->depth * 2);
|
bindings.dump(typeVar, llvm::errs(), solverState->depth * 2);
|
||||||
|
|||||||
@@ -4557,6 +4557,23 @@ private:
|
|||||||
/// if it has only concrete types or would resolve a closure.
|
/// if it has only concrete types or would resolve a closure.
|
||||||
bool favoredOverDisjunction(Constraint *disjunction) const;
|
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<TypeVariableType *,
|
||||||
|
ConstraintSystem::PotentialBindings>
|
||||||
|
&inferredBindings);
|
||||||
|
|
||||||
void dump(llvm::raw_ostream &out,
|
void dump(llvm::raw_ostream &out,
|
||||||
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
|
unsigned indent = 0) const LLVM_ATTRIBUTE_USED {
|
||||||
out.indent(indent);
|
out.indent(indent);
|
||||||
@@ -4625,22 +4642,6 @@ private:
|
|||||||
bool &addOptionalSupertypeBindings) const;
|
bool &addOptionalSupertypeBindings) const;
|
||||||
PotentialBindings getPotentialBindings(TypeVariableType *typeVar) 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<TypeVariableType *, PotentialBindings>
|
|
||||||
&inferredBindings,
|
|
||||||
PotentialBindings &bindings);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// Add a constraint to the constraint system.
|
/// Add a constraint to the constraint system.
|
||||||
SolutionKind addConstraintImpl(ConstraintKind kind, Type first, Type second,
|
SolutionKind addConstraintImpl(ConstraintKind kind, Type first, Type second,
|
||||||
|
|||||||
Reference in New Issue
Block a user