Require Import VST.floyd.base2.
Require Import VST.floyd.client_lemmas.
Require Import VST.floyd.type_induction.
(*Require Import VST.floyd.fieldlist.*)
Require Import VST.floyd.compact_prod_sum.
(*Require Import VST.floyd.aggregate_type.*)
Require Import VST.floyd.mapsto_memory_block.
Require Import VST.floyd.nested_pred_lemmas.
Require Import VST.floyd.jmeq_lemmas.
Require Import VST.floyd.sublist.

Require Export VST.floyd.fieldlist.
Require Export VST.floyd.aggregate_type.

Open Scope Z.
Open Scope logic.

(******************************************

Definition and lemmas about rangespec

******************************************)

Fixpoint rangespec (lo: Z) (n: nat) (P: Z -> val -> mpred): val -> mpred :=
  match n with
  | O => fun _ => emp
  | S n' => P lo * rangespec (Z.succ lo) n' P
 end.

Fixpoint fold_range' {A: Type} (f: Z -> A -> A) (zero: A) (lo: Z) (n: nat) : A :=
 match n with
  | O => zero
  | S n' => f lo (fold_range' f  zero (Z.succ lo) n')
 end.

Definition fold_range {A: Type} (f: Z -> A -> A) (zero: A) (lo hi: Z) : A :=
  fold_range' f zero lo (Z.to_nat (hi-lo)).

Lemma rangespec_shift_derives: forall lo lo' len P P' p p',
  (forall i i', lo <= i < lo + Z_of_nat len -> i - lo = i' - lo' -> P i p |-- P' i' p') ->
  rangespec lo len P p |-- rangespec lo' len P' p'.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
  revert lo lo' H;
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  induction len; intros.
  + simpl. auto.
  + simpl.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A0 P0 (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p)) (@sepcon mpred Nveric Sveric (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A1 P1 (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p)) *)
    apply sepcon_derives.
    - apply H; [| omega].
(* Goal: and (Z.le lo i) (Z.lt i (Z.add lo (Z.of_nat (S len)))) *)
      rewrite Nat2Z.inj_succ.
      rewrite <- Z.add_1_r.
(* Goal: @eq Z z z *)
      omega.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    - apply IHlen. intros.
(* Goal: @derives mpred Nveric (P i p) (P' i' p') *)
      apply H; [| omega].
(* Goal: and (Z.le lo i) (Z.lt i (Z.add lo (Z.of_nat (S len)))) *)
      rewrite Nat2Z.inj_succ.
      rewrite <- Z.add_1_r.
(* Goal: and (Z.le lo i) (Z.lt i (Z.add lo (Z.add (Z.of_nat len) (Zpos xH)))) *)
      pose proof Zle_0_nat (S len).
(* Goal: @eq Z z z *)
      omega.
Qed.

Lemma rangespec_ext_derives: forall lo len P P' p,
  (forall i, lo <= i < lo + Z_of_nat len -> P i p |-- P' i p) ->
  rangespec lo len P p |-- rangespec lo len P' p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (rangespec lo len P p) (rangespec lo len P' p) *)
  apply rangespec_shift_derives.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq Z z z *)
  assert (i = i') by omega.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
  subst.
(* Goal: @derives mpred Nveric (P i' p) (P' i' p) *)
  apply H.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  auto.
Qed.

Lemma rangespec_shift: forall lo lo' len P P' p p',
  (forall i i', lo <= i < lo + Z_of_nat len -> i - lo = i' - lo' -> P i p = P' i' p') ->
  rangespec lo len P p = rangespec lo' len P' p'.
Proof.
  intros; apply pred_ext; apply rangespec_shift_derives;
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
  + erewrite H; eauto. 
(* Goal: @derives mpred Nveric (P' i p') (P' i p') *)
(* Goal: and (Z.le lo i') (Z.lt i' (Z.add lo (Z.of_nat len))) *)
      apply derives_refl.
  + erewrite H; eauto.
(* Goal: @derives mpred Nveric (P' i p') (P' i p') *)
(* Goal: and (Z.le lo i') (Z.lt i' (Z.add lo (Z.of_nat len))) *)
      apply derives_refl.
(* Goal: @eq Z z z *)
    omega.
Qed.

Lemma rangespec_ext: forall lo len P P' p,
  (forall i, lo <= i < lo + Z_of_nat len -> P i p = P' i p) ->
  rangespec lo len P p = rangespec lo len P' p.
Proof.
  intros; apply pred_ext; apply rangespec_ext_derives;
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  intros; rewrite H; auto.
Qed.

Lemma rangespec_sepcon: forall lo len P Q p,
  rangespec lo len P p * rangespec lo len Q p = rangespec lo len (P * Q) p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert lo; induction len; intros.
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite sepcon_emp; auto.
  + simpl.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (P lo p) (rangespec (Z.succ lo) len P p)) (@sepcon mpred Nveric Sveric (Q lo p) (rangespec (Z.succ lo) len Q p))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (P lo p) (Q lo p)) (rangespec (Z.succ lo) len (fun (rho : Z) (rho0 : val) => @sepcon mpred Nveric Sveric (P rho rho0) (Q rho rho0)) p)) *)
    rewrite !sepcon_assoc.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
    rewrite <- sepcon_assoc, (sepcon_comm _ (Q lo p)), sepcon_assoc.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (rangespec (Z.succ lo) len P p) (rangespec (Z.succ lo) len Q p)) (rangespec (Z.succ lo) len (fun (rho : Z) (rho0 : val) => @sepcon mpred Nveric Sveric (P rho rho0) (Q rho rho0)) p) *)
    rewrite IHlen.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
    reflexivity.
Qed.

Lemma rangespec_elim: forall lo len P i,
  lo <= i < lo + Z_of_nat len -> rangespec lo len P |-- P i * TT.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros. revert lo i H; induction len; intros.
  + simpl in H. omega.
  + simpl. intros; destruct (Z.eq_dec i lo).
    - subst. cancel.
    - replace (P i x * !!True) with (TT * (P i x * TT)) by (apply pred_ext; cancel).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P lo x) (rangespec (Z.succ lo) len P x)) (@sepcon mpred Nveric Sveric (@TT mpred Nveric) (@sepcon mpred Nveric Sveric (P i x) (@TT mpred Nveric))) *)
      apply sepcon_derives; [cancel |].
(* Goal: @derives mpred Nveric (rangespec (Z.succ lo) len P x) (@sepcon mpred Nveric Sveric (P i x) (@TT mpred Nveric)) *)
      apply IHlen.
(* Goal: and (Z.le (Z.succ lo) i) (Z.lt i (Z.add (Z.succ lo) (Z.of_nat len))) *)
      rewrite Nat2Z.inj_succ in H.
      rewrite <- Z.add_1_l in *.
(* Goal: @eq Z z z *)
      omega.
Qed.

Inductive Forallz {A} (P: Z -> A->Prop) : Z -> list A -> Prop :=
 | Forallz_nil : forall i, Forallz P i nil
 | Forallz_cons : forall i x l, P i x -> Forallz P (Z.succ i) l -> Forallz P i (x::l).

(******************************************

Definition of aggregate predicates.

******************************************)

Definition array_pred {A: Type}{d: Inhabitant A}  (lo hi: Z) (P: Z -> A -> val -> mpred) (v: list A) (p: val) : mpred :=
  !! (Zlength v = hi - lo) &&
  rangespec lo (Z.to_nat (hi-lo)) (fun i => P i (Znth (i-lo) v)) p.

Definition struct_pred (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_prod (map A m)) (p: val): mpred.
Proof.
(* Goal: mpred *)
  destruct m as [| (i0, t0) m]; [exact emp |].
(* Goal: Prop *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros ? ? v.
  + simpl in v.
(* Goal: mpred *)
    exact (P _ v p).
  + simpl in v.
(* Goal: mpred *)
    exact ((P _ (fst v) p) * IHm i0 t0 (snd v)).
Defined.

(* when unfold, do cbv [struct_pred list_rect]. *)

Definition union_pred (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_sum (map A m)) (p: val): mpred.
Proof.
(* Goal: mpred *)
  destruct m as [| (i0, t0) m]; [exact emp |].
(* Goal: Prop *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros ? ? v.
  + simpl in v.
(* Goal: mpred *)
    exact (P _ v p).
  + simpl in v.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) v) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    destruct v as [v | v].
    - exact (P _ v p).
    - exact (IHm i0 t0 v).
Defined.

Definition array_Prop {A: Type} (d:A) (lo hi: Z) (P: Z -> A -> Prop) (v: list A) : Prop :=
   Zlength v = hi-lo /\ Forallz P 0 v.

Definition struct_Prop (m: members) {A: ident * type -> Type}
                             (P: forall it, A it -> Prop) (v: compact_prod (map A m)) : Prop.
Proof.
(* Goal: Prop *)
  destruct m as [| (i0, t0) m]; [exact True |].
(* Goal: Prop *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros ? ? v.
  + simpl in v.
(* Goal: Prop *)
    exact (P _ v).
  + simpl in v.
(* Goal: Prop *)
    exact ((P _ (fst v)) /\ IHm i0 t0 (snd v)).
Defined.

Definition union_Prop (m: members) {A: ident * type -> Type}
               (P: forall it, A it -> Prop) (v: compact_sum (map A m)): Prop.
Proof.
(* Goal: Prop *)
  destruct m as [| (i0, t0) m]; [exact True |].
(* Goal: Prop *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros ? ? v.
  + simpl in v.
(* Goal: Prop *)
    exact (P _ v).
  + simpl in v.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) v) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    destruct v as [v | v].
    - exact (P _ v).
    - exact (IHm i0 t0 v).
Defined.

(******************************************

Properties

******************************************)

Lemma array_pred_len_0: forall {A}{d: Inhabitant A} lo hi P p,
  hi = lo ->
  array_pred lo hi P nil p = emp.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
  replace (Z.to_nat (hi - lo)) with 0%nat by (symmetry; apply nat_of_Z_neg; omega).
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
  simpl.
(* Goal: @eq mpred (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A (@cons A v (@nil A))) (Zpos xH))) (P i (@Znth A d (Z.sub i i) (@cons A v (@nil A))) p)) (P i v p) *)
  rewrite prop_true_andp by (unfold Zlength; simpl; omega).
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
  reflexivity.
Qed.

Lemma array_pred_len_1: forall {A}{d: Inhabitant A} i P v p,
  array_pred i (i + 1) P (v :: nil) p = P i v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
  replace (i + 1 - i) with 1 by omega.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
  simpl. rewrite sepcon_emp.
(* Goal: @eq mpred (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A (@cons A v (@nil A))) (Zpos xH))) (P i (@Znth A d (Z.sub i i) (@cons A v (@nil A))) p)) (P i v p) *)
  rewrite prop_true_andp by (unfold Zlength; simpl; omega).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  unfold Znth. rewrite Z.sub_diag. rewrite if_false by omega. change (Z.to_nat 0) with 0%nat. auto.
Qed.

Lemma split_array_pred: forall {A}{d: Inhabitant A} lo mid hi P v p,
  lo <= mid <= hi ->
  Zlength v = hi - lo ->
  array_pred lo hi P v p =
  array_pred lo mid P (sublist 0 (mid-lo) v) p *
  array_pred mid hi P (sublist (mid-lo) (hi-lo) v) p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  normalize.
  rewrite prop_true_andp by (rewrite !Zlength_sublist by omega; omega).
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P v p) R *)
  clear H0.
  remember (Z.to_nat (mid-lo)) as n.
  replace (Z.to_nat (hi-lo)) with (n + Z.to_nat (hi-mid))%nat in *
    by (subst n; rewrite <- Z2Nat.inj_add by omega; f_equal; omega).
  assert (lo = mid - Z.of_nat n)
    by (rewrite Heqn; rewrite Z2Nat.id by omega; omega).
  clear Heqn.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert lo v H H0; induction n; intros.
  + subst lo.
    change (Z.of_nat 0) with 0 in *.
    simpl rangespec at 2. rewrite emp_sepcon.
    rewrite Z.sub_0_r, Z.sub_diag, plus_0_l.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    apply rangespec_ext; intros.
(* Goal: @eq Z z z *)
    rewrite Z2Nat.id in H0 by omega.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
(* Goal: @eq Z z z *)
    rewrite Znth_sublist, Z.add_0_r by omega.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
    reflexivity.
  + simpl plus at 1.
    unfold rangespec; fold rangespec.
    repeat match goal with |- context [(?A * ?B) p] => change ((A*B)p) with (A p * B p) end.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (P lo p) (rangespec (Z.succ lo) len P p)) (@sepcon mpred Nveric Sveric (Q lo p) (rangespec (Z.succ lo) len Q p))) (@sepcon mpred Nveric Sveric (@sepcon mpred Nveric Sveric (P lo p) (Q lo p)) (rangespec (Z.succ lo) len (fun (rho : Z) (rho0 : val) => @sepcon mpred Nveric Sveric (P rho rho0) (Q rho rho0)) p)) *)
    rewrite !sepcon_assoc.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
    - f_equal.
(* Goal: @eq mpred (P i (if zlt (Z.sub i i) Z0 then @default A d else @nth A (Z.to_nat (Z.sub i i)) (@cons A v (@nil A)) d) p) (P i v p) *)
      rewrite Z.sub_diag.
      subst lo.
      rewrite Znth_sublist by (try rewrite Nat2Z.inj_succ; omega).
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
    - replace (rangespec (Z.succ lo) (n + Z.to_nat (hi - mid))
              (fun i : Z => P i (Znth (i - lo) v)) p)
      with (rangespec (Z.succ lo) (n + Z.to_nat (hi - mid))
              (fun i : Z => P i (Znth (i - Z.succ lo) (skipn 1 v))) p).
      2:{
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
        apply rangespec_ext; intros.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
        f_equal.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite <- Znth_succ by omega; auto.
      }
      rewrite Nat2Z.inj_succ in H0.
(* Goal: @eq Z z z *)
      rewrite IHn by omega.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      * apply rangespec_ext; intros.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
        f_equal.
(* Goal: @eq Z z z *)
        rewrite Znth_sublist, Z.add_0_r by omega.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite <- Znth_succ by omega; auto.
(* Goal: @eq Z z z *)
        rewrite Znth_sublist, Z.add_0_r by omega.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
        reflexivity.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      * apply rangespec_ext; intros.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
        f_equal.
(* Goal: @eq Z z z *)
        rewrite Z2Nat.id in H1 by omega.
(* Goal: @eq Z z z *)
        rewrite Znth_sublist by omega.
(* Goal: @eq Z z z *)
        rewrite Znth_sublist by omega.
        replace (i - mid + (mid - Z.succ lo)) with (i - Z.succ lo) by omega.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite <- Znth_succ by omega; auto.
(* Goal: @eq Z z z *)
         f_equal; omega.
Qed.

Lemma array_pred_shift: forall {A}{d: Inhabitant A} (lo hi lo' hi' mv : Z) P' P v p,
  lo - lo' = mv ->
  hi - hi' = mv ->
 (forall i i', lo <= i < hi -> i - i' = mv -> P' i' (Znth (i-lo) v) p = P i (Znth (i-lo) v) p) ->
  array_pred lo' hi' P' v p = array_pred lo hi P v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@andp mpred Nveric (@prop mpred Nveric (and (@eq Z (@Zlength A v) (Z.sub hi lo)) (@eq Z (@Zlength A v) (Z.sub hi lo)))) (@sepcon mpred Nveric Sveric (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  apply andp_prop_ext; [omega | intros].
  replace (hi' - lo') with (hi - lo) by omega.
(* Goal: @eq Z z z *)
  destruct (zlt hi lo). rewrite Z2Nat_neg by omega. reflexivity.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  apply pred_ext; apply rangespec_shift_derives; intros.
(* Goal: @eq Z z z *)
  rewrite H4; rewrite Z2Nat.id in H3 by omega.
(* Goal: @eq Z z z *)
  rewrite H1; auto; omega.
  rewrite <- H4; rewrite Z2Nat.id in H3 by omega.
(* Goal: @eq Z z z *)
  rewrite H1; auto; omega.
Qed.

Lemma array_pred_ext_derives: forall {A B} (dA: Inhabitant A) (dB: Inhabitant B)
         lo hi P0 P1 (v0: list A) v1 p,
  (Zlength v0 = hi - lo -> Zlength v1 = hi - lo) ->
  (forall i, lo <= i < hi ->
    P0 i (Znth (i-lo) v0) p |-- P1 i (Znth (i-lo) v1) p) ->
  array_pred  lo hi P0 v0 p |-- array_pred lo hi P1 v1 p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  normalize.
(* Goal: @eq Z z z *)
  rewrite prop_true_andp by omega.
(* Goal: @derives mpred Nveric (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P0 i (@Znth A dA (Z.sub i lo) v0)) p) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P1 i (@Znth B dB (Z.sub i lo) v1)) p) *)
  apply rangespec_ext_derives.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (P0 i (@Znth A dA (Z.sub i lo) v0) p) (P1 i (@Znth B dB (Z.sub i lo) v1) p) *)
  destruct (zlt hi lo).
  + rewrite Z2Nat_neg  in H2 by omega.
(* Goal: @eq Z z z *)
    change (Z.of_nat 0) with 0 in H2. omega.
  + rewrite Z2Nat.id in H2 by omega.
(* Goal: @eq Z z z *)
    apply H0. omega.
Qed.

Lemma array_pred_ext: forall {A B} (dA: Inhabitant A) (dB: Inhabitant B) lo hi P0 P1 
        (v0: list A) (v1: list B) p,
  Zlength v0 = Zlength v1 ->
  (forall i, lo <= i < hi ->
    P0 i (Znth (i-lo) v0) p = P1 i (Znth (i-lo) v1) p) ->
  array_pred lo hi P0 v0 p = array_pred lo hi P1 v1 p.
Proof.
  intros; apply pred_ext; apply array_pred_ext_derives; intros; try omega;
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  rewrite H0; auto.
Qed.

Lemma at_offset_array_pred: forall  {A} {d: Inhabitant A} lo hi P v ofs p,
  at_offset (array_pred lo hi P v) ofs p = array_pred lo hi (fun i v => at_offset (P i v) ofs) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
  rewrite at_offset_eq.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
  f_equal.
(* Goal: @eq mpred (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) (offset_val ofs p)) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => at_offset (P i (@Znth A d (Z.sub i lo) v)) ofs) p) *)
  apply rangespec_shift.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P v p) R *)
  assert (i = i') by omega; subst i'; clear H0.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
  rewrite at_offset_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  auto.
Qed.

Lemma array_pred_sepcon: forall  {A} {d: Inhabitant A} lo hi P Q v p,
  array_pred lo hi P v p * array_pred lo hi Q v p = array_pred lo hi (P * Q) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  normalize.
(* Goal: @eq mpred (@andp mpred Nveric (@prop mpred Nveric (and (@eq Z (@Zlength A v) (Z.sub hi lo)) (@eq Z (@Zlength A v) (Z.sub hi lo)))) (@sepcon mpred Nveric Sveric (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  apply andp_prop_ext; [omega | intros].
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p)) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p) *)
  rewrite rangespec_sepcon.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  auto.
Qed.

Opaque member_dec.

Lemma struct_pred_ext_derives: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall i d0 d1, in_members i m ->
     P0 _ (proj_struct i m v0 d0) p |-- P1 _ (proj_struct i m v1 d1) p) ->
  struct_pred m P0 v0 p |-- struct_pred m P1 v1 p.
Proof.
(* Goal: forall (m : members) (A0 A1 : forall _ : prod ident type, Type) (P0 : forall (it : prod ident type) (_ : A0 it) (_ : val), mpred) (P1 : forall (it : prod ident type) (_ : A1 it) (_ : val), mpred) (v0 : compact_prod (@map (prod ident type) Type A0 m)) (v1 : compact_prod (@map (prod ident type) Type A1 m)) (p : val) (_ : @eq bool (members_no_replicate m) true) (_ : forall (i : ident) (d0 : A0 (@pair ident type i (field_type i m))) (d1 : A1 (@pair ident type i (field_type i m))) (_ : in_members i m), @derives mpred Nveric (P0 (@pair ident type i (field_type i m)) (@proj_struct i m A0 v0 d0) p) (P1 (@pair ident type i (field_type i m)) (@proj_struct i m A1 v1 d1) p)), @derives mpred Nveric (@struct_pred m A0 P0 v0 p) (@struct_pred m A1 P1 v1 p) *)
  unfold proj_struct, field_type.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @union_Prop m F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f m) *)
  destruct m as [| (i0, t0) m]; [simpl; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v0 v1 H H0; induction m as [| (i1, t1) m]; intros.
  + specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @derives mpred Nveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
    if_tac in H0; [| congruence].
(* Goal: @derives mpred Nveric (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@nil (prod ident type))) A0 P0 v0 p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@nil (prod ident type))) A1 P1 v1 p) *)
    specialize (H0 v0 v1).
(* Goal: @derives mpred Nveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
    spec H0; [left; reflexivity |].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r in H0; rewrite <- !eq_rect_eq in H0.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    simpl.
(* Goal: @derives mpred Nveric (P0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) d0 member_dec) p) (P1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) d1 member_dec) p) *)
    exact H0.
  + change (struct_pred ((i0, t0) :: (i1, t1) :: m) P0 v0 p) with
      (P0 (i0, t0) (fst v0) p * struct_pred ((i1, t1) :: m) P0 (snd v0) p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P1 v1 p) with
      (P1 (i0, t0) (fst v1) p * struct_pred ((i1, t1) :: m) P1 (snd v1) p).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A0 P0 (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p)) (@sepcon mpred Nveric Sveric (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A1 P1 (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p)) *)
    apply sepcon_derives.
    - specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @derives mpred Nveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
      if_tac in H0; [| congruence].
(* Goal: @derives mpred Nveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
      specialize (H0 (fst v0) (fst v1)).
(* Goal: @derives mpred Nveric (P0 (@pair ident type i0 t0) (@fst (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (P1 (@pair ident type i0 t0) (@fst (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
      spec H0; [left; reflexivity |].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
      destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
      unfold eq_rect_r in H0; rewrite <- !eq_rect_eq in H0.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
      simpl.
(* Goal: @derives mpred Nveric (P0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) d0 member_dec) p) (P1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) d1 member_dec) p) *)
      exact H0.
    - rewrite members_no_replicate_ind in H.
(* Goal: @derives mpred Nveric (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A0 P0 (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A1 P1 (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) p) *)
      apply IHm; [tauto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      specialize (H0 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @derives mpred Nveric (P0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) d0 member_dec) p) (P1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) d1 member_dec) p) *)
      if_tac in H0.
      * clear - H H1 H2.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
        subst.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        tauto.
      * specialize (H0 d0 d1).
(* Goal: @derives mpred Nveric (P0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) d0 member_dec) p) (P1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) d1 member_dec) p) *)
        spec H0; [right; auto |].
        change (if ident_eq i i1
                then Errors.OK t1
                else Ctypes.field_type i m) with (Ctypes.field_type i ((i1, t1) :: m)) in H0.
        destruct (member_dec
             (i,
             match Ctypes.field_type i ((i1, t1) :: m) with
             | Errors.OK t => t
             | Errors.Error _ => Tvoid
             end) (i0, t0)); [congruence |].
(* Goal: @derives mpred Nveric (P0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A0 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A0 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m with | nil => A0 (@pair ident type i1 t1) | cons T l => prod (A0 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A0 a) (map t) end) m)) end v0) d0 member_dec) p) (P1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@proj_compact_prod (prod ident type) A1 (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i1 t1) m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@cons (prod ident type) (@pair ident type i1 t1) m) (@snd (A1 (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m with | nil => A1 (@pair ident type i1 t1) | cons T l => prod (A1 (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A1 a) (map t) end) m)) end v1) d1 member_dec) p) *)
        exact H0.
Qed.

Lemma struct_pred_ext: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall i d0 d1, in_members i m ->
     P0 _ (proj_struct i m v0 d0) p = P1 _ (proj_struct i m v1 d1) p) ->
  struct_pred m P0 v0 p = struct_pred m P1 v1 p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
  apply pred_ext; eapply struct_pred_ext_derives; eauto;
(* Goal: @derives mpred Nveric (P' i p') (P' i p') *)
(* Goal: and (Z.le lo i') (Z.lt i' (Z.add lo (Z.of_nat len))) *)
  intros; erewrite H0 by eauto; auto;      apply derives_refl.
Qed.

Lemma struct_pred_not_member: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p,
  let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in
  ~ in_members i m ->
  struct_pred m P v p = struct_pred m P' v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@andp mpred Nveric Q (@union_pred m A P v p)) match m with | nil => @andp mpred Nveric Q (@emp mpred Nveric Sveric) | cons p0 l => @union_pred m A (fun (it : prod ident type) (v : A it) (p : val) => @andp mpred Nveric Q (P it v p)) v p end *)
  destruct m as [| (i0, t0) m]; [auto |].
  unfold proj_struct, field_type in *.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P' v p) *)
  revert i0 t0 H v; induction m as [| (i1, t1) m]; intros i0 t0 H.
  + intros; subst P'; simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_false; auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    intro; apply H; subst; left; auto.
  + set (M := (i1, t1) :: m).
(* Goal: forall v : compact_prod (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i0 t0) M)), @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P' v p) *)
    simpl compact_prod; simpl Ctypes.field_type.
(* Goal: forall v : prod (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end, @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P' v p) *)
    intros v.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P' v p) *)
    subst M.
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p)
      with (P _ (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P' v p)
      with (P' _ (fst v) p * struct_pred ((i1, t1) :: m) P' (snd v) p).
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    destruct (ident_eq i i0).
    - subst P'; intros; subst.
(* Goal: @derives mpred Nveric (P i' p) (P' i' p) *)
      exfalso; apply H.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      left; auto.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    - intros.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
      * unfold P'.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite if_false by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
      * apply IHm.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        intro; apply H; right; auto.
Qed.

Lemma struct_pred_proj: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in
  members_no_replicate m = true ->
  in_members i m ->
  struct_pred m P v p = P _ (proj_struct i m v d) p * struct_pred m P' v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@union_pred m A P (match m as l return (forall _ : @In (prod ident type) (@pair ident type i (field_type i m)) l, compact_sum (@map (prod ident type) Type A l)) with | nil => fun _ : @In (prod ident type) (@pair ident type i (field_type i m)) (@nil (prod ident type)) => tt | cons a0 l => fun i0 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a0 l) => @list_rect (prod ident type) (fun l0 : list (prod ident type) => forall (a1 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (fun (a1 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 (@nil (prod ident type)))) => match member_dec (@pair ident type i (field_type i m)) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : @In (prod ident type) a (@cons (prod ident type) a1 (@nil (prod ident type)))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) (fun (v0 : A a1) (_ : @In (prod ident type) a1 (@cons (prod ident type) a1 (@nil (prod ident type)))) => v0) (@pair ident type i (field_type i m)) e v0 i1 | right n => match @aux0 (prod ident type) (@pair ident type i (field_type i m)) a1 i1 n return (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) with end end) (fun (a1 : prod ident type) (l0 : list (prod ident type)) (IHl : forall (a2 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 l0))) (a2 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => match member_dec (@pair ident type i (field_type i m)) a2 with | left e => @eq_rect_r (prod ident type) a2 (fun a : prod ident type => forall (_ : A a) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0)))) (fun (v0 : A a2) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a2 (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a2 (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => @inl (A a2) match (fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0 with | nil => A a1 | cons T l1 => sum (A a1) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l2 as T1) => sum t (compact_sum T1) end) ((fix map (l2 : list (prod ident type)) : list Type := match l2 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0)) end v0) (@pair ident type i (field_type i m)) e v0 IHl i1 | right n => @inr (A a2) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (IHl a1 (@aux1 (prod ident type) (@pair ident type i (field_type i m)) a2 (@cons (prod ident type) a1 l0) i1 n)) end) l a0 i0 end H1) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  destruct m as [| (i0, t0) m]; [inv H0 |].
  unfold proj_struct, field_type in *.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 H v d H0; induction m as [| (i1, t1) m]; intros.
  + subst P'; simpl in *.
(* Goal: @eq mpred (P (@pair ident type i0 t0) match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) False), A (@pair ident type i0 t0)) (fun (v0 : A (@pair ident type i0 t0)) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 H1 | right n => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) H1 n return (A (@pair ident type i0 t0)) with end end p) (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct H0; [simpl in H0; subst i | tauto].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite sepcon_emp; auto.
  + pose proof H.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P (@upd_struct i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A v v0) p) (@sepcon mpred Nveric Sveric (P (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P' v p)) *)
    apply members_no_replicate_ind in H1; destruct H1.
(* Goal: forall v : compact_prod (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m))), @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P' v p) *)
    set (M := (i1, t1) :: m).
    simpl compact_prod in v |- *; simpl Ctypes.field_type in d |- *.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P v p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) M) A P' v p) *)
    subst M.
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p)
      with (P _ (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P' v p)
      with (P' _ (fst v) p * struct_pred ((i1, t1) :: m) P' (snd v) p).
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    destruct (ident_eq i i0).
    - subst i0.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
      * simpl.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (P (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i t0) (@pair ident type i t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i t0) => @pair (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i t0) e v0 | right n => @pair (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i t0) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i t0) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i t0) (@pair ident type i t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i t0) => @pair (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i t0) e v0 | right n => @pair (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i t0) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i t0) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p)) (@sepcon mpred Nveric Sveric (P (@pair ident type i t0) v0 p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p))) *)
        destruct (member_dec (i, t0) (i, t0)); [| congruence].
        unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      * erewrite struct_pred_not_member by eauto.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A (fun it : prod positive type => if ident_eq i (@fst positive type it) then fun (_ : A it) (_ : val) => @emp mpred Nveric Sveric else P it) (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p)) *)
        unfold P' at 1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite if_true by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite emp_sepcon; auto.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    - intros.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i0 t0) => @pair (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n => @pair (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i0 t0) => @pair (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n => @pair (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p)) (@sepcon mpred Nveric Sveric (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p))) *)
      destruct H0; [simpl in H0; congruence |].
      rewrite <- sepcon_assoc, (sepcon_comm _ (P' _ _ _)), sepcon_assoc.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
      * unfold P'.
(* Goal: @eq mpred (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) ((if ident_eq i i0 then fun (_ : A (@pair ident type i0 t0)) (_ : val) => @emp mpred Nveric Sveric else P (@pair ident type i0 t0)) (@fst (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) *)
        rewrite if_false by (simpl; congruence).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      * erewrite IHm by eauto.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
        f_equal.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
        simpl.
        match goal with
        | |- context [member_dec (i, ?t') (i0, t0)] =>
                destruct (member_dec (i, t') (i0, t0));
                  [inversion e; congruence |]
        end.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
Qed.

Lemma struct_pred_upd: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p v0,
  let P' it := if ident_eq i (fst it) then fun _ _ => emp else P it in
  members_no_replicate m = true ->
  in_members i m ->
  struct_pred m P (upd_struct i m v v0) p = P _ v0 p * struct_pred m P' v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@union_pred m A P (match m as l return (forall _ : @In (prod ident type) (@pair ident type i (field_type i m)) l, compact_sum (@map (prod ident type) Type A l)) with | nil => fun _ : @In (prod ident type) (@pair ident type i (field_type i m)) (@nil (prod ident type)) => tt | cons a0 l => fun i0 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a0 l) => @list_rect (prod ident type) (fun l0 : list (prod ident type) => forall (a1 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (fun (a1 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 (@nil (prod ident type)))) => match member_dec (@pair ident type i (field_type i m)) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : @In (prod ident type) a (@cons (prod ident type) a1 (@nil (prod ident type)))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) (fun (v0 : A a1) (_ : @In (prod ident type) a1 (@cons (prod ident type) a1 (@nil (prod ident type)))) => v0) (@pair ident type i (field_type i m)) e v0 i1 | right n => match @aux0 (prod ident type) (@pair ident type i (field_type i m)) a1 i1 n return (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) with end end) (fun (a1 : prod ident type) (l0 : list (prod ident type)) (IHl : forall (a2 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 l0))) (a2 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => match member_dec (@pair ident type i (field_type i m)) a2 with | left e => @eq_rect_r (prod ident type) a2 (fun a : prod ident type => forall (_ : A a) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0)))) (fun (v0 : A a2) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a2 (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a2 (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => @inl (A a2) match (fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0 with | nil => A a1 | cons T l1 => sum (A a1) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l2 as T1) => sum t (compact_sum T1) end) ((fix map (l2 : list (prod ident type)) : list Type := match l2 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0)) end v0) (@pair ident type i (field_type i m)) e v0 IHl i1 | right n => @inr (A a2) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (IHl a1 (@aux1 (prod ident type) (@pair ident type i (field_type i m)) a2 (@cons (prod ident type) a1 l0) i1 n)) end) l a0 i0 end H1) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  destruct m as [| (i0, t0) m]; [inv H0 |].
  unfold proj_struct, field_type in *.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 H v v0 H0; induction m as [| (i1, t1) m]; intros.
  + subst P'; simpl in *.
(* Goal: @eq mpred (P (@pair ident type i0 t0) match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) False), A (@pair ident type i0 t0)) (fun (v0 : A (@pair ident type i0 t0)) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 H1 | right n => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) H1 n return (A (@pair ident type i0 t0)) with end end p) (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct H0; [simpl in H0; subst i | tauto].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite sepcon_emp; auto.
  + pose proof H.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P (@upd_struct i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A v v0) p) (@sepcon mpred Nveric Sveric (P (@pair ident type i match Ctypes.field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P' v p)) *)
    apply members_no_replicate_ind in H1; destruct H1.
    simpl compact_prod in v |- *; simpl Ctypes.field_type in v0 |- *.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P (@upd_struct i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A v v0) p) (@sepcon mpred Nveric Sveric (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P' v p)) *)
    set (v' := (upd_struct i ((i0, t0) :: (i1, t1) :: m) v v0)).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v' p)
      with (P _ (fst v') p * struct_pred ((i1, t1) :: m) P (snd v') p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P' v p)
      with (P' _ (fst v) p * struct_pred ((i1, t1) :: m) P' (snd v) p).
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v') p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v') p)) (@sepcon mpred Nveric Sveric (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p))) *)
    subst v'.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end (@upd_struct i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A v v0)) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end (@upd_struct i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A v v0)) p)) (@sepcon mpred Nveric Sveric (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p))) *)
    simpl upd_struct.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    destruct (ident_eq i i0).
    - subst i0.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (P (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i t0) (@pair ident type i t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i t0) => @pair (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i t0) e v0 | right n => @pair (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i t0) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i t0) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end match member_dec (@pair ident type i t0) (@pair ident type i t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i t0) (fun a : prod ident type => forall _ : A a, prod (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end) (fun v0 : A (@pair ident type i t0) => @pair (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@pair ident type i t0) e v0 | right n => @pair (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end (@fst (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a0) (fun v0 : A a0 => v0) (@pair ident type i t0) e v0 | right n0 => v end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => prod (A a1) (compact_prod (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (v : prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall _ : A a, prod (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end) (fun v0 : A a1 => @pair (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) (@pair ident type i t0) e v0 | right n0 => @pair (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => prod (A a0) (compact_prod (@map (prod ident type) Type A l)) end (@fst (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v) (IHl a0 (@snd (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => prod (A a0) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => prod t (compact_prod T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v)) end) m (@pair ident type i1 t1) (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) end) p)) (@sepcon mpred Nveric Sveric (P (@pair ident type i t0) v0 p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p))) *)
      destruct (member_dec (i, t0) (i, t0)); [| congruence].
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
      * simpl.
        unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
      * unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end (@pair (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0 (@snd (A (@pair ident type i t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v))) p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p)) *)
        change (snd (v0, snd v)) with (snd v).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        erewrite struct_pred_not_member by eauto.
(* Goal: @eq mpred (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A (fun it : prod positive type => if ident_eq i (@fst positive type it) then fun (_ : A it) (_ : val) => @emp mpred Nveric Sveric else P it) (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@sepcon mpred Nveric Sveric (P' (@pair ident type i t0) (@fst (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P' (@snd (A (@pair ident type i t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p)) *)
        unfold P' at 1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite if_true by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        rewrite emp_sepcon; auto.
    - destruct H0; [simpl in H0; congruence |].
      rewrite <- sepcon_assoc, (sepcon_comm _ (P' _ _ _)), sepcon_assoc.
      match goal with
      | |- context [member_dec (i, ?t') (i0, t0)] =>
              destruct (member_dec (i, t') (i0, t0));
                [inversion e; congruence |]
      end.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
      f_equal.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
      * unfold P'; simpl.
(* Goal: @eq mpred (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) ((if ident_eq i i0 then fun (_ : A (@pair ident type i0 t0)) (_ : val) => @emp mpred Nveric Sveric else P (@pair ident type i0 t0)) (@fst (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type A m)) end v) p) *)
        rewrite if_false by (simpl; congruence).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        auto.
      * simpl snd.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        simpl in IHm |- *; erewrite IHm by auto.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
        reflexivity.
Qed.

Lemma struct_pred_ramif: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  in_members i m ->
  members_no_replicate m = true ->
  struct_pred m P v p |--
    P _ (proj_struct i m v d) p *
     (ALL v0: _, P _ v0 p -* struct_pred m P (upd_struct i m v v0) p).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@struct_pred m A P v p) (@sepcon mpred Nveric Sveric (P (@pair ident type i (field_type i m)) (@proj_struct i m A v d) p) (@allp mpred Nveric (A (@pair ident type i (field_type i m))) (fun v0 : A (@pair ident type i (field_type i m)) => @wand mpred Nveric Sveric (P (@pair ident type i (field_type i m)) v0 p) (@struct_pred m A P (@upd_struct i m A v v0) p)))) *)
  set (P' it := if ident_eq i (fst it) then fun _ _ => emp else P it).
(* Goal: @derives mpred Nveric (@struct_pred m A P v p) (@sepcon mpred Nveric Sveric (P (@pair ident type i (field_type i m)) (@proj_struct i m A v d) p) (@allp mpred Nveric (A (@pair ident type i (field_type i m))) (fun v0 : A (@pair ident type i (field_type i m)) => @wand mpred Nveric Sveric (P (@pair ident type i (field_type i m)) v0 p) (@struct_pred m A P (@upd_struct i m A v v0) p)))) *)
  apply RAMIF_Q.solve with (struct_pred m P' v p).
  + apply derives_refl'.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply struct_pred_proj; auto.
  + intro v0.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i m)) v0 p) (@union_pred m A P (@upd_union i m A v v0) p) *)
    apply derives_refl'.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@struct_pred m A P' v p) (P (@pair ident type i (field_type i m)) v0 p)) (@struct_pred m A P (@upd_struct i m A v v0) p) *)
    symmetry; rewrite sepcon_comm.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply struct_pred_upd; auto.
Qed.

Lemma at_offset_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs,
  at_offset (struct_pred m P v) ofs p = struct_pred m (fun it v => at_offset (P it v) ofs) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
  rewrite at_offset_eq.
(* Goal: @eq mpred (@andp mpred Nveric Q (@union_pred m A P v p)) match m with | nil => @andp mpred Nveric Q (@emp mpred Nveric Sveric) | cons p0 l => @union_pred m A (fun (it : prod ident type) (v : A it) (p : val) => @andp mpred Nveric Q (P it v p)) v p end *)
  destruct m as [| (i0, t0) m]; [auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
    rewrite at_offset_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + simpl.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
    rewrite at_offset_eq.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
Qed.

Lemma corable_andp_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q,
  corable Q ->
  Q && struct_pred m P v p =
  match m with
  | nil => Q && emp
  | _ => struct_pred m (fun it v p => Q && P it v p) v p
  end.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@andp mpred Nveric Q (@union_pred m A P v p)) match m with | nil => @andp mpred Nveric Q (@emp mpred Nveric Sveric) | cons p0 l => @union_pred m A (fun (it : prod ident type) (v : A it) (p : val) => @andp mpred Nveric Q (P it v p)) v p end *)
  destruct m as [| (i0, t0) m]; [auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p)
      with (P (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p).
    pattern Q at 1; rewrite <- (andp_dup Q).
(* Goal: @eq mpred (@andp mpred Nveric (@andp mpred Nveric Q Q) (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p))) (@struct_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (v : A it) (p : val) => @andp mpred Nveric Q (P it v p)) v p) *)
    rewrite andp_assoc.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite <- corable_sepcon_andp1 by auto.
(* Goal: @eq Prop (and (P (@pair ident type i1 t1) (@fst (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs (field_type (@fst ident type a) m0)) (map t) end) m with | nil => @reptype cs (field_type (@fst ident type (@pair ident type i0 t0)) m0) | cons T l => prod (@reptype cs (field_type (@fst ident type (@pair ident type i0 t0)) m0)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs (field_type (@fst ident type a) m0)) (map t) end) m)) end v)) (struct_value_fits_aux (@cons (prod ident type) (@pair ident type i0 t0) m) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i0 t0) m)) (@snd (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs (field_type (@fst ident type a) m0)) (map t) end) m with | nil => @reptype cs (field_type (@fst ident type (@pair ident type i0 t0)) m0) | cons T l => prod (@reptype cs (field_type (@fst ident type (@pair ident type i0 t0)) m0)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs (field_type (@fst ident type a) m0)) (map t) end) m)) end v))) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    rewrite IHm.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite <- corable_andp_sepcon1 by auto.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
    reflexivity.
Qed.

Lemma struct_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p,
  struct_pred m P v p * struct_pred m Q v p = struct_pred m (fun it => P it * Q it) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@union_pred m A P v p) (@union_pred m A Q v p)) (@union_pred m A (fun it : prod ident type => @sepcon (forall (_ : A it) (_ : val), mpred) (@LiftNatDed (A it) (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog (A it) (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric)) (P it) (Q it)) v p) *)
  destruct m as [| (i0, t0) m]; [| revert i0 t0 v; induction m as [| (i1, t1) m]; intros].
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite emp_sepcon; auto.
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p)
      with (P (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) Q v p)
      with (Q (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) Q (snd v) p).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) (fun it => P it * Q it) v p)
      with (P (i0, t0) (fst v) p * Q (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) (fun it => P it * Q it) (snd v) p).
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    rewrite !sepcon_assoc; f_equal.
    rewrite <- sepcon_assoc, (sepcon_comm _ (Q _ _ _)), sepcon_assoc; f_equal.
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c) (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
    apply IHm.
Qed.

Lemma compact_sum_inj_eq_spec: forall {A} a0 a1 (l: list A) F0 F1 (v0: compact_sum (map F0 (a0 :: a1 :: l))) (v1: compact_sum (map F1 (a0 :: a1 :: l))) H,
  ~ In a0 (a1 :: l) ->
 ((forall a, compact_sum_inj v0 a H <-> compact_sum_inj v1 a H) <->
  match v0, v1 with
  | inl _, inl _ => True
  | inr v0, inr v1 => forall a, compact_sum_inj (v0: compact_sum (map F0 (a1 :: l))) a H <-> compact_sum_inj (v1: compact_sum (map F1 (a1 :: l))) a H
  | _, _ => False
  end).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
  rename H0 into H_not_in.
  destruct v0, v1.
  + simpl.
    firstorder.
  + assert (~ (forall a : A,
      iff
        (@compact_sum_inj A F0 (@cons A a0 (@cons A a1 l))
           (@inl (F0 a0) (compact_sum (@map A Type F0 (@cons A a1 l))) f) a H)
        (@compact_sum_inj A F1 (@cons A a0 (@cons A a1 l))
           (@inr (F1 a0) (compact_sum (@map A Type F1 (@cons A a1 l))) c) a H))); [| tauto].
    intro.
    specialize (H0 a0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
    destruct (H a0 a0); [| congruence].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    tauto.
  + assert (~ (forall a : A,
      iff
        (@compact_sum_inj A F0 (@cons A a0 (@cons A a1 l))
           (@inr (F0 a0) (compact_sum (@map A Type F0 (@cons A a1 l))) c) a H)
        (@compact_sum_inj A F1 (@cons A a0 (@cons A a1 l))
           (@inl (F1 a0) (compact_sum (@map A Type F1 (@cons A a1 l))) f) a H))); [| tauto].
    intro.
    specialize (H0 a0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
    destruct (H a0 a0); [| congruence].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    tauto.
  + split; intros HH a; specialize (HH a).
    - pose proof compact_sum_inj_in c a H.
      pose proof compact_sum_inj_in c0 a H.
Opaque In.
      simpl in HH, H0, H1 |- *.
Transparent In.
      destruct (H a a0).
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
      * subst.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        tauto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      * tauto.
    - simpl in HH |- *.
      destruct (H a a0).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      * tauto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      * tauto.
Qed.

Lemma union_pred_ext_derives: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall it, members_union_inj v0 it <-> members_union_inj v1 it) ->
  (forall i d0 d1, members_union_inj v0 (i, field_type i m) -> members_union_inj v1 (i, field_type i m) ->
     P0 _ (proj_union i m v0 d0) p |-- P1 _ (proj_union i m v1 d1) p) ->
  union_pred m P0 v0 p |-- union_pred m P1 v1 p.
Proof.
  unfold members_union_inj, proj_union, field_type.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @union_Prop m F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f m) *)
  destruct m as [| (i0, t0) m]; [simpl; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v0 v1 H H0 H1; induction m as [| (i1, t1) m]; intros.
  + specialize (H1 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    simpl in H1.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    if_tac in H1; [| congruence].
    specialize (H1 v0 v1).
    spec H1; [if_tac; [auto | congruence] |].
    spec H1; [if_tac; [auto | congruence] |].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r in H1; rewrite <- !eq_rect_eq in H1.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    simpl.
    exact H1.
  + rewrite compact_sum_inj_eq_spec in H0.
    2:{
      clear - H.
      pose proof in_members_tail_no_replicate i0 _ _ _ H.
      intro HH; apply in_map with (f := fst) in HH.
      apply H0 in HH.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      tauto.
    }
    destruct v0 as [v0 | v0], v1 as [v1 | v1]; try solve [inversion H0].
    - specialize (H1 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      simpl in H1.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      if_tac in H1; [| congruence].
      specialize (H1 v0 v1).
      spec H1; [if_tac; [auto | congruence] |].
      spec H1; [if_tac; [auto | congruence] |].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
      destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
      unfold eq_rect_r in H1; rewrite <- !eq_rect_eq in H1.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
      simpl.
      exact H1.
    - rewrite members_no_replicate_ind in H.
      apply IHm; [tauto | tauto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) (P (@pair ident type i0 t0) d p) *)
      specialize (H1 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      simpl in H1.
      if_tac in H1. (* i = i0 vs i <> i0 *)
      * clear - H H2 H4 t0.
        pose proof compact_sum_inj_in v0 (i, field_type i ((i1, t1) :: m)) member_dec.
        spec H0; [exact H2 |].
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
        subst.
        apply in_map with (f := fst) in H0.
        unfold fst at 1 in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        tauto.
      * specialize (H1 d0 d1).
        change (if ident_eq i i1
                then Errors.OK t1
                else Ctypes.field_type i m) with (Ctypes.field_type i ((i1, t1) :: m)) in H1.
        destruct (member_dec
             (i,
             match Ctypes.field_type i ((i1, t1) :: m) with
             | Errors.OK t => t
             | Errors.Error _ => Tvoid
             end) (i0, t0)); [congruence |].
        spec H1; [auto |].
        spec H1; [auto |].
        exact H1.
Qed.

Lemma union_pred_ext: forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall it, members_union_inj v0 it <-> members_union_inj v1 it) ->
  (forall i d0 d1, members_union_inj v0 (i, field_type i m) -> members_union_inj v1 (i, field_type i m) ->
     P0 _ (proj_union i m v0 d0) p = P1 _ (proj_union i m v1 d1) p) ->
  union_pred m P0 v0 p = union_pred m P1 v1 p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
  assert (forall it, members_union_inj v1 it <-> members_union_inj v0 it)
    by (intro it; specialize (H0 it); tauto).
  apply pred_ext; eapply union_pred_ext_derives; auto;
(* Goal: @derives mpred Nveric (P' i p') (P' i p') *)
(* Goal: and (Z.le lo i') (Z.lt i' (Z.add lo (Z.of_nat len))) *)
  intros; erewrite H1 by eauto; apply derives_refl.
Qed.

Lemma union_pred_derives_const: forall m {A} (P: forall it, A it -> val -> mpred) p v R,
  members_no_replicate m = true ->
  m <> nil ->
  (forall i (v: A (i, field_type i m)), in_members i m -> P _ v p |-- R) ->
  union_pred m P v p |-- R.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@union_pred m A P v p) R *)
  destruct m as [| (i0, t0) m]; [congruence |].
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P v p) R *)
  clear H0.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v H H1; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    specialize (H1 i0); simpl in H1.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H1; left; auto.
  + destruct v; simpl.
    - specialize (H1 i0); simpl in H1.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
      destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H1; left; auto.
    - pose proof H.
(* Goal: @struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) F P (@compact_prod_gen (prod ident type) F f (@cons (prod ident type) (@pair ident type i1 t1) m)) *)
      rewrite members_no_replicate_ind in H; destruct H.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply (IHm i1 t1); auto.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) (P (@pair ident type i0 t0) d p) *)
      specialize (H1 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) R *)
      pose proof in_members_tail_no_replicate _ _ _ _ H0 H3.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) (P (@pair ident type i0 t0) d p) *)
      simpl in H1; destruct (ident_eq i i0); [congruence |].
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
      apply H1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      right; auto.
Qed.

Lemma union_pred_proj: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  members_no_replicate m = true ->
  in_members i m ->
  (forall i' (v': A (i', field_type i' m)), in_members i' m -> P _ v' p |-- P _ d p) ->
  union_pred m P v p |-- P _ (proj_union i m v d) p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@union_pred m A P (match m as l return (forall _ : @In (prod ident type) (@pair ident type i (field_type i m)) l, compact_sum (@map (prod ident type) Type A l)) with | nil => fun _ : @In (prod ident type) (@pair ident type i (field_type i m)) (@nil (prod ident type)) => tt | cons a0 l => fun i0 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a0 l) => @list_rect (prod ident type) (fun l0 : list (prod ident type) => forall (a1 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (fun (a1 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 (@nil (prod ident type)))) => match member_dec (@pair ident type i (field_type i m)) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : @In (prod ident type) a (@cons (prod ident type) a1 (@nil (prod ident type)))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) (fun (v0 : A a1) (_ : @In (prod ident type) a1 (@cons (prod ident type) a1 (@nil (prod ident type)))) => v0) (@pair ident type i (field_type i m)) e v0 i1 | right n => match @aux0 (prod ident type) (@pair ident type i (field_type i m)) a1 i1 n return (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) with end end) (fun (a1 : prod ident type) (l0 : list (prod ident type)) (IHl : forall (a2 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 l0))) (a2 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => match member_dec (@pair ident type i (field_type i m)) a2 with | left e => @eq_rect_r (prod ident type) a2 (fun a : prod ident type => forall (_ : A a) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0)))) (fun (v0 : A a2) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a2 (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a2 (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => @inl (A a2) match (fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0 with | nil => A a1 | cons T l1 => sum (A a1) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l2 as T1) => sum t (compact_sum T1) end) ((fix map (l2 : list (prod ident type)) : list Type := match l2 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0)) end v0) (@pair ident type i (field_type i m)) e v0 IHl i1 | right n => @inr (A a2) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (IHl a1 (@aux1 (prod ident type) (@pair ident type i (field_type i m)) a2 (@cons (prod ident type) a1 l0) i1 n)) end) l a0 i0 end H1) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  destruct m as [| (i0, t0) m]; [inv H0 |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v d H H0 H1; induction m as [| (i1, t1) m]; intros.
  + destruct H0; [simpl in H0; subst i | tauto].
    simpl in *.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + pose proof H.
(* Goal: @struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) F P (@compact_prod_gen (prod ident type) F f (@cons (prod ident type) (@pair ident type i1 t1) m)) *)
    rewrite members_no_replicate_ind in H; destruct H.
    simpl in *; destruct (ident_eq i i0), v.
    - subst i.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
      destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
      unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
    - subst i.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
      destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
      unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @derives mpred Nveric (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v with | inl v0 => P (@pair ident type i1 t1) v0 p | inr v0 => IHm i0 t0 v0 end) m i1 t1 y) (P (@pair ident type i0 t0) d p) *)
      apply (union_pred_derives_const ((i1, t1) :: m) P p y); [auto | congruence |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) (P (@pair ident type i0 t0) d p) *)
      specialize (H1 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
      pose proof in_members_tail_no_replicate _ _ _ _ H2 H4.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v p) (P (@pair ident type i0 t0) d p) *)
      simpl in H1; destruct (ident_eq i i0); [congruence |].
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
      apply H1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      right; auto.
    - match goal with
      | |- context [member_dec (i, ?t') (i0, t0)] =>
              destruct (member_dec (i, t') (i0, t0));
                [inversion e; congruence |]
      end.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
      specialize (H1 i0).
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
      destruct (ident_eq i0 i0); [| congruence].
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
      apply H1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      left; auto.
    - match goal with
      | |- context [member_dec (i, ?t') (i0, t0)] =>
              destruct (member_dec (i, t') (i0, t0));
                [inversion e; congruence |]
      end.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply (IHm i1 t1); auto.
      * destruct H0; [| auto].
(* Goal: in_members i (@cons (prod ident type) (@pair ident type i1 t1) m) *)
        simpl in H0; congruence.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      * intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
        specialize (H1 i').
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
        pose proof in_members_tail_no_replicate _ _ _ _ H2 H4.
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
        simpl in H1; destruct (ident_eq i' i0); [congruence |].
(* Goal: @derives mpred Nveric (P (@pair ident type i' match (if ident_eq i' i1 then @Errors.OK type t1 else Ctypes.field_type i' m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v' p) (P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) d p) *)
        apply H1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
        right; auto.
Qed.

Lemma union_pred_upd: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p v0,
  members_no_replicate m = true ->
  in_members i m ->
  union_pred m P (upd_union i m v v0) p = P _ v0 p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@union_pred m A P (@upd_union i m A v v0) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  unfold upd_union, upd_compact_sum.
  destruct (in_dec member_dec (i, field_type i m) m) as [?H | ?H];
    [| apply in_members_field_type in H0; tauto].
(* Goal: @eq mpred (@union_pred m A P (match m as l return (forall _ : @In (prod ident type) (@pair ident type i (field_type i m)) l, compact_sum (@map (prod ident type) Type A l)) with | nil => fun _ : @In (prod ident type) (@pair ident type i (field_type i m)) (@nil (prod ident type)) => tt | cons a0 l => fun i0 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a0 l) => @list_rect (prod ident type) (fun l0 : list (prod ident type) => forall (a1 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (fun (a1 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 (@nil (prod ident type)))) => match member_dec (@pair ident type i (field_type i m)) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : @In (prod ident type) a (@cons (prod ident type) a1 (@nil (prod ident type)))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) (fun (v0 : A a1) (_ : @In (prod ident type) a1 (@cons (prod ident type) a1 (@nil (prod ident type)))) => v0) (@pair ident type i (field_type i m)) e v0 i1 | right n => match @aux0 (prod ident type) (@pair ident type i (field_type i m)) a1 i1 n return (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) with end end) (fun (a1 : prod ident type) (l0 : list (prod ident type)) (IHl : forall (a2 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 l0))) (a2 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => match member_dec (@pair ident type i (field_type i m)) a2 with | left e => @eq_rect_r (prod ident type) a2 (fun a : prod ident type => forall (_ : A a) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0)))) (fun (v0 : A a2) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a2 (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a2 (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => @inl (A a2) match (fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0 with | nil => A a1 | cons T l1 => sum (A a1) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l2 as T1) => sum t (compact_sum T1) end) ((fix map (l2 : list (prod ident type)) : list Type := match l2 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0)) end v0) (@pair ident type i (field_type i m)) e v0 IHl i1 | right n => @inr (A a2) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (IHl a1 (@aux1 (prod ident type) (@pair ident type i (field_type i m)) a2 (@cons (prod ident type) a1 l0) i1 n)) end) l a0 i0 end H1) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  clear v.
(* Goal: @eq mpred (@union_pred m A P (match m as l return (forall _ : @In (prod ident type) (@pair ident type i (field_type i m)) l, compact_sum (@map (prod ident type) Type A l)) with | nil => fun _ : @In (prod ident type) (@pair ident type i (field_type i m)) (@nil (prod ident type)) => tt | cons a0 l => fun i0 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a0 l) => @list_rect (prod ident type) (fun l0 : list (prod ident type) => forall (a1 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (fun (a1 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a1 (@nil (prod ident type)))) => match member_dec (@pair ident type i (field_type i m)) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : @In (prod ident type) a (@cons (prod ident type) a1 (@nil (prod ident type)))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) (fun (v0 : A a1) (_ : @In (prod ident type) a1 (@cons (prod ident type) a1 (@nil (prod ident type)))) => v0) (@pair ident type i (field_type i m)) e v0 i1 | right n => match @aux0 (prod ident type) (@pair ident type i (field_type i m)) a1 i1 n return (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 (@nil (prod ident type))))) with end end) (fun (a1 : prod ident type) (l0 : list (prod ident type)) (IHl : forall (a2 : prod ident type) (_ : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 l0))) (a2 : prod ident type) (i1 : @In (prod ident type) (@pair ident type i (field_type i m)) (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => match member_dec (@pair ident type i (field_type i m)) a2 with | left e => @eq_rect_r (prod ident type) a2 (fun a : prod ident type => forall (_ : A a) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0)))) (fun (v0 : A a2) (_ : forall (a3 : prod ident type) (_ : @In (prod ident type) a2 (@cons (prod ident type) a3 l0)), compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a3 l0))) (_ : @In (prod ident type) a2 (@cons (prod ident type) a2 (@cons (prod ident type) a1 l0))) => @inl (A a2) match (fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0 with | nil => A a1 | cons T l1 => sum (A a1) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l2 as T1) => sum t (compact_sum T1) end) ((fix map (l2 : list (prod ident type)) : list Type := match l2 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l0)) end v0) (@pair ident type i (field_type i m)) e v0 IHl i1 | right n => @inr (A a2) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) a1 l0))) (IHl a1 (@aux1 (prod ident type) (@pair ident type i (field_type i m)) a2 (@cons (prod ident type) a1 l0) i1 n)) end) l a0 i0 end H1) p) (P (@pair ident type i (field_type i m)) v0 p) *)
  destruct m as [| (i0, t0) m]; [inv H0 |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v0 H H0 H1; induction m as [| (i1, t1) m]; intros.
  + simpl in *.
(* Goal: @eq mpred (P (@pair ident type i0 t0) match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) False), A (@pair ident type i0 t0)) (fun (v0 : A (@pair ident type i0 t0)) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 H1 | right n => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) H1 n return (A (@pair ident type i0 t0)) with end end p) (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else @Errors.Error type (@cons Errors.errcode (Errors.MSG (String (Ascii.Ascii true false true false true false true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true false true false true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii true true true true false true true false) (String (Ascii.Ascii true true true false true true true false) (String (Ascii.Ascii false true true true false true true false) (String (Ascii.Ascii false false false false false true false false) (String (Ascii.Ascii false true true false false true true false) (String (Ascii.Ascii true false false true false true true false) (String (Ascii.Ascii true false true false false true true false) (String (Ascii.Ascii false false true true false true true false) (String (Ascii.Ascii false false true false false true true false) (String (Ascii.Ascii false false false false false true false false) EmptyString))))))))))))))) (@cons Errors.errcode (Errors.CTX i) (@nil Errors.errcode)))) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct H0; [simpl in H0; subst i | tauto].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
    destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
    destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + destruct H0; [simpl in H0; subst i |].
    - simpl in *.
(* Goal: @eq mpred match match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
      destruct (ident_eq i0 i0); [| congruence].
(* Goal: @eq mpred match match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i0 t0) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e0 v0 i | right n => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e0 v0 IHl i | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) False) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i0 t0) e v0 i | right n0 => match @aux0 (prod ident type) (@pair ident type i0 t0) a0 i n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i : or (@eq (prod ident type) a1 (@pair ident type i0 t0)) (or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) l))) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i0 t0) e v0 IHl i | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i0 t0) a1 (@cons (prod ident type) a0 l) i n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i0 t0) v0 p) *)
      destruct (member_dec (i0, t0) (i0, t0)); [| congruence].
      unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
    - simpl in *.
(* Goal: @eq mpred match match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i2 : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i2 | right n => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i2 n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i2 : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i2 | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i2 n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i2 : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i2 | right n0 => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i2 n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i2 : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i2 | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i2 n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
      pose proof in_members_tail_no_replicate _ _ _ _ H H0.
(* Goal: @eq mpred match match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 a) (@In (prod ident type) a m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) a) (or (@eq (prod ident type) (@pair ident type i1 t1) a) (@In (prod ident type) a m))), sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end) (fun (v0 : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m)), match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end) (_ : or (@eq (prod ident type) (@pair ident type i0 t0) (@pair ident type i0 t0)) (or (@eq (prod ident type) (@pair ident type i1 t1) (@pair ident type i0 t0)) (@In (prod ident type) (@pair ident type i0 t0) m))) => @inl (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => sum t (compact_sum T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i2 : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) False) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 i2 | right n => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 i2 n return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i2 : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l))) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 v0 IHl i2 | right n => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 (@cons (prod ident type) a0 l) i2 n)) end) m) H1 | right n => @inr (A (@pair ident type i0 t0)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (a0 : prod ident type) (i2 : or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) False) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall (_ : A a) (_ : or (@eq (prod ident type) a0 a) False), A a0) (fun (v0 : A a0) (_ : or (@eq (prod ident type) a0 a0) False) => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 i2 | right n0 => match @aux0 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 i2 n0 return (A a0) with end end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l)), match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end) (a1 : prod ident type) (i2 : or (@eq (prod ident type) a1 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (or (@eq (prod ident type) a0 (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (@In (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) l))) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a) (@In (prod ident type) a l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a) (or (@eq (prod ident type) a0 a) (@In (prod ident type) a l))), sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) (fun (v0 : A a1) (_ : forall (a2 : prod ident type) (_ : or (@eq (prod ident type) a2 a1) (@In (prod ident type) a1 l)), match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end) (_ : or (@eq (prod ident type) a1 a1) (or (@eq (prod ident type) a0 a1) (@In (prod ident type) a1 l))) => @inl (A a1) match (fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l with | nil => A a0 | cons T l0 => sum (A a0) ((fix compact_sum (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l1 as T1) => sum t (compact_sum T1) end) ((fix map (l1 : list (prod ident type)) : list Type := match l1 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) l)) end v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e v0 IHl i2 | right n0 => @inr (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end (IHl a0 (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 (@cons (prod ident type) a0 l) i2 n0)) end) m (@pair ident type i1 t1) (@aux1 (prod ident type) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m) H1 n)) end with | inl v => P (@pair ident type i0 t0) v p | inr v => @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v0 : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v0 p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v0 : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v0 with | inl v1 => P (@pair ident type i1 t1) v1 p | inr v1 => IHm i0 t0 v1 end) m i1 t1 v end (P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) v0 p) *)
      destruct (ident_eq i i0); [congruence |].
      match goal with
      | |- context [member_dec (i, ?t') (i0, t0)] =>
              destruct (member_dec (i, t') (i0, t0));
                [inversion e; congruence |]
      end.
(* Goal: @struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) F P (@compact_prod_gen (prod ident type) F f (@cons (prod ident type) (@pair ident type i1 t1) m)) *)
      rewrite members_no_replicate_ind in H; destruct H.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply (IHm i1 t1); auto.
Qed.

Lemma union_pred_ramif: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  (forall i' (v': A (i', field_type i' m)), in_members i' m -> P _ v' p |-- P _ d p) ->
  in_members i m ->
  members_no_replicate m = true ->
  union_pred m P v p |--
    P _ (proj_union i m v d) p *
     (ALL v0: _, P _ v0 p -* union_pred m P (upd_union i m v v0) p).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@union_pred m A P v p) (@sepcon mpred Nveric Sveric (P (@pair ident type i (field_type i m)) (@proj_union i m A v d) p) (@allp mpred Nveric (A (@pair ident type i (field_type i m))) (fun v0 : A (@pair ident type i (field_type i m)) => @wand mpred Nveric Sveric (P (@pair ident type i (field_type i m)) v0 p) (@union_pred m A P (@upd_union i m A v v0) p)))) *)
  apply RAMIF_Q.solve with emp.
  + rewrite sepcon_emp.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply union_pred_proj; auto.
  + intro v0.
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (@emp mpred Nveric Sveric) (P (@pair ident type i (field_type i m)) v0 p)) (@union_pred m A P (@upd_union i m A v v0) p) *)
    rewrite emp_sepcon.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i m)) v0 p) (@union_pred m A P (@upd_union i m A v v0) p) *)
    apply derives_refl'.
(* Goal: @eq mpred (P (@pair ident type i (field_type i m)) v0 p) (@union_pred m A P (@upd_union i m A v v0) p) *)
    symmetry.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply union_pred_upd; auto.
Qed.

Lemma at_offset_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs,
  at_offset (union_pred m P v) ofs p = union_pred m (fun it v => at_offset (P it v) ofs) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
  rewrite at_offset_eq.
(* Goal: @union_Prop m F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f m) *)
  destruct m as [| (i0, t0) m]; [simpl; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @eq mpred (P (@pair ident type i0 t0) a (offset_val ofs p)) (at_offset (P (@pair ident type i0 t0) a) ofs p) *)
    rewrite at_offset_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + simpl.
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
    destruct v.
    - rewrite at_offset_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
    - apply IHm.
Qed.

Lemma andp_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q,
  Q && union_pred m P v p =
  match m with
  | nil => Q && emp
  | _ => union_pred m (fun it v p => Q && P it v p) v p
  end.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@andp mpred Nveric Q (@union_pred m A P v p)) match m with | nil => @andp mpred Nveric Q (@emp mpred Nveric Sveric) | cons p0 l => @union_pred m A (fun (it : prod ident type) (v : A it) (p : val) => @andp mpred Nveric Q (P it v p)) v p end *)
  destruct m as [| (i0, t0) m]; [auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + destruct v.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    - simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    - simpl.
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c) (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
      apply IHm.
Qed.

Lemma union_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p,
  union_pred m P v p * union_pred m Q v p = union_pred m (fun it => P it * Q it) v p.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@union_pred m A P v p) (@union_pred m A Q v p)) (@union_pred m A (fun it : prod ident type => @sepcon (forall (_ : A it) (_ : val), mpred) (@LiftNatDed (A it) (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog (A it) (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric)) (P it) (Q it)) v p) *)
  destruct m as [| (i0, t0) m]; [| revert i0 t0 v; induction m as [| (i1, t1) m]; intros].
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite sepcon_emp; auto.
  + simpl.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + destruct v.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    - simpl; auto.
    - apply IHm.
Qed.

Lemma struct_Prop_compact_prod_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it),
  members_no_replicate m = true ->
  (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) ->
  struct_Prop m P (compact_prod_gen f m).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @union_Prop m F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f m) *)
  destruct m as [| (i0, t0) m]; [simpl; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 H H0; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) v p) (@prop mpred Nveric (R (@pair ident type i0 t0) v)) *)
    specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H0; left; auto.
  + change (struct_Prop ((i0, t0) :: (i1, t1) :: m) P
             (compact_prod_gen f ((i0, t0) :: (i1, t1) :: m)))
    with (P (i0, t0) (f (i0, t0)) /\
            struct_Prop ((i1, t1) :: m) P (compact_prod_gen f ((i1, t1) :: m))).
(* Goal: and (P (@pair ident type i0 t0) (f (@pair ident type i0 t0))) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) F P (@compact_prod_gen (prod ident type) F f (@cons (prod ident type) (@pair ident type i1 t1) m))) *)
    split.
    - specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H0; left; auto.
    - rewrite members_no_replicate_ind in H; destruct H.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply (IHm i1 t1); auto.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      specialize (H0 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      destruct (ident_eq i i0); [subst; tauto |].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H0; right; auto.
Qed.

Lemma struct_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d,
  in_members i m ->
  struct_Prop m P v ->
  P (i, field_type i m) (proj_struct i m v d).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: P (@pair ident type i (field_type i m)) (@proj_union i m F v d) *)
  destruct m as [| (i0, t0) m]; [inversion H |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v d H H0; induction m as [| (i1, t1) m]; intros.
  + inversion H; [simpl in H0; subst| tauto].
    simpl in *.
(* Goal: P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
    destruct (ident_eq i0 i0); [| tauto].
(* Goal: P (@pair ident type i0 t0) match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 t0) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 t0) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 t0) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 t0) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 t0) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
    destruct (member_dec (i0, t0) (i0, t0)); [| tauto].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + destruct (ident_eq i i0).
    - subst.
      simpl in *.
(* Goal: P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (ident_eq i0 i0); [| tauto].
(* Goal: P (@pair ident type i0 t0) match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 t0) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 t0) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 t0) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 t0) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 t0) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (member_dec (i0, t0) (i0, t0)); [| tauto].
      unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: P (@pair ident type i0 t0) (@fst (F (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (F a) (map t) end) m with | nil => F (@pair ident type i1 t1) | cons T l => prod (F (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (F a) (map t) end) m)) end v) *)
      exact (proj1 H0).
    - assert (in_members i ((i1, t1) :: m)) by (inversion H; [subst; tauto | auto]).
      simpl in *.
(* Goal: P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (ident_eq i i0); [tauto |].
      destruct (member_dec
         (i,
         match
           (if ident_eq i i1 then Errors.OK t1 else Ctypes.field_type i m)
         with
         | Errors.OK t => t
         | Errors.Error _ => Tvoid
         end) (i0, t0)); [inversion e; subst; tauto |].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply IHm; auto.
(* Goal: @list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type F m with | nil => F (@pair ident type i0 t0) | cons T l => prod (F (@pair ident type i0 t0)) (compact_prod (@map (prod ident type) Type F m)) end), Prop) (fun (i0 : ident) (t0 : type) (v : F (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type F l with | nil => F (@pair ident type i0 t0) | cons T l0 => prod (F (@pair ident type i0 t0)) (compact_prod (@map (prod ident type) Type F l)) end), Prop) (i0 : ident) (t0 : type) (_ : prod (F (@pair ident type i0 t0)) match @map (prod ident type) Type F l with | nil => F p | cons T l0 => prod (F p) (compact_prod (@map (prod ident type) Type F l)) end), Prop) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type F m with | nil => F (@pair ident type i1 t1) | cons T l => prod (F (@pair ident type i1 t1)) (compact_prod (@map (prod ident type) Type F m)) end), Prop) (i1 : ident) (t1 : type) (v : prod (F (@pair ident type i1 t1)) match @map (prod ident type) Type F m with | nil => F (@pair ident type i0 t0) | cons T l => prod (F (@pair ident type i0 t0)) (compact_prod (@map (prod ident type) Type F m)) end) => and (P (@pair ident type i1 t1) (@fst (F (@pair ident type i1 t1)) match @map (prod ident type) Type F m with | nil => F (@pair ident type i0 t0) | cons T l => prod (F (@pair ident type i0 t0)) (compact_prod (@map (prod ident type) Type F m)) end v)) (IHm i0 t0 (@snd (F (@pair ident type i1 t1)) match @map (prod ident type) Type F m with | nil => F (@pair ident type i0 t0) | cons T l => prod (F (@pair ident type i0 t0)) (compact_prod (@map (prod ident type) Type F m)) end v))) m i1 t1 (@snd (F (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (F a) (map t) end) m with | nil => F (@pair ident type i1 t1) | cons T l => prod (F (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (F a) (map t) end) m)) end v) *)
      exact (proj2 H0).
Qed.

Lemma union_Prop_compact_sum_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it),
  members_no_replicate m = true ->
  (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) ->
  union_Prop m P (compact_sum_gen (fun _ => true) f m).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @union_Prop m F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f m) *)
  destruct m as [| (i0, t0) m]; [simpl; auto |].
(* Goal: @union_Prop (@cons (prod ident type) (@pair ident type i0 t0) m) F P (@compact_sum_gen (prod ident type) F (fun _ : prod ident type => true) f (@cons (prod ident type) (@pair ident type i0 t0) m)) *)
  destruct m as [| (i1, t1) m].
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) v p) (@prop mpred Nveric (R (@pair ident type i0 t0) v)) *)
    specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H0; left; auto.
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) v p) (@prop mpred Nveric (R (@pair ident type i0 t0) v)) *)
    specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H0; left; auto.
Qed.

Lemma union_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d,
  members_union_inj v (i, field_type i m) ->
  union_Prop m P v ->
  P (i, field_type i m) (proj_union i m v d).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: P (@pair ident type i (field_type i m)) (@proj_union i m F v d) *)
  destruct m as [| (i0, t0) m]; [inversion H |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v d H H0; induction m as [| (i1, t1) m]; intros.
  + simpl in H. if_tac in H; [| tauto].
(* Goal: @derives mpred Nveric (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (fun (i0 : ident) (t0 : type) (v : A (@pair ident type i0 t0)) => P (@pair ident type i0 t0) v p) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (t0 : type) (_ : match @map (prod ident type) Type A l with | nil => A (@pair ident type i0 t0) | cons T l0 => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A l)) end), mpred) (i0 : ident) (t0 : type) (_ : sum (A (@pair ident type i0 t0)) match @map (prod ident type) Type A l with | nil => A p | cons T l0 => sum (A p) (compact_sum (@map (prod ident type) Type A l)) end), mpred) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (t1 : type) (_ : match @map (prod ident type) Type A m with | nil => A (@pair ident type i1 t1) | cons T l => sum (A (@pair ident type i1 t1)) (compact_sum (@map (prod ident type) Type A m)) end), mpred) (i1 : ident) (t1 : type) (v : sum (A (@pair ident type i1 t1)) match @map (prod ident type) Type A m with | nil => A (@pair ident type i0 t0) | cons T l => sum (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A m)) end) => match v with | inl v0 => P (@pair ident type i1 t1) v0 p | inr v0 => IHm i0 t0 v0 end) m i1 t1 y) (P (@pair ident type i t0) match member_dec (@pair ident type i t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : A a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end), A a), A a) (fun (default : A (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A m with | nil => A a0 | cons T l => sum (A a0) (compact_sum (@map (prod ident type) Type A m)) end), A (@pair ident type i0 t0)) => default) (@pair ident type i t0) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end), A (@pair ident type i t0)) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a) (fun _ : A a0 => v) (@pair ident type i t0) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end), A (@pair ident type i t0)) (a1 : prod ident type) (v : sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end), A a), A a) (fun (default : A a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end), A a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i t0) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end), A (@pair ident type i t0)) (fun (a0 : prod ident type) (v : A a0) => match member_dec (@pair ident type i t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : A a, A a) (fun _ : A a0 => v) (@pair ident type i t0) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a1 | cons T l0 => sum (A a1) (compact_sum (@map (prod ident type) Type A l)) end), A (@pair ident type i t0)) (a1 : prod ident type) (v : sum (A a1) match @map (prod ident type) Type A l with | nil => A a0 | cons T l0 => sum (A a0) (compact_sum (@map (prod ident type) Type A l)) end) => match member_dec (@pair ident type i t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : A a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end), A a), A a) (fun (default : A a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type A l with | nil => A a2 | cons T l0 => sum (A a2) (compact_sum (@map (prod ident type) Type A l)) end), A a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i t0) e d IHl | right n0 => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m (@pair ident type i1 t1) y end p) *)
    inversion H1; subst i.
(* Goal: P (@pair ident type i0 (field_type i0 (@cons (prod ident type) (@pair ident type i0 t0) (@nil (prod ident type))))) (@proj_union i0 (@cons (prod ident type) (@pair ident type i0 t0) (@nil (prod ident type))) F v d) *)
    clear H1 H4.
    simpl in *.
(* Goal: P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
    destruct (ident_eq i0 i0); [| tauto].
(* Goal: P (@pair ident type i0 t0) match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 t0) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 t0) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 t0) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 t0) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 t0) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
    destruct (member_dec (i0, t0) (i0, t0)); [| tauto].
    unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    auto.
  + destruct (ident_eq i i0).
    - subst.
      simpl in *.
(* Goal: P (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 match (if ident_eq i0 i0 then @Errors.OK type t0 else if ident_eq i0 i1 then @Errors.OK type t1 else Ctypes.field_type i0 m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (ident_eq i0 i0); [| tauto].
(* Goal: P (@pair ident type i0 t0) match member_dec (@pair ident type i0 t0) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i0 t0) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i0 t0) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i0 t0) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i0 t0) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i0 t0) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i0 t0)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i0 t0) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i0 t0) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (member_dec (i0, t0) (i0, t0)); [| tauto].
      unfold eq_rect_r; rewrite <- eq_rect_eq.
(* Goal: P (@pair ident type i0 t0) match v with | inl v => v | inr v => d end *)
      destruct v; [| inversion H].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
    - assert (members_union_inj v (i, field_type i ((i1, t1) :: m))) by (simpl in H; destruct (ident_eq i i0); [tauto | auto]).
      simpl in *.
(* Goal: P (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) (@pair ident type i0 t0) with | left e => @eq_rect_r (prod ident type) (@pair ident type i0 t0) (fun a : prod ident type => forall (_ : F a) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F a), F a) (fun (default : F (@pair ident type i0 t0)) (_ : forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F m with | nil => F a0 | cons T l => sum (F a0) (compact_sum (@map (prod ident type) Type F m)) end), F (@pair ident type i0 t0)) => match v with | inl v => v | inr v => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d (@list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (fun (a0 : prod ident type) (v : F a0) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a0 with | left e0 => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end)) (a1 : prod ident type) (v : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) a1 with | left e0 => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v with | inl v0 => v0 | inr v0 => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e1 => Tvoid end) e0 d IHl | right n => match v with | inl v0 => d | inr v0 => IHl a0 v0 end end) m) | right n => match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n0 => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i match (if ident_eq i i0 then @Errors.OK type t0 else if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n0 => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end end *)
      destruct (ident_eq i i0); [tauto |].
      destruct (member_dec
         (i,
         match
           (if ident_eq i i1 then Errors.OK t1 else Ctypes.field_type i m)
         with
         | Errors.OK t => t
         | Errors.Error _ => Tvoid
         end) (i0, t0)); [inversion e; subst; tauto |].
(* Goal: P (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) match v with | inl v => d | inr v => @list_rect (prod ident type) (fun l : list (prod ident type) => forall (a0 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (fun (a0 : prod ident type) (v0 : F a0) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a0 with | left e => @eq_rect_r (prod ident type) a0 (fun a : prod ident type => forall _ : F a, F a) (fun _ : F a0 => v0) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d | right n => d end) (fun (a0 : prod ident type) (l : list (prod ident type)) (IHl : forall (a1 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a1 | cons T l0 => sum (F a1) (compact_sum (@map (prod ident type) Type F l)) end), F (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end)) (a1 : prod ident type) (v0 : sum (F a1) match @map (prod ident type) Type F l with | nil => F a0 | cons T l0 => sum (F a0) (compact_sum (@map (prod ident type) Type F l)) end) => match member_dec (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e => Tvoid end) a1 with | left e => @eq_rect_r (prod ident type) a1 (fun a : prod ident type => forall (_ : F a) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a), F a) (fun (default : F a1) (_ : forall (a2 : prod ident type) (_ : match @map (prod ident type) Type F l with | nil => F a2 | cons T l0 => sum (F a2) (compact_sum (@map (prod ident type) Type F l)) end), F a1) => match v0 with | inl v1 => v1 | inr v1 => default end) (@pair ident type i match (if ident_eq i i1 then @Errors.OK type t1 else Ctypes.field_type i m) with | Errors.OK t => t | Errors.Error e0 => Tvoid end) e d IHl | right n => match v0 with | inl v1 => d | inr v1 => IHl a0 v1 end end) m (@pair ident type i1 t1) v end *)
      destruct v; [tauto |].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply IHm; auto.
Qed.

Lemma array_pred_local_facts: forall {A}{d: Inhabitant A} lo hi P v p Q,
  (forall i x, lo <= i < hi -> P i x p |-- !! Q x) ->
  array_pred lo hi P v p |-- !! (Zlength v = hi - lo /\ Forall Q v).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  normalize.
  rewrite prop_and; apply andp_right; [normalize |].
  pose proof ZtoNat_Zlength v.
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A P v p) R *)
  rewrite H0 in H1; symmetry in H1; clear H0.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert hi lo H H1; induction v; intros.
  + apply prop_right; constructor.
  + replace (hi - lo) with (Z.succ (hi - Z.succ lo)) in * by omega.
    assert (hi - Z.succ lo >= 0).
    {
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      destruct (zlt (hi - Z.succ lo) 0); auto.
      assert (Z.succ (hi - Z.succ lo) <= 0) by omega.
      simpl length in H1.
      destruct (zeq (Z.succ (hi - Z.succ lo)) 0);
       [rewrite e in H1 | rewrite Z2Nat_neg in H1 by omega]; inv H1.
    }
    rewrite Z2Nat.inj_succ in H1 |- * by omega.
    inv H1.
    simpl rangespec.
    replace (rangespec (Z.succ lo) (length v)
              (fun i : Z => P i (Znth (i - lo) (a :: v))) p)
    with (rangespec (Z.succ lo) (length v)
            (fun i : Z => P i (Znth (i - Z.succ lo) v)) p).
    2:{
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      apply rangespec_ext; intros.
      change v with (skipn 1 (a :: v)) at 1.
      rewrite <- Znth_succ by omega.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
    }
    rewrite H3.
    eapply derives_trans; [apply sepcon_derives; [apply H | apply IHv; auto] |].
    - omega.
    - intros; apply H; omega.
    - rewrite sepcon_prop_prop.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      apply prop_derives; intros.
      rewrite Z.sub_diag in H1; cbv in H1.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      constructor; tauto.
Qed.

Lemma struct_pred_local_facts: forall m {A} (P: forall it, A it -> val -> mpred)v p (R: forall it, A it -> Prop),
  members_no_replicate m = true ->
  (forall i v0, in_members i m -> P (i, field_type i m) v0 p |-- !! R _ v0) ->
  struct_pred m P v p |-- !! struct_Prop m R v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@union_pred m A P v p) (@prop mpred Nveric (@union_Prop m A R v)) *)
  destruct m as [| (i0, t0) m]; [simpl; apply prop_right; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v H H0; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) v p) (@prop mpred Nveric (R (@pair ident type i0 t0) v)) *)
    specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H0; left; auto.
  + change (struct_Prop ((i0, t0) :: (i1, t1) :: m) R v)
      with (R (i0, t0) (fst v) /\ struct_Prop ((i1, t1) :: m) R (snd v)).
    change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p)
      with (P (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p).
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P v p) (@prop mpred Nveric (@union_Prop (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A R v)) *)
    rewrite members_no_replicate_ind in H.

(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    pose proof H0 i0.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    simpl in H1.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
    if_tac in H1; [| congruence].
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p)) (@prop mpred Nveric (and (R (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) A R (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)))) *)
    specialize (H1 (fst v)).
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p)) (@prop mpred Nveric (and (R (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) A R (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)))) *)
    spec H1; [left; auto |].

(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p)) (@prop mpred Nveric (and (R (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) A R (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)))) *)
    specialize (IHm i1 t1 (snd v)).
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c) p) (@prop mpred Nveric (@union_Prop (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A R (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c))) *)
    spec IHm; [tauto |].
(* Goal: @derives mpred Nveric (@sepcon mpred Nveric Sveric (P (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p) (@struct_pred (@cons (prod ident type) (@pair ident type i1 t1) m) A P (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v) p)) (@prop mpred Nveric (and (R (@pair ident type i0 t0) (@fst (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)) (@struct_Prop (@cons (prod ident type) (@pair ident type i1 t1) m) A R (@snd (A (@pair ident type i0 t0)) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m with | nil => A (@pair ident type i1 t1) | cons T l => prod (A (@pair ident type i1 t1)) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (A a) (map t) end) m)) end v)))) *)
    eapply derives_trans; [apply sepcon_derives; [apply H1 | apply IHm] |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    - intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      specialize (H0 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      destruct (ident_eq i i0); [subst; tauto |].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H0; right; auto.
    - rewrite sepcon_prop_prop; normalize.
Qed.

Lemma union_pred_local_facts: forall m {A} (P: forall it, A it -> val -> mpred)v p (R: forall it, A it -> Prop),
  members_no_replicate m = true ->
  (forall i v0, in_members i m -> P (i, field_type i m) v0 p |-- !! R _ v0) ->
  union_pred m P v p |-- !! union_Prop m R v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @derives mpred Nveric (@union_pred m A P v p) (@prop mpred Nveric (@union_Prop m A R v)) *)
  destruct m as [| (i0, t0) m]; [simpl; apply prop_right; auto |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v H H0; induction m as [| (i1, t1) m]; intros.
  + simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) v p) (@prop mpred Nveric (R (@pair ident type i0 t0) v)) *)
    specialize (H0 i0).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
    simpl in H0.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    rewrite if_true in H0 by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    apply H0; left; auto.
  + rewrite members_no_replicate_ind in H.
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
    destruct v.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    - simpl.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      pose proof H0 i0.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      simpl in H1.
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      if_tac in H1; [| congruence].
(* Goal: @derives mpred Nveric (P (@pair ident type i0 t0) a p) (@prop mpred Nveric (R (@pair ident type i0 t0) a)) *)
      specialize (H1 a).
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H1; left; auto.
    - specialize (IHm i1 t1 c).
(* Goal: @derives mpred Nveric (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A P (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c) p) (@prop mpred Nveric (@union_Prop (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A R (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c))) *)
      spec IHm; [tauto |].
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) (@inr (A (@pair ident type i0 t0)) (compact_sum (@map (prod ident type) Type A (@cons (prod ident type) (@pair ident type i1 t1) m))) c) (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
      apply IHm.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
      intros.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      specialize (H0 i).
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      simpl in H0.
(* Goal: @derives mpred Nveric (P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0 p) (@prop mpred Nveric (R (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i1 t1) m))) v0)) *)
      destruct (ident_eq i i0); [subst; tauto |].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      apply H0; right; auto.
Qed.

Section MEMORY_BLOCK_AGGREGATE.

Context {cs: compspecs}.

Lemma memory_block_array_pred: forall  {A}{d: Inhabitant A} sh t lo hi v b ofs,
  0 <= ofs + sizeof t * lo /\ ofs + sizeof t * hi < Ptrofs.modulus ->
  0 <= lo <= hi ->
  Zlength v = hi - lo ->
  array_pred lo hi
    (fun i _ p => memory_block sh (sizeof t) (offset_val (sizeof t * i) p)) v
    (Vptr b (Ptrofs.repr ofs)) =
   memory_block sh (sizeof t * (hi - lo)) (Vptr b (Ptrofs.repr (ofs + sizeof t * lo))).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d lo hi (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  unfold array_pred.
(* Goal: @eq mpred (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
  rewrite prop_true_andp by auto; clear H1.
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
  f_equal.
  remember (Z.to_nat (hi - lo)) as n eqn:HH.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert lo HH H H0 v; induction n; intros.
  + simpl.
(* Goal: @eq mpred (@emp mpred Nveric Sveric) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    pose proof arith_aux00 _ _ (proj2 H0) HH.
(* Goal: @eq mpred (@emp mpred Nveric Sveric) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    rewrite H1, Z.mul_0_r, memory_block_zero_Vptr.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
    reflexivity.
  + simpl.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.add (Ptrofs.repr ofs) (Ptrofs.repr (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    pose proof arith_aux01 _ _ _ HH.
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.add (Ptrofs.repr ofs) (Ptrofs.repr (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    solve_mod_modulus.
    pose_size_mult cenv_cs t (0 :: hi - Z.succ lo :: hi - lo :: nil).
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    rewrite IHn; [| apply arith_aux02; auto | omega | omega | exact v].
    replace (ofs + sizeof  t * Z.succ lo) with (ofs + sizeof t * lo + sizeof t) by omega.
    rewrite <- memory_block_split by (auto; omega).
(* Goal: @eq Ptrofs.int (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Ptrofs.repr ofs) *)
(* Goal: and (Z.le Z0 (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) Z0))) (Z.lt (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) z)) Ptrofs.modulus) *)
(* Goal: and (Z.le Z0 Z0) (Z.le Z0 z) *)
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) (Z.sub z Z0) *)
    f_equal.
(* Goal: @eq Z z z *)
    omega.
Qed.

Lemma memory_block_array_pred': forall {A}{d: Inhabitant A} (a: A) sh t z b ofs,
  0 <= z ->
  0 <= ofs /\ ofs + sizeof t * z < Ptrofs.modulus ->
  array_pred 0 z
     (fun i _ p =>
      memory_block sh (sizeof t) (offset_val (sizeof t * i) p))
             (list_repeat (Z.to_nat z) a)
     (Vptr b (Ptrofs.repr ofs))  =
  memory_block sh (sizeof t * z) (Vptr b (Ptrofs.repr ofs)).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq mpred (@array_pred A d Z0 z (fun (i : Z) (_ : A) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (@list_repeat A (Z.to_nat z) a) (Vptr b (Ptrofs.repr ofs))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) z) (Vptr b (Ptrofs.repr ofs))) *)
  rewrite memory_block_array_pred.
(* Goal: @eq Z z z *)
  f_equal. f_equal. omega. f_equal. f_equal. rewrite Z.mul_0_r. omega.
(* Goal: @eq Z z z *)
  rewrite Z.mul_0_r. split; omega. omega.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
  rewrite Z.sub_0_r. auto. rewrite Zlength_list_repeat', Z2Nat.id by omega.
(* Goal: @eq Z z z *)
  omega.
Qed.

Lemma memory_block_struct_pred: forall sh m sz {A} (v: compact_prod (map A m)) b ofs,
  (m = nil -> sz = 0) ->
  members_no_replicate m = true ->
  sizeof_struct cenv_cs 0 m <= sz < Ptrofs.modulus ->
  0 <= ofs /\ ofs + sz < Ptrofs.modulus ->
  struct_pred m
   (fun it _ p =>
     (memory_block sh (field_offset_next cenv_cs (fst it) m sz - field_offset cenv_cs (fst it) m))
     (offset_val (field_offset cenv_cs (fst it) m) p)) v (Vptr b (Ptrofs.repr ofs)) =
  memory_block sh sz (Vptr b (Ptrofs.repr ofs)).
Proof.
  unfold field_offset, Ctypes.field_offset, field_offset_next.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros sh m sz A v b ofs NIL_CASE NO_REPLI; intros.
(* Goal: @eq mpred (@union_pred m A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
  destruct m as [| (i0, t0) m].
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  1: rewrite (NIL_CASE eq_refl), memory_block_zero; simpl; normalize.
  assert (align 0 (alignof t0) = 0) by apply align_0, alignof_pos.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert H0; pattern ofs at 1 4; replace ofs with (ofs + align 0 (alignof t0)) by omega; intros.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert H; pattern sz at 2 4; replace sz with (sz - align 0 (alignof t0)) by omega; intros.
  pattern 0 at 1; rewrite <- H1.
  clear NIL_CASE H1.
  revert H H0; generalize 0 at 1 2 4 5 6 8 10 11; revert i0 t0 v NO_REPLI;
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  induction m as [| (i1, t1) m]; intros.
  + simpl.
    if_tac; [| congruence].
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.add (Ptrofs.repr ofs) (Ptrofs.repr (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    solve_mod_modulus.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
    reflexivity.
  + match goal with
    | |- struct_pred ((i0, t0) :: (i1, t1) :: m) ?P v ?p = _ =>
           change (struct_pred ((i0, t0) :: (i1, t1) :: m) P v p) with
             (P (i0, t0) (fst v) p * struct_pred ((i1, t1) :: m) P (snd v) p);
           simpl (P (i0, t0) (fst v) p)
    end.
    if_tac; [| congruence].
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.add (Ptrofs.repr ofs) (Ptrofs.repr (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
    solve_mod_modulus.
    erewrite struct_pred_ext.
    - rewrite members_no_replicate_ind in NO_REPLI; destruct NO_REPLI as [NOT_IN NO_REPLI].
      rewrite IHm with (z := align z (alignof t0) + sizeof t0);
        [| now auto
         | simpl in H |- *; pose_align_le; pose_sizeof_pos; omega
         | pose_align_le; pose_sizeof_pos; omega].
      replace (ofs + align (align z (alignof t0) + sizeof t0) (alignof t1)) with
        (ofs + align z (alignof t0) +
         (align (align z (alignof t0) + sizeof t0) (alignof t1) -
(* Goal: @eq Z z z *)
          align z (alignof t0))) by omega.
      rewrite <- memory_block_split by
        (simpl in H; revert H; pose_align_le; pose_sizeof_pos; intros; omega).
(* Goal: @eq Z z z *)
      f_equal; omega.
    - rewrite members_no_replicate_ind in NO_REPLI; destruct NO_REPLI as [NOT_IN NO_REPLI].
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      auto.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    - intros. instantiate (1 := (snd v)).
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (memory_block sh (@sizeof (@cenv_cs cs) t) (Vptr b (Ptrofs.add (Ptrofs.repr ofs) (Ptrofs.repr (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) (rangespec (Z.succ lo) n (fun (i : Z) (p : val) => memory_block sh (@sizeof (@cenv_cs cs) t) (offset_val (Z.mul (@sizeof (@cenv_cs cs) t) i) p)) (Vptr b (Ptrofs.repr ofs)))) (memory_block sh (Z.mul (@sizeof (@cenv_cs cs) t) (Z.sub hi lo)) (Vptr b (Ptrofs.repr (Z.add ofs (Z.mul (@sizeof (@cenv_cs cs) t) lo))))) *)
      solve_mod_modulus.
      unfold fst.
      pose proof in_members_tail_no_replicate _ _ _ _ NO_REPLI H2.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      rewrite (neq_field_offset_rec_cons cenv_cs i i0 t0) by auto.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
      rewrite (neq_field_offset_next_rec_cons cenv_cs i i0 t0) by auto.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
Qed.

Lemma memory_block_union_pred: forall sh m sz {A} (v: compact_sum (map A m)) b ofs,
  (m = nil -> sz = 0) ->
  union_pred m (fun it _ => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs)) =
  memory_block sh sz (Vptr b (Ptrofs.repr ofs)).
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros sh m sz A v b ofs NIL_CASE; intros.
(* Goal: @eq mpred (@union_pred m A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
  destruct m as [| (i0, t0) m].
(* Goal: @eq mpred (@sepcon mpred Nveric Sveric (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => P i (@Znth A d (Z.sub i lo) v)) p)) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => Q i (@Znth A d (Z.sub i lo) v)) p))) (@andp mpred Nveric (@prop mpred Nveric (@eq Z (@Zlength A v) (Z.sub hi lo))) (rangespec lo (Z.to_nat (Z.sub hi lo)) (fun i : Z => @sepcon (forall (_ : Z) (_ : A) (_ : val), mpred) (@LiftNatDed Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric))) (@LiftSepLog Z (forall (_ : A) (_ : val), mpred) (@LiftNatDed A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric)) (@LiftSepLog A (forall _ : val, mpred) (@LiftNatDed val mpred Nveric) (@LiftSepLog val mpred Nveric Sveric))) P Q i (@Znth A d (Z.sub i lo) v)) p)) *)
  1: rewrite (NIL_CASE eq_refl), memory_block_zero; simpl; normalize.
(* Goal: @eq mpred (@union_pred (@cons (prod ident type) (@pair ident type i0 t0) m) A (fun (it : prod ident type) (_ : A it) => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs))) (memory_block sh sz (Vptr b (Ptrofs.repr ofs))) *)
  clear NIL_CASE.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i1, t1) m]; intros.
  + simpl; auto.
  + destruct v.
(* Goal: @eq Z (@Zlength A (@list_repeat A (Z.to_nat z) a)) z *)
    - simpl; auto.
    - apply IHm.
Qed.

End MEMORY_BLOCK_AGGREGATE.

Module aggregate_pred.

Open Scope Z.
Open Scope logic.


Definition array_pred: forall {A: Type}{d: Inhabitant A} (lo hi: Z) (P: Z -> A -> val -> mpred) (v: list A),
    val -> mpred := @array_pred.

Definition struct_pred: forall (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_prod (map A m)) (p: val), mpred := @struct_pred.

Definition union_pred: forall (m: members) {A: ident * type -> Type} (P: forall it, A it -> val -> mpred) (v: compact_sum (map A m)) (p: val), mpred := @union_pred.

Definition array_Prop: forall {A: Type} (d:A) (lo hi: Z) (P: Z -> A -> Prop) (v: list A), Prop := @array_Prop.

Definition struct_Prop: forall (m: members) {A: ident * type -> Type} (P: forall it, A it -> Prop) (v: compact_prod (map A m)), Prop := @struct_Prop.

Definition union_Prop: forall (m: members) {A: ident * type -> Type} (P: forall it, A it -> Prop) (v: compact_sum (map A m)), Prop := union_Prop.

Definition array_pred_len_0: forall {A}{d: Inhabitant A} lo hi P p,
  hi = lo ->
  array_pred lo hi P nil p = emp
:= @array_pred_len_0.

Definition array_pred_len_1: forall {A}{d: Inhabitant A} i P v p,
  array_pred i (i + 1) P (v :: nil) p =  P i v p
:= @array_pred_len_1.

Definition split_array_pred: forall  {A}{d: Inhabitant A} lo mid hi P v p,
  lo <= mid <= hi ->
  Zlength v = (hi-lo) ->
  array_pred lo hi P v p =
  array_pred lo mid P (sublist 0 (mid-lo) v) p *
  array_pred mid hi P (sublist (mid-lo) (hi-lo) v) p
:= @split_array_pred.

Definition array_pred_shift: forall {A} {d: Inhabitant A} lo hi lo' hi' mv 
              P' P v p,
  lo - lo' = mv ->
  hi - hi' = mv ->
  (forall i i', lo <= i < hi -> i - i' = mv ->
           P' i' (Znth (i - lo) v) p = P i (Znth (i - lo) v) p) ->
  array_pred lo' hi' P' v p = array_pred lo hi P v p
:= @array_pred_shift.

Definition array_pred_ext_derives:
  forall {A B} {dA: Inhabitant A} {dB: Inhabitant B} lo hi P0 P1 
            (v0: list A) (v1: list B) p,
  (Zlength v0 = hi - lo -> Zlength v1 = hi - lo) ->
  (forall i, lo <= i < hi ->
      P0 i (Znth (i-lo) v0) p |-- P1 i (Znth (i-lo) v1) p) ->
  array_pred lo hi P0 v0 p |-- array_pred lo hi P1 v1 p
:= @array_pred_ext_derives.

Definition array_pred_ext:
  forall {A B} {dA: Inhabitant A} {dB: Inhabitant B} lo hi P0 P1 (v0: list A) (v1: list B)  p,
  Zlength v0 = Zlength v1 ->
  (forall i, lo <= i < hi ->
     P0 i (Znth (i - lo) v0) p = P1 i (Znth (i - lo) v1) p) ->
  array_pred lo hi P0 v0 p = array_pred lo hi P1 v1 p
:= @array_pred_ext.

Definition at_offset_array_pred: forall {A} {d: Inhabitant A} lo hi P v ofs p,
  at_offset (array_pred lo hi P v) ofs p = array_pred lo hi (fun i v => at_offset (P i v) ofs) v p
:= @at_offset_array_pred.

Definition array_pred_sepcon: forall  {A} {d: Inhabitant A} lo hi P Q v p,
  array_pred lo hi P v p * array_pred lo hi Q v p = array_pred lo hi (P * Q) v p
:= @array_pred_sepcon.

Definition struct_pred_ramif: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  in_members i m ->
  members_no_replicate m = true ->
  struct_pred m P v p |--
    P _ (proj_struct i m v d) p *
     allp ((fun v0: _ => P _ v0 p) -* (fun v0: _ => struct_pred m P (upd_struct i m v v0) p))
:= @struct_pred_ramif.

Definition struct_pred_ext_derives:
  forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall i d0 d1, in_members i m ->
     P0 _ (proj_struct i m v0 d0) p |-- P1 _ (proj_struct i m v1 d1) p) ->
  struct_pred m P0 v0 p |-- struct_pred m P1 v1 p
:= @struct_pred_ext_derives.

Definition struct_pred_ext:
  forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall i d0 d1, in_members i m ->
     P0 _ (proj_struct i m v0 d0) p = P1 _ (proj_struct i m v1 d1) p) ->
  struct_pred m P0 v0 p = struct_pred m P1 v1 p
:= @struct_pred_ext.

Definition at_offset_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs,
  at_offset (struct_pred m P v) ofs p = struct_pred m (fun it v => at_offset (P it v) ofs) v p
:= @at_offset_struct_pred.

Definition andp_struct_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q,
  corable Q ->
  Q && struct_pred m P v p =
  match m with
  | nil => Q && emp
  | _ => struct_pred m (fun it v p => Q && P it v p) v p
  end
:= @corable_andp_struct_pred.

Definition struct_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p,
  struct_pred m P v p * struct_pred m Q v p = struct_pred m (fun it => P it * Q it) v p
:= @struct_pred_sepcon.

Definition union_pred_ramif: forall m {A} (P: forall it, A it -> val -> mpred) (i: ident) v p d,
  (forall i' (v': A (i', field_type i' m)), in_members i' m -> P _ v' p |-- P _ d p) ->
  in_members i m ->
  members_no_replicate m = true ->
  union_pred m P v p |--
    P _ (proj_union i m v d) p *
     allp ((fun v0: _ => P _ v0 p) -* (fun v0 =>union_pred m P (upd_union i m v v0) p))
:= @union_pred_ramif.

Definition union_pred_ext_derives:
  forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall it, members_union_inj v0 it <-> members_union_inj v1 it) ->
  (forall i d0 d1, members_union_inj v0 (i, field_type i m) -> members_union_inj v1 (i, field_type i m) ->
     P0 _ (proj_union i m v0 d0) p |-- P1 _ (proj_union i m v1 d1) p) ->
  union_pred m P0 v0 p |-- union_pred m P1 v1 p
:= @union_pred_ext_derives.

Definition union_pred_ext:
  forall m {A0 A1} (P0: forall it, A0 it -> val -> mpred) (P1: forall it, A1 it -> val -> mpred) v0 v1 p,
  members_no_replicate m = true ->
  (forall it, members_union_inj v0 it <-> members_union_inj v1 it) ->
  (forall i d0 d1, members_union_inj v0 (i, field_type i m) -> members_union_inj v1 (i, field_type i m) ->
     P0 _ (proj_union i m v0 d0) p = P1 _ (proj_union i m v1 d1) p) ->
  union_pred m P0 v0 p = union_pred m P1 v1 p
:= @union_pred_ext.

Definition at_offset_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p ofs,
  at_offset (union_pred m P v) ofs p = union_pred m (fun it v => at_offset (P it v) ofs) v p
:= at_offset_union_pred.

Definition andp_union_pred: forall m {A} (P: forall it, A it -> val -> mpred) v p Q,
  Q && union_pred m P v p =
  match m with
  | nil => Q && emp
  | _ => union_pred m (fun it v p => Q && P it v p) v p
  end
:= @andp_union_pred.

Definition union_pred_sepcon: forall m {A} (P Q: forall it, A it -> val -> mpred) v p,
  union_pred m P v p * union_pred m Q v p = union_pred m (fun it => P it * Q it) v p
:= @union_pred_sepcon.

Definition struct_Prop_compact_prod_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it),
  members_no_replicate m = true ->
  (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) ->
  struct_Prop m P (compact_prod_gen f m)
:= @struct_Prop_compact_prod_gen.

Definition struct_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d,
  in_members i m ->
  struct_Prop m P v ->
  P (i, field_type i m) (proj_struct i m v d)
:= @struct_Prop_proj.

Definition union_Prop_compact_sum_gen: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) (f: forall it, F it),
  members_no_replicate m = true ->
  (forall i, in_members i m -> P (i, field_type i m) (f (i, field_type i m))) ->
  union_Prop m P (compact_sum_gen (fun _ => true) f m)
:= @union_Prop_compact_sum_gen.

Definition union_Prop_proj: forall m (F: ident * type -> Type) (P: forall it, F it -> Prop) v i d,
  members_union_inj v (i, field_type i m) ->
  union_Prop m P v ->
  P (i, field_type i m) (proj_union i m v d)
:= @union_Prop_proj.

Definition array_pred_local_facts: forall {A} {d: Inhabitant A} lo hi P v p Q,
  (forall i x, lo <= i < hi -> P i x p |-- !! Q x) ->
  array_pred lo hi P v p |-- !! (Zlength v = hi - lo /\ Forall Q v)
:= @array_pred_local_facts.

Definition struct_pred_local_facts: forall m {A} (P: forall it, A it -> val -> mpred)v p (R: forall it, A it -> Prop),
  members_no_replicate m = true ->
  (forall i v0, in_members i m -> P (i, field_type i m) v0 p |-- !! R _ v0) ->
  struct_pred m P v p |-- !! struct_Prop m R v
:= @struct_pred_local_facts.

Definition union_pred_local_facts: forall m {A} (P: forall it, A it -> val -> mpred)v p (R: forall it, A it -> Prop),
  members_no_replicate m = true ->
  (forall i v0, in_members i m -> P (i, field_type i m) v0 p |-- !! R _ v0) ->
  union_pred m P v p |-- !! union_Prop m R v
:= @union_pred_local_facts.

End aggregate_pred.

Require Import VST.floyd.reptype_lemmas.

(******************************************

Auxiliary predicates

******************************************)

Section AUXILIARY_PRED.

Context {cs: compspecs}.

Variable sh: share.

Definition struct_data_at_rec_aux (m m0: members) (sz: Z) (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> (val -> mpred)) m)) (v: compact_prod (map (fun it => reptype (field_type (fst it) m0)) m)) : (val -> mpred).
Proof.
(* Goal: forall _ : val, mpred *)
  destruct m as [| (i0, t0) m]; [exact (fun _ => emp) |].
(* Goal: Prop *)
  revert i0 t0 v P; induction m as [| (i0, t0) m]; intros ? ? v P.
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
    exact (withspacer sh
            (field_offset cenv_cs i0 m0 + sizeof (field_type i0 m0))
            (field_offset_next cenv_cs i0 m0 sz)
            (at_offset (a v) (field_offset cenv_cs i0 m0))).
  + simpl in v, P.
(* Goal: @eq Prop (and (P (@pair ident type i1 t1) (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e : list Type => match e with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a0 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a0 v) B H1) A (@f_equal (list Type) Type (fun e : list Type => match e with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e : list Type => match e with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) a b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)))) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l)))), Prop) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) | @Cons A B a0 b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b0 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a1 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b0)) B H1) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) a0 b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) P m)))) match ident_eq i1 i1 with | left e => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun H1 : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a0 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType (@nil Type)) => a1 v) B H2) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) a0 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)))) (fun a0 : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l)))), Prop) := a0 in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e0 => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e1 : list Type => match e1 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) | @Cons A B a1 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a2 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (b1 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => and (a2 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v) b1)) B H2) A (@f_equal (list Type) Type (fun e1 : list Type => match e1 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e1 : list Type => match e1 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) a1 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) H1) (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop)) (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (P (@pair ident type i1 t1)) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) P m)) | right n => False_rect Prop (n (@eq_refl ident i1)) end *)
    destruct (ident_eq i1 i1); [| congruence].
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
    exact (withspacer sh
            (field_offset cenv_cs i1 m0 + sizeof (field_type i1 m0))
            (field_offset_next cenv_cs i1 m0 sz)
            (at_offset (a (fst v)) (field_offset cenv_cs i1 m0)) * IHm i0 t0 (snd v) b)%logic.
Defined.

Definition union_data_at_rec_aux (m m0: members) (sz: Z) (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> (val -> mpred)) m)) (v: compact_sum (map (fun it => reptype (field_type (fst it) m0)) m)) : (val -> mpred).
Proof.
(* Goal: forall _ : val, mpred *)
  destruct m as [| (i0, t0) m]; [exact (fun _ => emp) |].
(* Goal: Prop *)
  revert i0 t0 v P; induction m as [| (i0, t0) m]; intros ? ? v P.
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: forall _ : val, mpred *)
    exact (withspacer sh (sizeof (field_type i0 m0)) sz (a v)).
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) v) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    destruct v as [v | v].
    - exact (withspacer sh (sizeof (field_type i1 m0)) sz (a v)).
    - exact (IHm i0 t0 v b).
Defined.

Lemma struct_data_at_rec_aux_spec: forall m m0 sz v P,
  struct_data_at_rec_aux m m0 sz
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> val -> mpred)
     P m) v =
  struct_pred m
   (fun it v =>
      withspacer sh
       (field_offset cenv_cs (fst it) m0 + sizeof (field_type (fst it) m0))
       (field_offset_next cenv_cs (fst it) m0 sz)
       (at_offset (P it v) (field_offset cenv_cs (fst it) m0))) v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  destruct m as [| (i0, t0) m]; [reflexivity |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros.
  + simpl; reflexivity.
  + replace
     (struct_data_at_rec_aux ((i1, t1) :: (i0, t0) :: m) m0 sz
     (ListTypeGen (fun it : ident * type => reptype (field_type (fst it) m0) -> val -> mpred)
        P ((i1, t1) :: (i0, t0) :: m)) v) with
     (withspacer sh
       (field_offset cenv_cs i1 m0 + sizeof (field_type i1 m0))
         (field_offset_next cenv_cs i1 m0 sz)
           (at_offset (P (i1, t1) (fst v)) (field_offset cenv_cs i1 m0)) *
      struct_data_at_rec_aux ((i0, t0) :: m) m0 sz
     (ListTypeGen (fun it : ident * type => reptype (field_type (fst it) m0) -> val -> mpred)
        P ((i0, t0) :: m)) (snd v))%logic.
    - rewrite IHm.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    - simpl.
(* Goal: @eq Prop (and (P (@pair ident type i1 t1) (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e : list Type => match e with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a0 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a0 v) B H1) A (@f_equal (list Type) Type (fun e : list Type => match e with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e : list Type => match e with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) a b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)))) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l)))), Prop) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) | @Cons A B a0 b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b0 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a1 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b0)) B H1) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) a0 b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) P m)))) match ident_eq i1 i1 with | left e => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun H1 : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a0 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType (@nil Type)) => a1 v) B H2) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) a0 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)))) (fun a0 : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l)))), Prop) := a0 in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e0 => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e1 : list Type => match e1 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) | @Cons A B a1 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a2 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (b1 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => and (a2 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v) b1)) B H2) A (@f_equal (list Type) Type (fun e1 : list Type => match e1 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e1 : list Type => match e1 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) a1 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) H1) (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop)) (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (P (@pair ident type i1 t1)) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) P m)) | right n => False_rect Prop (n (@eq_refl ident i1)) end *)
      destruct (ident_eq i1 i1); [| congruence].
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
Qed.

Lemma union_data_at_rec_aux_spec: forall m m0 sz v P,
  union_data_at_rec_aux m m0 sz
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> val -> mpred)
     P m) v =
  union_pred m
   (fun it v =>
      withspacer sh
       (sizeof (field_type (fst it) m0))
       sz
       (P it v)) v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  destruct m as [| (i0, t0) m]; [reflexivity |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros.
  + simpl. unfold union_pred. simpl. reflexivity.
  + destruct v as [v | v].
    - reflexivity.
    - match goal with
      | _ => apply IHm
      | _ => simpl ; f_equal ; apply IHm
      end.
Qed.

Definition struct_value_fits_aux (m m0: members)
      (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> Prop) m))
      (v: compact_prod (map (fun it => reptype (field_type (fst it) m0)) m)) : Prop.
Proof.
(* Goal: Prop *)
  destruct m as [| (i0, t0) m]; [exact True |].
(* Goal: Prop *)
  revert i0 t0 v P; induction m as [| (i0, t0) m]; intros ? ? v P.
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: Prop *)
    apply (a v).
  + simpl in v, P.
(* Goal: @eq Prop (and (P (@pair ident type i1 t1) (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e : list Type => match e with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a0 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a0 v) B H1) A (@f_equal (list Type) Type (fun e : list Type => match e with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e : list Type => match e with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) a b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)))) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l)))), Prop) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) | @Cons A B a0 b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b0 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a1 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b0)) B H1) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) a0 b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) P m)))) match ident_eq i1 i1 with | left e => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun H1 : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a0 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType (@nil Type)) => a1 v) B H2) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) a0 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)))) (fun a0 : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l)))), Prop) := a0 in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e0 => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e1 : list Type => match e1 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) | @Cons A B a1 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a2 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (b1 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => and (a2 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v) b1)) B H2) A (@f_equal (list Type) Type (fun e1 : list Type => match e1 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e1 : list Type => match e1 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) a1 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) H1) (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop)) (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (P (@pair ident type i1 t1)) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) P m)) | right n => False_rect Prop (n (@eq_refl ident i1)) end *)
    destruct (ident_eq i1 i1); [| congruence].
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: Prop *)
    apply (a (fst v) /\ IHm i0 t0 (snd v) b).
Defined.

Definition union_value_fits_aux (m m0: members)
      (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> Prop) m))
      (v: compact_sum (map (fun it => reptype (field_type (fst it) m0)) m)) : Prop.
Proof.
(* Goal: Prop *)
  destruct m as [| (i0, t0) m]; [exact True |].
(* Goal: Prop *)
  revert i0 t0 v P; induction m as [| (i0, t0) m]; intros ? ? v P.
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: Prop *)
    exact (a v).
  + simpl in v, P.
(* Goal: P (@pair ident type i (field_type i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)))) (@proj_union i (@cons (prod ident type) (@pair ident type i0 t0) (@cons (prod ident type) (@pair ident type i1 t1) m)) F v d) *)
    inversion P; subst.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) v) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
    destruct v as [v | v].
    - exact (a v).
    - exact (IHm i0 t0 v b).
Defined.

Lemma struct_value_fits_aux_spec: forall m m0 v P,
  struct_value_fits_aux m m0
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> Prop)
     P m) v =
  struct_Prop m P v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  destruct m as [| (i0, t0) m]; [reflexivity |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros.
  + simpl; reflexivity.
  + replace
     (struct_value_fits_aux ((i1, t1) :: (i0, t0) :: m) m0
     (ListTypeGen (fun it : ident * type => reptype (field_type (fst it) m0) -> Prop)
        P ((i1, t1) :: (i0, t0) :: m)) v) with
     (P (i1, t1) (fst v) /\  struct_value_fits_aux ((i0, t0) :: m) m0
     (ListTypeGen (fun it : ident * type => reptype (field_type (fst it) m0) -> Prop)
        P ((i0, t0) :: m)) (snd v)).
    - rewrite IHm.
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
(* Goal: @eq Prop (@eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@nil Type) (@nil Type)) (_ : T) (_ : ListType (@nil Type)), Prop) (fun H1 : @eq (list Type) (@nil Type) (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a v) (@nil Type) H1) (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop)) (@eq_refl (list Type) (@nil Type)) (P (@pair ident type i0 t0)) Nil) (P (@pair ident type i0 t0) v) *)
    - simpl.
(* Goal: @eq Prop (and (P (@pair ident type i1 t1) (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e : list Type => match e with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a0 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (_ : ListType (@nil Type)) => a0 v) B H1) A (@f_equal (list Type) Type (fun e : list Type => match e with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e : list Type => match e with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)) H) a b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@nil Type)))) (fun a : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) l)))), Prop) := a in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) | @Cons A B a0 b => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H1 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b0 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a1 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b0)) B H1) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) H) a0 b end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) match (fix map (l : list (prod ident type)) : list Type := match l with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end) ((fix compact_prod (T0 : list Type) : Type := match T0 with | nil => unit | cons t (nil as T1) => t | cons t (cons T2 l0 as T1) => prod t (compact_prod T1) end) ((fix map (l0 : list (prod ident type)) : list Type := match l0 with | nil => @nil Type | cons a t => @cons Type (@reptype cs match Ctypes.field_type (@fst ident type a) m0 with | Errors.OK t0 => t0 | Errors.Error e => Tvoid end) (map t) end) m)) end v) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e => Tvoid end, Prop) P m)))) match ident_eq i1 i1 with | left e => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (_ : T) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun H1 : @eq (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (b : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) => and (a (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v)) (@list_rect (prod ident type) (fun m : list (prod ident type) => forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (fun (i0 : ident) (_ : type) (v : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type))) => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e0 : list Type => match e0 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) | @Cons A B a0 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@nil Type)) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@nil Type) => @eq_rect_r (list Type) (@nil Type) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a1 : forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (_ : ListType (@nil Type)) => a1 v) B H2) A (@f_equal (list Type) Type (fun e0 : list Type => match e0 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) (@f_equal (list Type) (list Type) (fun e0 : list Type => match e0 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)) H) a0 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@nil Type)))) (fun a0 : prod ident type => let (i0, t0) as p return (forall (l : list (prod ident type)) (_ : forall (i0 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l))), Prop) (i0 : ident) (_ : type) (_ : prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l with | nil => @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l0 => prod (@reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) l)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type (@fst ident type p) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) l)))), Prop) := a0 in fun (m : list (prod ident type)) (IHm : forall (i1 : ident) (_ : type) (_ : match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (_ : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))), Prop) (i1 : ident) (_ : type) (v : prod (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end) (P : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)))) => match ident_eq i1 i1 with | left e0 => match P in (ListType l) return (forall _ : @eq (list Type) l (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))), Prop) with | Nil => fun H : @eq (list Type) (@nil Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => False_rect Prop (@eq_ind (list Type) (@nil Type) (fun e1 : list Type => match e1 with | nil => True | cons x x0 => False end) I (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) | @Cons A B a1 b0 => fun H : @eq (list Type) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => @eq_rect_r Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (fun T : Type => forall (_ : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) (_ : T) (_ : ListType B), Prop) (fun H2 : @eq (list Type) B (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) => @eq_rect_r (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)) (fun l : list Type => forall (_ : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (_ : ListType l), Prop) (fun (a2 : forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (b1 : ListType (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) => and (a2 (@fst (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v)) (IHm i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end) m)) end v) b1)) B H2) A (@f_equal (list Type) Type (fun e1 : list Type => match e1 with | nil => A | cons T l => T end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) (@f_equal (list Type) (list Type) (fun e1 : list Type => match e1 with | nil => B | cons T l => l end) (@cons Type A B) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m))) H) a1 b0 end (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e1 => Tvoid end, Prop) m)))) | right n => False_rect Prop (n (@eq_refl ident i1)) end) m i0 t0 (@snd (@reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) match @map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m with | nil => @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end | cons T l => prod (@reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) (compact_prod (@map (prod ident type) Type (fun it : prod ident type => @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end) m)) end v) b)) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m)) H1) (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@eq_refl Type (forall _ : @reptype cs match Ctypes.field_type i1 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop)) (@eq_refl (list Type) (@cons Type (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m))) (P (@pair ident type i1 t1)) (@Cons (forall _ : @reptype cs match Ctypes.field_type i0 m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) (@map (prod ident type) Type (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) m) (P (@pair ident type i0 t0)) (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs match Ctypes.field_type (@fst ident type it) m0 with | Errors.OK t => t | Errors.Error e0 => Tvoid end, Prop) P m)) | right n => False_rect Prop (n (@eq_refl ident i1)) end *)
      destruct (ident_eq i1 i1); [| congruence].
(* Goal: @eq Prop (union_value_fits_aux (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m))) (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) (@union_Prop (@cons (prod ident type) (@pair ident type i1 t1) (@cons (prod ident type) (@pair ident type i0 t0) m)) (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P (@inl (@reptype cs (field_type (@fst ident type (@pair ident type i1 t1)) m0)) (compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) (@cons (prod ident type) (@pair ident type i0 t0) m))) v)) *)
      reflexivity.
Qed.

Lemma union_value_fits_aux_spec: forall m m0 v P,
  union_value_fits_aux m m0
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> Prop)
     P m) v =
  union_Prop m P v.
Proof.
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  intros.
(* Goal: @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  destruct m as [| (i0, t0) m]; [reflexivity |].
(* Goal: forall (m m0 : members) (v : compact_sum (@map (prod ident type) Type (fun it : prod ident type => @reptype cs (field_type (@fst ident type it) m0)) m)) (P : forall A : prod ident type, (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) A), @eq Prop (union_value_fits_aux m m0 (@ListTypeGen (prod ident type) (fun it : prod ident type => forall _ : @reptype cs (field_type (@fst ident type it) m0), Prop) P m) v) (@union_Prop m (fun A : prod ident type => @reptype cs (field_type (@fst ident type A) m0)) P v) *)
  revert i0 t0 v; induction m as [| (i0, t0) m]; intros.
  + simpl. unfold union_Prop. simpl. reflexivity.
  + destruct v as [v | v].
    - reflexivity.
    - match goal with
      | _ => apply IHm
      | _ => simpl ; f_equal ; apply IHm
      end.
Qed.

End AUXILIARY_PRED.

Module auxiliary_pred.

Import aggregate_pred.

Definition struct_data_at_rec_aux:
   forall {cs: compspecs} (sh: share) (m m0: members) (sz: Z) (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> (val -> mpred)) m)) (v: compact_prod (map (fun it => reptype (field_type (fst it) m0)) m)), (val -> mpred)
:= @struct_data_at_rec_aux.

Definition union_data_at_rec_aux:
  forall {cs: compspecs} (sh: share) (m m0: members) (sz: Z) (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> (val -> mpred)) m)) (v: compact_sum (map (fun it => reptype (field_type (fst it) m0)) m)), (val -> mpred)
:= @union_data_at_rec_aux.

Definition struct_data_at_rec_aux_spec: forall {cs: compspecs} (sh: share) m m0 sz v P,
  struct_data_at_rec_aux sh m m0 sz
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> val -> mpred)
     P m) v =
  struct_pred m
   (fun it v =>
      withspacer sh
       (field_offset cenv_cs (fst it) m0 + sizeof (field_type (fst it) m0))
       (field_offset_next cenv_cs (fst it) m0 sz)
       (at_offset (P it v) (field_offset cenv_cs (fst it) m0))) v
:= @struct_data_at_rec_aux_spec.

Definition union_data_at_rec_aux_spec: forall {cs: compspecs} sh m m0 sz v P,
  union_data_at_rec_aux sh m m0 sz
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> val -> mpred)
     P m) v =
  union_pred m
   (fun it v =>
      withspacer sh
       (sizeof (field_type (fst it) m0))
       sz
       (P it v)) v
:= @union_data_at_rec_aux_spec.

Definition struct_value_fits_aux:
  forall {cs: compspecs} (m m0: members)
      (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> Prop) m))
      (v: compact_prod (map (fun it => reptype (field_type (fst it) m0)) m)), Prop
:= @struct_value_fits_aux.

Definition union_value_fits_aux:
  forall {cs: compspecs} (m m0: members)
      (P: ListType (map (fun it => reptype (field_type (fst it) m0) -> Prop) m))
      (v: compact_sum (map (fun it => reptype (field_type (fst it) m0)) m)), Prop
:= @union_value_fits_aux.

Definition struct_value_fits_aux_spec: forall {cs: compspecs} m m0 v P,
  struct_value_fits_aux m m0
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> Prop)
     P m) v =
  struct_Prop m P v
:= @struct_value_fits_aux_spec.

Definition union_value_fits_aux_spec: forall {cs: compspecs} m m0 v P,
  union_value_fits_aux m m0
   (ListTypeGen
     (fun it => reptype (field_type (fst it) m0) -> Prop)
     P m) v =
  union_Prop m P v
:= @union_value_fits_aux_spec.

Definition memory_block_array_pred:
  forall {cs: compspecs} {A : Type} {d : Inhabitant A} (a: A) sh t z b ofs,
  0 <= z ->
  0 <= ofs /\ ofs + sizeof t * z < Ptrofs.modulus ->
  array_pred 0 z
     (fun i _ p =>
      memory_block sh (sizeof t)
        (offset_val (sizeof t * i) p)) (list_repeat (Z.to_nat z) a)
     (Vptr b (Ptrofs.repr ofs))  =
  memory_block sh (sizeof t * z) (Vptr b (Ptrofs.repr ofs))
:= @memory_block_array_pred'.

Definition memory_block_struct_pred:
  forall {cs: compspecs} sh m sz {A} (v: compact_prod (map A m)) b ofs,
  (m = nil -> sz = 0) ->
  members_no_replicate m = true ->
  sizeof_struct cenv_cs 0 m <= sz < Ptrofs.modulus ->
  0 <= ofs /\ ofs + sz < Ptrofs.modulus ->
  struct_pred m
   (fun it _ p =>
     (memory_block sh (field_offset_next cenv_cs (fst it) m sz - field_offset cenv_cs (fst it) m))
     (offset_val (field_offset cenv_cs (fst it) m) p)) v (Vptr b (Ptrofs.repr ofs)) =
  memory_block sh sz (Vptr b (Ptrofs.repr ofs))
:= @memory_block_struct_pred.

Definition memory_block_union_pred:
  forall sh m sz {A} (v: compact_sum (map A m)) b ofs,
  (m = nil -> sz = 0) ->
  union_pred m (fun it _ => memory_block sh sz) v (Vptr b (Ptrofs.repr ofs)) =
  memory_block sh sz (Vptr b (Ptrofs.repr ofs))
:= @memory_block_union_pred.

End auxiliary_pred.
