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 mk_delayed_coercion(expr const & e, expr const & d_type, expr const & a_type) {
expr a = app_arg(e); expr a = app_arg(e);
expr m = mk_meta(some_expr(d_type), a.get_tag()); 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))); 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); return update_app(e, app_fn(e), m);
} }
@ -803,7 +803,7 @@ public:
} else if (is_meta(a_type) && has_coercions_to(d_type)) { } else if (is_meta(a_type) && has_coercions_to(d_type)) {
return mk_delayed_coercion(r, d_type, a_type); return mk_delayed_coercion(r, d_type, a_type);
} else { } 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)) { 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); expr new_a = apply_coercion(a, a_type, d_type);
bool coercion_worked = false; bool coercion_worked = false;
@ -818,7 +818,7 @@ public:
// rely on unification hints to solve this constraint // rely on unification hints to solve this constraint
add_cnstr(mk_eq_cnstr(a_type, d_type, j.get(), m_relax_main_opaque)); add_cnstr(mk_eq_cnstr(a_type, d_type, j.get(), m_relax_main_opaque));
} else { } 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()); 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 r;
format expected_fmt, given_fmt; format expected_fmt, given_fmt;
std::tie(expected_fmt, given_fmt) = pp_until_different(fmt, expected_type, given_type); std::tie(expected_fmt, given_fmt) = pp_until_different(fmt, expected_type, given_type);
r += format("type mismatch at application"); r += format("type mismatch at application");
r += pp_indent_expr(fmt, app); 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 += expected_fmt;
r += compose(line(), format("given type:")); r += compose(line(), format("but is given type"));
r += given_fmt; r += given_fmt;
return r; 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); std::tie(expected_fmt, given_fmt) = pp_until_different(fmt, expected_type, given_type);
format r("type mismatch at definition '"); format r("type mismatch at definition '");
r += format(n); r += format(n);
r += format("', expected type"); r += format("', it is expected of type");
r += expected_fmt; r += expected_fmt;
r += compose(line(), format("given type:")); r += compose(line(), format("but is given type"));
r += given_fmt; r += given_fmt;
return r; return r;
} }

View file

@ -11,7 +11,7 @@ namespace lean {
format pp_indent_expr(formatter const & fmt, expr const & e); format pp_indent_expr(formatter const & fmt, expr const & e);
format pp_type_expected(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_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_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); 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); 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): app_delayed_justification::app_delayed_justification(expr const & e, expr const & arg, expr const & f_type, expr const & a_type):
m_e(e), m_fn_type(f_type), m_arg_type(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) { auto pp_fn = [=](formatter const & fmt, substitution const & subst) {
substitution s(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); return mk_justification(e, pp_fn);
} }
@ -196,7 +196,7 @@ justification app_delayed_justification::get() {
if (!m_jst) { if (!m_jst) {
// We should not have a reference to this object inside the closure. // 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'. // 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; return *m_jst;
} }
@ -283,11 +283,11 @@ expr type_checker::infer_app(expr const & e, bool infer_only) {
if (!infer_only) { if (!infer_only) {
expr f_type = ensure_pi_core(infer_type_core(app_fn(e), infer_only), e); 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); 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)) { if (!is_def_eq(a_type, binding_domain(f_type), jst)) {
throw_kernel_exception(m_env, e, throw_kernel_exception(m_env, e,
[=](formatter const & fmt) { [=](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)); 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 \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. 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, \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 { class app_delayed_justification : public delayed_justification {
expr const & m_e; expr const & m_e;
expr const & m_arg;
expr const & m_fn_type; expr const & m_fn_type;
expr const & m_arg_type; expr const & m_arg_type;
optional<justification> m_jst; optional<justification> m_jst;
public: 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(); 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 : bool),
p → q → a p → q → a
given type: but is given type
∀ (p q : bool), ∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c) 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 : bool),
p → q → and p p p → q → and p p
given type: but is given type
∀ (p q : bool), ∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c) 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 : bool),
p → q → and q p p → q → and q p
given type: but is given type
∀ (p q : bool), ∀ (p q : bool),
p → q → (∀ (c : bool), (p → q → c) → c) p → q → (∀ (c : bool), (p → q → c) → c)
and_intro : ∀ (p q : bool), p → q → and p q 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 crash.lean:8:12: error: type mismatch at application
have H' : not P, from H, have H' : not P, from H,
_ _
expected type: term
H
is expected of type
not P not P
given type: but is given type
P 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), λ (p q : Prop) (H : (λ (p q : Prop), ∀ (c : Prop), (p → q → c) → c) p q),
H q (λ (H1 : p) (H2 : q), H2) H q (λ (H1 : p) (H2 : q), H2)
in and_intro 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 : Prop),
p → q → (λ (p q : Prop), ∀ (c : Prop), (p → q → c) → c) q p p → q → (λ (p q : Prop), ∀ (c : Prop), (p → q → c) → c) q p
given type: but is given type
∀ (p q : Prop), ∀ (p q : Prop),
p → q → (∀ (c : Prop), (p → q → c) → c) p → q → (∀ (c : Prop), (p → q → c) → c)

View file

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