Skip to content
This repository was archived by the owner on May 4, 2024. It is now read-only.

Commit 20a9e02

Browse files
authored
[prover] Added a Boogie model for vector::insert function (#831)
* [prover] Added a Boogie model for vector::insert function * Simplified ensures clause for testing vector::insert * Removed unnecessary new line * Updated test output * Replaced a broken link with another one
1 parent 5101dd2 commit 20a9e02

File tree

6 files changed

+60
-5
lines changed

6 files changed

+60
-5
lines changed

devtools/x-lint/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//! Lint engine.
66
//!
77
//! The overall design is generally inspired by
8-
//! [Arcanist](https://secure.phabricator.com/book/phabricator/article/arcanist_lint)'s lint engine.
8+
//! Arcanist](https://www.phacility.com/phabricator/arcanist)'s lint engine.
99
1010
pub mod content;
1111
pub mod file_path;

language/move-prover/boogie-backend/src/prelude/native.bpl

+19
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,25 @@ procedure {:inline 1} $1_vector_remove{{S}}(m: $Mutation (Vec ({{T}})), i: int)
187187
m' := $UpdateMutation(m, RemoveAtVec(v, i));
188188
}
189189

190+
procedure {:inline 1} $1_vector_insert{{S}}(m: $Mutation (Vec ({{T}})), val: {{T}}, i: int) returns (m': $Mutation (Vec ({{T}}))) {
191+
192+
var len: int;
193+
var v: Vec ({{T}});
194+
195+
v := $Dereference(m);
196+
197+
len := LenVec(v);
198+
if (i < 0 || i > len) {
199+
call $ExecFailureAbort();
200+
return;
201+
}
202+
if (i == len) {
203+
m' := $UpdateMutation(m, ExtendVec(v, val));
204+
} else {
205+
m' := $UpdateMutation(m, InsertAtVec(v, i, val));
206+
}
207+
}
208+
190209
procedure {:inline 1} $1_vector_swap_remove{{S}}(m: $Mutation (Vec ({{T}})), i: int) returns (e: {{T}}, m': $Mutation (Vec ({{T}})))
191210
{
192211
var len: int;

language/move-prover/boogie-backend/src/prelude/vector-array-intern-theory.bpl

+11
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,17 @@ function {:inline} RemoveAtVec<T>(v: Vec T, i: int): Vec T {
8787
l)))
8888
}
8989

90+
function {:inline} InsertAtVec<T>(v: Vec T, i: int, elem: T): Vec T {
91+
(var l := l#Vec(v) + 1;
92+
VecIntern(Vec(
93+
(lambda j: int ::
94+
if j >= 0 && j < l then
95+
if j < i then v#Vec(v)[j]
96+
else if j > i then v#Vec(v)[j-1] else elem
97+
else DefaultVecElem()),
98+
l)))
99+
}
100+
90101
function {:inline} ConcatVec<T>(v1: Vec T, v2: Vec T): Vec T {
91102
(var l1, m1, l2, m2 := l#Vec(v1), v#Vec(v1), l#Vec(v2), v#Vec(v2);
92103
VecIntern(Vec(

language/move-prover/boogie-backend/src/prelude/vector-array-theory.bpl

+11
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,17 @@ function {:inline} RemoveAtVec<T>(v: Vec T, i: int): Vec T {
6464
l))
6565
}
6666

67+
function {:inline} InsertAtVec<T>(v: Vec T, i: int, elem: T): Vec T {
68+
(var l := l#Vec(v) + 1;
69+
Vec(
70+
(lambda j: int ::
71+
if j >= 0 && j < l then
72+
if j < i then v#Vec(v)[j]
73+
else if j > i then v#Vec(v)[j-1] else elem
74+
else DefaultVecElem()),
75+
l))
76+
}
77+
6778
function {:inline} ConcatVec<T>(v1: Vec T, v2: Vec T): Vec T {
6879
(var l1, m1, l2, m2 := l#Vec(v1), v#Vec(v1), l#Vec(v2), v#Vec(v2);
6980
Vec(

language/move-prover/tests/sources/functional/loops_with_memory_ops.exp

+6-4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ error: unknown assertion failed
4747
= b = <redacted>
4848
= b = <redacted>
4949
= a = <redacted>
50-
= a = <redacted>
50+
= at <internal>:1
51+
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
5152
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
5253
= i = <redacted>
5354
= at tests/sources/functional/loops_with_memory_ops.move:86: nested_loop2
@@ -98,11 +99,12 @@ error: induction case of the loop invariant does not hold
9899
= at tests/sources/functional/loops_with_memory_ops.move:74: nested_loop2
99100
= at tests/sources/functional/loops_with_memory_ops.move:80: nested_loop2
100101
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
101-
= b = <redacted>
102-
= b = <redacted>
103-
= a = <redacted>
104102
= at <internal>:1
105103
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
104+
= at <internal>:1
105+
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
106+
= a = <redacted>
107+
= a = <redacted>
106108
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
107109
= i = <redacted>
108110
= at tests/sources/functional/loops_with_memory_ops.move:86: nested_loop2

language/move-prover/tests/sources/functional/verify_vector.move

+12
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,18 @@ module 0x42::VerifyVector {
291291
ensures old(v[i]) == result;
292292
}
293293

294+
// Add an element to the vector at index.
295+
fun verify_model_insert<Element>(v: &mut vector<Element>, e: Element, i: u64) {
296+
vector::insert(v, e, i); // inlining the built-in Boogie procedure
297+
}
298+
spec verify_model_insert {
299+
aborts_if i > len(v);
300+
ensures len(v) == len(old(v)) + 1;
301+
ensures v[i] == e;
302+
ensures old(v[0..i]) == v[0..i];
303+
ensures old(v)[i..len(old(v))] == v[i+1..len(v)];
304+
}
305+
294306
// Remove the `i`th element E of the vector by swapping it with the last element,
295307
// and then popping it off
296308
// It is O(1), but does not preserve ordering

0 commit comments

Comments
 (0)