diff --git a/src/frontends/lean/elaborator.cpp b/src/frontends/lean/elaborator.cpp index 7e491e6bd3..50c06beb3f 100644 --- a/src/frontends/lean/elaborator.cpp +++ b/src/frontends/lean/elaborator.cpp @@ -1840,33 +1840,35 @@ void elaborator::synthesize_numeral_types() { m_numeral_types = list(); } -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 to_keep; buffer> 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 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); } diff --git a/src/frontends/lean/elaborator.h b/src/frontends/lean/elaborator.h index 1d94cb7479..5869e870f6 100644 --- a/src/frontends/lean/elaborator.h +++ b/src/frontends/lean/elaborator.h @@ -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(); diff --git a/tests/lean/synth_inferred_mismatch.lean b/tests/lean/synth_inferred_mismatch.lean new file mode 100644 index 0000000000..3e8d970231 --- /dev/null +++ b/tests/lean/synth_inferred_mismatch.lean @@ -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)) diff --git a/tests/lean/synth_inferred_mismatch.lean.expected.out b/tests/lean/synth_inferred_mismatch.lean.expected.out new file mode 100644 index 0000000000..a85a9db497 --- /dev/null +++ b/tests/lean/synth_inferred_mismatch.lean.expected.out @@ -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