Import sets for ambient lemmas/axioms #37
Replies: 9 comments 5 replies
-
Recording these notes from chris for posterity:
Basically, to implement broadcast_forall for non-trusted axioms, Verus's termination checker needs a way to determine which lemmas are allowed to depend on a given broadcast_forall. It's likely that the import set concept here will play a role in that. |
Beta Was this translation helpful? Give feedback.
-
Tracking of libraries we may want to include:
|
Beta Was this translation helpful? Give feedback.
-
This feature would be useful in the page table verification project. Currently I'm using multiple lemmas with very general postconditions, which I call separately at the beginning of a lemma. I'd like to group them into one or more larger lemmas that simply re-export the postconditions but currently I have to re-state every postcondition I want to have on such a "collection lemma". This is possible but inconvenient. In particular re-exporting would make it easier to experiment with different collections of lemmas or to have multiple versions of them. |
Beta Was this translation helpful? Give feedback.
-
Per-file Broadcast forallsLet's say that I know I'm going to be using a specific data structure within a given refinement proof file over and over again. Say I've developed an algebra around this data structure (an example of this for us is A property of
However This property feels very natural however and when writing a bunch of proofs it's easy to forget to re-call the lemma (and it can take some time to figure out that you need to call it). It feels like something that we want always available when working frequently with it. That being said: there will still be many files (a majority) where it is not relevant for us to have access to this property at all. Thus I think per-file |
Beta Was this translation helpful? Give feedback.
-
Notes from the [Verus all-hands]:
|
Beta Was this translation helpful? Give feedback.
-
There is a work-in-progress implementation at https://github.com/verus-lang/verus/tree/reveal_group Here is a concrete syntax proposal, after discussion with @Chris-Hawblitzel (he suggested the mod ring {
use builtin::*;
pub struct Ring {
pub i: nat,
}
impl Ring {
pub closed spec fn inv(&self) -> bool {
self.i < 10
}
pub closed spec fn succ(&self) -> Ring {
Ring { i: if self.i == 9 { 0 } else { self.i + 1 } }
}
pub closed spec fn prev(&self) -> Ring {
Ring { i: if self.i == 0 { 9 } else { (self.i - 1) as nat } }
}
}
pub broadcast proof fn Ring_succ(p: Ring)
requires p.inv()
ensures p.inv() && (#[trigger] p.succ()).prev() == p
{ }
pub broadcast proof fn Ring_prev(p: Ring)
requires p.inv()
ensures p.inv() && (#[trigger] p.prev()).succ() == p
{ }
pub broadcast group Ring_properties (
Ring_succ,
Ring_prev,
)
pub broadcast group Ring_less_properties (
Ring_properties,
remove Ring_prev,
)
}
mod m1 {
use crate::ring::*;
proof fn p1(p: Ring) {
Ring_succ(p);
assert(p.succ().prev() == p);
}
proof fn p2(p: Ring) {
Ring_succ(*);
assert(p.succ().prev() == p);
}
proof fn p3(p: Ring) {
Ring_properties(*);
assert(p.succ().prev() == p);
assert(p.prev().succ() == p);
}
}
mod m2 {
use crate::ring::*;
broadcast ( // module-level
Ring_prev,
Ring_succ,
)
proof fn p3(p: Ring) {
assert(p.succ().prev() == p);
assert(p.prev().succ() == p);
}
} |
Beta Was this translation helpful? Give feedback.
-
Here are some slight variations on the syntax proposed above:
Subtraction could be supported outside of groups as well, like the current
In the implementation, |
Beta Was this translation helpful? Give feedback.
-
yes
Ah, yes, that makes more sense than what I wrote. I was intending to be consistent with |
Beta Was this translation helpful? Give feedback.
-
This feature is now largely implemented. More work is necessary in determining which (if any) other broadcast groups we should offer in |
Beta Was this translation helpful? Give feedback.
-
NOTE: This initial design is outdated, and uses outdates syntax.
@Chris-Hawblitzel, @jonhnet, and I discussed allowing control over automation by providing multiple import sets for ambient lemmas/axioms (global
forall
s), in part inspired by how some rust libraries re-export traits.To access a function defined as an
impl
for a certain trait, in Rust, you import the trait name, and get all the functions it defines as methods on objects with types that implement the trait. This is sometimes used to provide multiple import sets, sometimes including a “prelude” with some default imports, by constructing a module that re-exports various trait identifiers.Here's an example:
This would allow library authors to provide different levels of automation, with pre-packaged import sets of increasing power, and also allows the user to switch to a less "dangerous" set of foralls, and then selectively import the ones they need (or they can decide to call the lemmas explicitly).
We considered what the syntax may look like:
Beta Was this translation helpful? Give feedback.
All reactions