|
|
@@ -48,13 +48,10 @@ struct TypeChecker::SingleStepEqualityContext : public EqualityContext {
|
|
|
}
|
|
|
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
- Nonnull<const Expression*> witness_expr,
|
|
|
+ Nonnull<const Witness*> witness,
|
|
|
impl_scope_->Resolve(&assoc->interface(), &assoc->base(), source_loc,
|
|
|
*type_checker_));
|
|
|
- CARBON_ASSIGN_OR_RETURN(Nonnull<const Value*> witness_value,
|
|
|
- InterpExp(witness_expr, type_checker_->arena_,
|
|
|
- type_checker_->trace_stream_));
|
|
|
- impl_witness = dyn_cast<ImplWitness>(witness_value);
|
|
|
+ impl_witness = dyn_cast<ImplWitness>(witness);
|
|
|
if (impl_witness) {
|
|
|
return impl_witness;
|
|
|
}
|
|
|
@@ -1088,6 +1085,7 @@ auto TypeChecker::Substitute(
|
|
|
Nonnull<ImplBinding*> new_ib =
|
|
|
arena_->New<ImplBinding>(ib->source_loc(), bind_map[ib->type_var()],
|
|
|
Substitute(new_dict, ib->interface()));
|
|
|
+ // TODO: Should we set a symbolic identity on this impl binding?
|
|
|
new_ib->set_original(ib->original());
|
|
|
impl_bindings.push_back(new_ib);
|
|
|
}
|
|
|
@@ -1207,7 +1205,7 @@ auto TypeChecker::MatchImpl(const InterfaceType& iface,
|
|
|
const ImplScope::Impl& impl,
|
|
|
const ImplScope& impl_scope,
|
|
|
SourceLocation source_loc) const
|
|
|
- -> std::optional<Nonnull<Expression*>> {
|
|
|
+ -> std::optional<Nonnull<const Witness*>> {
|
|
|
if (trace_stream_) {
|
|
|
**trace_stream_ << "MatchImpl: looking for " << *impl_type << " as "
|
|
|
<< iface << "\n";
|
|
|
@@ -1251,7 +1249,7 @@ auto TypeChecker::MatchImpl(const InterfaceType& iface,
|
|
|
|
|
|
// Ensure the constraints on the `impl` are satisfied by the deduced
|
|
|
// arguments.
|
|
|
- ImplExpMap impls;
|
|
|
+ ImplWitnessMap impls;
|
|
|
if (ErrorOr<Success> e = SatisfyImpls(impl.impl_bindings, impl_scope,
|
|
|
source_loc, deduced_args, impls);
|
|
|
!e.ok()) {
|
|
|
@@ -1265,31 +1263,45 @@ auto TypeChecker::MatchImpl(const InterfaceType& iface,
|
|
|
**trace_stream_ << "matched with " << *impl.type << " as "
|
|
|
<< *impl.interface << "\n\n";
|
|
|
}
|
|
|
- return deduced_args.empty() ? impl.impl
|
|
|
- : arena_->New<InstantiateImpl>(
|
|
|
- source_loc, impl.impl, deduced_args, impls);
|
|
|
+ return deduced_args.empty()
|
|
|
+ ? impl.witness
|
|
|
+ : arena_->New<SymbolicWitness>(arena_->New<InstantiateImpl>(
|
|
|
+ source_loc, impl.witness,
|
|
|
+ Bindings(std::move(deduced_args), std::move(impls))));
|
|
|
}
|
|
|
|
|
|
auto TypeChecker::MakeConstraintWitness(
|
|
|
const ConstraintType& constraint,
|
|
|
- std::vector<Nonnull<Expression*>> impl_constraint_witnesses,
|
|
|
- SourceLocation source_loc) const -> Nonnull<Expression*> {
|
|
|
- return arena_->New<TupleLiteral>(source_loc,
|
|
|
- std::move(impl_constraint_witnesses));
|
|
|
+ std::vector<Nonnull<const Witness*>> impl_constraint_witnesses,
|
|
|
+ SourceLocation source_loc) const -> Nonnull<const Witness*> {
|
|
|
+ // TODO: Create a TupleValue when possible.
|
|
|
+ std::vector<Nonnull<Expression*>> witness_literals;
|
|
|
+ witness_literals.reserve(impl_constraint_witnesses.size());
|
|
|
+ // TODO: A witness expression has no type.
|
|
|
+ auto* witness_type = arena_->New<TypeType>();
|
|
|
+ for (const Witness* witness : impl_constraint_witnesses) {
|
|
|
+ witness_literals.push_back(arena_->New<ValueLiteral>(
|
|
|
+ source_loc, witness, witness_type, ValueCategory::Let));
|
|
|
+ }
|
|
|
+ return arena_->New<SymbolicWitness>(
|
|
|
+ arena_->New<TupleLiteral>(source_loc, std::move(witness_literals)));
|
|
|
}
|
|
|
|
|
|
-auto TypeChecker::MakeConstraintWitnessAccess(Nonnull<Expression*> witness,
|
|
|
+auto TypeChecker::MakeConstraintWitnessAccess(Nonnull<const Witness*> witness,
|
|
|
size_t impl_offset) const
|
|
|
- -> Nonnull<Expression*> {
|
|
|
- return arena_->New<IndexExpression>(
|
|
|
- witness->source_loc(), witness,
|
|
|
- arena_->New<IntLiteral>(witness->source_loc(), impl_offset));
|
|
|
+ -> Nonnull<const Witness*> {
|
|
|
+ SourceLocation no_source_loc("", 0);
|
|
|
+ return arena_->New<SymbolicWitness>(arena_->New<IndexExpression>(
|
|
|
+ no_source_loc,
|
|
|
+ const_cast<Expression*>(
|
|
|
+ &cast<SymbolicWitness>(witness)->impl_expression()),
|
|
|
+ arena_->New<IntLiteral>(no_source_loc, impl_offset)));
|
|
|
}
|
|
|
|
|
|
auto TypeChecker::SatisfyImpls(
|
|
|
llvm::ArrayRef<Nonnull<const ImplBinding*>> impl_bindings,
|
|
|
const ImplScope& impl_scope, SourceLocation source_loc,
|
|
|
- const BindingMap& deduced_type_args, ImplExpMap& impls) const
|
|
|
+ const BindingMap& deduced_type_args, ImplWitnessMap& impls) const
|
|
|
-> ErrorOr<Success> {
|
|
|
for (Nonnull<const ImplBinding*> impl_binding : impl_bindings) {
|
|
|
Nonnull<const Value*> interface =
|
|
|
@@ -1297,11 +1309,11 @@ auto TypeChecker::SatisfyImpls(
|
|
|
CARBON_CHECK(deduced_type_args.find(impl_binding->type_var()) !=
|
|
|
deduced_type_args.end());
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
- Nonnull<Expression*> impl,
|
|
|
+ Nonnull<const Value*> impl,
|
|
|
impl_scope.Resolve(interface,
|
|
|
deduced_type_args.at(impl_binding->type_var()),
|
|
|
source_loc, *this));
|
|
|
- impls.emplace(impl_binding, impl);
|
|
|
+ impls.insert({impl_binding, impl});
|
|
|
}
|
|
|
return Success();
|
|
|
}
|
|
|
@@ -1377,7 +1389,6 @@ auto TypeChecker::DeduceCallBindings(
|
|
|
CARBON_CHECK(generic_params.empty())
|
|
|
<< "did not find all generic parameters in parameter list";
|
|
|
|
|
|
- call.set_deduced_args(generic_bindings);
|
|
|
for (Nonnull<const GenericBinding*> deduced_param : deduced_bindings) {
|
|
|
// TODO: change the following to a CHECK once the real checking
|
|
|
// has been added to the type checking of function signatures.
|
|
|
@@ -1391,15 +1402,16 @@ auto TypeChecker::DeduceCallBindings(
|
|
|
}
|
|
|
|
|
|
// Find impls for all the required impl bindings.
|
|
|
- ImplExpMap impls;
|
|
|
+ ImplWitnessMap impls;
|
|
|
CARBON_RETURN_IF_ERROR(SatisfyImpls(
|
|
|
impl_bindings, impl_scope, call.source_loc(), generic_bindings, impls));
|
|
|
- call.set_impls(impls);
|
|
|
+ call.set_bindings(Bindings(std::move(generic_bindings), std::move(impls)));
|
|
|
|
|
|
// TODO: Ensure any equality constraints are satisfied.
|
|
|
|
|
|
// Convert the arguments to the parameter type.
|
|
|
- Nonnull<const Value*> param_type = Substitute(generic_bindings, params_type);
|
|
|
+ Nonnull<const Value*> param_type =
|
|
|
+ Substitute(call.bindings().args(), params_type);
|
|
|
|
|
|
// Convert the arguments to the deduced and substituted parameter type.
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
@@ -1661,7 +1673,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
|
|
|
access.set_static_type(inst_member_type);
|
|
|
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
- Nonnull<Expression*> impl,
|
|
|
+ Nonnull<const Witness*> impl,
|
|
|
impl_scope.Resolve(result.interface, &object_type,
|
|
|
e->source_loc(), *this));
|
|
|
access.set_impl(impl);
|
|
|
@@ -1684,7 +1696,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
|
|
|
ConstraintLookupResult result,
|
|
|
LookupInConstraint(e->source_loc(), "member access", &object_type,
|
|
|
access.member_name()));
|
|
|
- CARBON_ASSIGN_OR_RETURN(Nonnull<Expression*> impl,
|
|
|
+ CARBON_ASSIGN_OR_RETURN(Nonnull<const Witness*> impl,
|
|
|
impl_scope.Resolve(result.interface, type,
|
|
|
e->source_loc(), *this));
|
|
|
access.set_member(Member(result.member));
|
|
|
@@ -1884,7 +1896,7 @@ auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e,
|
|
|
if (std::optional<Nonnull<const Value*>> iface =
|
|
|
member_name.interface()) {
|
|
|
CARBON_ASSIGN_OR_RETURN(
|
|
|
- Nonnull<Expression*> impl,
|
|
|
+ Nonnull<const Witness*> impl,
|
|
|
impl_scope.Resolve(*iface, *base_type, e->source_loc(), *this));
|
|
|
access.set_impl(impl);
|
|
|
}
|
|
|
@@ -2652,20 +2664,21 @@ void TypeChecker::BringImplsIntoScope(
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-auto TypeChecker::CreateImplReference(Nonnull<const ImplBinding*> impl_binding)
|
|
|
- -> Nonnull<Expression*> {
|
|
|
+auto TypeChecker::CreateImplBindingWitness(
|
|
|
+ Nonnull<const ImplBinding*> impl_binding) -> Nonnull<const Witness*> {
|
|
|
auto impl_id =
|
|
|
arena_->New<IdentifierExpression>(impl_binding->source_loc(), "impl");
|
|
|
impl_id->set_value_node(impl_binding);
|
|
|
- return impl_id;
|
|
|
+ return arena_->New<SymbolicWitness>(impl_id);
|
|
|
}
|
|
|
|
|
|
void TypeChecker::BringImplIntoScope(Nonnull<const ImplBinding*> impl_binding,
|
|
|
ImplScope& impl_scope) {
|
|
|
- CARBON_CHECK(impl_binding->type_var()->symbolic_identity().has_value());
|
|
|
+ CARBON_CHECK(impl_binding->type_var()->symbolic_identity().has_value() &&
|
|
|
+ impl_binding->symbolic_identity().has_value());
|
|
|
impl_scope.Add(impl_binding->interface(),
|
|
|
*impl_binding->type_var()->symbolic_identity(),
|
|
|
- CreateImplReference(impl_binding), *this);
|
|
|
+ cast<Witness>(*impl_binding->symbolic_identity()), *this);
|
|
|
}
|
|
|
|
|
|
auto TypeChecker::TypeCheckTypeExp(Nonnull<Expression*> type_expression,
|
|
|
@@ -2804,7 +2817,7 @@ auto TypeChecker::TypeCheckPattern(
|
|
|
Nonnull<ImplBinding*> impl_binding =
|
|
|
arena_->New<ImplBinding>(binding.source_loc(), &binding, type);
|
|
|
impl_binding->set_symbolic_identity(
|
|
|
- arena_->New<SymbolicWitness>(CreateImplReference(impl_binding)));
|
|
|
+ CreateImplBindingWitness(impl_binding));
|
|
|
binding.set_impl_binding(impl_binding);
|
|
|
BringImplIntoScope(impl_binding, impl_scope);
|
|
|
}
|
|
|
@@ -3783,11 +3796,7 @@ auto TypeChecker::CheckAndAddImplBindings(
|
|
|
impl_decl->deduced_parameters().end());
|
|
|
|
|
|
// An expression that evaluates to this impl's witness.
|
|
|
- // TODO: Store witnesses as `Witness*` rather than `Expression*` everywhere
|
|
|
- // so we don't need to create this.
|
|
|
- auto* impl_expr = arena_->New<ValueLiteral>(
|
|
|
- impl_decl->source_loc(), arena_->New<ImplWitness>(impl_decl),
|
|
|
- arena_->New<TypeType>(), ValueCategory::Let);
|
|
|
+ auto* witness = arena_->New<ImplWitness>(impl_decl);
|
|
|
|
|
|
// Form the resolved constraint type by substituting `Self` for `.Self`.
|
|
|
Nonnull<const Value*> self = *impl_decl->self()->constant_value();
|
|
|
@@ -3818,7 +3827,7 @@ auto TypeChecker::CheckAndAddImplBindings(
|
|
|
|
|
|
scope_info.innermost_non_class_scope->Add(
|
|
|
iface_type, deduced_bindings, impl_type, impl_decl->impl_bindings(),
|
|
|
- impl_expr, *this);
|
|
|
+ witness, *this);
|
|
|
} else {
|
|
|
// TODO: Add support for implementing `adapter`s.
|
|
|
return CompilationError(impl_decl->source_loc())
|