feat(frontends/lean/elaborator): decorates error message with free variables introduced by the left-hand-side of the equation
closes #528
This commit is contained in:
parent
4a157ee676
commit
f723550d33
4 changed files with 41 additions and 2 deletions
|
@ -1100,15 +1100,39 @@ expr elaborator::visit_equations(expr const & eqns, constraint_seq & cs) {
|
||||||
optional<expr> first_eq;
|
optional<expr> first_eq;
|
||||||
for (expr const & eq : eqs) {
|
for (expr const & eq : eqs) {
|
||||||
expr new_eq;
|
expr new_eq;
|
||||||
|
constraint_seq new_cs;
|
||||||
|
buffer<expr> fns_locals;
|
||||||
|
fun_to_telescope(m_ngen, eq, fns_locals, optional<binder_info>());
|
||||||
|
list<expr> locals = to_list(fns_locals.begin() + num_fns, fns_locals.end());
|
||||||
if (first_eq) {
|
if (first_eq) {
|
||||||
// Replace first num_fns domains of eq with the ones in first_eq.
|
// Replace first num_fns domains of eq with the ones in first_eq.
|
||||||
// This is a trick/hack to ensure the fns in each equation have
|
// This is a trick/hack to ensure the fns in each equation have
|
||||||
// the same elaborated type.
|
// the same elaborated type.
|
||||||
new_eq = visit(copy_domain(num_fns, *first_eq, eq), cs);
|
new_eq = visit(copy_domain(num_fns, *first_eq, eq), new_cs);
|
||||||
} else {
|
} else {
|
||||||
new_eq = visit(eq, cs);
|
new_eq = visit(eq, new_cs);
|
||||||
first_eq = new_eq;
|
first_eq = new_eq;
|
||||||
}
|
}
|
||||||
|
// To produce more helpful error messages, we decorate all
|
||||||
|
// justifications created when processing eq with the list of local variables declared in the
|
||||||
|
// left-hand-side of the equation.
|
||||||
|
buffer<constraint> tmp_cs;
|
||||||
|
new_cs.linearize(tmp_cs);
|
||||||
|
for (constraint const & c : tmp_cs) {
|
||||||
|
justification j = c.get_justification();
|
||||||
|
auto pp_fn = [=](formatter const & fmt, pos_info_provider const * pp, substitution const & s) {
|
||||||
|
format r = j.pp(fmt, pp, s);
|
||||||
|
r += compose(line(), format("The following identifier(s) are introduced as free variables by the "
|
||||||
|
"left-hand-side of the equation:"));
|
||||||
|
format aux;
|
||||||
|
for (expr const & l : locals)
|
||||||
|
aux += compose(format(local_pp_name(l)), space());
|
||||||
|
r += nest(get_pp_indent(fmt.get_options()), compose(line(), aux));
|
||||||
|
return r;
|
||||||
|
};
|
||||||
|
justification new_j = mk_wrapper(j, j.get_main_expr(), pp_fn);
|
||||||
|
cs += update_justification(c, new_j);
|
||||||
|
}
|
||||||
new_eqs.push_back(new_eq);
|
new_eqs.push_back(new_eq);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
7
tests/lean/528.lean
Normal file
7
tests/lean/528.lean
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
variables {P : bool → Type} {x : P bool.tt} {y : P bool.ff}
|
||||||
|
|
||||||
|
example (b : bool) : P b :=
|
||||||
|
match b with
|
||||||
|
| tt := x
|
||||||
|
| ff := y
|
||||||
|
end
|
6
tests/lean/528.lean.expected.out
Normal file
6
tests/lean/528.lean.expected.out
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
528.lean:6:5: error: type mismatch at definition 'match', has type
|
||||||
|
P bool.ff
|
||||||
|
but is expected to have type
|
||||||
|
P bool.tt
|
||||||
|
The following identifier(s) are introduced as free variables by the left-hand-side of the equation:
|
||||||
|
ff
|
|
@ -6,3 +6,5 @@ has type
|
||||||
Γ ⊢ A ∨ B
|
Γ ⊢ A ∨ B
|
||||||
but is expected to have type
|
but is expected to have type
|
||||||
Γ ⊢ A ∧ B
|
Γ ⊢ A ∧ B
|
||||||
|
The following identifier(s) are introduced as free variables by the left-hand-side of the equation:
|
||||||
|
Γ A B Δ H Hs
|
||||||
|
|
Loading…
Reference in a new issue