feat(frontends/lean/elaborator): better error message when there is a mismatch between inferred and synthesized instances
This commit is contained in:
parent
8d51607ea0
commit
6a331e2ab8
4 changed files with 32 additions and 20 deletions
|
|
@ -1840,33 +1840,35 @@ void elaborator::synthesize_numeral_types() {
|
|||
m_numeral_types = list<expr>();
|
||||
}
|
||||
|
||||
bool elaborator::try_synthesize_type_class_instance(expr const & mvar) {
|
||||
expr inst = instantiate_mvars(mvar);
|
||||
if (!has_expr_metavar(inst)) {
|
||||
trace_elab(tout() << "skipping type class resolution at " << pos_string_for(mvar)
|
||||
<< ", placeholder instantiated using type inference\n";);
|
||||
return true;
|
||||
}
|
||||
expr inst_type = instantiate_mvars(infer_type(inst));
|
||||
bool elaborator::synthesize_type_class_instance_core(expr const & mvar, expr const & inferred_inst, expr const & inst_type) {
|
||||
if (has_expr_metavar(inst_type))
|
||||
return false;
|
||||
metavar_decl mdecl = *m_ctx.mctx().get_metavar_decl(mvar);
|
||||
expr ref = mvar;
|
||||
if (!is_def_eq(inst, mk_instance_core(mdecl.get_context(), inst_type, ref)))
|
||||
throw elaborator_exception(mvar, "failed to assign type class instance to placeholder");
|
||||
expr synthesized_inst = mk_instance_core(mdecl.get_context(), inst_type, ref);
|
||||
if (!is_def_eq(inferred_inst, synthesized_inst)) {
|
||||
auto pp_fn = mk_pp_ctx();
|
||||
throw elaborator_exception(mvar,
|
||||
format("synthesized type class instance is not definitionally equal to expression "
|
||||
"inferred by typing rules, synthesized")
|
||||
+ pp_indent(pp_fn, synthesized_inst)
|
||||
+ line() + format("inferred")
|
||||
+ pp_indent(pp_fn, inferred_inst));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool elaborator::try_synthesize_type_class_instance(expr const & mvar) {
|
||||
expr inst = instantiate_mvars(mvar);
|
||||
expr inst_type = instantiate_mvars(infer_type(inst));
|
||||
return synthesize_type_class_instance_core(mvar, inst, inst_type);
|
||||
}
|
||||
|
||||
void elaborator::synthesize_type_class_instances_step() {
|
||||
buffer<expr> to_keep;
|
||||
buffer<std::tuple<expr, expr, expr>> to_process;
|
||||
for (expr const & mvar : m_instances) {
|
||||
expr inst = instantiate_mvars(mvar);
|
||||
if (!has_expr_metavar(inst)) {
|
||||
trace_elab(tout() << "skipping type class resolution at " << pos_string_for(mvar)
|
||||
<< ", placeholder instantiated using type inference\n";);
|
||||
continue;
|
||||
}
|
||||
expr inst = instantiate_mvars(mvar);
|
||||
expr inst_type = instantiate_mvars(infer_type(inst));
|
||||
if (has_expr_metavar(inst_type)) {
|
||||
to_keep.push_back(mvar);
|
||||
|
|
@ -1879,10 +1881,7 @@ void elaborator::synthesize_type_class_instances_step() {
|
|||
expr mvar, inst, inst_type;
|
||||
for (std::tuple<expr, expr, expr> const & curr : to_process) {
|
||||
std::tie(mvar, inst, inst_type) = curr;
|
||||
metavar_decl mdecl = *m_ctx.mctx().get_metavar_decl(mvar);
|
||||
expr ref = mvar;
|
||||
if (!is_def_eq(inst, mk_instance_core(mdecl.get_context(), inst_type, ref)))
|
||||
throw elaborator_exception(mvar, "failed to assign type class instance to placeholder");
|
||||
synthesize_type_class_instance_core(mvar, inst, inst_type);
|
||||
}
|
||||
m_instances = to_list(to_keep);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ private:
|
|||
tactic_state mk_tactic_state_for(expr const & mvar);
|
||||
void invoke_tactic(expr const & mvar, expr const & tac);
|
||||
|
||||
bool synthesize_type_class_instance_core(expr const & mvar, expr const & inferred_inst, expr const & inst_type);
|
||||
bool try_synthesize_type_class_instance(expr const & mvar);
|
||||
void synthesize_numeral_types();
|
||||
void synthesize_type_class_instances_step();
|
||||
|
|
|
|||
8
tests/lean/synth_inferred_mismatch.lean
Normal file
8
tests/lean/synth_inferred_mismatch.lean
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
set_option new_elaborator true
|
||||
|
||||
constant f (c : Prop) [decidable c] : Prop
|
||||
constant fax (c : Prop) [decidable c] : f c
|
||||
attribute [elab_simple] fax
|
||||
|
||||
example (c : Prop) [decidable c] (h : c) : f c :=
|
||||
(fax _ : @f c (is_true h))
|
||||
4
tests/lean/synth_inferred_mismatch.lean.expected.out
Normal file
4
tests/lean/synth_inferred_mismatch.lean.expected.out
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
synth_inferred_mismatch.lean:8:1: error: synthesized type class instance is not definitionally equal to expression inferred by typing rules, synthesized
|
||||
_inst_1
|
||||
inferred
|
||||
is_true h
|
||||
Loading…
Add table
Reference in a new issue