diff --git a/src/library/unifier.cpp b/src/library/unifier.cpp index c57148599..6bc38c81d 100644 --- a/src/library/unifier.cpp +++ b/src/library/unifier.cpp @@ -632,15 +632,15 @@ struct unifier_fn { if (is_eq_deltas(lhs, rhs)) { // we need to create a backtracking point for this one add_cnstr(c, cnstr_group::Basic); - } else if (m_plugin->delay_constraint(*m_tc, c)) { - unsigned cidx = add_cnstr(c, cnstr_group::PluginDelayed); - add_meta_occs(lhs, cidx); - add_meta_occs(rhs, cidx); } else if (is_meta(lhs) && is_meta(rhs)) { // flex-flex constraints are delayed the most. unsigned cidx = add_cnstr(c, cnstr_group::FlexFlex); add_meta_occ(lhs, cidx); add_meta_occ(rhs, cidx); + } else if (m_plugin->delay_constraint(*m_tc, c)) { + unsigned cidx = add_cnstr(c, cnstr_group::PluginDelayed); + add_meta_occs(lhs, cidx); + add_meta_occs(rhs, cidx); } else if (is_meta(lhs)) { // flex-rigid constraints are delayed. unsigned cidx = add_cnstr(c, cnstr_group::FlexRigid); @@ -838,9 +838,40 @@ struct unifier_fn { } } + /** \brief Given a constraint of the form + f a_1 ... a_n =?= f b_1 ... b_n + Return singleton stream with the possible solution + a_i =?= b_i + If c is not of the expected form, then return the empty stream. + */ + lazy_list process_const_const_cnstr(constraint const & c) { + if (!is_eq_cnstr(c)) + return lazy_list(); + expr const & lhs = cnstr_lhs_expr(c); + expr const & rhs = cnstr_rhs_expr(c); + expr const & f_lhs = get_app_fn(lhs); + expr const & f_rhs = get_app_fn(rhs); + if (!is_constant(f_lhs) || !is_constant(f_rhs) || const_name(f_lhs) != const_name(f_rhs)) + return lazy_list(); + justification const & j = c.get_justification(); + buffer cs; + if (!is_def_eq(f_lhs, f_rhs, j, cs)) + return lazy_list(); + buffer args_lhs, args_rhs; + get_app_args(lhs, args_lhs); + get_app_args(rhs, args_rhs); + if (args_lhs.size() != args_rhs.size()) + return lazy_list(); + for (unsigned i = 0; i < args_lhs.size(); i++) + if (!is_def_eq(args_lhs[i], args_rhs[i], j, cs)) + return lazy_list(); + return lazy_list(to_list(cs.begin(), cs.end())); + } + bool process_plugin_constraint(constraint const & c) { lean_assert(!is_choice_cnstr(c)); lazy_list alts = m_plugin->solve(*m_tc, c, m_ngen.mk_child()); + alts = append(alts, process_const_const_cnstr(c)); return process_lazy_constraints(alts, c.get_justification()); } diff --git a/tests/lean/run/nat_bug3.lean b/tests/lean/run/nat_bug3.lean new file mode 100644 index 000000000..261c8b69e --- /dev/null +++ b/tests/lean/run/nat_bug3.lean @@ -0,0 +1,22 @@ +import logic num +using num eq_proofs + +inductive nat : Type := +| zero : nat +| succ : nat → nat + +abbreviation plus (x y : nat) : nat +:= nat_rec x (λn r, succ r) y +definition to_nat [coercion] [inline] (n : num) : nat +:= num_rec zero (λn, pos_num_rec (succ zero) (λn r, plus r (plus r (succ zero))) (λn r, plus r r) n) n +definition add (x y : nat) : nat +:= plus x y +variable le : nat → nat → Prop + +infixl `+`:65 := add +infix `≤`:50 := le +axiom add_one (n:nat) : n + (succ zero) = succ n +axiom add_le_right_inv {n m k : nat} (H : n + k ≤ m + k) : n ≤ m + +theorem succ_le_cancel {n m : nat} (H : succ n ≤ succ m) : n ≤ m +:= add_le_right_inv (add_one m⁻¹ ▸ add_one n⁻¹ ▸ H)