feat(frontends/lean): improve error message for placeholder that can't be synthesized

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-07-13 22:35:57 +01:00
parent 943092eaf0
commit bdfd219246

View file

@ -267,7 +267,7 @@ class elaborator {
This is a helper class for implementing this choice function. This is a helper class for implementing this choice function.
*/ */
struct class_elaborator : public choice_elaborator { struct placeholder_elaborator : public choice_elaborator {
elaborator & m_elab; elaborator & m_elab;
expr m_mvar; expr m_mvar;
expr m_mvar_type; // elaborated type of the metavariable expr m_mvar_type; // elaborated type of the metavariable
@ -277,7 +277,7 @@ class elaborator {
substitution m_subst; substitution m_subst;
justification m_jst; justification m_jst;
class_elaborator(elaborator & elab, expr const & mvar, expr const & mvar_type, placeholder_elaborator(elaborator & elab, expr const & mvar, expr const & mvar_type,
list<expr> const & local_insts, list<name> const & instances, bool has_tactic_hints, list<expr> const & local_insts, list<name> const & instances, bool has_tactic_hints,
context const & ctx, substitution const & s, justification const & j): context const & ctx, substitution const & s, justification const & j):
choice_elaborator(has_tactic_hints), choice_elaborator(has_tactic_hints),
@ -523,6 +523,22 @@ public:
return is_class(type); return is_class(type);
} }
/** \brief Return a 'failed to synthesize placholder' justification for the given
metavariable application \c m of the form (?m l_1 ... l_k) */
justification mk_failed_to_synthesize_jst(expr const & m) {
environment env = m_env;
return mk_justification(m, [=](formatter const & fmt, substitution const & subst) {
buffer<expr> locals;
expr mvar = get_app_args(m, locals);
mvar = update_mlocal(mvar, subst.instantiate(mlocal_type(mvar)));
for (auto & local : locals) local = subst.instantiate(local);
expr new_m = ::lean::mk_app(mvar, locals);
expr new_type = type_checker(env).infer(new_m);
proof_state ps(goals(goal(new_m, new_type)), substitution(), name_generator("dontcare"));
return format({format("failed to synthesize placeholder"), line(), ps.pp(fmt)});
});
}
/** \brief Create a metavariable, but also add a class-constraint if type is a class /** \brief Create a metavariable, but also add a class-constraint if type is a class
or a metavariable. or a metavariable.
*/ */
@ -530,7 +546,7 @@ public:
expr m = mk_meta(type, g); expr m = mk_meta(type, g);
if (!type || may_be_class(*type)) { if (!type || may_be_class(*type)) {
context ctx = m_ctx; context ctx = m_ctx;
justification j = mk_justification("failed to apply class instances", some_expr(m)); justification j = mk_failed_to_synthesize_jst(m);
auto choice_fn = [=](expr const & mvar, expr const & mvar_type, substitution const & s, name_generator const & /* ngen */) { auto choice_fn = [=](expr const & mvar, expr const & mvar_type, substitution const & s, name_generator const & /* ngen */) {
if (!is_class(mvar_type)) if (!is_class(mvar_type))
return lazy_list<constraints>(constraints()); return lazy_list<constraints>(constraints());
@ -553,7 +569,7 @@ public:
return lazy_list<constraints>(constraints()); return lazy_list<constraints>(constraints());
} else { } else {
bool has_tactic_hints = !empty(get_tactic_hints(m_env, const_name(get_app_fn(mvar_type)))); bool has_tactic_hints = !empty(get_tactic_hints(m_env, const_name(get_app_fn(mvar_type))));
return choose(std::make_shared<class_elaborator>(*this, mvar, mvar_type, local_insts, insts, has_tactic_hints, return choose(std::make_shared<placeholder_elaborator>(*this, mvar, mvar_type, local_insts, insts, has_tactic_hints,
ctx, s, j)); ctx, s, j));
} }
}; };