1 / 22

Tachio Terauchi Nagoya University

Relatively Complete Verification of Higher-Order Programs (via Automated Refinement Type Inference). Tachio Terauchi Nagoya University. TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: A A A A A A A A A. Verifying higher-order functional programs.

abra
Download Presentation

Tachio Terauchi Nagoya University

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Relatively Complete Verification of Higher-Order Programs (via Automated Refinement Type Inference) Tachio Terauchi Nagoya University TexPoint fonts used in EMF. Read the TexPoint manual before you delete this box.: AAAAAAAAA

  2. Verifying higher-order functional programs let rec F x c = c x in and G x y = assert x+1 ¸ y; F (y+1) (G y) in and Main w = F (w+1) (G w) Show : 8w:int. Main w is assertion safe • Refinement types approach: • F : x:int -> c:({u|u¸ x} -> *) -> * • G : x:int -> y:{u|x+1 ¸ y} -> * • Main: w:int -> *

  3. Much recent work on automated inference • Liquid types [Rondon, Kawaguchi, Jhala PLDI’08] • Dependent type inference with interpolants [Unno, Kobayashi PPDP’09] • Dependent types from counterexamples [Terauchi POPL’10] • Predicate abstraction and CEGAR for higher-order model checking [Kobayashi, Sato, Unno PLDI’11] • HMC: Verifying functional programs using abstract interpreters [Jhala, Majumdar, Rybalchenko CAV’11] • “?” [Jagannathan 2011] • Leverages advances in first-order program verification: • predicate abstraction, interpolation, CEGAR, SMT solvers, Test generation, etc. • “Model Checkers” for higher-order programs Incomplete

  4. Completeness and Incompleteness • Def: Refinement type system is soundiff • If a program is typable then it is safe. • Def: Refinement type system is completeiff • A program is typableiff it is safe. • Existing refinement type systems are sound, but incomplete • Different from incompleteness of inference algorithms

  5. Relative Completeness • Higher-order program verification is undecidable • Because it contains 1st-order program verification • Complete verification for 1st-ord programs • E.g., Hoare logic • Relative to expressive 1st-ord theory like PA • Allow arbitrary PA formulas as refinement predicates? i.e., { u | µ } µ2 PA • Sufficient for ord-1 programs • Not for general higher-order programs

  6. Refinement types incompleteness in detail • Problem:Higher-order functions • A typical relative completeness proof of Hoare logic • wpre(x = e, µ) = µ[x/e] • wpre(s1;s2, µ) = wpre(s1,wpre(s2, µ)) , … • Show the logic (PA) can express wpre(…) • Then, s is safe iffwpre(s,true) = true. • What’s wpre(f x, µ) where f : int -> * and x : int? • Or wpre(g f, µ) with g : (int -> *) -> * and f : (int -> *)?

  7. Weakest pre.of higher-order terms • Ideally: • wpre(f x, true) = “f x runs safe” • Ex. F f x = f x • F : f:(int->*)->x:{ u : int | “f u runs safe” }->* • But, ref. pred. inference becomes higher-order program verification! • To prevent circularity, we only allow 1st-ord formulas • I don’t have relative completeness for all higer-order programs yet  • I will show: How to get relative completeness for a class that haven’t been covered previously

  8. Closure Boudedness • Def: Size of a closure is the number of base-type values captured in the closure • Def: A program is closure-boundedif its evaluation only generates closures of bounded size • Def: Closure pattern is a closure with base-type values abstracted • E.g., F (G ®) ® represent infinite number of closures F (G 0) 0, F (G 0) 1, F (G 1) -1, … • In lambda, ¸x.(y (¸z.z®) ®), etc. • Lemma: Closure-bounded iff finite # of patterns

  9. Contribution • Relative completeness for closure-bounded programs • High-level Idea : Environment Passing Parametrize type of F with G ®, H ® • F c f = c f • G x k = k x • H x y = assert x · y; F (G y+1) (H y) • Main w = F (G w+1) (H w) Show: 8w:int. Main w as safe F : 8a1.8a2.c:(({u|µ1}->*)->*)->f:({u|µ2} ->*) ->* Intersection types to handle different contexts (this example needs none)

  10. Details • Naïve Approach : • Symbolically evaluate the program for n steps and recordclosure patterns seen • Build type shapes from the patterns • Check if typable restricted to the type shapes • If not typable, increase n and repeat • (In parallel) check for unsafety

  11. Symbolic Eval => Closure Patterns • Patterns A := F | ® | F A • Ex. • Evaluate from M with w : int • Patterns: F (G ®) ®, … • F c x = c x • G x y = assert x+1 · y ; F (G y) (y+1) • M w = F (G w) (w+1)

  12. Patterns => Type shapes • Types t := * | x:t -> t | {u|µ} | 8x.t | [A].t Æ [A].t • Type shapes = N £ types with µ erased • E.g., (3, f:{u|_}->*) • ord(A) = order of simple type of A • A => (v,t’) inductively on the order of A • Ex. A = F : • Seen patterns: F (G ®) ®, F (H ®®) ®, … • ty(F) = (0, [(G ®), ®].8a1.t1->®.s->* Æ[(H ®®), ®].8a18a2.t2->®.s->*) • ty(®) = (0,s), ty(G ®) = (1,t1), ty(H ®®) = (2, t2), …

  13. Checking typability • Shapes & patterns => derivation structure • For each F, have patterns A1, …, An for its args • Make type derivation per F, Ai • Ex. Patterns : F (G ®) (K ®) ® for F c f x = c f x • Track concrete patterns: c: G a1, f: K a2, x: x, …, up to base-type parameter variables • At function applications • Look up ty(...) for matching abstract patterns • Instantiate with captured base-type variables • Use “top” type to handle unmatched shapes • Infer satisfying assignment for µ’s • If none found, fail

  14. Summary of naïve approach • Symbolically evaluate the program for n steps and recordclosure patterns seen • Build type shapes from the patterns • Check if typable restricted to the type shapes • If not typable, increase n and repeat • (In parallel) check for unsafety • Thm: This is rel. comp. for closure-bounded programs • Pf. Like that of Hoare logic. “Thread” weakest precondition through the type derivation. • Cor: 1st-order program verification can be “lifted” to closure-bounded higher-order program verification

  15. Naïve approach • Relatively complete but not very clever • Patterns sufficient but not always necessary • Fails for non-closure-bounded programs • Better approach: • Try type inference w/o patterns • If type inference fails, then infer patterns • Repeat with the added patterns • Also, just add candidate 8x.t, e[e’] and have type inf. alg. figure out the rest (i.e., rid patterns from type inference)

  16. Check typability w/o patterns • Leverage existing algorithms • Liquid types [Rondon, Kawaguchi, Jhala PLDI’08] • Dependent type inference with interpolants [Unno, Kobayashi PPDP’09] • Dependent types from counterexamples [Terauchi POPL’10] • Predicate abstraction and CEGAR for higher-order model checking [Kobayashi, Sato, Unno PLDI’11] • HMC: Verifying functional programs using abstract interpreters [Jhala, Majumdar, Rybalchenko CAV’11]

  17. If inference fails, infer patterns • Use the symbolic evaluation as in naïve • Or use counterexample from type inference [Terauchi POPL’10][Kobayashi, Sato, Unno PLDI’11] • Unwound program slice without recursion • Infer patterns that occur in slice via flow analysis

  18. Check typability with the added patterns • Like the naïve approach, but • Instead of using the patterns • i.e., c : G w, …, and [(G ®), ®].8x.t1->®.s->*, …, etc. • Use the built type shapes minus the patterns • c : 8x.{u | _} -> *, … • And how to instantiate them • Let backend type inference alg. resolve type matching (as well as µ inference) • Implement as program translation

  19. Program Translation • Universal types 8x.t modeled by x:int -> t • Instantiationse[e’]modeled by e e’ • F c f = c f • G x k = k x • H x y = assert x · y • main w = F (G w) (H w) • F a1a2c f = c f • G x k = k x • H x y = assert x · y • main w = F w (G w) w (H w) ty(F) = (nil,8a1.8a2.c:(({u|_}->*)->*)->f:({u|_} ->*) ->*) ty(G ®) = ([w],…) ty(H ®) = ([w],…) Multiple trans. when ty(…) has intersection types (none needed for this example)

  20. Summary of translation approach • Try type inference w/o patterns • If type inference fails, then infer patterns • Repeat with the added patterns • Uses off-the-shelf refinement type inference algorithms • Complete relative to • Underlying refinement type inference • And patterngeneration • Incomplete in practice (obviously)

  21. Preliminary Experimental Results • Depcegar [Terauchi POPL’10]

  22. Conclusions • Relatively complete verification framework for higher-order programs • Based on refinement types • Good for “model checking” like automation • Frees the backend theorem prover/decision prover from directly reasoning about higher-order functions • High-level : Environment passing • Theory : Rel. comp. for closure-bounded programs • Practice: Iterative translation

More Related