feat(library/elaborator): add special treatment for constraints of the form ?m[inst:i v] << t, where t is a proposition
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
4e4fea1eca
commit
c841763a05
4 changed files with 37 additions and 3 deletions
|
@ -46,4 +46,17 @@ static list<context_entry> remove_core(list<context_entry> const & l, unsigned s
|
||||||
context context::remove(unsigned s, unsigned n) const {
|
context context::remove(unsigned s, unsigned n) const {
|
||||||
return context(remove_core(m_list, s, n));
|
return context(remove_core(m_list, s, n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static list<context_entry> insert_at_core(list<context_entry> const & l, unsigned i, name const & n, expr const & d) {
|
||||||
|
if (i == 0) {
|
||||||
|
return cons(context_entry(n, d), l);
|
||||||
|
} else {
|
||||||
|
lean_assert(l);
|
||||||
|
return cons(head(l), insert_at_core(tail(l), i - 1, n, d));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
context context::insert_at(unsigned i, name const & n, expr const & d) const {
|
||||||
|
return context(insert_at_core(m_list, i, n, d));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,12 @@ public:
|
||||||
\pre size() >= s + n
|
\pre size() >= s + n
|
||||||
*/
|
*/
|
||||||
context remove(unsigned s, unsigned n) const;
|
context remove(unsigned s, unsigned n) const;
|
||||||
|
/**
|
||||||
|
\brief Return a new context where then entry n : d is inserted at position i.
|
||||||
|
|
||||||
|
\pre size() >= i
|
||||||
|
*/
|
||||||
|
context insert_at(unsigned i, name const & n, expr const & d) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -398,6 +398,7 @@ class elaborator::imp {
|
||||||
*/
|
*/
|
||||||
enum status { Processed, Failed, Continue };
|
enum status { Processed, Failed, Continue };
|
||||||
status process_metavar(unification_constraint const & c, expr const & a, expr const & b, bool is_lhs) {
|
status process_metavar(unification_constraint const & c, expr const & a, expr const & b, bool is_lhs) {
|
||||||
|
context const & ctx = get_context(c);
|
||||||
if (is_metavar(a)) {
|
if (is_metavar(a)) {
|
||||||
if (is_assigned(a)) {
|
if (is_assigned(a)) {
|
||||||
// Case 1
|
// Case 1
|
||||||
|
@ -410,7 +411,7 @@ class elaborator::imp {
|
||||||
if (has_metavar(b, a)) {
|
if (has_metavar(b, a)) {
|
||||||
m_conflict = justification(new unification_failure_justification(c));
|
m_conflict = justification(new unification_failure_justification(c));
|
||||||
return Failed;
|
return Failed;
|
||||||
} else if (is_eq(c) || is_proposition(b, get_context(c))) {
|
} else if (is_eq(c) || is_proposition(b, ctx)) {
|
||||||
// At this point, we only assign metavariables if the constraint is an equational constraint,
|
// At this point, we only assign metavariables if the constraint is an equational constraint,
|
||||||
// or b is a proposition.
|
// or b is a proposition.
|
||||||
// It is important to handle propositions since we don't want to normalize them.
|
// It is important to handle propositions since we don't want to normalize them.
|
||||||
|
@ -426,7 +427,7 @@ class elaborator::imp {
|
||||||
justification new_jst(new normalize_justification(c));
|
justification new_jst(new normalize_justification(c));
|
||||||
expr new_a = pop_meta_context(a);
|
expr new_a = pop_meta_context(a);
|
||||||
expr new_b = lower_free_vars(b, me.s() + me.n(), me.n());
|
expr new_b = lower_free_vars(b, me.s() + me.n(), me.n());
|
||||||
context new_ctx = get_context(c).remove(me.s(), me.n());
|
context new_ctx = ctx.remove(me.s(), me.n());
|
||||||
if (!is_lhs)
|
if (!is_lhs)
|
||||||
swap(new_a, new_b);
|
swap(new_a, new_b);
|
||||||
push_new_constraint(is_eq(c), new_ctx, new_a, new_b, new_jst);
|
push_new_constraint(is_eq(c), new_ctx, new_a, new_b, new_jst);
|
||||||
|
@ -437,6 +438,20 @@ class elaborator::imp {
|
||||||
m_conflict = justification(new unification_failure_justification(c));
|
m_conflict = justification(new unification_failure_justification(c));
|
||||||
return Failed;
|
return Failed;
|
||||||
}
|
}
|
||||||
|
} else if (me.is_inst() && is_proposition(b, ctx) && !is_proposition(me.v(), ctx)) {
|
||||||
|
// If b is a proposition, and the value in the local context is not,
|
||||||
|
// we ignore it, and create new constraint without the head of the local context.
|
||||||
|
// This is a little bit hackish. We do it because we want to preserve
|
||||||
|
// the structure of the proposition. This is similar to the trick used
|
||||||
|
// in the assign(a, b, c) branch above.
|
||||||
|
justification new_jst(new normalize_justification(c));
|
||||||
|
expr new_a = pop_meta_context(a);
|
||||||
|
expr new_b = lift_free_vars(b, me.s(), 1);
|
||||||
|
context new_ctx = ctx.insert_at(me.s(), g_x_name, Type()); // insert a dummy at position s
|
||||||
|
if (!is_lhs)
|
||||||
|
swap(new_a, new_b);
|
||||||
|
push_new_constraint(is_eq(c), new_ctx, new_a, new_b, new_jst);
|
||||||
|
return Processed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -284,7 +284,7 @@ static void success(expr const & e, expr const & expected, environment const & e
|
||||||
std::cout << "\n" << e << "\n\n";
|
std::cout << "\n" << e << "\n\n";
|
||||||
expr r = elaborate(e, env);
|
expr r = elaborate(e, env);
|
||||||
std::cout << "\n" << e << "\n------>\n" << r << "\n";
|
std::cout << "\n" << e << "\n------>\n" << r << "\n";
|
||||||
lean_assert(r == expected);
|
lean_assert_eq(r, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check elaborator failure
|
// Check elaborator failure
|
||||||
|
|
Loading…
Reference in a new issue