-
Notifications
You must be signed in to change notification settings - Fork 109
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
Reenable datatype invariants #686
Conversation
prusti-tests/tests/verify/fail/invariants/invariants-basic-2.rs
Outdated
Show resolved
Hide resolved
@zgrannan I thought a bit about the possible implementation of type invariants and I think that the cleanest way of integrating them into the refactored system would be by renaming the new struct TypeDecl {
kind: TypeDeclKind,
user_invariant: Box<Expression>,
} Let me know if you have any questions or need help. |
@vakaras Is the new |
Why the |
@vakaras <https://github.com/vakaras> Is the new TypeDecl a misnomer
then? If these types are meant to be passed around similarly to ty::Ty or
(the old) vir::Type, they are not *declarations*.
It is a declaration. The thing passed around is `vir::high::Type`.
… |
Why the Box? It seems unnecessary.
Yes, mixed up code.
… |
If it turns out to be needed to cut a mutual recursion with the expression definition then I prefer it over |
So I've been thinking about this a little, particularly with adding "dependent parameters" expressed as const generics. The classic use case with a Type Alias is the following: #[invariant(_ < s.len())]
type Index<const s: &[u32]> = usize;
fn foo(s: &[i32], i: Index<{s}>) -> i32 { s[i] } Porting this from my work on Type Aliases to Datatypes wouldn't be so difficult, and it seems to be a super nice solution to the #[invariant(self.invariants_enabled ==> self.value <= 100)]
struct Percentage {
invariants_enabled: bool,
value: u8,
}
fn print_percentage(percentage: &Percentage) { }
#[requires(percentage.invariants_enabled)]
fn adjust_percentage(percentage: &mut Percentage) {
percentage.value += 10; // temporarily break invariant
percentage.invariants_enabled = false;
print_percentage(percentage);
percentage.invariants_enabled = true;
percentage.value -= 10; // restore invariant
} Would instead be: #[invariant(invariants_enabled ==> self.value <= 100)]
struct Percentage<const invariants_enabled: bool> {
value: u8,
}
fn print_percentage(percentage: &Percentage<{false}>) { }
fn adjust_percentage(percentage: &mut Percentage<{true}>) {
percentage.value += 10; // temporarily break invariant
print_percentage(percentage);
percentage.value -= 10; // restore invariant
} However, my current solution requires the whole thing be wrapped in a #![feature(const_generics_defaults)]
#[invariant(invariants_enabled ==> self.value <= 100)]
struct Percentage<const invariants_enabled: bool = true> {
value: u8,
}
fn print_percentage(percentage: &Percentage<false>) {}
fn adjust_percentage(percentage: &mut Percentage) {
percentage.value += 10; // temporarily break invariant
print_percentage(percentage as &Percentage<false>);
percentage.value -= 10; // restore invariant
} The only snag is that we cannot Edit: @vakaras suggested |
@vakaras prusti-dev/prusti-viper/src/encoder/encoder.rs Lines 625 to 637 in 2bce0c8
vir::Expr , but the type invariant encoder:
vir::Expression , and there is no way to go from polymorphic vir to high vir.
Is this still the case? |
Yes. And I doubt that #756 will be enough to fix that. |
68cce47
to
278fe66
Compare
I rebased this. I think the last comment still kind of applies. More specifically, I see:
So… should I just remove the |
Seems like that would be the easiest option. |
It seems that after the rebase, things don't work at all atm (i.e. things behave as if there was no invariant annotation) |
@JonasAlaif I do have some WIP for this locally, but I want to wait until after #899, because invariants with generics were not nice. |
37cb800
to
05d2592
Compare
05d2592
to
ca8ef2b
Compare
bors r+ (@vakaras I'll add the trusted flag shortly) |
901: NFM22 examples r=Aurel300 a=Aurel300 This is to allow linking the examples online from the paper. PRs to be done before the deadline: - [x] #686 - [x] #882 - [x] #887 - [x] #899 972: Fix slice with range encoding r=JonasAlaif a=JonasAlaif Fixes #960 Issue is described there. Not sure if this is the correct way to do the error reporting? It would be really nice to just have a contract for `index` and `index_mut` and report the error as a precondition violation of those. E.g. I really don't want to hardcode the pledge required for `index_mut` by hand. Co-authored-by: Aurel Bílý <aurel.bily@gmail.com> Co-authored-by: Jonas <jonas.fiala.cardiff@gmail.com>
No description provided.