Skip to content

Commit aa9543a

Browse files
committed
Check for ambiguity using unifier.
1 parent 4fe55b1 commit aa9543a

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

src/checker/Pulse.Checker.Prover.fst

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -540,12 +540,13 @@ let teq_nosmt_force_args (g: R.env) (x y: term) (fail_fast: bool) : Dv bool =
540540
let yh, ya = R.collect_app_ln y in
541541
go ((xh, R.Q_Explicit) :: xa) ((yh, R.Q_Explicit) :: ya)
542542

543-
module TermEq = FStar.Reflection.TermEq
544-
545-
let is_unamb (cands: list (int & slprop_view)) : bool =
543+
let is_unamb g (cands: list (int & slprop_view)) : T.Tac bool =
546544
match cands with
547545
| [] | [_] -> true
548-
| (_, x)::cands -> List.Tot.for_all (fun (_, y) -> TermEq.term_eq (elab_slprop x) (elab_slprop y)) cands
546+
| (_, x)::cands ->
547+
let unifies x y = with_uf_transaction fun _ ->
548+
teq_nosmt_force_args (elab_env g) x y true in
549+
forallb (fun (_, y) -> unifies (elab_slprop x) (elab_slprop y)) cands
549550

550551
// this matches atoms when they're the only unifiable pair
551552
// necessary for various gather like functions where you don't specify all arguments
@@ -566,7 +567,7 @@ let prove_atom_unamb (g: env) (ctxt: list slprop_view) (goal: slprop_view) :
566567
let ictxt = List.Tot.mapi (fun i ctxt -> i, ctxt) ctxt in
567568
let cands = T.filter (fun (i, ctxt) -> matches_mkeys ctxt) ictxt in
568569
if Nil? cands then None else
569-
if not (is_unamb cands) then None else
570+
if not (is_unamb g cands) then None else
570571
let (i, cand) :: _ = cands in
571572
debug_prover g (fun _ -> Printf.sprintf "prove_atom_unamb: commiting to unify %s and %s\n" (show (elab_slprop cand)) (show goal));
572573
ignore (teq_nosmt_force_args (elab_env g) (elab_slprop cand) goal false);
@@ -599,7 +600,7 @@ let prove_atom (g: env) (ctxt: list slprop_view) (allow_amb: bool) (goal: slprop
599600
let ictxt = List.Tot.mapi (fun i ctxt -> i, ctxt) ctxt in
600601
let cands = T.filter (fun (i, ctxt) -> matches_mkeys ctxt) ictxt in
601602
if Nil? cands then None else
602-
if (if allow_amb then false else not (is_unamb cands)) then None else
603+
if (if allow_amb then false else not (is_unamb g cands)) then None else
603604
let (i, cand)::_ = cands in
604605
debug_prover g (fun _ -> Printf.sprintf "commiting to unify %s and %s\n" (show (elab_slprop cand)) (show goal));
605606
ignore (teq_nosmt_force_args (elab_env g) (elab_slprop cand) goal false);

test/EverParseIssue.fst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
module EverParseIssue
2+
#lang-pulse
3+
open Pulse
4+
open Pulse.Lib.Trade
5+
open Pulse.Lib.Trade.Util { rewrite_with_trade, trans }
6+
7+
// EverParse heavily uses rewrite_with_trade to convert unifiable slprops
8+
let a = emp
9+
let b = a
10+
let c = b
11+
12+
fn foo ()
13+
requires a
14+
ensures c
15+
ensures trade c a
16+
{
17+
rewrite_with_trade a b;
18+
rewrite_with_trade b c;
19+
// ambiguous: `trade b a` unifies with both `trade c b` and `trade b a`
20+
trans c b a;
21+
}

0 commit comments

Comments
 (0)