Skip to content

Commit

Permalink
add support of abort when in spec
Browse files Browse the repository at this point in the history
  • Loading branch information
rahxephon89 committed Oct 11, 2024
1 parent b2781bf commit 2c9bf73
Show file tree
Hide file tree
Showing 7 changed files with 161 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ impl<'a> ExpRewriterFunctions for SpecConverter<'a> {
.into_exp()
},
// Deal with removing various occurrences of Abort and spec blocks
Call(id, Abort, _) | SpecBlock(id, ..) => {
SpecBlock(id, ..) => {
// Replace direct call by unit
Call(*id, Tuple, vec![]).into_exp()
},
Expand Down
21 changes: 21 additions & 0 deletions third_party/move/move-prover/boogie-backend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,27 @@ pub fn add_prelude(
sh_instances = vec![];
bv_instances = vec![];
}

let mut all_types = mono_info
.all_types
.iter()
.filter(|ty| ty.can_be_type_argument())
.map(|ty| TypeInfo::new(env, options, ty, false))
.collect::<BTreeSet<_>>()
.into_iter()
.collect_vec();
let mut bv_all_types = mono_info
.all_types
.iter()
.filter(|ty| ty.can_be_type_argument())
.map(|ty| TypeInfo::new(env, options, ty, true))
.filter(|ty_info| !all_types.contains(ty_info))
.collect::<BTreeSet<_>>()
.into_iter()
.collect_vec();
all_types.append(&mut bv_all_types);
context.insert("uninterpreted_instances", &all_types);

context.insert("sh_instances", &sh_instances);
context.insert("bv_instances", &bv_instances);
let mut vec_instances = mono_info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ options provided to the prover.
{% include "custom-natives" %}
{%- endif %}


// Uninterpreted function for all types

{% for instance in uninterpreted_instances %}

{%- set S = "'" ~ instance.suffix ~ "'" -%}
{%- set T = instance.name -%}

function $Uninterpreted_value_of_{{S}}(): {{T}};

{% endfor %}

// ============================================================================================
// Primitive Types

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,13 +991,22 @@ impl<'env> SpecTranslator<'env> {
self.translate_call(node_id, oper, &[args[args.len() - 1].clone()]);
emit!(self.writer, &")".repeat(count));
},
Operation::Abort => {
let exp_bv_flag = global_state.get_node_num_oper(node_id) == Bitwise;
emit!(
self.writer,
&format!(
"$Uninterpreted_value_of_'{}'()",
boogie_type_suffix_bv(self.env, &self.get_node_type(node_id), exp_bv_flag)
)
);
},
Operation::MoveFunction(_, _)
| Operation::BorrowGlobal(_)
| Operation::Borrow(..)
| Operation::Deref
| Operation::MoveTo
| Operation::MoveFrom
| Operation::Abort
| Operation::Old => {
panic!("operation unexpected: {}", oper.display(self.env, node_id))
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
module 0x42::TestAbortInFunction {

fun aborts_with(x: u64, y: u64): u64 {
if (x == 1) {
abort 2
} else if (y == 2) {
abort 3
} else {
x
}
}
spec aborts_with {
aborts_if x == 1 with 2;
aborts_if y == 2 with 3;
ensures result == x;
}

fun call_aborts_with(): u64 {
aborts_with(2, 3)
}

spec call_aborts_with {
ensures result == aborts_with(2, 3);
}

fun abort_generic<Element: copy + drop>(x: Element, y: Element): Element {
if (x == y) {
abort 0
} else {
x
}
}

fun call_aborts_generic(): u64 {
abort_generic(2, 3)
}

spec call_aborts_generic {
ensures result == abort_generic(2, 3);
}

struct S<Element: copy + drop> has copy, drop {
value: Element
}

fun abort_generic_struct<Element: copy + drop>(x: S<Element>, y: S<Element>): S<Element> {
if (x == y) {
abort 0
} else {
x
}
}

fun spec_abort_generic_struct<Element: copy + drop>(x: S<Element>, y: S<Element>): S<Element> {
if (x == y) {
abort 0
} else {
x
}
}

fun call_abort_generic_struct<Element: copy + drop>(x: Element, y: Element): Element {
let sx = S {
value: x
};
let sy = S {
value: y
};
abort_generic_struct(sx, sy).value
}

spec call_abort_generic_struct {
aborts_if x == y;
ensures result == call_abort_generic_struct(x, y);
}

struct T has copy, drop {
v: u64
}

fun call_abort_generic_struct_concrete(x: u64, y: u64): T {
let sx = S {
value: T {
v: x
}
};
let sy = S {
value: T {
v: y
}
};
abort_generic_struct(sx, sy).value
}

spec call_abort_generic_struct_concrete {
aborts_if x == y;
ensures result == call_abort_generic_struct_concrete(x, y);
ensures result == spec_call_abort_generic_struct_concrete(x, y);
}

spec fun spec_call_abort_generic_struct_concrete(x: u64, y: u64): T {
let sx = S {
value: T {
v: x
}
};
let sy = S {
value: T {
v: y
}
};
spec_abort_generic_struct(sx, sy).value
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ error: induction case of the loop invariant does not hold
= at tests/sources/functional/loops_with_memory_ops.move:80: nested_loop2
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= b = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= a = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
= i = <redacted>
Expand Down Expand Up @@ -104,8 +105,8 @@ error: unknown assertion failed
= at tests/sources/functional/loops_with_memory_ops.move:80: nested_loop2
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= b = <redacted>
= a = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= a = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
= i = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:86: nested_loop2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ error: induction case of the loop invariant does not hold
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= a = <redacted>
= b = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
= <redacted> = <redacted>
= i = <redacted>
Expand Down Expand Up @@ -100,9 +99,6 @@ error: unknown assertion failed
= at tests/sources/functional/loops_with_memory_ops.move:75: nested_loop2
= at tests/sources/functional/loops_with_memory_ops.move:80: nested_loop2
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= a = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:81: nested_loop2
= b = <redacted>
= at tests/sources/functional/loops_with_memory_ops.move:85: nested_loop2
= <redacted> = <redacted>
= i = <redacted>
Expand Down

0 comments on commit 2c9bf73

Please sign in to comment.