Skip to content

Latest commit

 

History

History
363 lines (204 loc) · 6.51 KB

README.md

File metadata and controls

363 lines (204 loc) · 6.51 KB
marp theme style
true
default
img[alt~="center"] { display: block; margin: 0 auto; }

Flux: Liquid types for Rust

Nico Lehmann, Adam Geller, Gilles Barthe, Niki Vazou, Ranjit Jhala


Motivation

Types vs. Floyd-Hoare logic

Demonstration

Flux - Liquid Types for Rust

Evaluation

Flux v. Prusti for Memory safety


Types vs. Floyd-Hoare logic


Liquid/Refinements 101

type Nat = {v: Int | 0 <= v}
  • Int is the base type of the value
  • v names the value being described
  • 0 <=v is a predicate constraint

Liquid/Refinements 101

Generate the sequence of values between lo and hi

range :: lo:Int -> {hi:Int | lo <= hi} -> List {v:Int|lo <= v && v < hi}

Liquid/Refinements 101

Generate the sequence of values between lo and hi

range :: lo:Int -> {hi:Int | lo <= hi} -> List {v:Int|lo <= v && v < hi}

Input Type is a Precondition

lo <= hi


Liquid/Refinements 101

Generate the sequence of values between lo and hi

range :: lo:Int -> {hi:Int | lo <= hi} -> List {v:Int|lo <= v && v < hi}

Output Type is a Postcondition

Every element in sequence is between lo and hi


Types vs. Floyd-Hoare logic

Types decompose (quantified) assertions to quantifier-free refinements


Lists in Dafny vs LiquidHaskell


width:1100px


Accessing the i-th List Element

width:1100px

Floyd-Hoare requires elements and quantified axioms

Liquid Parametric polymorphism yields spec for free


Building and Using Lists

width:1100px

Floyd-Hoare Quantified postcondition (hard to infer)


Building and Using Lists

width:1100px

Liquid Quantifier-free type (easy to infer)

Int -> k:Int -> List {v:Int| k <= v}

Types vs. Floyd-Hoare logic

Types decompose assertions to quantif-free refinements ...

... but what about imperative programs


Motivation

Types vs. Floyd-Hoare logic

Demonstration

Flux Liquid Types for Rust

Evaluation

Flux v. Prusti for Memory Safety


Flux Liquid Types for Rust

flux (/flʌks/)

n. 1 a flowing or flow. 2 a substance used to refine metals. v. 3 to melt; make fluid.


Flux Liquid Types for Rust

  1. basics

  2. borrows

  3. rvec-api

  4. vectors


Motivation

Types vs. Floyd-Hoare logic

Demonstration

Flux Liquid Types for Rust

Evaluation

Flux v. Prusti for Memory Safety


Evaluation

Flux v. Prusti for Memory Safety


Flux v. Prusti by the numbers

width:800px center


Flux v. Prusti : Types Simplify Specifications

// Rust
fn store(&mut self, idx: usize, value: T)

// Flux
fn store(self: &mut RVec<T>[@n], idx: usize{idx < n}, value: T)

// Prusti
requires(index < self.len())
ensures(self.len() == old(self.len()))
ensures(forall(|i:usize| (i < self.len() && i != index) ==>
                    self.lookup(i) == old(self.lookup(i))))
ensures(self.lookup(index) == value)

Quantifiers make SMT slow!


Flux v. Prusti : Types Enable Code Reuse


Example: kmeans.rs in flux


fn kmeans(n:usize, cs: k@RVec<RVec<f32>[n]>, ps: &RVec<RVec<f32>[n]>, iters: i32) -> RVec<RVec<f32>[n]>[k] where 0 < k
  • Point is an n dimensional float-vec RVec<f32>[n]

  • Centers are a vector of k points RVec<RVec<f32>[n]>[k]


Flux v. Prusti : Types Enable Code Reuse


Example: kmeans.rs in prusti


ensures(forall(|i:usize| (i < self.len() && i != index) ==>
                    self.lookup(i) == old(self.lookup(i))))

Value equality prevents vector nesting!

Have to duplicate code in new (untrusted) wrapper library


Flux v. Prusti : Types Simplify Invariants & Inference

Dimension preservation obfuscated by Prusti spec

#[requires(i < self.rows() && j < self.cols())]
#[ensures(self.cols() == old(self.cols()) && self.rows() == old(self.rows()))]
pub fn set(&mut self, i: usize, j: usize, value: T) {
  self.inner[i][j] = value;
}

Hassle programmer for dimension preservation invariants


Burden programmer with dimension preservation invariants

width:850px center


Flux v. Prusti : Types Simplify Invariants & Inference

width:850px

Types decompose quantified assertions to quantifier-free refinements

flux infers quantifier-free refinements via Horn-clauses/Liquid Typing


Flux v. Prusti : Types Simplify Invariants & Inference

kmp_search in prusti vs. flux

// Prusti
body_invariant!(forall(|x: usize| x < t.len() ==> t.lookup(x) < pat_len));

// Flux
t: RVec<{v:v < pat_len}>

Types decompose quantified assertions to quantifier-free refinements

flux infers quantifier-free refinements via Horn-clauses/Liquid Typing


Types decompose quantified assertions to quantifier-free refinements

kmp_search in prusti vs. flux

width:1000px


Motivation

Types vs. Floyd-Hoare logic

Demonstration

Flux Liquid Types for Rust

Evaluation

Flux v. Prusti for Memory Safety


Conclusions

Refinements + Rust's Ownership = Ergonomic Imperative Verification...

  • Specify complex invariants by composing type constructors & QF refinements

  • Verify complex invariants by decomposing validity checks via syntactic subtyping


Conclusions

Refinements + Rust's Ownership = Ergonomic Imperative Verification...

  • Specify complex invariants by composing type constructors & QF refinements

  • Verify complex invariants by decomposing validity checks via syntactic subtyping

... But this is just the beginning

  • Flux restricts specifications, Prusti allows way more ...

  • ... how to stretch types to "full functional correctness"?

What are interesting application domains to focus on?