fix(frontends/lean/placeholder_elaborator): local context must be adjusted when performing class-instance resolution modulo Pi-abstraction, fixes #293

This commit is contained in:
Leonardo de Moura 2014-11-04 18:41:27 -08:00
parent b5ad0fb504
commit 6944c7d902
3 changed files with 73 additions and 23 deletions

View file

@ -48,15 +48,13 @@ struct placeholder_context {
io_state m_ios; io_state m_ios;
name_generator m_ngen; name_generator m_ngen;
type_checker_ptr m_tc; type_checker_ptr m_tc;
local_context m_ctx;
bool m_relax; bool m_relax;
bool m_use_local_instances; bool m_use_local_instances;
placeholder_context(environment const & env, io_state const & ios, local_context const & ctx, placeholder_context(environment const & env, io_state const & ios,
name const & prefix, bool relax, bool use_local_instances): name const & prefix, bool relax, bool use_local_instances):
m_ios(ios), m_ios(ios),
m_ngen(prefix), m_ngen(prefix),
m_tc(mk_type_checker(env, m_ngen.mk_child(), relax)), m_tc(mk_type_checker(env, m_ngen.mk_child(), relax)),
m_ctx(ctx),
m_relax(relax), m_relax(relax),
m_use_local_instances(use_local_instances) { m_use_local_instances(use_local_instances) {
} }
@ -67,7 +65,7 @@ struct placeholder_context {
type_checker & tc() const { return *m_tc; } type_checker & tc() const { return *m_tc; }
}; };
pair<expr, constraint> mk_placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, pair<expr, constraint> mk_placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, local_context const & ctx,
optional<expr> const & type, tag g); optional<expr> const & type, tag g);
/** \brief Whenever the elaborator finds a placeholder '_' or introduces an /** \brief Whenever the elaborator finds a placeholder '_' or introduces an
@ -82,6 +80,7 @@ pair<expr, constraint> mk_placeholder_elaborator(std::shared_ptr<placeholder_con
*/ */
struct placeholder_elaborator : public choice_iterator { struct placeholder_elaborator : public choice_iterator {
std::shared_ptr<placeholder_context> m_C; std::shared_ptr<placeholder_context> m_C;
local_context m_ctx;
expr m_meta; expr m_meta;
// elaborated type of the metavariable // elaborated type of the metavariable
expr m_meta_type; expr m_meta_type;
@ -94,11 +93,11 @@ struct placeholder_elaborator : public choice_iterator {
list<name> m_instances; list<name> m_instances;
justification m_jst; justification m_jst;
placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, local_context const & ctx,
expr const & meta, expr const & meta_type, expr const & meta, expr const & meta_type,
list<expr> const & local_insts, list<name> const & instances, list<expr> const & local_insts, list<name> const & instances,
justification const & j): justification const & j):
choice_iterator(), m_C(C), m_meta(meta), m_meta_type(meta_type), choice_iterator(), m_C(C), m_ctx(ctx), m_meta(meta), m_meta_type(meta_type),
m_local_instances(local_insts), m_instances(instances), m_jst(j) { m_local_instances(local_insts), m_instances(instances), m_jst(j) {
} }
@ -110,9 +109,8 @@ struct placeholder_elaborator : public choice_iterator {
type_checker & tc = m_C->tc(); type_checker & tc = m_C->tc();
name_generator & ngen = m_C->m_ngen; name_generator & ngen = m_C->m_ngen;
tag g = inst.get_tag(); tag g = inst.get_tag();
local_context & ctx = m_C->m_ctx;
try { try {
flet<local_context> scope(ctx, ctx); flet<local_context> scope(m_ctx, m_ctx);
buffer<expr> locals; buffer<expr> locals;
expr meta_type = m_meta_type; expr meta_type = m_meta_type;
while (true) { while (true) {
@ -121,7 +119,7 @@ struct placeholder_elaborator : public choice_iterator {
break; break;
expr local = mk_local(ngen.next(), binding_name(meta_type), expr local = mk_local(ngen.next(), binding_name(meta_type),
binding_domain(meta_type), binding_info(meta_type)); binding_domain(meta_type), binding_info(meta_type));
ctx.add_local(local); m_ctx.add_local(local);
locals.push_back(local); locals.push_back(local);
meta_type = instantiate(binding_body(meta_type), local); meta_type = instantiate(binding_body(meta_type), local);
} }
@ -132,7 +130,7 @@ struct placeholder_elaborator : public choice_iterator {
type = tc.whnf(type).first; type = tc.whnf(type).first;
if (!is_pi(type)) if (!is_pi(type))
break; break;
pair<expr, constraint> ac = mk_placeholder_elaborator(m_C, some_expr(binding_domain(type)), g); pair<expr, constraint> ac = mk_placeholder_elaborator(m_C, m_ctx, some_expr(binding_domain(type)), g);
expr arg = ac.first; expr arg = ac.first;
cs.push_back(ac.second); cs.push_back(ac.second);
r = mk_app(r, arg, g); r = mk_app(r, arg, g);
@ -184,21 +182,21 @@ struct placeholder_elaborator : public choice_iterator {
}; };
constraint mk_placeholder_cnstr(std::shared_ptr<placeholder_context> const & C, expr const & m) { constraint mk_placeholder_cnstr(std::shared_ptr<placeholder_context> const & C, local_context const & ctx, expr const & m) {
environment const & env = C->env(); environment const & env = C->env();
justification j = mk_failed_to_synthesize_jst(env, m); justification j = mk_failed_to_synthesize_jst(env, m);
auto choice_fn = [=](expr const & meta, expr const & meta_type, substitution const &, name_generator const &) { auto choice_fn = [=](expr const & meta, expr const & meta_type, substitution const &, name_generator const &) {
if (auto cls_name_it = is_ext_class(C->tc(), meta_type)) { if (auto cls_name_it = is_ext_class(C->tc(), meta_type)) {
name cls_name = *cls_name_it; name cls_name = *cls_name_it;
list<expr> const & ctx = C->m_ctx.get_data(); list<expr> const & ctx_lst = ctx.get_data();
list<expr> local_insts; list<expr> local_insts;
if (C->use_local_instances()) if (C->use_local_instances())
local_insts = get_local_instances(C->tc(), ctx, cls_name); local_insts = get_local_instances(C->tc(), ctx_lst, cls_name);
list<name> insts = get_class_instances(env, cls_name); list<name> insts = get_class_instances(env, cls_name);
if (empty(local_insts) && empty(insts)) if (empty(local_insts) && empty(insts))
return lazy_list<constraints>(); // nothing to be done return lazy_list<constraints>(); // nothing to be done
// we are always strict with placeholders associated with classes // we are always strict with placeholders associated with classes
return choose(std::make_shared<placeholder_elaborator>(C, meta, meta_type, local_insts, insts, j)); return choose(std::make_shared<placeholder_elaborator>(C, ctx, meta, meta_type, local_insts, insts, j));
} else { } else {
// do nothing, type is not a class... // do nothing, type is not a class...
return lazy_list<constraints>(constraints()); return lazy_list<constraints>(constraints());
@ -210,10 +208,10 @@ constraint mk_placeholder_cnstr(std::shared_ptr<placeholder_context> const & C,
owner, j, relax); owner, j, relax);
} }
pair<expr, constraint> mk_placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, pair<expr, constraint> mk_placeholder_elaborator(std::shared_ptr<placeholder_context> const & C, local_context const & ctx,
optional<expr> const & type, tag g) { optional<expr> const & type, tag g) {
expr m = C->m_ctx.mk_meta(C->m_ngen, type, g); expr m = ctx.mk_meta(C->m_ngen, type, g);
constraint c = mk_placeholder_cnstr(C, m); constraint c = mk_placeholder_cnstr(C, ctx, m);
return mk_pair(m, c); return mk_pair(m, c);
} }
@ -237,8 +235,8 @@ static bool has_expr_metavar_relaxed(expr const & e) {
return found; return found;
} }
constraint mk_placeholder_root_cnstr(std::shared_ptr<placeholder_context> const & C, expr const & m, bool is_strict, constraint mk_placeholder_root_cnstr(std::shared_ptr<placeholder_context> const & C, local_context const & ctx,
unifier_config const & cfg, delay_factor const & factor) { expr const & m, bool is_strict, unifier_config const & cfg, delay_factor const & factor) {
environment const & env = C->env(); environment const & env = C->env();
justification j = mk_failed_to_synthesize_jst(env, m); justification j = mk_failed_to_synthesize_jst(env, m);
@ -251,7 +249,7 @@ constraint mk_placeholder_root_cnstr(std::shared_ptr<placeholder_context> const
pair<expr, justification> mj = update_meta(meta, s); pair<expr, justification> mj = update_meta(meta, s);
expr new_meta = mj.first; expr new_meta = mj.first;
justification new_j = mj.second; justification new_j = mj.second;
constraint c = mk_placeholder_cnstr(C, new_meta); constraint c = mk_placeholder_cnstr(C, ctx, new_meta);
unifier_config new_cfg(cfg); unifier_config new_cfg(cfg);
new_cfg.m_discard = false; new_cfg.m_discard = false;
new_cfg.m_use_exceptions = false; new_cfg.m_use_exceptions = false;
@ -332,9 +330,9 @@ pair<expr, constraint> mk_placeholder_elaborator(
environment const & env, io_state const & ios, local_context const & ctx, environment const & env, io_state const & ios, local_context const & ctx,
name const & prefix, optional<name> const & suffix, bool relax, bool use_local_instances, name const & prefix, optional<name> const & suffix, bool relax, bool use_local_instances,
bool is_strict, optional<expr> const & type, tag g, unifier_config const & cfg) { bool is_strict, optional<expr> const & type, tag g, unifier_config const & cfg) {
auto C = std::make_shared<placeholder_context>(env, ios, ctx, prefix, relax, use_local_instances); auto C = std::make_shared<placeholder_context>(env, ios, prefix, relax, use_local_instances);
expr m = C->m_ctx.mk_meta(C->m_ngen, suffix, type, g); expr m = ctx.mk_meta(C->m_ngen, suffix, type, g);
constraint c = mk_placeholder_root_cnstr(C, m, is_strict, cfg, delay_factor()); constraint c = mk_placeholder_root_cnstr(C, ctx, m, is_strict, cfg, delay_factor());
return mk_pair(m, c); return mk_pair(m, c);
} }
} }

View file

@ -0,0 +1,18 @@
import general_notation type
inductive fibrant [class] (T : Type) : Type :=
fibrant_mk : fibrant T
inductive path {A : Type'} [fA : fibrant A] (a : A) : A → Type :=
idpath : path a a
notation a ≈ b := path a b
axiom path_fibrant {A : Type'} [fA : fibrant A] (a b : A) : fibrant (path a b)
instance [persistent] path_fibrant
axiom imp_fibrant {A : Type'} {B : Type'} [C1 : fibrant A] [C2 : fibrant B] : fibrant (A → B)
instance imp_fibrant
definition test {A : Type} [fA : fibrant A] {x y : A} :
Π (z : A), y ≈ z → fibrant (x ≈ y → x ≈ z) := _

View file

@ -0,0 +1,34 @@
import general_notation
inductive fibrant [class] (T : Type) : Type :=
fibrant_mk : fibrant T
axiom pi_fibrant {A : Type} {B : A → Type} [C1 : fibrant A] [C2 : Πx : A, fibrant (B x)] :
fibrant (Πx : A, B x)
instance pi_fibrant
inductive path {A : Type} [fA : fibrant A] (a : A) : A → Type :=
idpath : path a a
axiom path_fibrant {A : Type} [fA : fibrant A] (a b : A) : fibrant (path a b)
instance [persistent] path_fibrant
notation a ≈ b := path a b
definition test {A : Type} [fA : fibrant A] {x y : A} :
Π (z : A), y ≈ z → fibrant (x ≈ y → x ≈ z) := take z p, _
definition test2 {A : Type} [fA : fibrant A] {x y : A} :
Π (z : A), y ≈ z → fibrant (x ≈ y → x ≈ z) := _
definition test3 {A : Type} [fA : fibrant A] {x y : A} :
Π (z : A), y ≈ z → fibrant (x ≈ z) := _
definition test4 {A : Type} [fA : fibrant A] {x y z : A} :
fibrant (x ≈ y → x ≈ z) := _
axiom imp_fibrant {A : Type} {B : Type} [C1 : fibrant A] [C2 : fibrant B] : fibrant (A → B)
instance imp_fibrant
definition test5 {A : Type} [fA : fibrant A] {x y : A} :
Π (z : A), y ≈ z → fibrant (x ≈ y → x ≈ z) := _