(* * Copyright (c) 2009 Robert Dockins and Aquinas Hobor. * *)
(** Here we prove that the "obvious" typing rule for allp introduction is incorrect. The correct rule has the "value restriction."  We want to show that this typing rule would allow us to type an unsafe program.  Here is the form of the incorrect rule. *)
Definition bad_UnivI_rule :=
forall G e (X:pred world -> pred world),
(forall tau, Typ G e (X tau)) ->
Typ G e (allp X).
(* Here is the program.  The problem is that the reference 'r' is used at two incompatible types. This program eventually attepmts to apply the nat 5 to the nat 42 which gets stuck.  The program, in pseudo-ML, is:  let f := (let r := new none in fun x => r := some x; r) in let a := f (fun z => z) in let b := f 5 in out (fun z => z) (!a) 42  *)
Definition crash :=
e_let
(* f := *)
( e_let (* r := *) (New none) (* in *)
(Lam (* x *)
(Update (Var 1 (*r*))
(*:=*) (App some (Var 0 (*x*))) (* ; *) (Var 1 (*r*))))) (* in *)
( e_let (* a := *) (App (Var 0 (*f*)) (Lam (Var 0))) (* in *)
(e_let (* b := *) (App (Var 1 (*f*)) (Nat 5))       (* in *)
(App (App (App out (Lam (Var 0))) (Deref (Var 1 (*a*)))) (Nat 42))
)).

(* Apply the counterexample to show that the rule is unsound. *)
Theorem unrestricted_universals_inconsistent : ~bad_UnivI_rule.
Definition ok_program :=
e_let
(Lam
( e_let (* r := *) (New none) (* in *)
(Lam (* x *)
(Update (Var 1 (*r*))
( e_let (* a := *) (App (App (Var 0 (*f*)) (Nat 0)) (Lam (Var 0))) (* in *)
(e_let (* b := *) (App (App (Var 1 (*f*)) (Nat 0)) (Nat 5))       (* in *)
(App (App (App out (Lam (Var 0))) (Deref (Var 1 (*a*)))) (Nat 42))
)).