feat(frontends/lean): allow 'sorry' implicit argument to access the whole context, and avoid cryptic error message
See new test for explanation.
This commit is contained in:
parent
efdf7420b5
commit
2730e5163e
4 changed files with 35 additions and 1 deletions
|
@ -28,6 +28,7 @@ Author: Leonardo de Moura
|
||||||
#include "library/reducible.h"
|
#include "library/reducible.h"
|
||||||
#include "library/locals.h"
|
#include "library/locals.h"
|
||||||
#include "library/let.h"
|
#include "library/let.h"
|
||||||
|
#include "library/sorry.h"
|
||||||
#include "library/deep_copy.h"
|
#include "library/deep_copy.h"
|
||||||
#include "library/metavar_closure.h"
|
#include "library/metavar_closure.h"
|
||||||
#include "library/typed_expr.h"
|
#include "library/typed_expr.h"
|
||||||
|
@ -100,6 +101,7 @@ class elaborator : public coercion_info_manager {
|
||||||
// we set is to true whenever we find no_info annotation.
|
// we set is to true whenever we find no_info annotation.
|
||||||
bool m_no_info;
|
bool m_no_info;
|
||||||
info_manager m_pre_info_data;
|
info_manager m_pre_info_data;
|
||||||
|
bool m_has_sorry;
|
||||||
unifier_config m_unifier_config;
|
unifier_config m_unifier_config;
|
||||||
|
|
||||||
/** \brief 'Choice' expressions <tt>(choice e_1 ... e_n)</tt> are mapped into a metavariable \c ?m
|
/** \brief 'Choice' expressions <tt>(choice e_1 ... e_n)</tt> are mapped into a metavariable \c ?m
|
||||||
|
@ -149,6 +151,7 @@ public:
|
||||||
m_context(),
|
m_context(),
|
||||||
m_full_context(),
|
m_full_context(),
|
||||||
m_unifier_config(env.m_ios.get_options(), true /* use exceptions */, true /* discard */) {
|
m_unifier_config(env.m_ios.get_options(), true /* use exceptions */, true /* discard */) {
|
||||||
|
m_has_sorry = has_sorry(m_env.m_env),
|
||||||
m_relax_main_opaque = false;
|
m_relax_main_opaque = false;
|
||||||
m_no_info = false;
|
m_no_info = false;
|
||||||
m_tc[0] = mk_type_checker(env.m_env, m_ngen.mk_child(), false);
|
m_tc[0] = mk_type_checker(env.m_env, m_ngen.mk_child(), false);
|
||||||
|
@ -750,6 +753,17 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_sorry(expr const & e) const {
|
||||||
|
return m_has_sorry && ::lean::is_sorry(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr visit_sorry(expr const & e) {
|
||||||
|
level u = mk_meta_univ(m_ngen.next());
|
||||||
|
expr t = mk_sort(u);
|
||||||
|
expr m = m_full_context.mk_meta(m_ngen, some_expr(t), e.get_tag());
|
||||||
|
return mk_app(update_constant(e, to_list(u)), m, e.get_tag());
|
||||||
|
}
|
||||||
|
|
||||||
expr visit_core(expr const & e, constraint_seq & cs) {
|
expr visit_core(expr const & e, constraint_seq & cs) {
|
||||||
if (is_placeholder(e)) {
|
if (is_placeholder(e)) {
|
||||||
return visit_placeholder(e, cs);
|
return visit_placeholder(e, cs);
|
||||||
|
@ -768,6 +782,8 @@ public:
|
||||||
return visit_typed_expr(e, cs);
|
return visit_typed_expr(e, cs);
|
||||||
} else if (is_implicit(e)) {
|
} else if (is_implicit(e)) {
|
||||||
return visit_core(get_implicit_arg(e), cs);
|
return visit_core(get_implicit_arg(e), cs);
|
||||||
|
} else if (is_sorry(e)) {
|
||||||
|
return visit_sorry(e);
|
||||||
} else {
|
} else {
|
||||||
switch (e.kind()) {
|
switch (e.kind()) {
|
||||||
case expr_kind::Local: return e;
|
case expr_kind::Local: return e;
|
||||||
|
@ -795,7 +811,11 @@ public:
|
||||||
constraint_seq cs;
|
constraint_seq cs;
|
||||||
if (is_explicit(e)) {
|
if (is_explicit(e)) {
|
||||||
b = get_explicit_arg(e);
|
b = get_explicit_arg(e);
|
||||||
r = visit_core(get_explicit_arg(e), cs);
|
if (is_sorry(b)) {
|
||||||
|
r = visit_constant(b);
|
||||||
|
} else {
|
||||||
|
r = visit_core(b, cs);
|
||||||
|
}
|
||||||
} else if (is_explicit(get_app_fn(e))) {
|
} else if (is_explicit(get_app_fn(e))) {
|
||||||
r = visit_core(e, cs);
|
r = visit_core(e, cs);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,4 +42,5 @@ environment declare_sorry(environment const & env) {
|
||||||
|
|
||||||
expr mk_sorry() { return mk_constant(*g_sorry_name); }
|
expr mk_sorry() { return mk_constant(*g_sorry_name); }
|
||||||
name const & get_sorry_name() { return *g_sorry_name; }
|
name const & get_sorry_name() { return *g_sorry_name; }
|
||||||
|
bool is_sorry(expr const & e) { return is_constant(e) && const_name(e) == get_sorry_name(); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,8 @@ environment declare_sorry(environment const & env);
|
||||||
/** \brief Return the constant \c sorry */
|
/** \brief Return the constant \c sorry */
|
||||||
expr mk_sorry();
|
expr mk_sorry();
|
||||||
name const & get_sorry_name();
|
name const & get_sorry_name();
|
||||||
|
/** \brief Return true iff \c e is a sorry expression */
|
||||||
|
bool is_sorry(expr const & e);
|
||||||
void initialize_sorry();
|
void initialize_sorry();
|
||||||
void finalize_sorry();
|
void finalize_sorry();
|
||||||
}
|
}
|
||||||
|
|
11
tests/lean/run/cast_sorry_bug.lean
Normal file
11
tests/lean/run/cast_sorry_bug.lean
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import logic data.nat
|
||||||
|
open nat
|
||||||
|
|
||||||
|
inductive fin : ℕ → Type :=
|
||||||
|
zero : Π {n : ℕ}, fin (succ n),
|
||||||
|
succ : Π {n : ℕ}, fin n → fin (succ n)
|
||||||
|
|
||||||
|
theorem foo (n m : ℕ) (a : fin n) (b : fin m) (H : n = m) : cast (congr_arg fin H) a = b :=
|
||||||
|
have eq : fin n = fin m, from congr_arg fin H,
|
||||||
|
have ceq : cast eq a = b, from sorry, -- sorry implicit argument must have access to eq
|
||||||
|
sorry
|
Loading…
Reference in a new issue