Track witnesses wherever possible (#2263)

Change explorer's handling of witnesses to track them wherever possible. Associated constant support needs witnesses to be available much more pervasively.

The main changes here are:

-   `Substitute` now takes a set of bindings covering both `Value`s for `GenericBinding`s and `Witness`es for `ImplBinding`s, and substitutes both.
-   Witnesses are now tracked within `ConstraintType`s. The `.Self` type has an `ImplBinding` that self-references from parts of the constraint to other parts of the constraint can use to access the witness for the constraint.
-   The constraint type for an `impl` and for a `GenericBinding` are now stored in pre-substituted form, with references to the actual constrained type rather than symbolic references to `.Self`. This results in minor changes in diagnostic text.

Argument deduction still performs substitutions without remapping witnesses.
This commit is contained in:
Richard Smith
2022-10-11 15:20:23 -07:00
committed by GitHub
parent 05b6c4f310
commit 9feff92f22
30 changed files with 702 additions and 409 deletions
+36 -1
View File
@@ -4,11 +4,46 @@
#include "explorer/ast/bindings.h"
#include "common/error.h"
#include "explorer/ast/impl_binding.h"
#include "explorer/ast/pattern.h"
namespace Carbon {
void Bindings::Add(Nonnull<const GenericBinding*> binding,
Nonnull<const Value*> value,
std::optional<Nonnull<const Value*>> witness) {
bool added_value = args_.insert({binding, value}).second;
CARBON_CHECK(added_value) << "Add of already-existing binding";
if (witness) {
// TODO: Eventually we should check that we have a witness if and only if
// the binding has an impl binding.
auto impl_binding = binding->impl_binding();
CARBON_CHECK(impl_binding) << "Given witness but have no impl binding";
bool added_witness = witnesses_.insert({*impl_binding, *witness}).second;
CARBON_CHECK(added_witness) << "Add of already-existing binding";
}
}
auto Bindings::None() -> Nonnull<const Bindings*> {
static Nonnull<const Bindings*> bindings = new Bindings({}, {});
static Nonnull<const Bindings*> bindings = new Bindings;
return bindings;
}
auto Bindings::SymbolicIdentity(
Nonnull<Arena*> arena,
llvm::ArrayRef<Nonnull<const GenericBinding*>> bindings)
-> Nonnull<const Bindings*> {
auto* result = arena->New<Bindings>();
for (auto* binding : bindings) {
std::optional<Nonnull<const Value*>> witness;
if (binding->impl_binding()) {
witness = *binding->impl_binding().value()->symbolic_identity();
}
result->Add(binding, *binding->symbolic_identity(), witness);
}
return result;
}
} // namespace Carbon