relational reasoning using concurrent separation logic
play

Relational reasoning using concurrent separation logic Robbert - PowerPoint PPT Presentation

Relational reasoning using concurrent separation logic Robbert Krebbers 1 Delft University of Technology, The Netherlands January 20, 2020 @ ADSL, New Orleans, USA 1 This is joint work with Dan Frumin (Radboud University) and Lars Birkedal (Aarhus


  1. Proof of the refinement � � true , ( λ b . ¬ b ) , ( λ b . b ) pack � � � 1 , ( λ n . if n = 0 then 1 else 0) , ( λ n . n = 1) pack : ∃ α. α × ( α → α ) × ( α → bool ) 15

  2. Proof of the refinement � � true , ( λ b . ¬ b ) , ( λ b . b ) pack � � � 1 , ( λ n . if n = 0 then 1 else 0) , ( λ n . n = 1) pack : ∃ α. α × ( α → α ) × ( α → bool ) Need to come with with an R : Val × Val → Prop 15

  3. Proof of the refinement where R � { ( true , 1) , ( false , 0) } � � true , ( λ b . ¬ b ) , ( λ b . b ) pack � � � 1 , ( λ n . if n = 0 then 1 else 0) , ( λ n . n = 1) pack : ∃ α. α × ( α → α ) × ( α → bool ) Need to come with with an R : Val × Val → Prop 15

  4. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = � � true , ( λ b . ¬ b ) , ( λ b . b ) � � � 1 , ( λ n . if n = 0 then 1 else 0) , ( λ n . n = 1) : α × ( α → α ) × ( α → bool ) 15

  5. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = � � true , ( λ b . ¬ b ) , ( λ b . b ) � � � 1 , ( λ n . if n = 0 then 1 else 0) , ( λ n . n = 1) : α × ( α → α ) × ( α → bool ) Use structural rule for products 15

  6. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ b . b ) � ( λ n . n = 1) : α → bool 15

  7. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ b . b ) � ( λ n . n = 1) : α → bool 15

  8. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α (by def of R ) ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ b . b ) � ( λ n . n = 1) : α → bool 15

  9. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α (by def of R ) ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ -rule + symb. exec.) ( λ b . b ) � ( λ n . n = 1) : α → bool After using the λ rule and case analysis on R : ¬ true � if 1 = 0 then 1 else 0 : α ¬ false � if 0 = 0 then 1 else 0 : α 15

  10. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α (by def of R ) ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ -rule + symb. exec.) ( λ b . b ) � ( λ n . n = 1) : α → bool ( λ -rule + symb. exec.) 15

  11. Proof of the refinement where R � { ( true , 1) , ( false , 0) } [ α := R ] | = true � 1 : α (by def of R ) ( λ b . ¬ b ) � ( λ n . if n = 0 then 1 else 0) : α → α ( λ -rule + symb. exec.) ( λ b . b ) � ( λ n . n = 1) : α → bool ( λ -rule + symb. exec.) � 15

  12. Reasoning about mutable state Separation logic to the rescue! 16

  13. “Vanilla” separation logic [O’Hearn, Reynolds, Yang; CSL’01] Propositions P , Q denote ownership of resources Points-to connective ℓ �→ v : Exclusive ownership of location ℓ with value v Separating conjunction P ∗ Q : The resources consists of separate parts satisfying P and Q Basic example: { ℓ 1 �→ v 1 ∗ ℓ 2 �→ v 2 } swap ( ℓ 1 , ℓ 2 ) { ℓ 1 �→ v 2 ∗ ℓ 2 �→ v 1 } the ∗ ensures that ℓ 1 and ℓ 2 are different memory locations 17

  14. Mutable state and separation logic for refinements There are two versions of the points-to connective: ◮ ℓ �→ i v for the left-hand side/implementation ◮ ℓ �→ s v for the right-hand side/specification 18

  15. Mutable state and separation logic for refinements There are two versions of the points-to connective: ◮ ℓ �→ i v for the left-hand side/implementation ◮ ℓ �→ s v for the right-hand side/specification Example: (! ℓ 1 ) � ( ℓ 2 ← 4; ! ℓ 2 ) : int ℓ 1 �→ i 4 − ∗ ℓ 2 �→ s 0 − ∗ 18

  16. Some rules for mutable state Symbolic execution = K [ () ] � e 2 : τ ) ∗ ℓ 1 �→ i − ∗ ( ℓ 1 �→ i v 1 − ∗ ∆ || = K [ ℓ 1 ← v 1 ] � e 2 : τ ∆ || 19

  17. Some rules for mutable state Symbolic execution = K [ () ] � e 2 : τ ) ∗ ℓ 1 �→ i − ∗ ( ℓ 1 �→ i v 1 − ∗ ∆ || = K [ ℓ 1 ← v 1 ] � e 2 : τ ∆ || = e 1 � K [ () ] : τ ) ∗ ℓ 2 �→ s − ∗ ( ℓ 2 �→ s v 2 − ∗ ∆ || = e 1 � K [ ℓ 2 ← v 2 ] : τ ∆ || 19

  18. Some rules for mutable state Symbolic execution = K [ () ] � e 2 : τ ) ∗ ℓ 1 �→ i − ∗ ( ℓ 1 �→ i v 1 − ∗ ∆ || = K [ ℓ 1 ← v 1 ] � e 2 : τ ∆ || = e 1 � K [ () ] : τ ) ∗ ℓ 2 �→ s − ∗ ( ℓ 2 �→ s v 2 − ∗ ∆ || = e 1 � K [ ℓ 2 ← v 2 ] : τ ∆ || = K [ ℓ 1 ] � e 2 : τ ∗ = e � K [ ℓ 2 ] : τ ∗ ∀ ℓ 1 . ℓ 1 �→ i v 1 − ∗ ∆ || ∀ ℓ 2 . ℓ 2 �→ s v 2 − ∗ ∆ || = K [ ref ( v 1 ) ] � e 2 : τ = e 1 � K [ ref ( v 2 ) ] : τ ∆ || ∆ || 19

  19. Reasoning about higher-order functions and concurrency 20

  20. State encapsulation Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . The reference can only be used in the closure 21

  21. State encapsulation Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . The reference can only be used in the closure Simple example: � �� � counter � λ () . let x = ref (1) in λ () . FAA ( x , 1) : unit → ( unit → int ) ◮ counter () constructs an instance c : unit → int of the counter module ◮ Calling c () in subsequently gives 1 , 2 , . . . ◮ The reference x is private to the module 21

  22. The problem Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . � �� � f 22

  23. The problem Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . � �� � f Reasoning about such modules is challenging: ◮ f can be called multiple times by clients So, the value of x can change in each call 22

  24. The problem Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . � �� � f Reasoning about such modules is challenging: ◮ f can be called multiple times by clients So, the value of x can change in each call ◮ f can even be called even in parallel! So, f cannot get exclusive access to x �→ v 22

  25. The problem Modules with encapsulated state : � � let x = ref ( e ) in λ y . . . . � �� � f Reasoning about such modules is challenging: ◮ f can be called multiple times by clients So, the value of x can change in each call ◮ f can even be called even in parallel! So, f cannot get exclusive access to x �→ v We need to guarantee that closures do not get access to exclusive resources 22

  26. Persistent resources The “persistent” modality � in Iris/ReLoC: � P � “ P holds without assuming exclusive resources” Examples: ◮ Equality is persistent: ( x = y ) ⊢ � ( x = y ) ◮ Points-to connectives are not: (( ℓ �→ v ) �⊢ � ( ℓ �→ v ) ◮ More examples later. . . 23

  27. ReLoC’s λ -rule again The � modality makes sure no exclusive resources can escape into closures: � ∀ v 1 v 2 . � τ � ∆ ( v 1 , v 2 ) − � ∗ � = e 1 [ v 1 / x 1 ] � e 2 [ v 2 / x 2 ] : σ ∆ || ∗ = λ x 1 . e 1 � λ x 2 . e 2 : τ → σ ∆ || 24

  28. ReLoC’s λ -rule again The � modality makes sure no exclusive resources can escape into closures: � ∀ v 1 v 2 . � τ � ∆ ( v 1 , v 2 ) − � ∗ � = e 1 [ v 1 / x 1 ] � e 2 [ v 2 / x 2 ] : σ ∆ || ∗ = λ x 1 . e 1 � λ x 2 . e 2 : τ → σ ∆ || Prohibits “wrong” refinements, for example: � � � � � � ctx λ () . 1 let x = ref (0) in ( λ () . x ← (1 + ! x ); ! x ) Due to � , the resource x �→ s 0 cannot be used to prove the closure 24

  29. But it should be possible to use resources in closures For example: � �� � λ () . let x = ref (1) in λ () . FAA ( x , 1) �   λ () . let x = ref (1) , l = newlock () in λ () . acquire( l );     let v = ! x in     x ← v + 1;   release( l ); v 25

  30. Iris-style Invariants The invariant connective R expresses that R is maintained as an invariant on the state 26

  31. Iris-style Invariants The invariant connective R expresses that R is maintained as an invariant on the state Invariants allow to share resources: ◮ A resource R can be turned into R at any time ◮ Invariants are persistent: R ⊢ � R ◮ . . . thus can be used to prove closures 26

  32. Iris-style Invariants The invariant connective R expresses that R is maintained as an invariant on the state Invariants allow to share resources: ◮ A resource R can be turned into R at any time ◮ Invariants are persistent: R ⊢ � R ◮ . . . thus can be used to prove closures But that comes with a cost: ◮ Invariants R can only be accessed during atomic steps on the left-hand side ◮ . . . while multiple steps on the right-hand side can be performed 26

  33. Example let x = ref (1) in ( λ () . FAA ( x , 1)) � let x = ref (1) , l = newlock () in ( λ () . acquire( l ); let v = ! x in x ← v + 1; release( l ); v ) 27

  34. Example let x = ref (1) in ( λ () . FAA ( x , 1)) � let x = ref (1) , l = newlock () in ( λ () . acquire( l ); let v = ! x in x ← v + 1; release( l ); v ) 27

  35. Example ( λ () . FAA ( x 1 , 1)) � x 1 �→ i 1 let x = ref (1) , l = newlock () in ( λ () . acquire( l ); let v = ! x in x ← v + 1; release( l ); v ) 27

  36. Example ( λ () . FAA ( x 1 , 1)) � x 1 �→ i 1 let x = ref (1) , l = newlock () in ( λ () . acquire( l ); let v = ! x in x ← v + 1; release( l ); v ) 27

  37. Example ( λ () . FAA ( x 1 , 1)) � x 1 �→ i 1 let l = newlock () in x 2 �→ s 1 ( λ () . acquire( l ); let v = ! x 2 in x 2 ← v + 1; release( l ); v ) 27

  38. Example ( λ () . FAA ( x 1 , 1)) � x 1 �→ i 1 let l = newlock () in x 2 �→ s 1 ( λ () . acquire( l ); let v = ! x 2 in x 2 ← v + 1; release( l ); v ) 27

  39. Example ( λ () . FAA ( x 1 , 1)) � x 1 �→ i 1 ( λ () . acquire( l ); let v = ! x 2 in x 2 �→ s 1 x 2 ← v + 1; isLock( l , unlocked ) release( l ); v ) 27

  40. Example ( λ () . FAA ( x 1 , 1)) � ∃ n . x 1 �→ i n ( λ () . acquire( l ); let v = ! x 2 in x 2 �→ s n x 2 ← v + 1; isLock( l , unlocked ) release( l ); v ) 27

  41. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ ( λ () . FAA ( x 1 , 1)) isLock( l , unlocked ) � ( λ () . acquire( l ); let v = ! x 2 in x 2 ← v + 1; release( l ); v ) 27

  42. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ FAA ( x 1 , 1) isLock( l , unlocked ) � acquire( l ); let v = ! x 2 in x 2 ← v + 1; release( l ); v 27

  43. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ FAA ( x 1 , 1) isLock( l , unlocked ) � acquire( l ); let v = ! x 2 in x 2 ← v + 1; release( l ); v 27

  44. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ FAA ( x 1 , 1) isLock( l , unlocked ) � x 1 �→ i n acquire( l ); x 2 �→ s n let v = ! x 2 in isLock( l , unlocked ) x 2 ← v + 1; release( l ); v 27

  45. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 acquire( l ); x 2 �→ s n let v = ! x 2 in isLock( l , unlocked ) x 2 ← v + 1; release( l ); v 27

  46. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 acquire( l ); x 2 �→ s n let v = ! x 2 in isLock( l , unlocked ) x 2 ← v + 1; release( l ); v 27

  47. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n let v = ! x 2 in isLock( l , locked ) x 2 ← v + 1; release( l ); v 27

  48. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n let v = ! x 2 in isLock( l , locked ) x 2 ← v + 1; release( l ); v 27

  49. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n isLock( l , locked ) x 2 ← n + 1; release( l ); n 27

  50. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n isLock( l , locked ) x 2 ← n + 1; release( l ); n 27

  51. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n + 1 isLock( l , locked ) release( l ); n 27

  52. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n + 1 isLock( l , locked ) release( l ); n 27

  53. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � x 1 �→ i n + 1 x 2 �→ s n + 1 isLock( l , unlocked ) n 27

  54. Example ∃ n . x 1 �→ i n ∗ x 2 �→ s n ∗ n isLock( l , unlocked ) � n 27

  55. Wrapping up. . . ◮ ReLoC provides rules allowing this kind of simulation reasoning, formally ◮ The example can be done in Coq in almost the same fashion ◮ The approach scales to: lock-free concurrent data structures, generative ADTs, examples from the logical relations literature 28

  56. Implementation in Coq 29

  57. ReLoC ReLoC is build on top of the Iris framework , so we can inherit: ◮ Iris’s invariants ◮ Iris’s ghost state ◮ Iris’s Coq infrastructure ◮ . . . 30

  58. The proofs we have done in Coq ReLoC judgments e 1 � e 2 : τ are modeled as a shallow embedding using the “logical approach” to logical relations Proved in Coq: ◮ Proof rules: All the ReLoC rules hold in the shallow embedding ◮ Soundness: e 1 � e 2 : τ = ⇒ e 1 � ctx e 2 : τ ◮ Actual program refinements: concurrent data structures, and examples from the logical relations literature 31

  59. Need to reason in separation logic! 32

  60. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . Proof . iIntros "[H1 [H2 H3]]" . iDestruct "H2" as (x) "H2". iSplitL "H3". - iAssumption. - iExists x. iFrame. Qed. 33

  61. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . Proof . iIntros "[H1 [H2 H3]]" . Lemma in the Iris logic iDestruct "H2" as (x) "H2". iSplitL "H3". - iAssumption. - iExists x. iFrame. Qed. 33

  62. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : 1 subgoal P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . A : Type P , Q : iProp Proof . Ψ : A → iProp iIntros "[H1 [H2 H3]]" . x : A iDestruct "H2" as (x) "H2". (1/1) iSplitL "H3". "H1" : P - iAssumption. "H2" : Ψ x - iExists x. "H3" : Q iFrame. − − − − − − − − − − − − − − − − − − − − − −∗ Q ∗ ( ∃ a : A , P ∗ Ψ a ) Qed. 33

  63. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : 1 subgoal P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . A : Type P , Q : iProp Proof . Ψ : A → iProp iIntros "[H1 [H2 H3]]" . x : A iDestruct "H2" as (x) "H2". (1/1) iSplitL "H3". "H1" : P - iAssumption. "H2" : Ψ x - iExists x. "H3" : Q iFrame. − − − − − − − − − − − − − − − − − − − − − −∗ Q ∗ ( ∃ a : A , P ∗ Ψ a ) Qed. ∗ means: resources should be split 33

  64. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : 1 subgoal P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . A : Type P , Q : iProp Proof . Ψ : A → iProp iIntros "[H1 [H2 H3]]" . x : A iDestruct "H2" as (x) "H2". (1/1) iSplitL "H3". "H1" : P - iAssumption. "H2" : Ψ x - iExists x. "H3" : Q The hypotheses for the left conjunct iFrame. − − − − − − − − − − − − − − − − − − − − − −∗ Q ∗ ( ∃ a : A , P ∗ Ψ a ) Qed. ∗ means: resources should be split 33

  65. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : 2 subgoals P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . A : Type P , Q : iProp Proof . Ψ : A → iProp iIntros "[H1 [H2 H3]]" . x : A iDestruct "H2" as (x) "H2". (1/2) iSplitL "H3". "H3" : Q - iAssumption. − − − − − − − − − − − − − − − − − − − − − −∗ - iExists x. Q The hypotheses for the left conjunct iFrame. (2/2) Qed. "H1" : P "H2" : Ψ x − − − − − − − − − − − − − − − − − − − − − −∗ ∃ a : A , P ∗ Ψ a 33

  66. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . Proof . iIntros "[H1 [H2 H3]]" . iDestruct "H2" as (x) "H2". iSplitL "H3". - iAssumption. - iExists x. iFrame. Qed. 33

  67. Iris Proof Mode (IPM) [Krebbers et al. ; POPL’17] Lemma test { A } ( P Q : iProp ) (Ψ : A → iProp ) : No more subgoals . P ∗ ( ∃ a , Ψ a ) ∗ Q −∗ Q ∗ ∃ a , P ∗ Ψ a . Proof . iIntros "[H1 [H2 H3]]" . by iFrame. Qed. We can also solve this lemma automatically 33

Recommend


More recommend