[ConstraintSystem] Use originating constraint as a source for a binding

Unify all of the fields of `PotentialBinding` which have to do with
location information into a single field with is either a constraint
(for regular bindings) or constraint locator (for "holes").

This helps to reduce the amount of space used by `PotentialBinding`
 as well as propagate more contextual information when binding gets
 attempted.
This commit is contained in:
Pavel Yaskevich
2019-12-11 16:30:35 -08:00
parent 9cbc761a89
commit bb51a8f97d
2 changed files with 91 additions and 52 deletions

View File

@@ -3288,28 +3288,72 @@ private:
/// The kind of bindings permitted.
AllowedBindingKind Kind;
/// The kind of the constraint this binding came from.
ConstraintKind BindingSource;
/// The defaulted protocol associated with this binding.
ProtocolDecl *DefaultedProtocol;
/// If this is a binding that comes from a \c Defaultable constraint,
/// the locator of that constraint.
ConstraintLocator *DefaultableBinding = nullptr;
protected:
/// The source of the type information.
///
/// Determines whether this binding represents a "hole" in
/// constraint system. Such bindings have no originating constraint
/// because they are synthetic, they have a locator instead.
PointerUnion<Constraint *, ConstraintLocator *> BindingSource;
PotentialBinding(Type type, AllowedBindingKind kind,
ConstraintKind bindingSource,
ProtocolDecl *defaultedProtocol = nullptr,
ConstraintLocator *defaultableBinding = nullptr)
PointerUnion<Constraint *, ConstraintLocator *> source)
: BindingType(type->getWithoutParens()), Kind(kind),
BindingSource(bindingSource), DefaultedProtocol(defaultedProtocol),
DefaultableBinding(defaultableBinding) {}
BindingSource(source) {}
bool isDefaultableBinding() const { return DefaultableBinding != nullptr; }
public:
PotentialBinding(Type type, AllowedBindingKind kind, Constraint *source)
: BindingType(type->getWithoutParens()), Kind(kind),
BindingSource(source) {}
bool isDefaultableBinding() const {
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
return constraint->getKind() == ConstraintKind::Defaultable;
// If binding source is not constraint - it's a hole, which is
// a last resort default binding for a type variable.
return true;
}
bool hasDefaultedLiteralProtocol() const {
return bool(getDefaultedLiteralProtocol());
}
ProtocolDecl *getDefaultedLiteralProtocol() const {
auto *constraint = BindingSource.dyn_cast<Constraint *>();
if (!constraint)
return nullptr;
return constraint->getKind() == ConstraintKind::LiteralConformsTo
? constraint->getProtocol()
: nullptr;
}
ConstraintKind getSourceKind() const {
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
return constraint->getKind();
// If binding source is not constraint - it's a hole which is
// always a `Bind` constraint.
return ConstraintKind::Bind;
}
ConstraintLocator *getLocator() const {
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
return constraint->getLocator();
return BindingSource.get<ConstraintLocator *>();
}
PotentialBinding withType(Type type) const {
return {type, Kind, BindingSource, DefaultedProtocol, DefaultableBinding};
return {type, Kind, BindingSource};
}
PotentialBinding withSameSource(Type type, AllowedBindingKind kind) {
return {type, Kind, BindingSource};
}
static PotentialBinding forHole(ASTContext &ctx,
ConstraintLocator *locator) {
return {ctx.TheUnresolvedType, AllowedBindingKind::Exact,
/*source=*/locator};
}
};
@@ -3464,9 +3508,8 @@ private:
out << "(supertypes of) ";
break;
}
if (binding.DefaultedProtocol)
out << "(default from "
<< binding.DefaultedProtocol->getName() << ") ";
if (auto *literal = binding.getDefaultedLiteralProtocol())
out << "(default from " << literal->getName() << ") ";
out << type.getString(PO);
},
[&]() { out << "; "; });
@@ -4196,7 +4239,9 @@ public:
bool isDefaultable() const { return Binding.isDefaultableBinding(); }
bool hasDefaultedProtocol() const { return Binding.DefaultedProtocol; }
bool hasDefaultedProtocol() const {
return Binding.hasDefaultedLiteralProtocol();
}
bool attempt(ConstraintSystem &cs) const;