Improve application type mismatch error messages
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
72188691de
commit
fd44ec8d79
11 changed files with 60 additions and 61 deletions
|
@ -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)});
|
||||||
|
|
|
@ -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"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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⟩
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue