Definition weight_typenv (e: typenv) : nat :=
weight_constraints e.(te_typ) e.(te_sub).
(** Iterative solving of the remaining constraints *)
Function solve_constraints (e: typenv) {measure weight_typenv e}: res typenv :=
match solve_rec {| te_typ := e.(te_typ); te_sub := nil |} false e.(te_sub) with
| OK(e', false) => OK e                   (**r no more changes, fixpoint reached *)
| OK(e', true)  => solve_constraints e'   (**r one more iteration *)
| Error msg => Error msg
end.
Definition typassign := positive -> T.t.
Definition makeassign (e: typenv) : typassign :=
fun x => match e.(te_typ)!x with Some(B lo hi s) => lo | None => T.default end.
Definition solve (e: typenv) : res typassign :=
do e' <- solve_constraints e; OK(makeassign e').
(** What it means to be a solution *)
Definition satisf (te: typassign) (e: typenv) : Prop :=
(forall x lo hi s, e.(te_typ)!x = Some(B lo hi s) -> T.sub lo (te x) /\ T.sub (te x) hi)
/\ (forall x y, In (x, y) e.(te_sub) -> T.sub (te x) (te y)).

(* Specifications: *)
Lemma satisf_initial: forall te, satisf te initial.
(** Soundness proof *)
Lemma type_def_incr:
forall te x ty e e', type_def e x ty = OK e' -> satisf te e' -> satisf te e.