Skip to content

Commit bcc1693

Browse files
committed
Fix issue 583.
1 parent c5c34b5 commit bcc1693

6 files changed

Lines changed: 72 additions & 14 deletions

File tree

lib/pulse/lib/Pulse.Lib.Array.fst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module Pulse.Lib.Array
1818
#lang-pulse
1919
open Pulse.Lib.Core
2020
open Pulse.Lib.Reference
21+
open Pulse.Lib.WithPure
2122
open Pulse.Lib.Array.Basic
2223
open Pulse.Class.PtsTo
2324
open FStar.Ghost

lib/pulse/lib/Pulse.Lib.Pervasives.fst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ include Pulse.Lib.Core
2121
include Pulse.Lib.Inv
2222
include Pulse.Lib.Send
2323
include Pulse.Lib.Forall
24+
include Pulse.Lib.WithPure
2425
include Pulse.Lib.Array
2526
include Pulse.Lib.Reference
2627
include Pulse.Lib.Reference.Array

src/checker/Pulse.Checker.While.fst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ let rec subst_loop_requires_marker (t: term) (v: term -> term) : Dv term =
6363
| _ -> default ()
6464
)
6565
| R.Tv_Abs b body ->
66-
R.pack_ln (R.Tv_Abs b (subst_loop_requires_marker body v))
66+
let b = R.inspect_binder b in
67+
let b = { b with sort = subst_loop_requires_marker b.sort v } in
68+
R.pack_ln (R.Tv_Abs (R.pack_binder b) (subst_loop_requires_marker body v))
6769
| _ -> t
6870

6971
let subst_loop_requires_marker_with_true t = subst_loop_requires_marker t fun _ -> tm_l_true

src/checker/Pulse.JoinComp.fst

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,8 @@ let rec close_post x_ret dom_g g1 (bs1:env_bindings) (post:slprop)
4343
tm_exists_sl u b (close_term post y)
4444
)
4545
in
46-
(* generate exists (_:squash pr). post
47-
Useful if the well-formedness of post depends on pr in scope *)
48-
let guard_with_squash pr (post:slprop) : T.Tac slprop =
49-
let n, u, pr = pr in
50-
let b = {binder_ty=mk_squash u pr; binder_ppname=n; binder_attrs=Sealed.seal []} in
51-
tm_exists_sl u_zero b post
52-
in
5346
let maybe_elim_rewrites_to pr (post:term) : T.Tac term =
54-
let _, _, property = pr in
47+
let n, _, property = pr in
5548
let open R in
5649
let hd, args = T.collect_app_ln property in
5750
match T.inspect_ln hd, args with
@@ -62,15 +55,15 @@ let rec close_post x_ret dom_g g1 (bs1:env_bindings) (post:slprop)
6255
| Tv_Var n1 ->
6356
let n1 = inspect_namedv n1 in
6457
if n1.uniq = x_ret then
65-
tm_star post (tm_pure (RT.eq2 u typ lhs rhs))
58+
tm_with_pure (RT.eq2 u typ lhs rhs) n post
6659
else
6760
Pulse.Syntax.Naming.subst_term post [RT.NT n1.uniq rhs]
6861
| _ ->
6962
let eq = RT.eq2 u typ lhs rhs in
70-
tm_star post (tm_pure eq)
63+
tm_with_pure eq n post
7164
)
72-
else tm_star post (tm_pure property) //guard_with_squash pr post?
73-
| _ -> tm_star post (tm_pure property) //guard_with_squash pr post?
65+
else tm_with_pure property n post
66+
| _ -> tm_with_pure property n post
7467
in
7568
let close_post = close_post x_ret dom_g g1 in
7669
match bs1 with
@@ -257,7 +250,15 @@ and combine_args g b (args1 args2:list R.argv) : T.Tac (list R.argv) =
257250
(combine_terms true g b (a1, a2), v1)::combine_args g b args1 args2
258251
| _ -> []
259252

260-
let join_slprop g b (ex1 ex2:list (universe & binder)) (p1 p2:slprop)
253+
let guard_with_pure then_ b (pred: term) n (acc: slprop) : slprop =
254+
match inspect_term acc with
255+
| Tm_IsUnreachable -> acc
256+
| _ ->
257+
tm_with_pure
258+
(mk_imp (RT.eq2 u0 tm_bool b (if then_ then tm_true else tm_false)) pred)
259+
n acc
260+
261+
let rec join_slprop g b (ex1 ex2:list (universe & binder)) (p1 p2:slprop)
261262
: T.Tac slprop
262263
= match inspect_term p1, inspect_term p2 with
263264
| Tm_IsUnreachable, _ -> p2
@@ -270,6 +271,11 @@ let join_slprop g b (ex1 ex2:list (universe & binder)) (p1 p2:slprop)
270271
//Not doing anything interesting to share binders
271272
RT.mk_if b p1 p2
272273

274+
| Tm_WithPure pred1 n1 p1, _ ->
275+
guard_with_pure true b pred1 n1 <| join_slprop g b ex1 ex1 p1 p2
276+
| _, Tm_WithPure pred2 n2 p2 ->
277+
guard_with_pure false b pred2 n2 <| join_slprop g b ex1 ex1 p1 p2
278+
273279
| _ ->
274280
let open Pulse.Show in
275281
let p1s, p2s = slprop_as_list p1, slprop_as_list p2 in

test/bug-reports/Bug583.fst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module Bug583
2+
open Pulse
3+
#lang-pulse
4+
5+
fn problem () {
6+
let mut i = 0sz;
7+
let mut j = 1sz;
8+
while ((!j `SizeT.sub` !i) <> 0sz)
9+
invariant live i
10+
invariant live j
11+
invariant pure (!i `SizeT.lte` !j)
12+
{}
13+
}

test/bug-reports/Bug583b.fst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module Bug583b
2+
open Pulse
3+
#lang-pulse
4+
open Pulse.Lib.BoundedIntegers
5+
module SZ = FStar.SizeT
6+
module R = Pulse.Lib.Reference
7+
8+
fn binary_search_style_FAILS
9+
(lo_init hi_init: SZ.t)
10+
requires pure (SZ.v lo_init < SZ.v hi_init /\ SZ.v hi_init <= 100)
11+
returns _: unit
12+
ensures pure True
13+
{
14+
let mut lo: SZ.t = lo_init;
15+
let mut hi: SZ.t = hi_init;
16+
17+
while (
18+
let vlo = !lo;
19+
let vhi = !hi;
20+
(vhi - vlo) > 1sz
21+
)
22+
invariant exists* vlo vhi.
23+
R.pts_to lo vlo **
24+
R.pts_to hi vhi **
25+
pure (
26+
SZ.v vlo <= SZ.v vhi /\
27+
SZ.v vhi <= 100
28+
)
29+
{
30+
let vlo = !lo;
31+
let vhi = !hi;
32+
let mid = vlo + ((vhi - vlo) / 2sz);
33+
lo := mid
34+
}
35+
}

0 commit comments

Comments
 (0)