fix(kernel/type_checker): bug in quick_is_conv, it was not converting free variables to local constants.
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
7eb9496643
commit
4be4f21de6
2 changed files with 39 additions and 13 deletions
|
@ -12,7 +12,7 @@ Author: Leonardo de Moura
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
|
expr instantiate(expr const & a, unsigned s, unsigned n, expr const * subst) {
|
||||||
if (s >= get_free_var_range(a))
|
if (s >= get_free_var_range(a) || n == 0)
|
||||||
return a;
|
return a;
|
||||||
return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
|
return replace(a, [=](expr const & m, unsigned offset) -> optional<expr> {
|
||||||
unsigned s1 = s + offset;
|
unsigned s1 = s + offset;
|
||||||
|
|
|
@ -299,6 +299,42 @@ struct type_checker::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Given lambda/Pi expressions \c t and \c s, return true iff \c t is convertible to \c s.
|
||||||
|
|
||||||
|
The argument \c def_eq is used to decide whether the body of the binder is checked for
|
||||||
|
definitional equality or convertability.
|
||||||
|
|
||||||
|
If t and s are lambda expressions, then then t is convertible to s
|
||||||
|
iff
|
||||||
|
domain(t) is definitionally equal to domain(s)
|
||||||
|
and
|
||||||
|
body(t) is definitionally equal to body(s)
|
||||||
|
|
||||||
|
For Pi expressions, it is slighly different.
|
||||||
|
If t and s are Pi expressions, then then t is convertible to s
|
||||||
|
iff
|
||||||
|
domain(t) is definitionally equal to domain(s)
|
||||||
|
and
|
||||||
|
body(t) is convertible to body(s)
|
||||||
|
*/
|
||||||
|
bool is_conv_binder(expr t, expr s, bool def_eq) {
|
||||||
|
lean_assert(t.kind() == s.kind());
|
||||||
|
lean_assert(is_binder(t));
|
||||||
|
expr_kind k = t.kind();
|
||||||
|
buffer<expr> subst;
|
||||||
|
do {
|
||||||
|
expr var_t_type = instantiate(binder_domain(t), subst.size(), subst.data());
|
||||||
|
expr var_s_type = instantiate(binder_domain(s), subst.size(), subst.data());
|
||||||
|
if (!is_def_eq(var_t_type, var_s_type))
|
||||||
|
return false;
|
||||||
|
subst.push_back(mk_local(m_gen.next(), var_s_type));
|
||||||
|
t = binder_body(t);
|
||||||
|
s = binder_body(s);
|
||||||
|
} while (t.kind() == k && s.kind() == k);
|
||||||
|
return is_conv(instantiate(t, subst.size(), subst.data()), instantiate(s, subst.size(), subst.data()), def_eq);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
\brief This is an auxiliary method for is_conv. It handles the "easy cases".
|
\brief This is an auxiliary method for is_conv. It handles the "easy cases".
|
||||||
|
|
||||||
|
@ -318,19 +354,9 @@ struct type_checker::imp {
|
||||||
if (t.kind() == s.kind()) {
|
if (t.kind() == s.kind()) {
|
||||||
switch (t.kind()) {
|
switch (t.kind()) {
|
||||||
case expr_kind::Lambda:
|
case expr_kind::Lambda:
|
||||||
// t and s are lambda expression, then then t is convertible to s
|
return to_lbool(is_conv_binder(t, s, true));
|
||||||
// iff
|
|
||||||
// domain(t) is definitionally equal to domain(s)
|
|
||||||
// and
|
|
||||||
// body(t) is definitionally equal to body(s)
|
|
||||||
return to_lbool(is_def_eq(binder_domain(t), binder_domain(s)) && is_def_eq(binder_body(t), binder_body(s)));
|
|
||||||
case expr_kind::Pi:
|
case expr_kind::Pi:
|
||||||
// t and s are Pi expressions, then then t is convertible to s
|
return to_lbool(is_conv_binder(t, s, def_eq));
|
||||||
// iff
|
|
||||||
// domain(t) is definitionally equal to domain(s)
|
|
||||||
// and
|
|
||||||
// body(t) is convertible to body(s)
|
|
||||||
return to_lbool(is_def_eq(binder_domain(t), binder_domain(s)) && is_conv(binder_body(t), binder_body(s), def_eq));
|
|
||||||
case expr_kind::Sort:
|
case expr_kind::Sort:
|
||||||
// t and s are Sorts
|
// t and s are Sorts
|
||||||
if (is_trivial(sort_level(t), sort_level(s)) && (!def_eq || is_trivial(sort_level(s), sort_level(t))))
|
if (is_trivial(sort_level(t), sort_level(s)) && (!def_eq || is_trivial(sort_level(s), sort_level(t))))
|
||||||
|
|
Loading…
Reference in a new issue