Tachio Terauchi Nagoya University

1 / 22

# Tachio Terauchi Nagoya University - PowerPoint PPT Presentation

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.

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'Tachio Terauchi Nagoya University' - abra

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### 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

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 -> *
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

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
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
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 -> *)?
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
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
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)

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
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)
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), …
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
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
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)
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]
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
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
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)

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)
Preliminary Experimental Results
• Depcegar [Terauchi POPL’10]
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