fix(frontends/lean/elaborator): fixes #724

This commit is contained in:
Leonardo de Moura 2015-07-06 15:19:19 -07:00
parent 7e0844a9e6
commit b0c56273e2
2 changed files with 47 additions and 11 deletions

View file

@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura Author: Leonardo de Moura
*/ */
#include <functional>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include "util/flet.h" #include "util/flet.h"
@ -2053,22 +2054,39 @@ std::tuple<expr, level_param_names> elaborator::apply(substitution & s, expr con
return std::make_tuple(r, to_list(new_ps.begin(), new_ps.end())); return std::make_tuple(r, to_list(new_ps.begin(), new_ps.end()));
} }
struct pos_info_hash {
unsigned operator()(pos_info const & p) const { return hash(p.first, p.second); }
};
void elaborator::check_used_local_tactic_hints() { void elaborator::check_used_local_tactic_hints() {
expr_struct_map<name> pretac2name; std::unordered_set<pos_info, pos_info_hash, std::equal_to<pos_info>> pos_set;
// the same pretac may be processed several times because of choice-exprs // The same pretac may be processed several times because of choice-exprs.
// The pretactics may be structurally different in each branch (because of unique local constant names).
// So, we use their positions to identify which tactic hints were used
if (!pip())
return; // position information is not available
m_local_tactic_hints.for_each([&](name const & n, expr const & e) { m_local_tactic_hints.for_each([&](name const & n, expr const & e) {
if (m_used_local_tactic_hints.contains(n)) if (m_used_local_tactic_hints.contains(n)) {
pretac2name.insert(mk_pair(e, n)); if (auto p = pip()->get_pos_info(e)) {
pos_set.insert(*p);
}
}
}); });
m_local_tactic_hints.for_each([&](name const & n, expr const & e) { m_local_tactic_hints.for_each([&](name const & n, expr const & e) {
if (!m_used_local_tactic_hints.contains(n) && if (m_used_local_tactic_hints.contains(n))
pretac2name.find(e) == pretac2name.end()) { return; // local hint was used
char const * msg = "unnecessary tactic was provided, placeholder was automatically synthesized by the elaborator"; if (auto p = pip()->get_pos_info(e)) {
if (auto it = m_mvar2meta.find(n)) if (pos_set.find(*p) == pos_set.end()) {
throw_elaborator_exception(msg, *it); char const * msg = "unnecessary tactic was provided, placeholder was automatically "
else "synthesized by the elaborator";
throw exception(msg); if (auto it = m_mvar2meta.find(n))
throw_elaborator_exception(msg, *it);
else
throw exception(msg);
}
} }
// Remark: we are ignoring expressions that do not have location information.
// This is a little bit hackish
}); });
} }

18
tests/lean/run/724.lean Normal file
View file

@ -0,0 +1,18 @@
import data.list
open list bool nat
definition filter {A} : list A → (A → bool) → list A
| filter [] p := []
| filter (a :: l) p :=
match p a with
| tt := a :: filter l p
| ff := filter l p
end
example : list := filter [0, 3, 7, 2, 4, 6, 3, 4]
(λ(n : ), begin induction n, exact tt, induction v_0, exact tt, exact ff end)
definition foo : list := filter [0, 3, 7, 2, 4, 6, 3, 4]
(λ(n : ), begin induction n, exact tt, induction v_0, exact tt, exact ff end)
example : foo = [0, 2, 4, 6, 4] := rfl