fix(frontends/lean/elaborator): fixes #724
This commit is contained in:
parent
7e0844a9e6
commit
b0c56273e2
2 changed files with 47 additions and 11 deletions
|
@ -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
18
tests/lean/run/724.lean
Normal 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
|
Loading…
Reference in a new issue