forked from move-language/move
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[move-prover] data invariant assume and assertion for
&mut
params
For functions with `&mut` params `s: S`, the data invariant for `S` will be assumed at function entry (via `Wellformedness` - this is already done) and re-checked on any write-back to this reference --- this is newly added in this commit. This PR is the opposite of PR move-language#783 which does the opposite, i.e., drop the assumption at the function entry. PR move-language#783 is proposed following the following guideline: > Data invariants are only checked when the `&mut` borrow ends. During > the lifetime of the `&mut` reference, the invariant can be temporarily > violated and hence, assuming data invariants there can lead to > inconsistency issues. In theory, both PR's fix are better than the current practice (which is essentially assuming without assertion). However, as the test result in PR move-language#783 shows, the `Options.move` in `stdlib` heavily relies on the entrypoint assumption that a `&mut Option` has either 0 or 1 entry in its vector. Therefore, in this commit, we tighten the conditions where we assert data invariant. In summary, after this PR, data invariants will be checked: - on write-backs to local root, arised from `let r = &mut s` where `s` is a local variable - on write-backs to global root, arised from `let r = borrow_global_mut<S>(addr)` - on write-backs to `&mut` parameter. ```move struct S { f: u8 } spec S { invariant f != 0; } fun foo(s: &mut S) { // spec: assume s.f != 0; let r = &mut s.f; r = 0; // spec: write-back[s.f](r); // spec: assert s.f != 0; } ```
- Loading branch information
1 parent
4c622fd
commit a7c3345
Showing
5 changed files
with
106 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
24 changes: 24 additions & 0 deletions
24
language/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.exp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
Move prover returns: exiting with verification errors | ||
error: data invariant does not hold | ||
┌─ tests/sources/functional/data_invariant_for_mut_ref_arg.move:8:9 | ||
│ | ||
8 │ invariant len(v) == 0; | ||
│ ^^^^^^^^^^^^^^^^^^^^^^ | ||
│ | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:15: push_1 | ||
= s = <redacted> | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:17: push_1 | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:19: push_1 | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:8 | ||
|
||
error: data invariant does not hold | ||
┌─ tests/sources/functional/data_invariant_for_mut_ref_arg.move:8:9 | ||
│ | ||
8 │ invariant len(v) == 0; | ||
│ ^^^^^^^^^^^^^^^^^^^^^^ | ||
│ | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:22: push_2 | ||
= s = <redacted> | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:24: push_2 | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:26: push_2 | ||
= at tests/sources/functional/data_invariant_for_mut_ref_arg.move:8 |
30 changes: 30 additions & 0 deletions
30
language/move-prover/tests/sources/functional/data_invariant_for_mut_ref_arg.move
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module 0x42::struct_invariant_mut_ref_param { | ||
use std::vector; | ||
|
||
struct S { | ||
v: vector<u64>, | ||
} | ||
spec S { | ||
invariant len(v) == 0; | ||
} | ||
|
||
public fun empty(): S { | ||
S { v: vector::empty<u64>() } | ||
} | ||
|
||
public fun push_1(s: &mut S) { | ||
spec { | ||
assert len(s.v) == 0; | ||
}; | ||
vector::push_back(&mut s.v, 1); | ||
} | ||
|
||
public fun push_2(s: &mut S) { | ||
spec { | ||
assert len(s.v) == 0; | ||
}; | ||
vector::push_back(&mut s.v, 2); | ||
let t = freeze(s); | ||
let _ = vector::length(&t.v); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters