Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making Reals erasable, and providing a reflection API for real literals #3242

Merged
merged 12 commits into from
Apr 18, 2024

Conversation

mtzguido
Copy link
Member

Our FStar.Real module did not make much sense, in that it supported decidable operations (like equality) over arbitrary reals, and a total of_string operation to make a real from a string (although this was uninterpreted logically, so not unsound, but it also did not have a runtime implementation).

This PR makes the real type erasable, and removes the of_string operation and the extraction rules for reals (which would never be triggered now).

It also adds them to the vconst view that Meta-F* exposes.

@mtzguido
Copy link
Member Author

This will help in using literal real permissions in pulse, replacing half_perm (half_perm full_perm) by 0.25R, etc. In fact, just using coercions between reals and perms almost does the trick, except that it requires many more rewrites since Pulse will not unify real_to_perm 1.0 and full_perm (though it may soon, if we make it call the unifier).

@mtzguido
Copy link
Member Author

Updated to put the comparison operations in prop instead of GTot bool. Conceptually, putting them in GTot bool would make use of the strong excluded middle axiom, which a user may want to avoid. Though with the current interface it does not really make a difference (one can only construct rational combinations of 1 and sqrt(2), so it could in fact be decidable).

But, with more ways to construct reals (if we do not restrict to a computable subset, which I expect we won't as we are using Z3's real theory), it may be that one can recover the strong excluded middle from these GTot bool operations. I have a hard time thinking how such a proof would go... but using prop feels like the right thing to do.

It does impact Pulse slightly, the following patch would be needed:

diff --git a/lib/pulse/core/PulseCore.FractionalPermission.fst b/lib/pulse/core/PulseCore.FractionalPermission.fst
index 5ec4d7e2..b5d61535 100644
--- a/lib/pulse/core/PulseCore.FractionalPermission.fst
+++ b/lib/pulse/core/PulseCore.FractionalPermission.fst
@@ -31,4 +31,4 @@ noeq type perm : Type0 =
 /// A reference is only safely writeable if we have full permission
-let writeable (p: perm) : GTot bool =
-  MkPerm?.v p = one
+let writeable (p: perm) : prop =
+  MkPerm?.v p == one
 
@@ -43,6 +43,6 @@ let sum_perm (p1 p2: perm) : Tot perm =
 /// Helper to compare two permissions
-let lesser_equal_perm (p1 p2:perm) : GTot bool =
+let lesser_equal_perm (p1 p2:perm) : prop =
   MkPerm?.v p1 <=.  MkPerm?.v p2
 
-let lesser_perm (p1 p2:perm) : GTot bool =
+let lesser_perm (p1 p2:perm) : prop =
   MkPerm?.v p1 <.  MkPerm?.v p2
diff --git a/lib/pulse/lib/Pulse.Lib.FractionalAnchoredPreorder.fst b/lib/pulse/lib/Pulse.Lib.FractionalAnchoredPreorder.fst
index 4b44db28..069d4332 100644
--- a/lib/pulse/lib/Pulse.Lib.FractionalAnchoredPreorder.fst
+++ b/lib/pulse/lib/Pulse.Lib.FractionalAnchoredPreorder.fst
@@ -137,6 +137,2 @@ type knowledge (#v:Type) (#p:preorder v) (anchors:anchor_rel p) =
 
-let b2p (b:bool)
-  : prop
-  = b == true
-
 /// Fractional permissions are composable when their sum <= 1.0
@@ -147,4 +143,4 @@ let perm_opt_composable (p0 p1:option perm)
     | Some p, None
-    | None, Some p -> b2p (p `lesser_equal_perm` full_perm)
-    | Some p0, Some p1 -> b2p (sum_perm p0 p1 `lesser_equal_perm` full_perm)
+    | None, Some p -> p `lesser_equal_perm` full_perm
+    | Some p0, Some p1 -> sum_perm p0 p1 `lesser_equal_perm` full_perm
 
diff --git a/lib/pulse/lib/Pulse.Lib.PCM.Fraction.fst b/lib/pulse/lib/Pulse.Lib.PCM.Fraction.fst
index f0a04952..83a4f271 100755
--- a/lib/pulse/lib/Pulse.Lib.PCM.Fraction.fst
+++ b/lib/pulse/lib/Pulse.Lib.PCM.Fraction.fst
@@ -45,3 +45,3 @@ let mk_frame_preserving_upd_none
 
-let perm_ok p : prop = (p.v <=. one == true)
+let perm_ok p : prop = p.v <=. one
 
diff --git a/share/pulse/examples/by-example/PulseTutorial.Ref.fst b/share/pulse/examples/by-example/PulseTutorial.Ref.fst
index 92593edb..45b082c1 100755
--- a/share/pulse/examples/by-example/PulseTutorial.Ref.fst
+++ b/share/pulse/examples/by-example/PulseTutorial.Ref.fst
@@ -207,3 +207,3 @@ ensures
 fn max_perm #a (r:ref a) #p anything
-requires pts_to r #p 'v ** pure (not (p `lesser_equal_perm` full_perm))
+requires pts_to r #p 'v ** pure (~(p `lesser_equal_perm` full_perm))
 returns _:squash False`

Seems not too bad... thoughts?

[of_string "1.1"]
*)
val of_string: string -> Tot real
val to_string: real -> GTot string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to keep the ghost to_string function? Is there any way to execute it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah good point. There's no implementation nor axioms, so probably best to just drop it.

@mtzguido
Copy link
Member Author

Downstream PRs:

Will merge once we confirm Steel & friends are not badly broken by this

@mtzguido mtzguido merged commit e95e387 into FStarLang:master Apr 18, 2024
2 checks passed
@mtzguido mtzguido deleted the reals branch April 18, 2024 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants