Presentation is loading. Please wait.

Presentation is loading. Please wait.

Software Verification With Liquid Types Ranjit Jhala, UC San Diego (with Pat Rondon, Ming Kawaguchi)

Similar presentations


Presentation on theme: "Software Verification With Liquid Types Ranjit Jhala, UC San Diego (with Pat Rondon, Ming Kawaguchi)"— Presentation transcript:

1 Software Verification With Liquid Types Ranjit Jhala, UC San Diego (with Pat Rondon, Ming Kawaguchi)

2 int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; } Software Verification

3 int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; } Example: Memory Safety Access In Array Bounds ?

4 int min_index(int [] a){ r = 0; n = a.length; for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; } Example: Memory Safety How to prove assert ? assert (0<=r && r<n)

5 int min_index(int [] a){ r = 0; n = a.length; //@invariant: 0 · i Æ 0 · r Æ r<n for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; } Example: Memory Safety

6 int min_index(int [] a){ r = 0; n = a.length; //@invariant: 0 · i Æ 0 · r Æ r<n for (i = 0; i < n; i++){ if (a[i] < a[r]) r = i; } return r; } Invariants By Man [Floyd-Hoare] Or Machine [Cousot-Cousot]

7 But, what of … Closures Collections Polymorphism Data Structures …?

8 H-O Logics? Quantifiers? Induction? But, what of …

9 Automation

10 H-O Logics? Quantifiers? Induction? A Solution: Types

11 Part I Part II Part III Types and Invariants Closures, Collections, Generics Induction for Data Structures

12 Part I Types and Invariants

13 Part I Refinement Types [Zenger ’97, Owre-Rushby-Shankar ’98, Xi-Pfenning ’98]

14 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 min_index: a:int array -> int

15 min_index: {a:int array|0 ≺ a.len} -> {v:int|0 ≼ v ≺ a.len} Type Refinement let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

16 min_index: {a:int array|0 ≺ a.len} -> {v:int|0 ≼ v ≺ a.len} “Requires” let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

17 min_index: {a:int array|0 ≺ a.len} -> {v:int|0 ≼ v ≺ a.len} “Ensures” let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

18 {r:int|0 ≼ r ≺ a.len}->{i:int|0 ≼ i}->{v:int|0 ≼ v ≺ a.len} loop: let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

19 {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} loop: let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

20 {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} “Requires” loop: let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

21 {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} “Ensures” loop: let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0

22 Part I Refinement Types 1. Type-checking 2. Refine-checking 3. Refine-Inference

23 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop : r:int -> i:int -> int Assume 1 loop : … r : int i : int Prove output is int r “subtype-of” int ⊢

24 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop : r:int -> i:int -> int Assume 1 loop : … r : int i : int Prove output is int r <: int ⊢

25 loop : r:int -> i:int -> int Assume 1 2 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop : … r : int i : int Prove index is int ⊢ i <: int

26 loop : r:int -> i:int -> int Assume 1 3 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 2 loop : … i : int r : int r': int i': int Prove input is int ⊢ r' <: int

27 loop : r:int -> i:int -> int Assume loop r' i' <: int Prove output is int 1 3 4 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 2 loop : … i : int r : int r': int i': int ⊢

28 loop : r:int -> i:int -> int AssumeProve input is int 1 3 4 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 2 5 loop : … i : int r : int r': int i': int ⊢ 0 <: int

29 Part I Refinement Types 1. Type-checking 2. Refine-checking 3. Refine-Inference

30 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} min_index {a:0 ≺ a.len}->{v:0 ≼ v ≺ a.len}

31 r :0 ≼ r ≺ a.len i :0 ≼ i Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 3 4 2 5 [i ≽ a.len]

32 r :0 ≼ r ≺ a.len i :0 ≼ i [i ≽ a.len] Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured ⊢ {v=r} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len}

33 r :0 ≼ r ≺ a.len i :0 ≼ i [i ≽ a.len] Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured ⊢ {v=r} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len}

34 Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured ⊢ {v=r} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≽ a.len

35 Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured {v=r} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≽ a.len ⋀

36 Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≽ a.len ⋀ ⇒ v=r 0 ≼ v ≺ a.len

37 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} v=r 0 ≼ v ≺ a.len ⋀ 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≽ a.len Is Valid? Yes. ⇒

38 Assume let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 r :0 ≼ r ≺ a.len i :0 ≼ i [i ≺ a.len] Prove index in bounds ⊢ {v=i} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 1 3 4 2 5 [i ≺ a.len]

39 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} ⇒ v=i 0 ≼ v ≺ a.len ⋀ 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≺ a.len Is Valid? Yes. 2

40 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove input as required ⊢ {v=r'} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 1 3 4 2 5

41 Assume let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 r :0 ≼ r ≺ a.len i :0 ≼ i [i ≺ a.len] i':i'=i+1 Prove input as required ⊢ {v=r'} <: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 3 r':r'=i ∨ r'=r

42 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 3 ⇒ v=r' 0 ≼ v ≺ a.len ⋀ Is Valid? Yes! 0 ≼ r ≺ a.len ⋀ 0 ≼ i ⋀ i ≺ a.len ⋀ r'=i ∨ r'=r ⋀ i'=i+1

43 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured ⊢ {0 ≼ v ≺ a.len}<: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 1 3 4 2 5 Trivial.

44 Assume let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 a :0 ≺ a.len Prove input as required ⊢ {v=0}<: {0 ≼ v ≺ a.len} loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 1 3 4 2 5

45 ⇒ ⋀ let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 v=0 0 ≼ v ≺ a.len loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 5 Is Valid? Indeed. 0 ≺ a.len

46 Part I Refinement Types 1. Type-checking 2. Refine-checking 3. Refine-Inference

47 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} min_index {a:0 ≺ a.len}->{v:0 ≼ v ≺ a.len}

48 loop {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} min_index {a:0 ≺ a.len}->{v:0 ≼ v ≺ a.len} Writing Types is Hard Work!

49 Automatic Refinement Inference Writing Types is Hard Work! loop: ???

50 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] loop: ???

51 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] loop : r:int -> i:int -> int

52 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] loop : {r:int| ? } -> {i:int| ? } -> {v:int| ? }

53 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } Types + X for unknown refinements

54 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out }

55 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] Type Checking, but with Templates

56 r : X r i : X i [i ≽ a.len] Assume 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } ⊢ {v=r} <: { X out }

57 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } ⋀ X r ⋀ X i ⋀ i ≽ a.len Is Valid? ⇒ v=r X out “It is too soon to say. ”

58 1 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } X r ⋀ X i ⋀ i ≽ a.len ⋀ v=r ⇒ X out Constraint 1

59 Assume let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove index in bounds ⊢ {v=i} <: {0 ≼ v ≺ a.len} 1 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } r : X r i : X i [i ≺ a.len]

60 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} 2 X r ⋀ X i ⋀ i ≺ a.len ⋀ v=i ⇒ 0 ≼ v ≺ a.len Constraint 2

61 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove input as required ⊢ {v:v=r'} <: {r:int| X r } 1 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } Assume r : X r i : X i [i ≺ a.len] r':r'=i ∨ r'=r i':i'=i+1

62 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 loop: {r:0 ≼ r ≺ a.len}->{i:0 ≼ i}->{v:0 ≼ v ≺ a.len} Constraint 3 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ v=r' X r [v/r ] ⇒

63 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove output is ensured 1 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } Constraint 4 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out X out ⇒

64 let min_index a = let rec loop r i = if i >= a.length then r else let r' = a[i] < a[r] ? i : r let i' = i + 1 loop r' i' loop 0 0 Prove input as required 1 3 4 2 5 loop :{r:int| X r } -> {i:int| X i } -> {v:int| X out } Constraint 5 0 ≺ a.len ⋀ v=0 X r [v/r ] ⇒

65 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] Type Checking, but with Templates

66 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] 0 ≺ a.len ⋀ v=0 ⇒ X r [v/r ] 1 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ v=r' ⇒ X r [v/r ] X r ⋀ X i ⋀ i ≺ a.len ⋀ v=i ⇒ 0 ≼ v ≺ a.len X r ⋀ X i ⋀ i ≽ a.len ⋀ v=r ⇒ X out 2 3 4 5

67 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out 4 ⋀ X i ⋀ P ⇒ X

68 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out 4 ⋀ X i ⋀ P ⇒ X

69 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out 4 ⋀ X i ⋀ P ⇒ X

70 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] 0 ≺ a.len ⋀ v=0 ⇒ X r [v/r ] 1 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ v=r' ⇒ X r [v/r ] X r ⋀ X i ⋀ i ≽ a.len ⋀ v=r ⇒ X out 2 3 4 5 X r ⋀ X i ⋀ i ≺ a.len ⋀ v=i ⇒ 0 ≼ v ≺ a.len ⋀ X i ⋀ P ⇒ Q

71 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] 0 ≺ a.len ⋀ v=0 ⇒ X r [v/r ] 1 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ v=r' ⇒ X r [v/r ] X r ⋀ X i ⋀ i ≽ a.len ⋀ v=r ⇒ X out 2 3 4 5 X r ⋀ X i ⋀ i ≺ a.len ⋀ v=i ⇒ 0 ≼ v ≺ a.len ⋀ X i ⋀ P ⇒ Q

72 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] 0 ≺ a.len ⋀ v=0 ⇒ X r [v/r ] 1 X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ X out ⇒ X out X r ⋀ X i ⋀ i ≺ a.len ⋀ (r'=i ∨ r'=r) ⋀ v=r' ⇒ X r [v/r ] X r ⋀ X i ⋀ i ≽ a.len ⋀ v=r ⇒ X out 2 3 4 5 X r ⋀ X i ⋀ i ≺ a.len ⋀ v=i ⇒ 0 ≼ v ≺ a.len ⋀ X i ⋀ P ⇒ Q

73 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] ⋀ X i ⋀ P ⇒ Q ⋀ X i ⋀ P ⇒ X (Post*) (Safe)

74 Automatic Refinement Inference 1. Templates 2. Constraints 3. Fixpoint [MC/AI] ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q

75 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q “Horn Clauses”

76 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q “Positive Implications”

77 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q “Non-Linear Implications”

78 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q 1. Reduce to simple “first-order” program Reuse any abs-interpreter, model-checker e.g. Interproc, SLAM, BLAST, ARMC [CAV 11]

79 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q 2. Monomial Predicate Abstraction (“Houdini”) Input : Candidates Q = {q 1 … q n } Output : X ↦ ⋀ q j satisfying constraints

80 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q 2. Monomial Predicate Abstraction (“Houdini”) Input : Q = { ⋆≼ v, v ≼ ⋆, v ≺ ⋆, v ≺ ⋆.len } ⋆ = any variable or constant

81 Automatic Refinement Inference Fixpoint Solution ⋀ X i ⋀ P ⇒ X ⋀ X i ⋀ P ⇒ Q 2. Monomial Predicate Abstraction (“Houdini”) Input : Q = { ⋆≼ v, v ≼ ⋆, v ≺ ⋆, v ≺ ⋆.len } Output : X r = 0 ≼ v ⋀ v ≺ a.len X i = 0 ≼ v X out = 0 ≼ v ⋀ v ≺ a.len

82 2. Monomial Predicate Abstraction (“Houdini”) Input : Q = { ⋆≼ v, v ≼ ⋆, v ≺ ⋆, v ≺ ⋆.len } Output : X r = 0 ≼ v ⋀ v ≺ a.len X i = 0 ≼ v X out = 0 ≼ v ⋀ v ≺ a.len Automatic Refinement Inference Plug Solution In Template loop: {r:int| X r } -> {i:int| X i } -> {v:int| X out }

83 2. Monomial Predicate Abstraction (“Houdini”) Input : Q = { ⋆≼ v, v ≼ ⋆, v ≺ ⋆, v ≺ ⋆.len } Output : X r = 0 ≼ v ⋀ v ≺ a.len X i = 0 ≼ v X out = 0 ≼ v ⋀ v ≺ a.len Automatic Refinement Inference Plug Solution In Template loop: {r:int|0 ≼ r ≺ a.len}->{i:int|0 ≼ i}->{v:int|0 ≼ v ≺ a.len}

84 Automatic Refinement Inference loop: {r:int|0 ≼ r ≺ a.len}->{i:int|0 ≼ i}->{v:int|0 ≼ v ≺ a.len} Inferred Refinement Type

85 Automatic Refinement Inference loop: {r:int|0 ≼ r ≺ a.len}->{i:int|0 ≼ i}->{v:int|0 ≼ v ≺ a.len} Liquid Type of loop

86 Recap Program Templates Constraints AI, MC, PA … {i:int| X i } -> {v:int| X o } ⋀ X i ⋀ P ⇒ X

87 Part I Part II Part III Liquid Types Closures, Collections, Generics Induction for Data Structures

88 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

89 Closures / Higher-Order Functions let rec ffor l u f = if l < u then f l; ffor (l+1) u f

90 let rec ffor l u f = if l < u then ( f l; ffor (l+1) u f ) Type of f int ! unit

91 let rec ffor l u f = if l < u then ( f l; ffor (l+1) u f ) Template of f {v:int| X 1 } ! unit

92 let rec ffor l u f = if l < u then ( f l; ffor (l+1) u f ) Template of f {v:int| X 1 } ! unit Check: input l as required by f

93 let rec ffor l u f = if l < u then ( f l; ffor (l+1) u f ) Template of f {v:int| X 1 } ! unit l ≺ u ⊢ {v:int | v=l} <: {v:int |X 1 } l ≺ u Æ v=l ) X 1 Solution X 1 = l ≼ v Æ v ≺ u Reduces to

94 let rec ffor l u f = if l < u then ( f l; ffor (l+1) u f ) Template of f {v:int| X 1 } ! unit Solution X 1 = l ≼ v Æ v ≺ u Liquid Type of f {v:int|l ≼ v Æ v ≺ u} ! unit

95 Closures / Higher-Order Functions let rec ffor l u f = if l < u then f l; ffor (l+1) u f Liquid Type of ffor l:int ! u:int ! ( {v:int | l ≼ v ≺ u} ! unit ) ! unit Liquid Type of f {v:int|l ≼ v Æ v ≺ u} ! unit

96 let rec ffor l u f = if l < u then f l; ffor (l+1) u f let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r := i ); !r Min-Index Revisited

97 Liquid Type of ffor l:int ! u:int ! ( {v:int | l ≼ v ≺ u} ! unit ) ! unit let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r

98 Liquid Type of ffor 0 u:int ! ( {v:int | 0 ≼ v ≺ u} ! unit ) ! unit let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r

99 Liquid Type of ffor 0 a.len ( {v:int | 0 ≼ v ≺ a.len} ! unit ) ! unit let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r

100 Liquid Type of ffor 0 a.len ( {v:int | 0 ≼ v ≺ a.len} ! unit ) ! unit Template of (fun i ->...) {v:int| X i } ! unit let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r

101 Liquid Type of ffor 0 a.len ( {v:int | 0 ≼ v ≺ a.len} ! unit ) ! unit Template of (fun i ->...) {v:int| X i } ! unit let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r Check: input ( fun i... ) as required by ffor

102 Liquid Type of ffor 0 a.len ( {v:int | 0 ≼ v ≺ a.len} ! unit ) ! unit Template of (fun i ->...) {v:int| X i } ! unit { X i } ! unit <:{0 ≼ v ≺ a.len} ! unit Check: input ( fun i... ) as required by ffor

103 {0 ≼ v ≺ a.len} unit {Xi}{Xi} { X i } ! unit <:{0 ≼ v ≺ a.len} ! unit {0 ≼ v ≺ a.len} <: { X i } unit <: unit Trivial Function Subtyping Splits Into

104 { X i } ! unit <:{0 ≼ v ≺ a.len} ! unit 0 ≼ v ≺ a.len ) X i

105 Solution X i = 0 ≼ v ≺ a.len

106 Template of (fun i ->...) {v:int| X i } ! unit

107 Solution X i = 0 ≼ v ≺ a.len Liquid Type of (fun i ->...) {v:int | 0 ≼ v ≺ a.len} ! unit

108 let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r Liquid Type of r {v:int | 0 ≼ v ≺ a.len} ref Liquid Type of (fun i ->...) {v:int | 0 ≼ v ≺ a.len} ! unit

109 let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r Liquid Type of r {v:int | 0 ≼ v ≺ a.len} ref Access Safe

110 let min_index a = let r = ref 0 ffor 0 a.len (fun i -> if a.(i) < a.(!r) then r:= i) !r Liquid Type of r {v:int | 0 ≼ v ≺ a.len} ref Liquid Type of min_index a:int array ! {v:int | 0 ≼ v ≺ a.len}

111 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

112 let rec range l u = if l < u then l :: (range (l+1) u) else [] Collections (e.g. Lists) Type of range l:int ! u:int ! int list

113 let rec range l u = if l < u then l :: (range (l+1) u) else [] Collections (e.g. Lists) Template of range l:int ! u:int ! {v:int| X out } list

114 let rec range l u = if l < u then l :: (range (l+1) u) else [] Template of range l:int ! u:int ! {v:int| X out } list Template of “ then ”: {v:int| X out } list

115 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required Template of “ then ”: {v:int| X out } list

116 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required l ≺ u ⊢ “head” <: {v:int |X out } Template of “ then ”: {v:int| X out } list

117 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required l ≺ u ⊢ “head” <: {v:int |X out } l ≺ u ⊢ “tail” <: {v:int |X out } list Template of “ then ”: {v:int| X out } list

118 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required l ≺ u ⊢ “head” <: {v:int |X out }

119 let rec range l u = if l < u then l :: (range (l+1) u) else [] l ≺ u Æ v=l ) X out Reduces To (1) Check: “head” and “tail” as required l ≺ u ⊢ {v:int | v=l} <: {v:int |X out }

120 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required l ≺ u ⊢ “tail” <: {v:int |X out } list

121 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” and “tail” as required l ≺ u ⊢ { X out [l+1/l]} list <: { X out } list By List-Subtyping, Reduces To l ≺ u ⊢ { X out [l+1/l]} <: { X out }

122 Check: “head” and “tail” as required l ≺ u ⊢ { X out [l+1/l]} list <: { X out } list Reduces To (2) l ≺ u Æ X out [l+1/l] ) X out

123 (2) (1) Solution X out = l ≼ v ≺ u l ≺ u Æ v=l ) X out l ≺ u Æ X out [l+1/l] ) X out

124 let rec range l u = if l < u then l :: (range (l+1) u) else [] Collections (e.g. Lists) Template of range l:int ! u:int ! {v:int| X out } list Solution X out = l ≼ v ≺ u

125 let rec range l u = if l < u then l :: (range (l+1) u) else [] Collections (e.g. Lists) Liquid Type of range l:int ! u:int ! {v:int|l ≼ v ≺ u} list Solution X out = l ≼ v ≺ u

126 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

127 let rec range l u = if l < u then l :: (range (l+1) u) else [] Generics/Polymorphism

128 let rec range l u = if l < u then l :: (range (l+1) u) else [] let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r) 0 indices Generics/Polymorphism

129 Instance Type a = int b = int Generic Type of fold_left (a ! b ! a) ! a ! b list ! a let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices

130 Generic Type of fold_left (a ! b ! a) ! a ! b list ! a Instance Template a = {v:int| X a } b = {v:int| X b } let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices

131 Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Instance Template a = {v:int| X a } b = {v:int| X b } let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices

132 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Template of r {v:int | X a }

133 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Template of i {v:int | X b }

134 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Template of min_index a:int array ! {v:int | X a }

135 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Check: args as required

136 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Check: args as required 1

137 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Check: args as required 1 2

138 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Instance Template of fold_left ( { X a } ! { X b } ! { X a } ) ! { X a } ! { X b }list ! { X a } Check: args as required 1 2 3

139 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Constraints 1 2 3 r:int ! i:int ! {v=i ∨ v=r} <: { X a } ! { X b } ! { X a } {v:int | v=0} <: {v:int | X a } {v:int | 0 ≼ v ≺ a.len} list <: {v:int | X b } list 1 2 3

140 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Subtyping Reduces To Implications 1 2 3 r:int ! i:int ! {v=i ∨ v=r} <: { X a } ! { X b } ! { X a } {v:int | v=0} <: {v:int | X a } {v:int | 0 ≼ v ≺ a.len} list <: {v:int | X b } list X a [r/v] Æ X b [i/v] Æ ( v=i ∨ v=r ) ) X a v=0 ) X a 0 ≼ v ≺ a.len ) X b 1 2 3

141 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len

142 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len Templates r : {v:int| X a } i : {v:int| X b }

143 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len Liquid Types r : {v:int| 0 ≼ v ≺ a.len} i : {v:int| 0 ≼ v ≺ a.len}

144 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len Liquid Types r : {v:int| 0 ≼ v ≺ a.len} i : {v:int| 0 ≼ v ≺ a.len} Safe

145 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len Template of min_index a:int array ! {v:int | X a }

146 let min_index a = let indices = range 0 a.len fold_left (fun r i -> if a.(i) < a.(r) then i else r ) 0 indices Solution X a, X b = 0 ≼ v ≺ a.len Liquid Type of min_index a:int array ! {v:int | 0 ≼ v ≺ a.len}

147 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

148 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

149 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

150 Data (Structure) Properties Piggyback Predicates On Types

151 [] :: {x:int|0<x} listint list 0<x Describes all elements x : int Representation

152 [] :: 0<x x : int Type Unfolding [] :: 0<h h : int [] :: 0<x x : int HeadTailEmpty PositiveProperty holds recursively List of positive integers

153 [] :: 0<x Describes all elements x : int x<v v Describes tail elements Representation

154 [] :: x<v x : int Type Unfolding [] :: h : int [] :: x<v x : int HeadTailEmpty Elements larger than head Property holds recursively List of sorted integers h<v Push Edge Predicate Into NodeRename Variable h<x

155 Piggyback Predicates On Types Data (Structure) Properties

156 [] :: x : int Unfold :: h : int [] :: x : int l:sorted listh:intt:sorted list & {h<x} list Instantiate tl match l with h :: t x<V h<x Quantifier Instantiation

157 Piggyback Predicates On Types Data (Structure) Properties

158 [] :: x : int Fold h : int [] :: x : int :: l:sorted listh:intt:sorted list & {h<x} list Generalize tl let l = h :: t in x<V h<x Quantifier Generalization

159 Another Example: Trees Leaf Node x : int x<V V<x

160 Node Leaf Node x : int Leaf Node x : int Node Leaf x<V V<x x<V V<x r<V V<r Another Example: Trees r : int Unfold

161 < RHS nodesLHS nodes < root Node Leaf Node x : int Leaf Node x : int Node Leaf x<V V<x x<V V<x r<x x<r Another Example: Trees r : int Push Edge Predicates Invariant: Binary Search Trees

162 Demo isort,bst

163 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

164 Piggyback Predicates On Types (Data) Structure Properties

165 measure len = | [] -> 0 | x::xs -> 1 + len xs Representation: List Length

166 8 l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs)

167 Piggyback Predicates On Types (Data) Structure Properties

168 l:’a list h:’a t:’a list len(l)=1+len(t) Instantiate match l with h :: t Quantifier Instantiation 8 l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs)

169 Piggyback Predicates On Types (Data) Structure Properties

170 h:’a t:’a list Quantifier Generalization 8 l,x,xs. len([]) = 0 len(x::xs) = 1+len(xs) Generalize let l = h :: t in h:’a t:’a list l:’a list len(l)=1+len(t)

171 Demo listlen, msortb

172 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

173 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

174 Leaf l r l = Left subtree r = Right subtree treeHeight H l = Left subtree’s height H r = Right subtree’s height measure H = | Leaf = 0 | Node(x,l,r) = 1 + max (H l) (H r) Height Balanced Tree | Hl–Hr |< 2 Node Height difference bounded at each node

175 Demo eval

176 Refinement Type Inference By Predicate Abstraction

177 0<x [] :: x : int x<v Automatic Inference Predicates Determine Invariant Let X 1, X 2,... = Unknown Predicates Complex Subtyping Between data types X1X1 X2X2 Reduces To Simple Implications Between X 1, X 2,... Solved by Predicate Abstraction Over atoms 0< ⋆, ⋆ <v,...

178 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

179 Program (ML)Verified Safety Properties List-based SortingSorted, Outputs Permutation of Input Finite MapBalance, BST, Implements a Set Red-Black TreesBalance, BST, Color StablesortSorted Extensible VectorsBalance, Bounds Checking, … Binary HeapsHeap, Returns Min, Implements Set Splay HeapsBST, Returns Min, Implements Set MallocUsed and Free Lists Are Accurate BDDsVariable Order Union FindAcyclicity Bitvector UnificationAcyclicity

180 Finite Maps (ML) 5: ‘cat’ 3: ‘cow’ 8: ‘tic’ 1: ‘doc’ 4: ‘hog’ 7: ‘ant’ 9: ‘emu’ From Ocaml Standard Library Implemented as AVL Trees Rotate/Rebalance on Insert/Delete Verified Invariants Binary Search Ordered Height Balanced Keys Implement Set

181 Binary Decision Diagrams (ML) X1X1 X2X2 X2X2 X3X3 X4X4 X4X4 1 Graph-Based Boolean Formulas [Bryant 86] X 1  X 2  X 3  X 4 Efficient Formula Manipulation Memoizing Results on Subformulas Verified Invariant Variables Ordered Along Each Path

182 Vec: Extensible Arrays (317 LOC) “Python-style” extensible arrays for Ocaml find, insert, delete, join etc. Efficiency via balanced trees Balanced Height difference between siblings ≤ 2 Dsolve found balance violation

183 Debugging via Inference Using Dsolve we found Where imbalance occurred (specific path conditions) How imbalance occurred (left tree off by up to 4) Leading to test and fix

184 Part I Part II Part III Refinement Types Closures, Collections, Generics Induction for Data Structures

185 Take Home Lessons Why is Verification difficult? Complex “Invariants” How to represent invariants? Factor into liquid type How to infer liquid type? Subtyping + Predicate Abstraction

186 “Back-End” Logic Constraint Solving Rich Decidable Logics Predicate Discovery… Much Work Remains…

187 “Front-End” Types Destructive Update Concurrency Objects & Classes Dynamic Languages… Much Work Remains…

188 User Interface The smarter your analysis, the harder to tell why it fails! Much Work Remains…

189 Details Ocaml (Pure functional) [PLDI 08] “Liquid Types” [PLDI 09] “Type-based Data-Structure Verification” Constraint Solving [CAV 11] “Hindley-Milner-Cousots” C (Pointers/Arithmetic, Aliasing, Mutation) [POPL 10] “Low-level Liquid Types”

190 POPL Lightning Talk/Demo Ocaml (Pure functional) [PLDI 08] “Liquid Types” [PLDI 09] “Type-based Data-Structure Verification” Constraint Solving [CAV 11] “Hindley-Milner-Cousots” C (Pointers/Arithmetic, Aliasing, Mutation) [POPL 10] “Low-level Liquid Types” Patrick Rondon (PhD ’12) Demo + Lightning Talk

191 http://goto.ucsd.edu/liquid source, papers, demo, etc.

192 ProgramLines DML Annot. Liquid Annot. Liquid Time(s) dotprod 730 0.3 bsearch 2430 0.5 queens 3070 0.7 insersort 33120 0.9 tower 3681 3.3 matmult 43100 1.8 heapsort 84110 0.5 fft 107131 9.1 simplex 118330 7.7 gauss 142221 3.1 Total 6321253 27.9 Evaluation: Array Bounds Checking

193 DML @ 20% LOC vs. Liquid @ 0.5% LOC

194 The end

195 let rec range l u = if l < u then l :: (range (l+1) u) else [] Template of “ then ”-expression {v:int| X out } list Check: “head” and “tail” as required l ≺ u ⊢ “head” <: {v:int |X out } l ≺ u ⊢ “tail” <: {v:int |X out } list

196 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “head” as required l ≺ u ⊢ {v:int | v=l} <: {v:int |X out } l ≺ u Æ v=l ) X out Reduces To 1

197 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required Template of range l:int ! u:int ! {v:int| X out } list

198 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required Template of range (l+1) u:int ! {v:int| X out [l+1/l]} list

199 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required Template of range (l+1) u {v:int| X out [l+1/l][u/u]} list

200 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required Template of range (l+1) u {v:int| X out [l+1/l]} list { X out [l+1/l]} list <: then-“tail”

201 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: then-“tail” Template of “ then ”-expression {v:int| X out } list

202 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: { X out } list Template of “ then ”-expression {v:int| X out } list

203 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: { X out } list Template of range l:int ! u:int ! {v:int| X out } list

204 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: { X out } list Template of “ then ”-expression {v:int| X out } list

205 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: { X out } list Template of “ then ”-expression {v:int| X out } list

206 let rec range l u = if l < u then l :: (range (l+1) u) else [] Check: “tail” as required { X out [l+1/l]} list <: { X out } list Template of “ then ”-expression {v:int| X out } list


Download ppt "Software Verification With Liquid Types Ranjit Jhala, UC San Diego (with Pat Rondon, Ming Kawaguchi)"

Similar presentations


Ads by Google