# Example for typing rules v2 ## Example in rust ```rust #[flux::sig(fn(bool) -> i32{v : v >= 0})] fn ref_join(b: bool) -> i32 { let mut x = 1; let mut y = 2; let r = if b { &mut x } else { &mut y }; decr(r); x } #[flux::sig(fn(&mut i32{v : v >= 0}))] fn decr(r: &mut i32); ``` ## Lambda_flux ```rust let ref_join = rec f〈a0〉(b) := let x = new(ρx) in let y = new(ρy) in x := 1; y := 2; let r = if b { &mut x } else { &mut y } in call decr(r); *x decr : fn(&mut i32{v : v >= 0}) -> ↯ ``` ## Typechecking Comments show the state of the checker _after_ the statement ```rust let ref_join = rec f〈a0〉(b) := // t-fun with type ∀a0:bool. fn(bool〈a0〉) -> i32{v : v ≥ 0} // Δ := a0:bool // T := ∅ // Γ := b:bool〈a0〉 // technically Γ also contains f: ∀a0:bool. fn(bool〈a0〉) -> i32{v : v ≥ 0}, which I'm going to omit... let x = new(ρx) in // t-new // a0:bool, ρx:loc // ρx↦↯ // b:bool〈a0〉, x:ptr(ρx) let y = new(ρy) in // t-new // a0:bool, ρx:loc, ρy:loc // ρx↦↯, ρy↦↯ // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) x := 1; // t-assign-strg // a0:bool, ρx:loc, ρy:loc // ρx↦i32〈1〉, ρy↦↯ // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) y := 2; // t-assign-strg // a0:bool, ρx:loc, ρy:loc // ρx → i32〈1〉, ρy → i32〈2〉 // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) let r = if b { // t-if // a0:bool, ρx:loc, ρy:loc, a0 // ρx → i32〈1〉, ρy → i32〈2〉 // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) &mut x // t-strg-mut-rebor // a0:bool, ρx:loc, ρy:loc, a0 // ρx↦{v. i32〈v〉 | v ≥ 0}, ρy↦i32〈2〉 // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) // // ρx:loc, ρy:loc ⊢ i32〈1〉 <: {v. i32〈v〉 | v ≥ 0} } else { // t-if // a0:bool, ρx:loc, ρy:loc, ~a0 // ρx → i32〈1〉, ρy → i32〈2〉 // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) &mut y // t-strg-mut-rebor // a0:bool, ρx:loc, ρy:loc, ~a0 // ρx↦i32〈1〉, ρy↦{v. i32〈v〉 | v ≥ 0} // b:bool〈a0〉, x:ptr(ρx), y:ptr(ρy) // // a0: bool, ρx:loc, ρy:loc ⊢ i32〈2〉 <: {v. i32〈v〉 | v ≥ 0} } in // t-if + t-let // a0:bool, ρx:loc, ρy:loc // b:bool〈a0〉, ρx↦{v. i32〈v〉 | v ≥ 0}, ρy↦{v. i32〈v〉 | v ≥ 0} // x:ptr(ρx), y:ptr(ρy), r:&mut {v. i32〈v〉 | v ≥ 0} call decr(r); // t-call // a0:bool, ρx:loc, ρy:loc // b:bool〈a0〉, ρx↦{v. i32〈v〉 | v ≥ 0}, ρy↦{v. i32〈v〉 | v ≥ 0} // x:ptr(ρx), y:ptr(ρy), r:&mut {v. i32〈v〉 | v ≥ 0} // // arg subtyping: // a0:bool, ρx:loc, ρy:loc ⊢ &mut {v. i32〈v〉 | v ≥ 0} <: &mut {v. i32〈v〉 | v ≥ 0} *x // t-deref-strg + t-fun // // return type: // a0: bool, ρx:loc, ρy:loc, a1:int, a1 ≥ 0 ⊢ {v. i32〈v〉 | v ≥ 0} <: i32{v. i32〈v〉 | v ≥ 0} ``` ```rust let init_zeros = rec f<a0>(n) := let x = new(ρx) in let vec = new(ρv) in x := 0; vec := Vec<f32>::new(); let k = rec k<a, b>() := if i < n { Vec::push<ρv,b>(vec, 0); i := *i + 1; call k<a+1, b+1>() } else { *vec } in call k<0, 0>() } ```