diff --git a/_CoqProject b/_CoqProject index d914ff878dd64dc93325097c297ef93486ca4027..28a244a52fc3f4023e523ab031b6fb6cb2b05dd8 100644 --- a/_CoqProject +++ b/_CoqProject @@ -47,4 +47,5 @@ theories/typing/tests/get_x.v theories/typing/tests/rebor.v theories/typing/tests/unbox.v theories/typing/tests/init_prod.v +theories/typing/tests/option_as_mut.v theories/typing/unsafe/cell.v diff --git a/theories/lang/new_delete.v b/theories/lang/new_delete.v index 5b5be8279fabfc7e849d40a5ba712e1df3cb5c90..d8f685623dacec379df2d3ca8d23457f2a99f243 100644 --- a/theories/lang/new_delete.v +++ b/theories/lang/new_delete.v @@ -41,10 +41,10 @@ Section specs. Qed. End specs. -(* FIXME : why are these notations not pretty-printed. *) -Notation "'letalloc:' x := e1 'in' e2" := +(* FIXME : why are these notations not pretty-printed? *) +Notation "'letalloc:' x <- e1 'in' e2" := ((Lam (@cons binder x%E%E%E nil) (x <- e1 ;; e2)) [new [ #1]])%E (at level 102, x at level 1, e1, e2 at level 200) : expr_scope. -Notation "'letalloc:' x :={ n } ! e1 'in' e2" := +Notation "'letalloc:' x <⋯ !{ n } e1 'in' e2" := ((Lam (@cons binder x%E%E%E nil) (x <⋯ !{n%Z%V}e1 ;; e2)) [new [ #n]])%E (at level 102, x at level 1, e1, e2 at level 200) : expr_scope. diff --git a/theories/lang/notation.v b/theories/lang/notation.v index 915062ba05a8abba8506803f9d0d5a1923667631..dcd053b6fe9506c548013135d9f256a55109ddfe 100644 --- a/theories/lang/notation.v +++ b/theories/lang/notation.v @@ -25,9 +25,9 @@ Notation "# l" := (Lit l%Z%V) (at level 8, format "# l") : expr_scope. (** Syntax inspired by Coq/Ocaml. Constructions with higher precedence come first. *) Notation "'case:' e0 'of' el" := (Case e0%E el%E) - (at level 102, e0, el at level 200) : expr_scope. + (at level 102, e0, el at level 150) : expr_scope. Notation "'if:' e1 'then' e2 'else' e3" := (If e1%E e2%E e3%E) - (at level 200, e1, e2, e3 at level 200) : expr_scope. + (only parsing, at level 200, e1, e2, e3 at level 150) : expr_scope. Notation "()" := LitUnit : val_scope. Notation "! e" := (Read Na1Ord e%E) (at level 9, format "! e") : expr_scope. Notation "!ˢᶜ e" := (Read ScOrd e%E) (at level 9, format "!ˢᶜ e") : expr_scope. @@ -65,25 +65,25 @@ Notation "'funrec:' f xl := e" := (rec: f ("return"::xl) := e)%V Notation "'let:' x := e1 'in' e2" := ((Lam (@cons binder x%RustB nil) e2%E) (@cons expr e1%E nil)) - (at level 102, x at level 1, e1, e2 at level 200) : expr_scope. + (at level 102, x at level 1, e1, e2 at level 150) : expr_scope. Notation "e1 ;; e2" := (let: <> := e1 in e2)%E - (at level 100, e2 at level 200, format "e1 ;; e2") : expr_scope. + (at level 100, e2 at level 150, format "e1 ;; e2") : expr_scope. (* These are not actually values, but we want them to be pretty-printed. *) Notation "'let:' x := e1 'in' e2" := (LamV (@cons binder x%RustB nil) e2%E (@cons expr e1%E nil)) - (at level 102, x at level 1, e1, e2 at level 200) : val_scope. + (at level 102, x at level 1, e1, e2 at level 150) : val_scope. Notation "e1 ;; e2" := (let: <> := e1 in e2)%V - (at level 100, e2 at level 200, format "e1 ;; e2") : val_scope. + (at level 100, e2 at level 150, format "e1 ;; e2") : val_scope. -Notation "'letcont:' k xl := e1 'in' e2" := - ((Lam (@cons binder k%RustB nil) e2%E) [Rec k%RustB xl%RustB e1%E]) - (only parsing, at level 102, k, xl at level 1, e1, e2 at level 200) : expr_scope. +Notation "e1 'cont:' k xl := e2" := + ((Lam (@cons binder k%RustB nil) e1%E) [Rec k%RustB xl%RustB e2%E]) + (only parsing, at level 151, k, xl at level 1, e2 at level 150) : expr_scope. Notation "'call:' f args → k" := (f (@cons expr k args))%E (only parsing, at level 102, f, args, k at level 1) : expr_scope. Notation "'letcall:' x := f args 'in' e" := - (letcont: "_k" [ x ] := e in call: f args → "_k")%E - (at level 102, x, f, args at level 1, e at level 200) : expr_scope. + (call: f args → "_k" cont: "_k" [ x ] := e)%E + (at level 102, x, f, args at level 1, e at level 150) : expr_scope. Notation "e1 <-{ i } '☇'" := (e1 <- #i)%E (only parsing, at level 80) : expr_scope. diff --git a/theories/typing/cont.v b/theories/typing/cont.v index c282642773ed0f0fe012275a7862edafc9383c8a..fd3731326f68da626495980e91cde3dafd22d7a8 100644 --- a/theories/typing/cont.v +++ b/theories/typing/cont.v @@ -19,14 +19,14 @@ Section typing. rewrite -{3}(vec_to_list_of_list args). iApply ("HC" with "* Htl HL HT"). Qed. - Lemma type_cont argsb L1 T' E L2 C T econt e2 kb : + Lemma type_cont argsb L1 (T' : vec val (length argsb) → _) E L2 C T econt e2 kb : Closed (kb :b: argsb +b+ []) econt → Closed (kb :b: []) e2 → - (∀ k args, typed_body E L1 (k â—cont(L1, T') :: C) (T' args) - (subst_v (kb::argsb) (k:::args) econt)) → (∀ k, typed_body E L2 (k â—cont(L1, T') :: C) T (subst' kb k e2)) → - typed_body E L2 C T (letcont: kb argsb := econt in e2). + (∀ k (args : vec val (length argsb)), + typed_body E L1 (k â—cont(L1, T') :: C) (T' args) (subst_v (kb::argsb) (k:::args) econt)) → + typed_body E L2 C T (e2 cont: kb argsb := econt). Proof. - iIntros (Hc1 Hc2 Hecont He2) "!#". iIntros (tid qE) "#HEAP #LFT Htl HE HL HC HT". iApply wp_let'. + iIntros (Hc1 Hc2 He2 Hecont) "!#". iIntros (tid qE) "#HEAP #LFT Htl HE HL HC HT". iApply wp_let'. { simpl. rewrite decide_left. done. } iModIntro. iApply (He2 with "* HEAP LFT Htl HE HL [HC] HT"). clear He2. iIntros "HE". iLöb as "IH". iIntros (x) "H". diff --git a/theories/typing/function.v b/theories/typing/function.v index 0b97434e0d4952aa69802914c234c331d6b4d359..4890d0cf8a681f173d352cfc4af8d2b743e069a6 100644 --- a/theories/typing/function.v +++ b/theories/typing/function.v @@ -231,9 +231,6 @@ Section typing. + by eapply is_closed_weaken, list_subseteq_nil. + eapply Is_true_eq_left, forallb_forall, List.Forall_forall, Forall_impl=>//. intros. eapply Is_true_eq_true, is_closed_weaken=>//. set_solver+. - - intros k ret. inv_vec ret=>ret. rewrite /subst_v /=. - rewrite ->(is_closed_subst []), incl_cctx_incl; first done; try set_solver+. - apply subst'_is_closed; last done. apply is_closed_of_val. - intros. (* TODO : make [simpl_subst] work here. *) change (subst' "_k" k (p (Var "_k" :: ps))) with @@ -242,6 +239,9 @@ Section typing. assert (map (subst "_k" k) ps = ps) as ->. { clear -Hpsc. induction Hpsc=>//=. rewrite is_closed_nil_subst //. congruence. } eapply type_call; try done. constructor. done. + - move=>/= k ret. inv_vec ret=>ret. rewrite /subst_v /=. + rewrite ->(is_closed_subst []), incl_cctx_incl; first done; try set_solver+. + apply subst'_is_closed; last done. apply is_closed_of_val. Qed. Lemma type_rec {A} E L E' fb (argsb : list binder) e diff --git a/theories/typing/lft_contexts.v b/theories/typing/lft_contexts.v index aab3d1c2f56e98c5a1d3845c8af2f1593d0ae739..2093f918a1805b199bdbb1ced97441d0371ab40b 100644 --- a/theories/typing/lft_contexts.v +++ b/theories/typing/lft_contexts.v @@ -444,8 +444,8 @@ Arguments elctx_incl {_ _ _} _%EL _%LL _%EL _%EL. [tctx_extract_hasty] to suceed even if the type is an evar, and merging makes it diverge in this case. *) Ltac solve_typing := - (eauto 100 with lrust_typing typeclass_instances; fail) || - (eauto 100 with lrust_typing lrust_typing_merge typeclass_instances; fail). + (eauto 100 with lrust_typing typeclass_instances lia; fail) || + (eauto 100 with lrust_typing lrust_typing_merge typeclass_instances lia; fail). Create HintDb lrust_typing_merge. Hint Constructors Forall Forall2 elem_of_list : lrust_typing. diff --git a/theories/typing/own.v b/theories/typing/own.v index c63a3aa6bf48679a3a7764c54cc1c0923a6e7e1e..322a06d32e6417116c0dac0b86dd8645e8b078f4 100644 --- a/theories/typing/own.v +++ b/theories/typing/own.v @@ -256,7 +256,7 @@ Section typing. tctx_extract_hasty E L p ty T T' → ty.(ty_size) = 1%nat → (∀ (v : val), typed_body E L C ((v â— own 1 ty)::T') (subst x v e)) → - typed_body E L C T (letalloc: x := p in e). + typed_body E L C T (letalloc: x <- p in e). Proof. intros. eapply type_new. - rewrite /Closed /=. rewrite !andb_True. @@ -278,7 +278,7 @@ Section typing. tctx_extract_hasty E L p ty1 T T' → (∀ (v : val), typed_body E L C ((v â— own (ty.(ty_size)) ty)::(p â— ty2)::T') (subst x v e)) → - typed_body E L C T (letalloc: x :={ty.(ty_size)} !p in e). + typed_body E L C T (letalloc: x <⋯ !{ty.(ty_size)}p in e). Proof. intros. eapply type_new. - rewrite /Closed /=. rewrite !andb_True. diff --git a/theories/typing/sum.v b/theories/typing/sum.v index e42e2536f173cfdf302d3d9567d4d70d0a7ed285..d2da2e67386b708d646f2690de53265197c29db7 100644 --- a/theories/typing/sum.v +++ b/theories/typing/sum.v @@ -235,6 +235,6 @@ End sum. (* Σ is commonly used for the current functor. So it cannot be defined as Î for products. We stick to the following form. *) Notation "Σ[ ty1 ; .. ; tyn ]" := - (sum (cons ty1 (..(cons tyn nil)..))) : lrust_typing. + (sum (cons ty1%T (..(cons tyn%T nil)..))) : lrust_type_scope. Hint Resolve sum_mono' sum_proper' : lrust_typing. diff --git a/theories/typing/tests/get_x.v b/theories/typing/tests/get_x.v index 80f507e37fb9c26ebc5485f284224e188b8f51f8..2140dcaffa0c0b945dc39e45af9af7a5b6552bed 100644 --- a/theories/typing/tests/get_x.v +++ b/theories/typing/tests/get_x.v @@ -10,7 +10,7 @@ Section get_x. Definition get_x : val := funrec: <> ["p"] := let: "p'" := !"p" in - letalloc: "r" := "p'" +â‚— #0 in + letalloc: "r" <- "p'" +â‚— #0 in delete [ #1; "p"] ;; "return" ["r"]. Lemma get_x_type : diff --git a/theories/typing/tests/option_as_mut.v b/theories/typing/tests/option_as_mut.v new file mode 100644 index 0000000000000000000000000000000000000000..2a735e97fe92fefd1e173d38ed0a0e96816d5cdf --- /dev/null +++ b/theories/typing/tests/option_as_mut.v @@ -0,0 +1,40 @@ +From lrust.lifetime Require Import definitions. +From lrust.lang Require Import new_delete. +From lrust.typing Require Import programs product product_split own uniq_bor + shr_bor int function lft_contexts uninit cont borrow type_sum. +Set Default Proof Using "Type". + +Section option_as_mut. + Context `{typeG Σ}. + + Definition option_as_mut := + (funrec: <> ["o"] := + let: "o'" := !"o" in case: !"o'" of + [ let: "r" := new [ #2 ] in "r" <-{0} ☇;; + "k" ["r"]; + let: "r" := new [ #2 ] in "r" <-{1} "o'" +â‚— #1;; + "k" ["r"] ] + cont: "k" ["r"] := + delete [ #1; "o"];; "return" ["r"])%E. + + Lemma option_as_mut_type Ï„ : + typed_instruction_ty [] [] [] option_as_mut + (fn (λ α, [☀α])%EL (λ α, [# own 1 (&uniq{α}Σ[unit; Ï„])]) + (λ α, own 2 (Σ[unit; &uniq{α}Ï„]))). + Proof. + apply type_fn; try apply _. move=> /= α ret p. inv_vec p=>o. simpl_subst. + eapply (type_cont [_] [] (λ r, [o â— _; r!!!0 â— _])%TC) ; try solve_typing. + - intros k. simpl_subst. + eapply type_deref; try solve_typing; [apply read_own_move|done|]=>o'. simpl_subst. + eapply type_case_uniq; try solve_typing. constructor; last constructor; last constructor. + + left. eapply type_new; try solve_typing. intros r. simpl_subst. + eapply (type_sum_assign_unit [unit; &uniq{α}Ï„]%T); try solve_typing. by apply write_own. + eapply (type_jump [_]); solve_typing. + + left. eapply type_new; try solve_typing. intros r. simpl_subst. + eapply (type_sum_assign [unit; &uniq{α}Ï„]%T); try solve_typing. by apply write_own. + eapply (type_jump [_]); solve_typing. + - move=>/= k r. inv_vec r=>r. simpl_subst. + eapply type_delete; try solve_typing. + eapply (type_jump [_]); solve_typing. + Qed. +End option_as_mut. diff --git a/theories/typing/tests/rebor.v b/theories/typing/tests/rebor.v index 6a8c4a739df35b3ed40c3f3f27f3776e36d56829..39cc4532cc288016f93cf04f7de902612e316679 100644 --- a/theories/typing/tests/rebor.v +++ b/theories/typing/tests/rebor.v @@ -10,11 +10,11 @@ Section rebor. Definition rebor : val := funrec: <> ["t1"; "t2"] := Newlft;; - letalloc: "x" := "t1" in + letalloc: "x" <- "t1" in let: "x'" := !"x" in let: "y" := "x'" +â‚— #0 in "x" <- "t2";; let: "y'" := !"y" in - letalloc: "r" := "y'" in + letalloc: "r" <- "y'" in Endlft ;; delete [ #2; "t1"] ;; delete [ #2; "t2"] ;; delete [ #1; "x"] ;; "return" ["r"]. diff --git a/theories/typing/tests/unbox.v b/theories/typing/tests/unbox.v index f2af4f94cb5faef1d06e75bce394d123fcb2c0e1..d25078036e826661e272c26287d8b051952392c9 100644 --- a/theories/typing/tests/unbox.v +++ b/theories/typing/tests/unbox.v @@ -10,7 +10,7 @@ Section unbox. Definition unbox : val := funrec: <> ["b"] := let: "b'" := !"b" in let: "bx" := !"b'" in - letalloc: "r" := "bx" +â‚— #0 in + letalloc: "r" <- "bx" +â‚— #0 in delete [ #1; "b"] ;; "return" ["r"]. Lemma ubox_type : diff --git a/theories/typing/type_sum.v b/theories/typing/type_sum.v index 0e7412d6c3d29bb6accf686d5747f91eaaf4a4d8..93f37f87d7066e8b35da37ca99649996b068c6f0 100644 --- a/theories/typing/type_sum.v +++ b/theories/typing/type_sum.v @@ -151,12 +151,12 @@ Section case. apply type_case_shr'; first done. eapply Forall2_impl; first done. auto. Qed. - Lemma type_sum_assign {E L} (i : nat) tyl ty1 ty2 ty p1 p2 : - tyl !! i = Some ty → + Lemma type_sum_assign_instr {E L} (i : nat) ty1 tyl ty ty2 p1 p2 : typed_write E L ty1 (sum tyl) ty2 → + tyl !! i = Some ty → typed_instruction E L [p1 â— ty1; p2 â— ty] (p1 <-{i} p2) (λ _, [p1 â— ty2]%TC). Proof. - iIntros (Hty Hw) "!# * #HEAP #LFT $ HE HL Hp". + iIntros (Hw Hty) "!# * #HEAP #LFT $ HE HL Hp". rewrite tctx_interp_cons tctx_interp_singleton. iDestruct "Hp" as "[Hp1 Hp2]". iDestruct (closed_hasty with "Hp1") as "%". iDestruct (closed_hasty with "Hp2") as "%". wp_bind p1. @@ -178,7 +178,20 @@ Section case. iExists i, [_], _. rewrite -Hlen nth_lookup Hty. auto. Qed. - Lemma type_sum_assign_unit {E L} (i : nat) tyl ty1 ty2 p : + Lemma type_sum_assign {E L} tyl i ty1 ty ty1' C T T' p1 p2 e: + Closed [] e → + 0 ≤ i → + tctx_extract_ctx E L [p1 â— ty1; p2 â— ty] T T' → + typed_write E L ty1 (sum tyl) ty1' → + tyl !! (Z.to_nat i) = Some ty → + typed_body E L C ((p1 â— ty1') :: T') e → + typed_body E L C T (p1 <-{i} p2 ;; e). + Proof. + intros. rewrite -(Z2Nat.id i) //. + eapply type_seq; [done|by eapply type_sum_assign_instr|done|done]. + Qed. + + Lemma type_sum_assign_unit_instr {E L} (i : nat) tyl ty1 ty2 p : tyl !! i = Some unit → typed_write E L ty1 (sum tyl) ty2 → typed_instruction E L [p â— ty1] (p <-{i} ☇) (λ _, [p â— ty2]%TC). @@ -193,7 +206,20 @@ Section case. iExists i, [], _. rewrite -Hlen nth_lookup Hty. auto. Qed. - Lemma type_sum_memcpy {E L} (i : nat) tyl ty1 ty1' ty2 ty2' ty p1 p2 : + Lemma type_sum_assign_unit {E L} tyl i ty1 ty1' C T T' p e: + Closed [] e → + 0 ≤ i → + tctx_extract_hasty E L p ty1 T T' → + typed_write E L ty1 (sum tyl) ty1' → + tyl !! (Z.to_nat i) = Some unit → + typed_body E L C ((p â— ty1') :: T') e → + typed_body E L C T (p <-{i} ☇ ;; e). + Proof. + intros. rewrite -(Z2Nat.id i) //. + eapply type_seq; [done|by eapply type_sum_assign_unit_instr|solve_typing|done]. + Qed. + + Lemma type_sum_memcpy_instr {E L} (i : nat) tyl ty1 ty1' ty2 ty2' ty p1 p2 : tyl !! i = Some ty → typed_write E L ty1 (sum tyl) ty1' → typed_read E L ty2 ty ty2' → @@ -230,4 +256,19 @@ Section case. iExists _. iFrame. rewrite /= drop_length. iPureIntro. lia. - iExists _. iFrame. Qed. + + Lemma type_sum_assign_memcpy {E L} tyl i ty1 ty2 ty n ty1' ty2' C T T' p1 p2 e: + Closed [] e → + 0 ≤ i → + tctx_extract_ctx E L [p1 â— ty1; p2 â— ty2] T T' → + typed_write E L ty1 (sum tyl) ty1' → + typed_read E L ty2 ty ty2' → + Z.of_nat (ty.(ty_size)) = n → + tyl !! (Z.to_nat i) = Some ty → + typed_body E L C ((p1 â— ty1') :: (p2 â— ty2') :: T') e → + typed_body E L C T (p1 <⋯{i} !{n}p2 ;; e). + Proof. + intros ???? Hr ???. subst. rewrite -(Z2Nat.id i) //. + by eapply type_seq; [done|eapply type_sum_memcpy_instr, Hr|done|done]. + Qed. End case.