Improve application type mismatch error messages

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-09-02 18:28:12 -07:00
parent 72188691de
commit fd44ec8d79
11 changed files with 60 additions and 61 deletions

View file

@ -331,7 +331,7 @@ class elaborator::imp {
modified = true; modified = true;
args[i] = mk_app(coercion, args[i]); args[i] = mk_app(coercion, args[i]);
} else { } else {
throw app_type_mismatch_exception(m_env, ctx, e, i, expected, given); throw app_type_mismatch_exception(m_env, ctx, e, types.size(), types.data());
} }
} }
} }
@ -722,17 +722,6 @@ public:
format pp(formatter & f, options const & o) const { format pp(formatter & f, options const & o) const {
format r; format r;
bool first = true; bool first = true;
for (unsigned i = 0; i < m_metavars.size(); i++) {
metavar_info const & info = m_metavars[i];
expr m = ::lean::mk_metavar(i);
if (first) first = false; else r += line();
format r_assignment;
if (info.m_assignment)
r_assignment = f(info.m_assignment, o);
else
r_assignment = highlight(format("[unassigned]"));
r += group(format{f(m,o), space(), g_assignment_fmt, line(), r_assignment});
}
for (auto c : m_constraints) { for (auto c : m_constraints) {
if (first) first = false; else r += line(); if (first) first = false; else r += line();
r += group(format{f(c.m_lhs, o), space(), g_unification_fmt, line(), f(c.m_rhs, o)}); r += group(format{f(c.m_lhs, o), space(), g_unification_fmt, line(), f(c.m_rhs, o)});

View file

@ -90,22 +90,17 @@ public:
have type get_expected_type(). have type get_expected_type().
*/ */
class app_type_mismatch_exception : public type_checker_exception { class app_type_mismatch_exception : public type_checker_exception {
context m_context; context m_context;
expr m_app; expr m_app;
unsigned m_arg_pos; std::vector<expr> m_arg_types;
expr m_expected_type;
expr m_given_type;
public: public:
app_type_mismatch_exception(environment const & env, context const & ctx, expr const & app, unsigned pos, expr const & expected, expr const & given): app_type_mismatch_exception(environment const & env, context const & ctx, expr const & app, unsigned num, expr const * arg_types):
type_checker_exception(env), m_context(ctx), m_app(app), m_arg_pos(pos), type_checker_exception(env), m_context(ctx), m_app(app), m_arg_types(arg_types, arg_types+num) {}
m_expected_type(expected), m_given_type(given) {}
virtual ~app_type_mismatch_exception() {} virtual ~app_type_mismatch_exception() {}
context const & get_context() const { return m_context; } context const & get_context() const { return m_context; }
expr const & get_application() const { return m_app; } expr const & get_application() const { return m_app; }
virtual expr const & get_main_expr() const { return get_application(); } virtual expr const & get_main_expr() const { return get_application(); }
unsigned get_arg_pos() const { return m_arg_pos; } std::vector<expr> const & get_arg_types() const { return m_arg_types; }
expr const & get_expected_type() const { return m_expected_type; }
expr const & get_given_type() const { return m_given_type; }
virtual char const * what() const noexcept { return "application argument type mismatch"; } virtual char const * what() const noexcept { return "application argument type mismatch"; }
}; };

View file

@ -40,10 +40,6 @@ class type_checker::imp {
throw function_expected_exception(m_env, ctx, s); throw function_expected_exception(m_env, ctx, s);
} }
expr infer_pi(expr const & e, context const & ctx) {
return check_pi(infer_type(e, ctx), e, ctx);
}
public: public:
imp(environment const & env): imp(environment const & env):
m_env(env), m_env(env),
@ -82,15 +78,19 @@ public:
r = mk_type(ty_level(e) + 1); r = mk_type(ty_level(e) + 1);
break; break;
case expr_kind::App: { case expr_kind::App: {
expr f_t = infer_pi(arg(e, 0), ctx);
unsigned i = 1;
unsigned num = num_args(e); unsigned num = num_args(e);
lean_assert(num >= 2); lean_assert(num >= 2);
buffer<expr> arg_types;
for (unsigned i = 0; i < num; i++) {
arg_types.push_back(infer_type(arg(e, i), ctx));
}
expr f_t = check_pi(arg_types[0], e, ctx);
unsigned i = 1;
while (true) { while (true) {
expr const & c = arg(e, i); expr const & c = arg(e, i);
expr c_t = infer_type(c, ctx); expr const & c_t = arg_types[i];
if (!m_normalizer.is_convertible(abst_domain(f_t), c_t, ctx)) if (!m_normalizer.is_convertible(abst_domain(f_t), c_t, ctx))
throw app_type_mismatch_exception(m_env, ctx, e, i, abst_domain(f_t), c_t); throw app_type_mismatch_exception(m_env, ctx, e, arg_types.size(), arg_types.data());
if (closed(abst_body(f_t))) if (closed(abst_body(f_t)))
f_t = abst_body(f_t); f_t = abst_body(f_t);
else if (closed(c)) else if (closed(c))

View file

@ -45,15 +45,26 @@ format formatter::operator()(kernel_exception const & ex, options const & opts)
} else if (app_type_mismatch_exception const * _ex = dynamic_cast<app_type_mismatch_exception const *>(&ex)) { } else if (app_type_mismatch_exception const * _ex = dynamic_cast<app_type_mismatch_exception const *>(&ex)) {
unsigned indent = get_pp_indent(opts); unsigned indent = get_pp_indent(opts);
format app_f = operator()(_ex->get_context(), _ex->get_application(), false, opts); format app_f = operator()(_ex->get_context(), _ex->get_application(), false, opts);
format given_f = operator()(_ex->get_context(), _ex->get_given_type(), false, opts); std::vector<expr> const & arg_types = _ex->get_arg_types();
format expected_f = operator()(_ex->get_context(), _ex->get_expected_type(), false, opts); auto it = arg_types.begin();
unsigned arg_pos = _ex->get_arg_pos(); format f_type_fmt = operator()(_ex->get_context(), *it, false, opts);
return format({format("type mismatch at application argument"), space(), format(arg_pos), space(), format("of"), format arg_types_fmt;
++it;
for (; it != arg_types.end(); ++it) {
format arg_type_fmt = operator()(_ex->get_context(), *it, false, opts);
arg_types_fmt += nest(indent, compose(line(), arg_type_fmt));
}
format arg_type_msg;
if (arg_types.size() > 2)
arg_type_msg = format("arguments types");
else
arg_type_msg = format("argument type");
return format({format("type mismatch at application"),
nest(indent, compose(line(), app_f)), nest(indent, compose(line(), app_f)),
line(), format("expected type"), line(), format("function type"),
nest(indent, compose(line(), expected_f)), nest(indent, compose(line(), f_type_fmt)),
line(), format("given type"), line(), arg_type_msg,
nest(indent, compose(line(), given_f))}); arg_types_fmt});
} else if (function_expected_exception const * _ex = dynamic_cast<function_expected_exception const *>(&ex)) { } else if (function_expected_exception const * _ex = dynamic_cast<function_expected_exception const *>(&ex)) {
unsigned indent = get_pp_indent(opts); unsigned indent = get_pp_indent(opts);
format expr_f = operator()(_ex->get_context(), _ex->get_expr(), false, opts); format expr_f = operator()(_ex->get_context(), _ex->get_expr(), false, opts);

View file

@ -40,12 +40,8 @@ static void success(expr const & e, expr const & expected, frontend const & env)
std::cout << infer_type(elaborate(e, env), env) << "\n"; std::cout << infer_type(elaborate(e, env), env) << "\n";
} catch (app_type_mismatch_exception & ex) { } catch (app_type_mismatch_exception & ex) {
context const & ctx = ex.get_context(); context const & ctx = ex.get_context();
std::cout << "Application type mismatch at argument " << ex.get_arg_pos() << "\n" std::cout << "Application type mismatch at\n"
<< " " << mk_pair(ex.get_application(), ctx) << "\n" << " " << mk_pair(ex.get_application(), ctx) << "\n";
<< "expected type\n"
<< " " << mk_pair(ex.get_expected_type(), ctx) << "\n"
<< "given type\n"
<< " " << mk_pair(ex.get_given_type(), ctx) << "\n";
lean_unreachable(); lean_unreachable();
} }
} }

View file

@ -7,11 +7,12 @@ Error (line: 8, pos: 0) invalid object declaration, environment already has an o
Assumed: b Assumed: b
and a b and a b
Assumed: A Assumed: A
Error (line: 12, pos: 11) type mismatch at application argument 2 of Error (line: 12, pos: 11) type mismatch at application
and a A and a A
expected type function type
Bool -> Bool -> Bool
arguments types
Bool Bool
given type
Type Type
Variable A : Type Variable A : Type
⟨lean::pp::notation ↦ false, pp::colors ↦ false⟩ ⟨lean::pp::notation ↦ false, pp::colors ↦ false⟩

View file

@ -1,3 +1,4 @@
Set pp::colors false
Variable myeq : Pi (A : Type), A -> A -> Bool Variable myeq : Pi (A : Type), A -> A -> Bool
Show myeq _ true false Show myeq _ true false
Variable T : Type Variable T : Type

View file

@ -1,18 +1,23 @@
Set: pp::colors
Assumed: myeq Assumed: myeq
myeq Bool myeq Bool
Assumed: T Assumed: T
Assumed: a Assumed: a
Error (line: 5, pos: 6) type mismatch at application argument 3 of Error (line: 6, pos: 6) type mismatch at application
myeq Bool a myeq Bool a
expected type function type
Π (A : Type) (_ _ : A), Bool
arguments types
Type
Bool Bool
given type
T T
Assumed: myeq2 Assumed: myeq2
Set: lean::pp::implicit Set: lean::pp::implicit
Error (line: 9, pos: 15) type mismatch at application argument 3 of Error (line: 10, pos: 15) type mismatch at application
myeq2::explicit Bool a myeq2::explicit Bool a
expected type function type
Π (A : Type) (a b : A), Bool
arguments types
Type
Bool Bool
given type
T T

View file

@ -4,8 +4,6 @@
Error (line: 5, pos: 40) application type mismatch during term elaboration at term Error (line: 5, pos: 40) application type mismatch during term elaboration at term
f B a f B a
Elaborator state Elaborator state
?M0 := [unassigned]
?M1 := [unassigned]
#0 ≈ lift:0:2 ?M0 #0 ≈ lift:0:2 ?M0
Assumed: myeq Assumed: myeq
myeq (Π (A : Type) (a : A), A) (λ (A : Type) (a : A), a) (λ (B : Type) (b : B), b) myeq (Π (A : Type) (a : A), A) (λ (A : Type) (a : A), a) (λ (B : Type) (b : B), b)

View file

@ -1,3 +1,4 @@
Set pp::colors false
Variable f : Pi A : Type, A -> A -> A Variable f : Pi A : Type, A -> A -> A
Variable N : Type Variable N : Type
Variable g : N -> N -> Bool Variable g : N -> N -> Bool

View file

@ -1,10 +1,12 @@
Set: pp::colors
Assumed: f Assumed: f
Assumed: N Assumed: N
Assumed: g Assumed: g
Assumed: a Assumed: a
Error (line: 5, pos: 6) type mismatch at application argument 1 of Error (line: 6, pos: 6) type mismatch at application
g (f _ a a) g (f _ a a)
expected type function type
N N → N → Bool
given type arguments types
Bool Bool
?M0