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:
Leonardo de Moura 2013-12-06 04:51:07 -08:00
parent 4e4fea1eca
commit c841763a05
4 changed files with 37 additions and 3 deletions

View file

@ -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 {
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));
}
}

View file

@ -51,6 +51,12 @@ public:
\pre size() >= s + n
*/
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;
};
/**

View file

@ -398,6 +398,7 @@ class elaborator::imp {
*/
enum status { Processed, Failed, Continue };
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_assigned(a)) {
// Case 1
@ -410,7 +411,7 @@ class elaborator::imp {
if (has_metavar(b, a)) {
m_conflict = justification(new unification_failure_justification(c));
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,
// or b is a proposition.
// 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));
expr new_a = pop_meta_context(a);
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)
swap(new_a, new_b);
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));
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;
}
}
}

View file

@ -284,7 +284,7 @@ static void success(expr const & e, expr const & expected, environment const & e
std::cout << "\n" << e << "\n\n";
expr r = elaborate(e, env);
std::cout << "\n" << e << "\n------>\n" << r << "\n";
lean_assert(r == expected);
lean_assert_eq(r, expected);
}
// Check elaborator failure