Local Open Scope logic.
Definition funsig_of_funspec (fs: funspec) : funsig :=
match fs with mk_funspec fsig _ _ _ _ _ _ => fsig end.
Definition params_of_funspec (fs: funspec) : list (ident * type) :=
fst (funsig_of_funspec fs).
Definition return_of_funspec (fs: funspec) : type :=
snd (funsig_of_funspec fs).
Definition funsig_tycontext (fs: funsig) : tycontext :=
make_tycontext (fst fs) nil nil (snd fs) nil nil nil.
Definition funsig_of_function (f: function) : funsig :=
(fn_params f, fn_return f).
(* If we were to require that a non-void-returning function must, at a function call, have its result assigned to a temp, then we could change "ret0_tycon" to "ret_tycon" in this definition (and in NDsubsume_funspec). *)
Definition subsume_funspec (f1 f2 : funspec) :=
let Delta := (funsig_tycontext (funsig_of_funspec f1)) in
match f1 with
| mk_funspec fsig1 cc1 A1 P1 Q1 _ _ =>
match f2 with
| mk_funspec fsig2 cc2 A2 P2 Q2 _ _ =>
fsig1 = fsig2 /\ cc1 = cc2 /\
forall ts2 x2,
ENTAIL Delta, P2 ts2 x2 |-- EX ts1: list Type, EX x1:_, EX F:mpred,
((`F * P1 ts1 x1) &&
(!! (ENTAIL (ret0_tycon Delta), `F * Q1 ts1 x1
|-- Q2 ts2 x2)))
end end.
Definition NDsubsume_funspec (f1 f2 : funspec) :=
let Delta := (funsig_tycontext (funsig_of_funspec f1)) in
match f1 with
| mk_funspec fsig1 cc1 (rmaps.ConstType A1) P1 Q1 _ _ =>
match f2 with
| mk_funspec fsig2 cc2 (rmaps.ConstType A2) P2 Q2 _ _ =>
fsig1 = fsig2 /\ cc1 = cc2 /\  forall x2,
ENTAIL Delta, P2 nil x2 |-- EX x1:_, EX F:mpred,
((`F * P1 nil x1) &&
(!! (ENTAIL (ret0_tycon Delta), `F * Q1 nil x1
|-- Q2 nil x2)))
| _ => False end
| _ => False end.
Definition is_NDfunspec (fs: funspec) :=
match fs with
| mk_funspec _ _ (rmaps.ConstType A) P Q _ _ =>
(forall ts, P ts = P nil /\ Q ts = Q nil)
| _ => False
end.

(* Specifications: *)
Lemma NDsubsume_subsume:
forall f1 f2,
is_NDfunspec f2 ->
NDsubsume_funspec f1 f2 ->
subsume_funspec f1 f2.