(** 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))
     )).

(* Specifications: *)
Lemma crash_steps : exists m, stepstar (empty_mem, crash) (m, App (Nat 5) (Nat 42)).
Lemma crash_unsafe : ~safe_prog crash.
Lemma bad_rule_crash : bad_UnivI_rule -> Typ nil crash ty_nat.
Theorem unrestricted_universals_inconsistent : ~bad_UnivI_rule.