Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup...

36
Introduction Generics Delegate clients Capturing delegates Verifying Generics and Delegates Kasper Svendsen Lars Birkedal Matthew Parkinson ECOOP 2010 June 23, 2010

Transcript of Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup...

Page 1: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Verifying Generics and Delegates

Kasper SvendsenLars Birkedal

Matthew Parkinson

ECOOP 2010

June 23, 2010

Page 2: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Introduction

HO separation logic for C# subset with generics and delegates

• Hoare-style program logic for proving functional correctness

• Separation logic for modular reasoning about state

In HOSL & Hoare Type Theory one can reason about

• polymorphism using universal quantification over predicates

• first-class functions using nested Hoare triples

We extend these techniques to reason about C#

• Main challenge: C# variable capture

Page 3: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

C# variable capture

Example

public delegate Y Func〈Y〉 ();

Func〈int〉 counter() {int x = 0;return delegate () { return ++x; };}

C# semantics

• Inline delegate captures the location of x

• Lifetime of captured x extended to lifetime of delegate

Page 4: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Outline

Introduction

Generics

Delegate clients

Capturing delegates

Page 5: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Setup

C# subset

• Basic imperative features + generics + delegates

Assertion logic

• Logic for reasoning about computational states

• Higher-order separation logic

• Spacial connectives, emp, ∗,−∗, for controlling aliasing

• State assertions, M.f 7→ N, ..., for describing state

Specification logic

• Logic for relating initial and terminal state

Page 6: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Integer list

class Node {Node next;Integer val;}

• Representation predicate

list(x , ε)def= x = null

list(x , a · α)def= ∃n,∃v . x .next 7→ n ∗ x .val 7→ v ∗

Int(v , a) ∗ list(n, α)

• Int(v , a): v is a representation of the integer a

Page 7: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Integer list

class Node {Node next;Integer val;}

• Representation predicate

list(x , ε)def= x = null

list(x , a · α)def= ∃n,∃v . x .next 7→ n ∗ x .val 7→ v ∗

Int(v , a) ∗ list(n, α)

• Int(v , a): v is a representation of the integer a

Page 8: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Generic list

class Node〈X〉 {Node〈X〉 next;X val;}

• Representation predicate

list(x , ε,P)def= x = null

list(x , a · α,P)def= ∃n,∃v . x .next 7→ n ∗ x .val 7→ v ∗

P(v , a) ∗ list(n, α,P)

• P(v , a): v is a representation of a

Page 9: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

void fold〈X〉(Node〈X〉 lst, Action〈Node〈X〉〉 f) {if(lst != null) {

Node〈X〉 next = lst.next;f(lst);fold(next, f);}}

• foreach

• Stateful fold-right – accumulator maintained by delegate

Page 10: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

void fold〈X〉(Node〈X〉 lst, Action〈Node〈X〉〉 f) {if(lst != null) {

Node〈X〉 next = lst.next;f(lst);fold(next, f);}}

• foreach

• Stateful fold-right – accumulator maintained by delegate

Page 11: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

· · ·

Q(ε) ∗ list(lst, a1 · a2 · a3 · α, P )

lst

• Q(α): accumulator predicate; state after having folded over α

Page 12: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

· · ·

Q(a1 · ε) ∗ list(lst, a2 · a3 · α, P )

lst

• Q(α): accumulator predicate; state after having folded over α

Page 13: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

· · ·

list(lst, a3 · α, P )Q(a2 · a1 · ε) ∗

lst

• Q(α): accumulator predicate; state after having folded over α

Page 14: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

Specification

void fold〈X〉(Node〈X〉 lst, Action〈Node〈X〉〉 f) { ... }∀α : Val. ∀P : Val× Val→ Prop. ∀Q : Val→ Prop.

{list(lst, α,P) ∗Q(ε) ∗ ∀a, β, y : Val.

f 7→ 〈(x). {x .next 7→ ∗ x .val 7→ y ∗ P(y , a) ∗Q(β)}{Q(a · β)}〉}

{Q(rev(α))}

• Q(α): accumulator predicate; state after having folded over α

• rev(α): mathematical reverse function

• M 7→ 〈(φ).{P} {Q}〉: M denotes delegate satisfying spec

Page 15: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – Fold

Specification

void fold〈X〉(Node〈X〉 lst, Action〈Node〈X〉〉 f) { ... }∀α : Val. ∀P : Val× Val→ Prop. ∀Q : Val→ Prop.

{list(lst, α,P) ∗Q(ε) ∗ ∀a, β, y : Val.

f 7→ 〈(x). {x .next 7→ ∗ x .val 7→ y ∗ P(y , a) ∗Q(β)}{Q(a · β)}〉}

{Q(rev(α))}

• Q(α): accumulator predicate; state after having folded over α

• rev(α): mathematical reverse function

• M 7→ 〈(φ).{P} {Q}〉: M denotes delegate satisfying spec

Page 16: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Increment example

int x = 0;Action f = delegate () {

x++;

};

f();

Page 17: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Increment example

int x = 0;Action f = delegate () {

{ x = n }x++;{ x = n + 1 }

};{ x = 0 ∗ ∀n. f 7→ 〈{ x = n } { x = n + 1 }〉 }

f();

Page 18: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Increment example

int x = 0;Action f = delegate () {

{ x = n }x++;{ x = n + 1 }

};{ x = 0 ∗ ∀n. f 7→ 〈{ x = n } { x = n + 1 }〉 }

f(); ⇒ f 7→〈{ 0 = 0 } { 0 = 1 }〉

Page 19: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Increment example

int x = 0;Action f = delegate () {

{ emp }x++;{ emp }

};{ x = 0 ∗ f 7→ 〈{ emp } { emp }〉 }

f();

Page 20: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Increment example

int x = 0;Action f = delegate () {

{ emp }x++;{ emp }

};{ x = 0 ∗ f 7→ 〈{ emp } { emp }〉 }

f();

Issues

• How to refer to captured variables in nested specs

• How to keep track of potentially modified variables

Page 21: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Variable assertions

• Extend assertion logic with variable assertions Ms7→ N,&x

• Ms7→ N: location M is allocated on the stack and contains N

• &x : denotes location of program variable x

Inline delegate

int x = 0;Action f = delegate () {{ P }

B{ Q }

};{ x = 0 ∗ f 7→ 〈{ ∃y. &x

s7→ y ∗ [y/x]P } { ∃y. &xs7→ y ∗ [y/x]Q }〉 }

Page 22: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Variable assertions

• Extend assertion logic with variable assertions Ms7→ N,&x

• Ms7→ N: location M is allocated on the stack and contains N

• &x : denotes location of program variable x

Inline delegate

int x = 0;Action f = delegate () {{ P }

B{ Q }

};{ x = 0 ∗ f 7→ 〈{ ∃y. &x

s7→ y ∗ [y/x]P } { ∃y. &xs7→ y ∗ [y/x]Q }〉 }

Page 23: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Variable assertions

• Extend assertion logic with variable assertions Ms7→ N,&x

• Ms7→ N: location M is allocated on the stack and contains N

• &x : denotes location of program variable x

Inline delegate

int x = 0;Action f = delegate () {{ x = n }

x++;{ x = n + 1 }

};{ x = 0 ∗ ∀n. f 7→ 〈{ &x

s7→ n } { &xs7→ n + 1 }〉 }

Page 24: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Variable assertions

• Extend assertion logic with variable assertions Ms7→ N,&x

• Ms7→ N: location M is allocated on the stack and contains N

• &x : denotes location of program variable x

Inline delegate

int x = 0;Action f = delegate () {{ emp }

x++;{ emp }

};{ x = 0 ∗ f 7→ 〈{ ∃y. &x

s7→ y } { ∃y. &xs7→ y }〉 }

Page 25: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Aliasing

• Var. assertions introduce aliasing in reasoning about variables:

• Build separation into specification logic:• Can either reason directly or indirectly, but not both• Reason directly about variables in the program var. ctx. φ

• Hoare’s assignment rule thus stil sound

φ;ψ ` P : Prop x , y ∈ φφ;ψ ` {P[y/x ]}x := y{P}

Page 26: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Aliasing

• Var. assertions introduce aliasing in reasoning about variables:

• Build separation into specification logic:• Can either reason directly or indirectly, but not both• Reason directly about variables in the program var. ctx. φ• Hoare’s assignment rule thus stil sound

φ;ψ ` P : Prop x , y ∈ φφ;ψ ` {P[y/x ]}x := y{P}

Page 27: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Capturing delegates

• Verify body using Hoare treatment of variables

• Switch to SL treatment of captured variables in nested spec

• Switch back to Hoare treatment of variables to verify calls

x 6∈ FV (s)

φ;ψ ` {∃x : Val. ls7→ x ∗ P}s{∃x : Val. l

s7→ x ∗Q}φ, x ;ψ ` {&x = l ∧ P}s{Q}

Page 28: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Variable capture

Capturing delegates

• Verify body using Hoare treatment of variables

• Switch to SL treatment of captured variables in nested spec

• Switch back to Hoare treatment of variables to verify calls

x 6∈ FV (s)

φ;ψ ` {∃x : Val. ls7→ x ∗ P}s{∃x : Val. l

s7→ x ∗Q}φ, x ;ψ ` {&x = l ∧ P}s{Q}

Page 29: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

Page 30: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

· · ·

head lst

Page 31: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

null · · ·

head lst

Page 32: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

null · · ·

head lst

Page 33: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

∀α : Val. ∀P : Val× Val→ Prop.

{list(lst, α,P)}{r .list(r , rev(α),P)}

Page 34: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

· · ·· · ·

Q(β) ∗ list(lst, a · α, P )

head

where Q(α) = ∃n : Val. &heads7→ n ∗ list(n, α,P)

Page 35: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Example – In-place reverse

Node〈X〉 reverse〈X〉(Node〈X〉 lst) {Node〈X〉 head = null;fold〈X〉(lst, delegate (Node〈X〉 x) { x.next = head; head = x; });return head;}

· · ·· · ·

Q(a · β) list(lst, α, P )∗

head

where Q(α) = ∃n : Val. &heads7→ n ∗ list(n, α,P)

Page 36: Verifying Generics and Delegates · IntroductionGenericsDelegate clientsCapturing delegates Setup C# subset Basic imperative features + generics + delegates Assertion logic Logic

Introduction Generics Delegate clients Capturing delegates

Conclusion

Generics and non-capturing delegates

• HOL & nested Hoare triples (standard)

Capturing delegates

• Separation logic treatment of variables

• Variable separation build into specification logic

• Unified treatment of local state on the heap and/or stack

• Reasoning standard when there is no capturing