feat(library/unifier): postpone as much as possible universe constraints of the form ?m1 =?= max(l1, l2) and ?m1 =?= imax(l1, l2) where ?m1 occurs in the right hand side. When there is nothing else to be done, try to solve them by reducing to ?m1 = l1 and ?m1 = l2.
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
a62e6f84e3
commit
5e2185cfbe
2 changed files with 74 additions and 5 deletions
|
@ -1581,12 +1581,51 @@ struct unifier_fn {
|
||||||
return try_level_eq_zero(rhs, lhs, j);
|
return try_level_eq_zero(rhs, lhs, j);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** \brief Try to solve constraints of the form
|
||||||
|
(?m1 =?= max ?m2 ?m3)
|
||||||
|
(?m1 =?= max ?m2 ?m3)
|
||||||
|
by assigning ?m1 =?= ?m2 and ?m1 =?= ?m3
|
||||||
|
|
||||||
|
\remark we may miss solutions.
|
||||||
|
*/
|
||||||
|
status try_merge_max_core(level const & lhs, level const & rhs, justification const & j) {
|
||||||
|
level m1 = lhs;
|
||||||
|
level m2, m3;
|
||||||
|
if (is_max(rhs)) {
|
||||||
|
m2 = max_lhs(rhs);
|
||||||
|
m3 = max_rhs(rhs);
|
||||||
|
} else if (is_imax(rhs)) {
|
||||||
|
m2 = imax_lhs(rhs);
|
||||||
|
m3 = imax_rhs(rhs);
|
||||||
|
} else {
|
||||||
|
return Continue;
|
||||||
|
}
|
||||||
|
if (process_constraint(mk_level_eq_cnstr(m1, m2, j)) &&
|
||||||
|
process_constraint(mk_level_eq_cnstr(m1, m3, j)))
|
||||||
|
return Solved;
|
||||||
|
else
|
||||||
|
return Failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \see try_merge_max_core */
|
||||||
|
status try_merge_max(constraint const & c) {
|
||||||
|
lean_assert(is_level_eq_cnstr(c));
|
||||||
|
level const & lhs = cnstr_lhs_level(c);
|
||||||
|
level const & rhs = cnstr_rhs_level(c);
|
||||||
|
justification const & j = c.get_justification();
|
||||||
|
status st = try_merge_max_core(lhs, rhs, j);
|
||||||
|
if (st != Continue) return st;
|
||||||
|
return try_merge_max_core(rhs, lhs, j);
|
||||||
|
}
|
||||||
|
|
||||||
/** \brief Process the next constraint in the constraint queue m_cnstrs */
|
/** \brief Process the next constraint in the constraint queue m_cnstrs */
|
||||||
bool process_next() {
|
bool process_next() {
|
||||||
lean_assert(!m_cnstrs.empty());
|
lean_assert(!m_cnstrs.empty());
|
||||||
lean_assert(!m_tc[0]->next_cnstr());
|
lean_assert(!m_tc[0]->next_cnstr());
|
||||||
lean_assert(!m_tc[1]->next_cnstr());
|
lean_assert(!m_tc[1]->next_cnstr());
|
||||||
constraint c = m_cnstrs.min()->first;
|
auto const * p = m_cnstrs.min();
|
||||||
|
unsigned cidx = p->second;
|
||||||
|
constraint c = p->first;
|
||||||
m_cnstrs.erase_min();
|
m_cnstrs.erase_min();
|
||||||
if (is_choice_cnstr(c)) {
|
if (is_choice_cnstr(c)) {
|
||||||
return process_choice_constraint(c);
|
return process_choice_constraint(c);
|
||||||
|
@ -1600,10 +1639,14 @@ struct unifier_fn {
|
||||||
if (modified)
|
if (modified)
|
||||||
return process_constraint(c);
|
return process_constraint(c);
|
||||||
status st = try_level_eq_zero(c);
|
status st = try_level_eq_zero(c);
|
||||||
if (st != Continue)
|
if (st != Continue) return st == Solved;
|
||||||
return st == Solved;
|
if (cidx < get_group_first_index(cnstr_group::FlexFlex)) {
|
||||||
else
|
add_cnstr(c, cnstr_group::FlexFlex);
|
||||||
return process_plugin_constraint(c);
|
return true;
|
||||||
|
}
|
||||||
|
st = try_merge_max(c);
|
||||||
|
if (st != Continue) return st == Solved;
|
||||||
|
return process_plugin_constraint(c);
|
||||||
} else {
|
} else {
|
||||||
lean_assert(is_eq_cnstr(c));
|
lean_assert(is_eq_cnstr(c));
|
||||||
if (is_delta_cnstr(c)) {
|
if (is_delta_cnstr(c)) {
|
||||||
|
|
26
tests/lean/run/univ_bug1.lean
Normal file
26
tests/lean/run/univ_bug1.lean
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
----------------------------------------------------------------------------------------------------
|
||||||
|
--- Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
||||||
|
--- Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
|
--- Author: Jeremy Avigad
|
||||||
|
----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import logic data.nat
|
||||||
|
using nat
|
||||||
|
|
||||||
|
namespace simp
|
||||||
|
-- set_option pp.universes true
|
||||||
|
-- set_option pp.implicit true
|
||||||
|
|
||||||
|
-- first define a class of homogeneous equality
|
||||||
|
inductive simplifies_to {T : Type} (t1 t2 : T) : Prop :=
|
||||||
|
| mk : t1 = t2 → simplifies_to t1 t2
|
||||||
|
|
||||||
|
theorem get_eq {T : Type} {t1 t2 : T} (C : simplifies_to t1 t2) : t1 = t2 :=
|
||||||
|
simplifies_to_rec (λx, x) C
|
||||||
|
|
||||||
|
theorem infer_eq {T : Type} (t1 t2 : T) {C : simplifies_to t1 t2} : t1 = t2 :=
|
||||||
|
simplifies_to_rec (λx, x) C
|
||||||
|
|
||||||
|
theorem simp_app [instance] (S T : Type) (f1 f2 : S → T) (s1 s2 : S)
|
||||||
|
(C1 : simplifies_to f1 f2) (C2 : simplifies_to s1 s2) : simplifies_to (f1 s1) (f2 s2) :=
|
||||||
|
mk (congr (get_eq C1) (get_eq C2))
|
Loading…
Reference in a new issue