fix(frontends/lean/elaborator): bug when mixing implicit arguments and sections
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
e817260c6d
commit
6b60db7b93
6 changed files with 52 additions and 16 deletions
|
@ -258,7 +258,7 @@ environment definition_cmd_core(parser & p, bool is_theorem, bool _is_opaque) {
|
||||||
type = Pi_as_is(section_ps, type, p);
|
type = Pi_as_is(section_ps, type, p);
|
||||||
value = Fun_as_is(section_ps, value, p);
|
value = Fun_as_is(section_ps, value, p);
|
||||||
levels section_ls = collect_section_levels(ls, p);
|
levels section_ls = collect_section_levels(ls, p);
|
||||||
expr ref = mk_app(mk_explicit(mk_constant(real_n, section_ls)), section_ps);
|
expr ref = mk_implicit(mk_app(mk_explicit(mk_constant(real_n, section_ls)), section_ps));
|
||||||
p.add_local_expr(n, ref);
|
p.add_local_expr(n, ref);
|
||||||
}
|
}
|
||||||
level_param_names new_ls;
|
level_param_names new_ls;
|
||||||
|
|
|
@ -947,8 +947,14 @@ public:
|
||||||
r = visit_core(get_explicit_arg(e));
|
r = visit_core(get_explicit_arg(e));
|
||||||
} else if (is_explicit(get_app_fn(e))) {
|
} else if (is_explicit(get_app_fn(e))) {
|
||||||
r = visit_core(e);
|
r = visit_core(e);
|
||||||
|
} else {
|
||||||
|
if (is_implicit(e)) {
|
||||||
|
r = get_implicit_arg(e);
|
||||||
|
if (is_explicit(r)) r = get_explicit_arg(r);
|
||||||
|
r = visit_core(r);
|
||||||
} else {
|
} else {
|
||||||
r = visit_core(e);
|
r = visit_core(e);
|
||||||
|
}
|
||||||
if (!is_lambda(r)) {
|
if (!is_lambda(r)) {
|
||||||
tag g = e.get_tag();
|
tag g = e.get_tag();
|
||||||
expr r_type = whnf(infer_type(r));
|
expr r_type = whnf(infer_type(r));
|
||||||
|
|
|
@ -10,6 +10,7 @@ Author: Leonardo de Moura
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
static name g_explicit_name("@");
|
static name g_explicit_name("@");
|
||||||
|
static name g_implicit_name("@^-1");
|
||||||
static name g_as_is_name("as_is");
|
static name g_as_is_name("as_is");
|
||||||
[[ noreturn ]] static void throw_ex(name const & n) { throw exception(sstream() << "unexpected occurrence of '" << n << "' expression"); }
|
[[ noreturn ]] static void throw_ex(name const & n) { throw exception(sstream() << "unexpected occurrence of '" << n << "' expression"); }
|
||||||
|
|
||||||
|
@ -26,20 +27,22 @@ public:
|
||||||
virtual void write(serializer &) const { throw_ex(get_name()); }
|
virtual void write(serializer &) const { throw_ex(get_name()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class as_is_macro_cell : public explicit_macro_cell {
|
struct as_is_macro_cell : public explicit_macro_cell { virtual name get_name() const { return g_as_is_name; } };
|
||||||
public:
|
struct implicit_macro_cell : public explicit_macro_cell { virtual name get_name() const { return g_implicit_name; } };
|
||||||
virtual name get_name() const { return g_as_is_name; }
|
|
||||||
};
|
|
||||||
|
|
||||||
static macro_definition g_explicit(new explicit_macro_cell());
|
static macro_definition g_explicit(new explicit_macro_cell());
|
||||||
static macro_definition g_as_is(new as_is_macro_cell());
|
static macro_definition g_as_is(new as_is_macro_cell());
|
||||||
|
static macro_definition g_implicit(new implicit_macro_cell());
|
||||||
|
|
||||||
expr mk_explicit(expr const & e) { return mk_macro(g_explicit, 1, &e); }
|
expr mk_explicit(expr const & e) { return mk_macro(g_explicit, 1, &e); }
|
||||||
bool is_explicit(expr const & e) { return is_macro(e) && macro_def(e) == g_explicit; }
|
bool is_explicit(expr const & e) { return is_macro(e) && macro_def(e) == g_explicit; }
|
||||||
expr mk_as_is(expr const & e) { return mk_macro(g_as_is, 1, &e); }
|
expr mk_as_is(expr const & e) { return mk_macro(g_as_is, 1, &e); }
|
||||||
bool is_as_is(expr const & e) { return is_macro(e) && macro_def(e) == g_as_is; }
|
bool is_as_is(expr const & e) { return is_macro(e) && macro_def(e) == g_as_is; }
|
||||||
|
expr mk_implicit(expr const & e) { return mk_macro(g_implicit, 1, &e); }
|
||||||
|
bool is_implicit(expr const & e) { return is_macro(e) && macro_def(e) == g_implicit; }
|
||||||
expr const & get_explicit_arg(expr const & e) { lean_assert(is_explicit(e)); return macro_arg(e, 0); }
|
expr const & get_explicit_arg(expr const & e) { lean_assert(is_explicit(e)); return macro_arg(e, 0); }
|
||||||
expr const & get_as_is_arg(expr const & e) { lean_assert(is_as_is(e)); return macro_arg(e, 0); }
|
expr const & get_as_is_arg(expr const & e) { lean_assert(is_as_is(e)); return macro_arg(e, 0); }
|
||||||
|
expr const & get_implicit_arg(expr const & e) { lean_assert(is_implicit(e)); return macro_arg(e, 0); }
|
||||||
|
|
||||||
static int mk_explicit(lua_State * L) { return push_expr(L, mk_explicit(to_expr(L, 1))); }
|
static int mk_explicit(lua_State * L) { return push_expr(L, mk_explicit(to_expr(L, 1))); }
|
||||||
static int is_explicit(lua_State * L) { return push_boolean(L, is_explicit(to_expr(L, 1))); }
|
static int is_explicit(lua_State * L) { return push_boolean(L, is_explicit(to_expr(L, 1))); }
|
||||||
|
|
|
@ -9,29 +9,35 @@ Author: Leonardo de Moura
|
||||||
#include "kernel/expr.h"
|
#include "kernel/expr.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
/**
|
/** \brief Create an explicit expression '@ f'.
|
||||||
\brief Create an explicit expression '@ f'.
|
|
||||||
This only affects the elaborator behavior.
|
This only affects the elaborator behavior.
|
||||||
*/
|
*/
|
||||||
expr mk_explicit(expr const & e);
|
expr mk_explicit(expr const & e);
|
||||||
/** \brief Return true iff \c e is an explicit expression. */
|
/** \brief Return true iff \c e is an explicit expression. */
|
||||||
bool is_explicit(expr const & e);
|
bool is_explicit(expr const & e);
|
||||||
/**
|
/** \brief Create an explicit expression that is accepted as is
|
||||||
\brief Create an explicit expression that is accepted as is
|
|
||||||
by the elaborator.
|
by the elaborator.
|
||||||
*/
|
*/
|
||||||
expr mk_as_is(expr const & e);
|
expr mk_as_is(expr const & e);
|
||||||
/** \brief Return true iff \c e was created with mk_as_is. */
|
/** \brief Return true iff \c e was created with mk_as_is. */
|
||||||
bool is_as_is(expr const & e);
|
bool is_as_is(expr const & e);
|
||||||
/**
|
/** \brief Create an implicit expression '@^-1 f'.
|
||||||
\brief Return the argument of an explicit expression.
|
This only affects the elaborator behavior. This expression "cancels" the effect of '@'
|
||||||
|
*/
|
||||||
|
expr mk_implicit(expr const & e);
|
||||||
|
/** \brief Return true iff \c e is an implicit expression. */
|
||||||
|
bool is_implicit(expr const & e);
|
||||||
|
/** \brief Return the argument of an explicit expression.
|
||||||
\pre is_explicit(e)
|
\pre is_explicit(e)
|
||||||
*/
|
*/
|
||||||
expr const & get_explicit_arg(expr const & e);
|
expr const & get_explicit_arg(expr const & e);
|
||||||
/**
|
/** \brief Return the argument of an expression created using mk_as_is.
|
||||||
\brief Return the argument of an expression created using mk_as_is.
|
|
||||||
\pre is_as_is(e)
|
\pre is_as_is(e)
|
||||||
*/
|
*/
|
||||||
expr const & get_as_is_arg(expr const & e);
|
expr const & get_as_is_arg(expr const & e);
|
||||||
|
/** \brief Return the argument of an implicit expression.
|
||||||
|
\pre is_implicit(e)
|
||||||
|
*/
|
||||||
|
expr const & get_implicit_arg(expr const & e);
|
||||||
void open_explicit(lua_State * L);
|
void open_explicit(lua_State * L);
|
||||||
}
|
}
|
||||||
|
|
20
tests/lean/run/bug6.lean
Normal file
20
tests/lean/run/bug6.lean
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import standard
|
||||||
|
section
|
||||||
|
parameter {A : Type}
|
||||||
|
theorem T {a b : A} (H : a = b) : b = a
|
||||||
|
:= symm H
|
||||||
|
variables x y : A
|
||||||
|
axiom H : x = y
|
||||||
|
check T H
|
||||||
|
check T
|
||||||
|
end
|
||||||
|
|
||||||
|
section
|
||||||
|
parameter {A : Type}
|
||||||
|
theorem T2 ⦃a b : A⦄ (H : a = b) : b = a
|
||||||
|
:= symm H
|
||||||
|
variables x y : A
|
||||||
|
axiom H : x = y
|
||||||
|
check T2 H
|
||||||
|
check T2
|
||||||
|
end
|
|
@ -35,6 +35,7 @@ section
|
||||||
definition add_in (a : int) (b : nat) := a + (of_nat b)
|
definition add_in (a : int) (b : nat) := a + (of_nat b)
|
||||||
infixl + := add_ni
|
infixl + := add_ni
|
||||||
infixl + := add_in
|
infixl + := add_in
|
||||||
|
check add_ni
|
||||||
|
|
||||||
check i + n
|
check i + n
|
||||||
check n + i
|
check n + i
|
||||||
|
|
Loading…
Reference in a new issue