feat(kernel/error_msgs): improve application type mismatch error messages

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2014-07-28 07:08:12 -07:00
parent 555425539d
commit 5f360cd8ec
9 changed files with 40 additions and 30 deletions

View file

@ -743,7 +743,7 @@ public:
expr mk_delayed_coercion(expr const & e, expr const & d_type, expr const & a_type) {
expr a = app_arg(e);
expr m = mk_meta(some_expr(d_type), a.get_tag());
justification j = mk_app_justification(e, d_type, a_type);
justification j = mk_app_justification(e, a, d_type, a_type);
add_cnstr(mk_delayed_coercion_cnstr(m, a, a_type, j, to_delay_factor(cnstr_group::Basic)));
return update_app(e, app_fn(e), m);
}
@ -803,7 +803,7 @@ public:
} else if (is_meta(a_type) && has_coercions_to(d_type)) {
return mk_delayed_coercion(r, d_type, a_type);
} else {
app_delayed_justification j(r, f_type, a_type);
app_delayed_justification j(r, a, f_type, a_type);
if (!m_tc[m_relax_main_opaque]->is_def_eq(a_type, d_type, j)) {
expr new_a = apply_coercion(a, a_type, d_type);
bool coercion_worked = false;
@ -818,7 +818,7 @@ public:
// rely on unification hints to solve this constraint
add_cnstr(mk_eq_cnstr(a_type, d_type, j.get(), m_relax_main_opaque));
} else {
throw_kernel_exception(m_env, r, [=](formatter const & fmt) { return pp_app_type_mismatch(fmt, e, d_type, a_type); });
throw_kernel_exception(m_env, r, [=](formatter const & fmt) { return pp_app_type_mismatch(fmt, e, a, d_type, a_type); });
}
}
}

View file

@ -47,15 +47,17 @@ std::tuple<format, format> pp_until_different(formatter const & fmt, expr const
return pp_until_different(fmt, e1, e2, get_distinguishing_pp_options());
}
format pp_app_type_mismatch(formatter const & fmt, expr const & app, expr const & expected_type, expr const & given_type) {
format pp_app_type_mismatch(formatter const & fmt, expr const & app, expr const & arg, expr const & expected_type, expr const & given_type) {
format r;
format expected_fmt, given_fmt;
std::tie(expected_fmt, given_fmt) = pp_until_different(fmt, expected_type, given_type);
r += format("type mismatch at application");
r += pp_indent_expr(fmt, app);
r += compose(line(), format("expected type:"));
r += compose(line(), format("term"));
r += pp_indent_expr(fmt, arg);
r += compose(line(), format("is expected of type"));
r += expected_fmt;
r += compose(line(), format("given type:"));
r += compose(line(), format("but is given type"));
r += given_fmt;
return r;
}
@ -65,9 +67,9 @@ format pp_def_type_mismatch(formatter const & fmt, name const & n, expr const &
std::tie(expected_fmt, given_fmt) = pp_until_different(fmt, expected_type, given_type);
format r("type mismatch at definition '");
r += format(n);
r += format("', expected type");
r += format("', it is expected of type");
r += expected_fmt;
r += compose(line(), format("given type:"));
r += compose(line(), format("but is given type"));
r += given_fmt;
return r;
}

View file

@ -11,7 +11,7 @@ namespace lean {
format pp_indent_expr(formatter const & fmt, expr const & e);
format pp_type_expected(formatter const & fmt, expr const & e);
format pp_function_expected(formatter const & fmt, expr const & e);
format pp_app_type_mismatch(formatter const & fmt, expr const & app, expr const & expected_type, expr const & given_type);
format pp_app_type_mismatch(formatter const & fmt, expr const & app, expr const & arg, expr const & expected_type, expr const & given_type);
format pp_def_type_mismatch(formatter const & fmt, name const & n, expr const & expected_type, expr const & given_type);
format pp_decl_has_metavars(formatter const & fmt, name const & n, expr const & e, bool is_type);

View file

@ -181,13 +181,13 @@ void type_checker::check_level(level const & l, expr const & s) {
throw_kernel_exception(m_env, sstream() << "invalid reference to undefined universe level parameter '" << *n2 << "'", s);
}
app_delayed_justification::app_delayed_justification(expr const & e, expr const & f_type, expr const & a_type):
m_e(e), m_fn_type(f_type), m_arg_type(a_type) {}
app_delayed_justification::app_delayed_justification(expr const & e, expr const & arg, expr const & f_type, expr const & a_type):
m_e(e), m_arg(arg), m_fn_type(f_type), m_arg_type(a_type) {}
justification mk_app_justification(expr const & e, expr const & d_type, expr const & a_type) {
justification mk_app_justification(expr const & e, expr const & arg, expr const & d_type, expr const & a_type) {
auto pp_fn = [=](formatter const & fmt, substitution const & subst) {
substitution s(subst);
return pp_app_type_mismatch(fmt, s.instantiate(e), s.instantiate(d_type), s.instantiate(a_type));
return pp_app_type_mismatch(fmt, s.instantiate(e), s.instantiate(arg), s.instantiate(d_type), s.instantiate(a_type));
};
return mk_justification(e, pp_fn);
}
@ -196,7 +196,7 @@ justification app_delayed_justification::get() {
if (!m_jst) {
// We should not have a reference to this object inside the closure.
// So, we create the following locals that will be captured by the closure instead of 'this'.
m_jst = mk_app_justification(m_e, binding_domain(m_fn_type), m_arg_type);
m_jst = mk_app_justification(m_e, m_arg, binding_domain(m_fn_type), m_arg_type);
}
return *m_jst;
}
@ -283,11 +283,11 @@ expr type_checker::infer_app(expr const & e, bool infer_only) {
if (!infer_only) {
expr f_type = ensure_pi_core(infer_type_core(app_fn(e), infer_only), e);
expr a_type = infer_type_core(app_arg(e), infer_only);
app_delayed_justification jst(e, f_type, a_type);
app_delayed_justification jst(e, app_arg(e), f_type, a_type);
if (!is_def_eq(a_type, binding_domain(f_type), jst)) {
throw_kernel_exception(m_env, e,
[=](formatter const & fmt) {
return pp_app_type_mismatch(fmt, e, binding_domain(f_type), a_type);
return pp_app_type_mismatch(fmt, e, app_arg(e), binding_domain(f_type), a_type);
});
}
return instantiate(binding_body(f_type), app_arg(e));

View file

@ -208,7 +208,7 @@ certified_declaration check(environment const & env, declaration const & d, name
\brief Create a justification for an application \c e where the expected type must be \c d_type and
the argument type is \c a_type.
*/
justification mk_app_justification(expr const & e, expr const & d_type, expr const & a_type);
justification mk_app_justification(expr const & e, expr const & arg, expr const & d_type, expr const & a_type);
/**
\brief Create a justification for a application type mismatch,
@ -216,11 +216,12 @@ justification mk_app_justification(expr const & e, expr const & d_type, expr con
*/
class app_delayed_justification : public delayed_justification {
expr const & m_e;
expr const & m_arg;
expr const & m_fn_type;
expr const & m_arg_type;
optional<justification> m_jst;
public:
app_delayed_justification(expr const & e, expr const & f_type, expr const & a_type);
app_delayed_justification(expr const & e, expr const & arg, expr const & f_type, expr const & a_type);
virtual justification get();
};
}

View file

@ -1,19 +1,19 @@
bug1.lean:9:7: error: type mismatch at definition 'and_intro', expected type
bug1.lean:9:7: error: type mismatch at definition 'and_intro', it is expected of type
∀ (p q : bool),
p → q → a
given type:
but is given type
∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c)
bug1.lean:13:7: error: type mismatch at definition 'and_intro', expected type
bug1.lean:13:7: error: type mismatch at definition 'and_intro', it is expected of type
∀ (p q : bool),
p → q → and p p
given type:
but is given type
∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c)
bug1.lean:17:7: error: type mismatch at definition 'and_intro', expected type
bug1.lean:17:7: error: type mismatch at definition 'and_intro', it is expected of type
∀ (p q : bool),
p → q → and q p
given type:
but is given type
∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c)
and_intro : ∀ (p q : bool), p → q → and p q

View file

@ -1,7 +1,9 @@
crash.lean:8:12: error: type mismatch at application
have H' : not P, from H,
_
expected type:
term
H
is expected of type
not P
given type:
but is given type
P

View file

@ -27,9 +27,12 @@ let1.lean:16:10: error: type mismatch at application
λ (p q : Prop) (H : (λ (p q : Prop), ∀ (c : Prop), (p → q → c) → c) p q),
H q (λ (H1 : p) (H2 : q), H2)
in and_intro
expected type:
term
λ (p q : Prop) (H1 : p) (H2 : q) (c : Prop) (H : p → q → c),
H H1 H2
is expected of type
∀ (p q : Prop),
p → q → (λ (p q : Prop), ∀ (c : Prop), (p → q → c) → c) q p
given type:
but is given type
∀ (p q : Prop),
p → q → (∀ (c : Prop), (p → q → c) → c)

View file

@ -1,9 +1,11 @@
ite (and p q) (f x) y : N
t10.lean:14:6: error: type mismatch at application
ite (and p q) q
expected type:
term
q
is expected of type
N
given type:
but is given type
B
cons x (cons y (cons z (cons x (cons y (cons y nil))))) : list
cons x nil : list