Build value representations for all kinds of witness (#2250)

Instead of forming a `SymbolicWitness` that contains an `Expression` when we can't directly resolve a witness to an `impl`, form different kinds of `Witness` values for the various situations:

- A `BindingWitness` witnesses that a type implements a constraint by reference to an `ImplBinding`.
- A `ConstraintWitness` witnesses that a type implements a constraint by reference to witnesses for each of the impl constraints within the constraint.
- A `ConstraintImplWitness` witnesses that a type implements a constraint by reference to a larger constraint which contains that constraint as an impl constraint.

Remove `SymbolicWitness` values and `InstantiateImpl` expressions, which are now unused. In order to remove the final usage of `SymbolicWitness`, I fixed a TODO to give `Self` the proper type within an interface declaration. I don't think this is an observable change.

No functional change intended.
This commit is contained in:
Richard Smith
2022-10-04 12:14:52 -07:00
committed by GitHub
parent 8e8e8ced60
commit 2340cb6703
13 changed files with 260 additions and 188 deletions
+44 -31
View File
@@ -50,34 +50,27 @@ static auto GetMember(Nonnull<Arena*> arena, Nonnull<const Value*> v,
}
// Associated functions.
switch (witness->kind()) {
case Value::Kind::ImplWitness: {
auto* impl_witness = cast<ImplWitness>(witness);
if (std::optional<Nonnull<const Declaration*>> mem_decl =
FindMember(f, impl_witness->declaration().members());
mem_decl.has_value()) {
const auto& fun_decl = cast<FunctionDeclaration>(**mem_decl);
if (fun_decl.is_method()) {
return arena->New<BoundMethodValue>(&fun_decl, v,
&impl_witness->bindings());
} else {
// Class function.
auto* fun = cast<FunctionValue>(*fun_decl.constant_value());
return arena->New<FunctionValue>(&fun->declaration(),
&impl_witness->bindings());
}
if (auto* impl_witness = dyn_cast<ImplWitness>(witness)) {
if (std::optional<Nonnull<const Declaration*>> mem_decl =
FindMember(f, impl_witness->declaration().members());
mem_decl.has_value()) {
const auto& fun_decl = cast<FunctionDeclaration>(**mem_decl);
if (fun_decl.is_method()) {
return arena->New<BoundMethodValue>(&fun_decl, v,
&impl_witness->bindings());
} else {
return CompilationError(source_loc)
<< "member " << f << " not in " << *witness;
// Class function.
auto* fun = cast<FunctionValue>(*fun_decl.constant_value());
return arena->New<FunctionValue>(&fun->declaration(),
&impl_witness->bindings());
}
} else {
return CompilationError(source_loc)
<< "member " << f << " not in " << *witness;
}
case Value::Kind::SymbolicWitness: {
return RuntimeError(source_loc)
<< "member lookup for " << f << " in symbolic " << *witness
<< " not implemented yet";
}
default:
CARBON_FATAL() << "expected Witness, not " << *witness;
} else {
return RuntimeError(source_loc)
<< "member lookup for " << f << " in symbolic " << *witness;
}
}
switch (v->kind()) {
@@ -455,13 +448,29 @@ void Value::Print(llvm::raw_ostream& out) const {
}
case Value::Kind::ImplWitness: {
const auto& witness = cast<ImplWitness>(*this);
out << "witness " << *witness.declaration().impl_type() << " as "
out << "witness for impl " << *witness.declaration().impl_type() << " as "
<< witness.declaration().interface();
break;
}
case Value::Kind::SymbolicWitness: {
const auto& witness = cast<SymbolicWitness>(*this);
out << "witness " << witness.impl_expression();
case Value::Kind::BindingWitness: {
const auto& witness = cast<BindingWitness>(*this);
out << "witness for " << *witness.binding()->type_var();
break;
}
case Value::Kind::ConstraintWitness: {
const auto& witness = cast<ConstraintWitness>(*this);
out << "(";
llvm::ListSeparator sep;
for (auto* elem : witness.witnesses()) {
out << sep << *elem;
}
out << ")";
break;
}
case Value::Kind::ConstraintImplWitness: {
const auto& witness = cast<ConstraintImplWitness>(*this);
out << "witness " << witness.index() << " of "
<< *witness.constraint_witness();
break;
}
case Value::Kind::ParameterizedEntityName:
@@ -767,7 +776,9 @@ auto TypeEqual(Nonnull<const Value*> t1, Nonnull<const Value*> t2,
<< *t1 << "\n"
<< *t2;
case Value::Kind::ImplWitness:
case Value::Kind::SymbolicWitness:
case Value::Kind::BindingWitness:
case Value::Kind::ConstraintWitness:
case Value::Kind::ConstraintImplWitness:
CARBON_FATAL() << "TypeEqual: unexpected Witness";
break;
case Value::Kind::AutoType:
@@ -868,7 +879,9 @@ auto ValueStructurallyEqual(
case Value::Kind::InterfaceType:
case Value::Kind::ConstraintType:
case Value::Kind::ImplWitness:
case Value::Kind::SymbolicWitness:
case Value::Kind::BindingWitness:
case Value::Kind::ConstraintWitness:
case Value::Kind::ConstraintImplWitness:
case Value::Kind::ChoiceType:
case Value::Kind::ContinuationType:
case Value::Kind::VariableType: