├── guide ├── .gitignore ├── src │ ├── images │ │ ├── why3-ide-ensures.png │ │ └── why3-ide-startup.png │ ├── representation_of_types.md │ ├── basic_concepts │ │ └── variants.md │ ├── trusted.md │ └── quickstart │ │ └── editor_config.md ├── book.toml └── highlight.js │ └── src │ └── languages │ └── pearlite.js ├── pearlite-syn ├── tests │ └── debug.rs └── src │ ├── lib.rs │ └── print.rs ├── static └── marteau.jpg ├── tests ├── creusot-contracts │ ├── creusot-contracts.rs │ └── creusot-contracts │ │ └── why3shapes.gz ├── should_succeed │ ├── bug │ │ ├── 168 │ │ │ └── proof.json │ │ ├── 173 │ │ │ └── proof.json │ │ ├── 195 │ │ │ └── proof.json │ │ ├── 206 │ │ │ └── proof.json │ │ ├── 217 │ │ │ └── proof.json │ │ ├── 235 │ │ │ └── proof.json │ │ ├── 256 │ │ │ └── proof.json │ │ ├── 258 │ │ │ └── proof.json │ │ ├── 273 │ │ │ └── proof.json │ │ ├── 395 │ │ │ └── proof.json │ │ ├── 463 │ │ │ └── proof.json │ │ ├── 486 │ │ │ └── proof.json │ │ ├── 528 │ │ │ └── proof.json │ │ ├── 545 │ │ │ └── proof.json │ │ ├── 641 │ │ │ └── proof.json │ │ ├── 691 │ │ │ └── proof.json │ │ ├── 766 │ │ │ └── proof.json │ │ ├── 789 │ │ │ └── proof.json │ │ ├── 791 │ │ │ └── proof.json │ │ ├── 793 │ │ │ └── proof.json │ │ ├── 962 │ │ │ └── proof.json │ │ ├── 991 │ │ │ └── proof.json │ │ ├── 1030 │ │ │ └── proof.json │ │ ├── 1208 │ │ │ └── proof.json │ │ ├── 1239 │ │ │ └── proof.json │ │ ├── 1342 │ │ │ └── proof.json │ │ ├── 1504 │ │ │ └── proof.json │ │ ├── 1538 │ │ │ └── proof.json │ │ ├── 1575 │ │ │ └── proof.json │ │ ├── 1674 │ │ │ └── proof.json │ │ ├── 789.rs │ │ ├── 02_derive.rs │ │ ├── 168.rs │ │ ├── 528.rs │ │ ├── 258.rs │ │ ├── 693.rs │ │ ├── 269.rs │ │ ├── 791.rs │ │ ├── minus_assoc.rs │ │ ├── 1337.rs │ │ ├── 395.rs │ │ ├── 545.rs │ │ ├── 793.rs │ │ ├── 195.rs │ │ ├── 256.rs │ │ ├── 273.rs │ │ ├── 510.rs │ │ ├── 235.rs │ │ ├── 797.rs │ │ ├── 653.rs │ │ ├── 1504.rs │ │ ├── 486.rs │ │ ├── 1030.coma │ │ ├── eq_panic.rs │ │ ├── pure_neq.rs │ │ ├── box_borrow_resolve.rs │ │ ├── 265.rs │ │ ├── 1342.rs │ │ ├── 691.rs │ │ ├── 1312.rs │ │ ├── 641.rs │ │ ├── nonreturning.rs │ │ ├── 217.rs │ │ ├── 768.rs │ │ ├── 1538.rs │ │ ├── 463.rs │ │ ├── 874.rs │ │ ├── 1575.rs │ │ ├── 1674.rs │ │ ├── 1773.rs │ │ ├── 1538.coma │ │ ├── 1239.coma │ │ ├── 1410.rs │ │ ├── 791.coma │ │ ├── 1030.rs │ │ ├── 962.rs │ │ ├── 789.coma │ │ ├── 206.rs │ │ ├── 181_ident.rs │ │ ├── pure_neq.coma │ │ ├── fake_ref.rs │ │ ├── 766.rs │ │ ├── minus_assoc.coma │ │ ├── 1438.rs │ │ ├── pure_neq │ │ │ └── proof.json │ │ ├── minus_assoc │ │ │ └── proof.json │ │ ├── 682.rs │ │ ├── 761.rs │ │ ├── 528.coma │ │ ├── 195.coma │ │ ├── 545.coma │ │ ├── 02_derive.coma │ │ ├── vcgen │ │ │ └── proof.json │ │ ├── 181_ident │ │ │ └── proof.json │ │ ├── generic_trait_predicate.rs │ │ ├── 02_derive │ │ │ └── proof.json │ │ ├── box_borrow_resolve │ │ │ └── proof.json │ │ ├── 641.coma │ │ ├── 570.rs │ │ ├── 235.coma │ │ ├── 691.coma │ │ ├── 168.coma │ │ ├── eq_panic │ │ │ └── proof.json │ │ ├── 1239.rs │ │ ├── 271.rs │ │ ├── 564.rs │ │ └── vcgen.rs │ ├── lang │ │ ├── empty.rs │ │ ├── unary_op.rs │ │ ├── literals.rs │ │ ├── unions.rs │ │ ├── move_path.rs │ │ ├── while_let.rs │ │ ├── multiple_scopes.rs │ │ ├── empty.coma │ │ ├── cast_ptr.rs │ │ ├── or_pat.rs │ │ ├── weak_opacity.rs │ │ ├── unsized_quant.rs │ │ ├── empty │ │ │ └── proof.json │ │ ├── or_pat │ │ │ └── proof.json │ │ ├── unary_op │ │ │ └── proof.json │ │ ├── unions │ │ │ └── proof.json │ │ ├── move_path │ │ │ └── proof.json │ │ ├── unsized_quant │ │ │ └── proof.json │ │ ├── while_let │ │ │ └── proof.json │ │ ├── unary_op.coma │ │ ├── assoc_type │ │ │ └── proof.json │ │ ├── module_paths │ │ │ └── proof.json │ │ ├── literals │ │ │ └── proof.json │ │ ├── multiple_scopes.coma │ │ ├── multiple_scopes │ │ │ └── proof.json │ │ ├── weak_opacity.coma │ │ ├── module_paths.rs │ │ ├── weak_opacity │ │ │ └── proof.json │ │ ├── cast_ptr │ │ │ └── proof.json │ │ └── unions.coma │ ├── std_types.rs │ ├── iterators │ │ ├── 04_skip │ │ │ └── why3shapes.gz │ │ ├── 05_map │ │ │ └── why3shapes.gz │ │ ├── 07_fuse │ │ │ └── why3shapes.gz │ │ ├── 09_empty │ │ │ └── why3shapes.gz │ │ ├── 17_filter │ │ │ └── why3shapes.gz │ │ └── 06_map_precond │ │ │ └── why3shapes.gz │ ├── immut.rs │ ├── syntax │ │ ├── 05_annotations.rs │ │ ├── 14_const_fns.rs │ │ ├── 08_const.rs │ │ ├── int_suffix.rs │ │ ├── 13_vec_macro.rs │ │ ├── 04_assoc_prec.rs │ │ ├── 11_array_types.rs │ │ ├── 14_const_fns │ │ │ └── proof.json │ │ ├── 05_annotations │ │ │ └── proof.json │ │ └── big_types │ │ │ └── proof.json │ ├── prophecy.rs │ ├── specification │ │ ├── division.rs │ │ ├── loops.rs │ │ ├── logic_call.rs │ │ ├── opaque │ │ │ └── proof.json │ │ ├── division │ │ │ └── proof.json │ │ ├── forall.rs │ │ ├── logic_call │ │ │ └── proof.json │ │ ├── loops │ │ │ └── proof.json │ │ ├── forall │ │ │ └── proof.json │ │ └── opaque.rs │ ├── closures │ │ ├── 02_nested.rs │ │ ├── 03_generic_bound.rs │ │ ├── 04_generic_closure.rs │ │ ├── 09_fnonce_resolve │ │ │ └── proof.json │ │ └── 12_borrow_instances │ │ │ └── proof.json │ ├── replace.rs │ ├── invariant_moves.rs │ ├── traits │ │ ├── 11 │ │ │ └── proof.json │ │ ├── 01.rs │ │ ├── 06.rs │ │ ├── 09.rs │ │ ├── 02.rs │ │ ├── 11.rs │ │ ├── 08.rs │ │ ├── 19_sealed.rs │ │ ├── 13_assoc_types.rs │ │ ├── 19_sealed │ │ │ └── proof.json │ │ ├── 16_impl_cloning.rs │ │ ├── 04.rs │ │ ├── 16_impl_cloning │ │ │ └── proof.json │ │ ├── 12_default_method.rs │ │ ├── 15_impl_interfaces │ │ │ └── proof.json │ │ ├── 07.rs │ │ ├── 15_impl_interfaces.coma │ │ ├── 14_assoc_in_logic.rs │ │ ├── 06 │ │ │ └── proof.json │ │ ├── 09 │ │ │ └── proof.json │ │ ├── 02 │ │ │ └── proof.json │ │ └── 01 │ │ │ └── proof.json │ ├── loop.rs │ ├── termination │ │ ├── warn_unneeded_variant.rs │ │ ├── recursion_logic.rs │ │ ├── call_in_contract.coma │ │ ├── call_in_contract.rs │ │ ├── warn_unneeded_variant.stderr │ │ ├── recursion_logic │ │ │ └── proof.json │ │ ├── call_in_contract │ │ │ └── proof.json │ │ ├── warn_unneeded_variant │ │ │ └── proof.json │ │ └── default_impl.rs │ ├── unnest.rs │ ├── one_side_update.rs │ ├── mc91.rs │ ├── resolve_drop.rs │ ├── vector │ │ ├── 07_read_write.rs │ │ ├── 09_capacity.rs │ │ └── 01.rs │ ├── switch_struct.rs │ ├── cc │ │ ├── arithmetic.rs │ │ ├── array.rs │ │ └── arithmetic │ │ │ └── proof.json │ ├── unused_in_loop.rs │ ├── slices │ │ ├── range.rs │ │ └── 02_std.rs │ ├── clones │ │ ├── 01.rs │ │ ├── 03.rs │ │ ├── 04.rs │ │ ├── 04 │ │ │ └── proof.json │ │ ├── 02 │ │ │ └── proof.json │ │ ├── 02.rs │ │ └── 02.coma │ ├── pair_bor_mut.rs │ ├── type_constructors.rs │ ├── sum.rs │ ├── simple_trigger.rs │ ├── cell │ │ └── 01_basic.rs │ ├── type_invariants │ │ ├── type_invariants.rs │ │ ├── vec_inv │ │ │ └── proof.json │ │ ├── generated │ │ │ └── proof.json │ │ ├── type_invariants │ │ │ └── proof.json │ │ ├── quant.rs │ │ ├── vec_inv.rs │ │ └── quant │ │ │ └── proof.json │ ├── immut │ │ └── proof.json │ ├── loop │ │ └── proof.json │ ├── prophecy │ │ └── proof.json │ ├── two_modules.rs │ ├── match_int │ │ └── proof.json │ ├── resolve_drop │ │ └── proof.json │ ├── std_types │ │ └── proof.json │ ├── one_side_update │ │ └── proof.json │ ├── spec_tests.rs │ ├── type_constructors │ │ └── proof.json │ ├── ghost │ │ ├── disjoint_raw_ptr.rs │ │ ├── loop_in_ghost.rs │ │ └── loop_in_ghost │ │ │ └── proof.json │ ├── match_int.rs │ ├── mc91 │ │ └── proof.json │ ├── resource_algebras │ │ ├── agree.rs │ │ └── excl.rs │ ├── fmap_indexing │ │ └── proof.json │ ├── replace │ │ └── proof.json │ ├── unnest │ │ └── proof.json │ ├── mapping_indexing │ │ └── proof.json │ ├── switch.rs │ ├── type_constructors.coma │ ├── fmap_indexing.rs │ ├── pair_bor_mut │ │ └── proof.json │ ├── unused_in_loop │ │ └── proof.json │ ├── arc_and_rc.rs │ ├── std_types.coma │ ├── partially_opaque │ │ └── proof.json │ ├── swap_borrows.rs │ ├── simple_trigger │ │ └── proof.json │ ├── printing.rs │ ├── all_zero │ │ └── proof.json │ ├── projection_toggle.rs │ ├── trigger.rs │ ├── trigger │ │ └── proof.json │ └── trigger2.rs └── should_fail │ ├── infinite_size.rs │ ├── zst │ └── why3shapes.gz │ ├── bug │ ├── 222 │ │ └── why3shapes.gz │ ├── 492 │ │ └── why3shapes.gz │ ├── 692 │ │ └── why3shapes.gz │ ├── 695 │ │ └── why3shapes.gz │ ├── 869 │ │ └── why3shapes.gz │ ├── 878 │ │ └── why3shapes.gz │ ├── 1204 │ │ └── why3shapes.gz │ ├── 1496.rs │ ├── specialize │ │ └── why3shapes.gz │ ├── subregion │ │ └── why3shapes.gz │ ├── 01_resolve_unsoundness │ │ └── why3shapes.gz │ ├── 1439.rs │ ├── 603.rs │ ├── 211.rs │ ├── 1762.stderr │ ├── 1439.stderr │ ├── 436_0.stderr │ ├── 1762.rs │ ├── 1496.stderr │ ├── 436_2.stderr │ ├── 436_1.stderr │ ├── borrowed_ghost.stderr │ ├── 773.stderr │ ├── 400.rs │ ├── ice-final-borrows.rs │ ├── 1565.rs │ ├── 1204.rs │ ├── 436_1.rs │ ├── 436_0.rs │ ├── 1565.stderr │ ├── 492.rs │ ├── subregion.rs │ ├── 400.stderr │ ├── borrowed_ghost.rs │ ├── 459.rs │ ├── 1204.stderr │ ├── 436_2.rs │ ├── 1610-crash.rs │ └── ice-final-borrows.stderr │ ├── impl_trait │ └── why3shapes.gz │ ├── const_default │ └── why3shapes.gz │ ├── final_borrows │ └── why3shapes.gz │ ├── ignore_overflow │ └── why3shapes.gz │ ├── wrong_permissions │ └── why3shapes.gz │ ├── generic_deref_ghost │ └── why3shapes.gz │ ├── generic_deref_snap │ └── why3shapes.gz │ ├── opaque_unproveable │ └── why3shapes.gz │ ├── unsupported │ ├── 1827 │ │ ├── test2.rs │ │ ├── test3.rs │ │ ├── test1.stderr │ │ ├── test2.stderr │ │ ├── test4.rs │ │ ├── test3.stderr │ │ ├── test4.stderr │ │ └── test1.rs │ ├── hash_map │ │ └── why3shapes.gz │ ├── macros.rs │ ├── char_pattern.rs │ ├── char_pattern.stderr │ └── macros.stderr │ ├── traits │ └── 17_impl_refinement │ │ └── why3shapes.gz │ ├── type_invariants │ ├── borrows │ │ └── why3shapes.gz │ └── partial_instance │ │ └── why3shapes.gz │ ├── non_bool_assertion.rs │ ├── terminates │ ├── incorrect_variant │ │ └── why3shapes.gz │ ├── invalid_variant_type.rs │ ├── simple_recursion.rs │ ├── terminates-calls-nonterminate.rs │ ├── terminates-calls-nonterminate.stderr │ ├── recursion_with_substitution.stderr │ ├── loops_in_terminates.rs │ ├── mutual_recursion.rs │ ├── default_function_non_logic.rs │ ├── simple_recursion.stderr │ ├── mutual_recursion_trait.rs │ ├── trait_def_and_impl_disagree.rs │ ├── default_function_non_open.rs │ ├── default_function_non_logic.stderr │ ├── recursion_through_contract.rs │ └── complicated_traits_recursion.rs │ ├── ghost │ ├── capture_non_copy_data.rs │ ├── create_in_program.rs │ ├── mutate_in_program.rs │ ├── mutate_in_program.stderr │ ├── non_ghost.stderr │ ├── non_ghost.rs │ ├── create_in_program.stderr │ ├── non_terminating.rs │ ├── capture_non_copy_data.stderr │ └── deref_in_program.rs │ ├── tokens_new_not_in_main.rs │ ├── bad_borrow.rs │ ├── unsafe.rs │ ├── builtin_with_contract.rs │ ├── dead_term.stderr │ ├── ignore_overflow.rs │ ├── result_param.rs │ ├── bad_law.rs │ ├── result_param.stderr │ ├── cycle.rs │ ├── inexhaustive_match.rs │ ├── logic_prophetic_impl.stderr │ ├── opaque.stderr │ ├── alloc_max_size.rs │ ├── impure_functions.rs │ ├── duplicate_specs.stderr │ ├── diagnostics │ ├── div_unimplemented.rs │ ├── rem_unimplemented.rs │ ├── index_unimplemented.rs │ └── view_unimplemented.rs │ ├── alloc_max_size.stderr │ ├── logic_prophetic_impl.rs │ ├── builtin_with_contract.stderr │ ├── dead_term.rs │ ├── tokens_new_not_in_main.stderr │ ├── const_default.rs │ ├── array.stderr │ ├── lints │ └── contractless_external_function.rs │ ├── generic_deref_ghost.rs │ ├── generic_deref_snap.rs │ ├── opaque_unproveable.coma │ ├── sealed.stderr │ ├── array.rs │ ├── opaque_unproveable.rs │ ├── trait_item_types_mismatch.rs │ ├── unsafe.stderr │ ├── non_bool_assertion.stderr │ ├── impure_functions.stderr │ ├── bad_law.stderr │ ├── opaque.rs │ ├── cycle.stderr │ ├── duplicate_specs.rs │ ├── const_default.coma │ ├── sealed.rs │ ├── impl_trait.rs │ ├── bad_borrow.stderr │ ├── unsound_dyn.stderr │ ├── trait_item_types_mismatch.stderr │ └── unsound_dyn.rs ├── rust-toolchain ├── ci └── html │ ├── header.html │ └── postscript.html ├── creusot-contracts ├── src │ ├── cell.rs │ └── std │ │ ├── cell.rs │ │ └── convert.rs └── tests │ └── compile_test.rs ├── fmt ├── .vscode └── settings.json ├── exercises ├── 03_division.rs ├── 01_sum.rs └── 04_all_zero.rs ├── .gitattributes ├── prelude-generator └── Cargo.toml ├── creusot-dev-config └── Cargo.toml ├── creusot-contracts-proc └── src │ └── creusot │ └── derive.rs ├── why3 ├── src │ └── lib.rs └── README.md ├── ide ├── nix ├── z3.nix ├── alt-ergo.nix └── default.nix ├── creusot ├── src │ └── contracts_items.rs └── messages.ftl ├── creusot-args └── Cargo.toml ├── creusot-setup └── Cargo.toml ├── INSTALL ├── creusot-install └── Cargo.toml ├── rustfmt.toml ├── creusot-metadata └── Cargo.toml └── .gitignore /guide/.gitignore: -------------------------------------------------------------------------------- 1 | book/ 2 | -------------------------------------------------------------------------------- /pearlite-syn/tests/debug.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /static/marteau.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/static/marteau.jpg -------------------------------------------------------------------------------- /tests/creusot-contracts/creusot-contracts.rs: -------------------------------------------------------------------------------- 1 | // dummy file, read during the `why3` test 2 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/789.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn meta(_x: usize) {} 4 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/empty.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f() { 4 | return; 5 | } 6 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "nightly-2025-11-13" 3 | components = [ "rustfmt", "rustc-dev", "llvm-tools" ] 4 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/02_derive.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | #[derive(Clone)] 4 | pub struct Lit {} 5 | -------------------------------------------------------------------------------- /ci/html/header.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /guide/src/images/why3-ide-ensures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/guide/src/images/why3-ide-ensures.png -------------------------------------------------------------------------------- /guide/src/images/why3-ide-startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/guide/src/images/why3-ide-startup.png -------------------------------------------------------------------------------- /tests/should_fail/infinite_size.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | struct Node2(Tree2); 4 | struct Tree2(Node2); 5 | -------------------------------------------------------------------------------- /tests/should_fail/zst/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/zst/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/222/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/222/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/492/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/492/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/692/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/692/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/695/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/695/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/869/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/869/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/878/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/878/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/bug/168.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn max_int() -> usize { 4 | usize::MAX 5 | } 6 | -------------------------------------------------------------------------------- /pearlite-syn/src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | pub(crate) mod macros; 3 | pub(crate) mod print; 4 | 5 | pub mod term; 6 | pub use term::*; 7 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1204/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/1204/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/impl_trait/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/impl_trait/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/bug/528.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn neq(a: bool, b: bool) -> bool { 4 | a != b 5 | } 6 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/258.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn err(_to: usize) {} 4 | 5 | pub fn err2(_bbb: usize) {} 6 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/693.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f(_: IfC) {} 4 | 5 | pub fn g() { 6 | f(0) 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1496.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn foo(x: *const T) -> &'static T { 4 | unsafe { &*x } 5 | } 6 | -------------------------------------------------------------------------------- /tests/should_fail/bug/specialize/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/specialize/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/bug/subregion/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/subregion/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/const_default/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/const_default/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/final_borrows/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/final_borrows/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/ignore_overflow/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/ignore_overflow/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/std_types.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub struct MyType(pub Option); 4 | 5 | pub fn x(_x: MyType) {} 6 | -------------------------------------------------------------------------------- /tests/should_fail/wrong_permissions/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/wrong_permissions/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/generic_deref_ghost/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/generic_deref_ghost/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/generic_deref_snap/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/generic_deref_snap/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/opaque_unproveable/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/opaque_unproveable/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/unsupported/hash_map/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/unsupported/hash_map/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/iterators/04_skip/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/04_skip/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/iterators/05_map/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/05_map/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/iterators/07_fuse/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/07_fuse/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/bug/269.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic(open)] 6 | pub fn my_lemma() {} 7 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/791.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn i_love_floats() { 4 | let _ = 0.000001; 5 | let _: f64 = 1e-320; 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_succeed/iterators/09_empty/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/09_empty/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/iterators/17_filter/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/17_filter/why3shapes.gz -------------------------------------------------------------------------------- /creusot-contracts/src/cell.rs: -------------------------------------------------------------------------------- 1 | //! Interior mutability 2 | 3 | mod permcell; 4 | mod predcell; 5 | 6 | pub use permcell::PermCell; 7 | pub use predcell::PredCell; 8 | -------------------------------------------------------------------------------- /tests/creusot-contracts/creusot-contracts/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/creusot-contracts/creusot-contracts/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/traits/17_impl_refinement/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/traits/17_impl_refinement/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/type_invariants/borrows/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/type_invariants/borrows/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/immut.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f() { 4 | let mut a = 10; 5 | let b = &mut a; 6 | let _c: &u32 = b; 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_fail/bug/01_resolve_unsoundness/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/bug/01_resolve_unsoundness/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/non_bool_assertion.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | fn main() { 5 | proof_assert! { 1 }; 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_succeed/iterators/06_map_precond/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_succeed/iterators/06_map_precond/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/terminates/incorrect_variant/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/terminates/incorrect_variant/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_fail/unsupported/macros.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(open)] 5 | pub fn f() { 6 | panic!() 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/minus_assoc.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[ensures(0 - (1 - 1) == 0)] 6 | pub fn f() {} 7 | -------------------------------------------------------------------------------- /fmt: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | SCRIPTPATH=$(dirname "$BASH_SOURCE") 6 | pushd $SCRIPTPATH > /dev/null 7 | rustfmt $@ $(git ls-files '*.rs') 8 | popd > /dev/null 9 | -------------------------------------------------------------------------------- /tests/should_fail/type_invariants/partial_instance/why3shapes.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creusot-rs/creusot/HEAD/tests/should_fail/type_invariants/partial_instance/why3shapes.gz -------------------------------------------------------------------------------- /tests/should_succeed/bug/1337.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | #[derive(Debug)] 4 | pub enum T { 5 | A { x: i8, y: i8 }, 6 | B(i8, i8, i8, i8, i8, i8), 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/395.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn signed_division() { 4 | let x = 10; 5 | let y = 1; 6 | 7 | assert!(x / y == 10); 8 | } 9 | -------------------------------------------------------------------------------- /guide/book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | authors = ["The Creusot Contributors"] 3 | language = "en" 4 | src = "src" 5 | title = "Creusot User Guide" 6 | 7 | [output.html.playground] 8 | runnable = false -------------------------------------------------------------------------------- /tests/should_succeed/bug/545.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn negative_is_negative() { 5 | proof_assert!(0 > -100); 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/793.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(x@ < u32::MAX@ / 1)] 5 | pub fn div_err(f: f64, x: u32) {} 6 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unary_op.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | // Simple check that unary operators can be translated 4 | pub fn f() { 5 | assert!(!false); 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1439.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub enum Empty {} 5 | 6 | #[requires(match empty { })] 7 | pub fn foo(empty: Empty) {} 8 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/capture_non_copy_data.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn capture_non_copy_data(v: Vec) { 5 | ghost!(v); 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/create_in_program.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn create_ghost_in_program() { 5 | let _g = Ghost::new(1); 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_fail/tokens_new_not_in_main.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::ghost::local_invariant::Tokens; 3 | 4 | pub fn foo() { 5 | let _ = Tokens::new(); 6 | } 7 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/char_pattern.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn char_match_bad(x: char) { 4 | match x { 5 | 'a' => (), 6 | _ => (), 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/05_annotations.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub fn assertion(x: T) { 6 | proof_assert! { x == x }; 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_fail/bad_borrow.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | fn bad_borrow() { 4 | let mut x = 0; 5 | let a = &mut x; 6 | let b = &mut x; 7 | 8 | *a += *b; 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/prophecy.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f() { 4 | let mut x = 0; 5 | let y = &mut x; 6 | 7 | // assert ^y = 5 8 | 9 | *y = 5; 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/14_const_fns.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(x@ == 3)] 5 | pub const fn omg(x: i32) -> i32 { 6 | x - 1 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "rust-analyzer.rustc.source": "discover", 3 | "rust-analyzer.diagnostics.disabled": [ 4 | "unresolved-proc-macro", 5 | "unresolved-extern-crate" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_fail/unsafe.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | unsafe fn evil() {} 5 | 6 | #[ensures(true)] 7 | pub fn main() { 8 | evil(); 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/195.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | #[requires(_example_parameter == _example_parameter)] 4 | pub fn example(_example_parameter: bool) {} 5 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/256.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn u8_safe(u: u8) { 4 | let _ = u + 0; 5 | } 6 | // `String` includes `u8` internally. 7 | // 8 | pub fn bug_256(_x: String) {} 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/273.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn ex() { 5 | if let Some(b) = Some(true) { 6 | proof_assert!(b); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/510.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn test_bool(inp: bool) { 4 | let _bing = inp as u8; 5 | } 6 | 7 | pub fn test_char() { 8 | 22 as char; 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/literals.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn float_operation() -> f32 { 4 | let x: f32 = 0.0; 5 | 6 | if x + 1.0005 == 2.0 { 3.0 - 1.0 } else { 0.0 } 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/08_const.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::Seq, prelude::*}; 3 | 4 | #[logic(open)] 5 | pub fn omg() -> Seq { 6 | Seq::empty() 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/int_suffix.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(*result == 1int)] 5 | pub fn foo() -> Ghost { 6 | ghost!(1int) 7 | } 8 | -------------------------------------------------------------------------------- /exercises/03_division.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Implement and prove the Euclidean division 5 | fn divide(u: i64, b: i64) -> i64 { 6 | todo!() 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/mutate_in_program.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn mutate_ghost_in_program() { 5 | let mut g = ghost!(2); 6 | *g = 3; 7 | } 8 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/division.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[requires(x != 0u32)] 6 | pub fn divide(y: u32, x: u32) -> u32 { 7 | y / x 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_fail/bug/603.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub struct S(); 4 | 5 | impl Iterator for S { 6 | type Item = (); 7 | fn next(&mut self) -> Option<()> { 8 | None 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/char_pattern.stderr: -------------------------------------------------------------------------------- 1 | error: match on char is currently unsupported 2 | --> char_pattern.rs:4:5 3 | | 4 | 4 | match x { 5 | | ^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/235.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub fn f() { 6 | #[invariant(0 <= 1)] 7 | #[allow(while_true)] 8 | while true {} 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/loops.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(!x)] 5 | pub fn while_loop_variant(x: bool) { 6 | #[variant(0)] 7 | while x {} 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_fail/builtin_with_contract.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic] 5 | #[ensures(true && false)] 6 | #[builtin("dummy_function")] 7 | pub fn builtin_with_contract() {} 8 | -------------------------------------------------------------------------------- /tests/should_succeed/closures/02_nested.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn nested_closure() { 4 | let a = true; 5 | let _a = (|| { 6 | let omg = || a; 7 | (omg)() 8 | })(); 9 | } 10 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | creusot/tests/**/*.coma linguist-generated=true 2 | creusot/tests/**/why3session.xml linguist-generated=true 3 | creusot/tests/**/why3shapes.gz linguist-generated=true 4 | creusot/tests/**/proof.json linguist-generated=true 5 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/mutate_in_program.stderr: -------------------------------------------------------------------------------- 1 | error: dereference of a ghost variable in program context 2 | --> mutate_in_program.rs:6:5 3 | | 4 | 6 | *g = 3; 5 | | ^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/797.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::Mapping, prelude::*}; 3 | 4 | #[logic(open)] 5 | pub fn make_mapping() -> Mapping<(Int, Int), bool> { 6 | |(x, y)| x + y == 0 7 | } 8 | -------------------------------------------------------------------------------- /guide/src/representation_of_types.md: -------------------------------------------------------------------------------- 1 | # Representation of types 2 | 3 | Creusot translates Rust code to Why3. But Rust types don't always exist in Why3, and would not have the same semantics: thus we need to map each Rust type to a Why3 type. 4 | -------------------------------------------------------------------------------- /prelude-generator/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "prelude-generator" 3 | version.workspace = true 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | creusot-setup = { path = "../creusot-setup" } 9 | anyhow = "1.0" 10 | -------------------------------------------------------------------------------- /tests/should_fail/bug/211.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub enum E { 4 | A, 5 | B, 6 | C, 7 | } 8 | 9 | struct S(E); 10 | 11 | fn ex(s: S) { 12 | match s.0 { 13 | E::A => {} 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_fail/dead_term.stderr: -------------------------------------------------------------------------------- 1 | error: The `dead` term can only be used for the body of `logic(opaque)` functions 2 | --> dead_term.rs:11:5 3 | | 4 | 11 | dead 5 | | ^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/ignore_overflow.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | #![allow(unused)] 3 | 4 | extern crate creusot_contracts; 5 | use creusot_contracts::prelude::*; 6 | 7 | pub fn f(x: u32, y: u32) { 8 | const { N + 1 }; 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/result_param.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Should fail saying result is not a valid parameter name 5 | #[ensures(result == result)] 6 | pub fn result_arg(result: u32) {} 7 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/invalid_variant_type.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | struct S; 5 | 6 | pub fn foo() { 7 | let x = S; 8 | #[variant(x)] 9 | while true {} 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/replace.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub struct Something { 4 | pub a: u32, 5 | pub b: Option>, 6 | } 7 | 8 | pub fn test(mut _a: Something, b: Something) { 9 | _a = b; 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/non_ghost.stderr: -------------------------------------------------------------------------------- 1 | error: called non-ghost function `terminating` in ghost context 2 | --> non_ghost.rs:9:9 3 | | 4 | 9 | terminating(); 5 | | ^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/653.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | #![no_std] 4 | extern crate creusot_contracts; 5 | use creusot_contracts::prelude::*; 6 | 7 | #[ensures(result@ == n@ * (n@ + 1) / 2)] 8 | pub fn omg(n: usize) -> usize { 9 | n 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/closures/03_generic_bound.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | extern crate creusot_contracts; 4 | 5 | fn closure_param(f: F) { 6 | (f)(0) 7 | } 8 | 9 | pub fn caller() { 10 | closure_param(|_x: u32| ()) 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/invariant_moves.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub fn test_invariant_move(mut x: Vec) { 6 | #[invariant(x == x)] 7 | while let Some(_) = { (&mut x).pop() } {} 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/01.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | // Broken because of trait generics 4 | pub trait A { 5 | fn from_b(x: Self) -> B; 6 | } 7 | 8 | pub fn uses_generic(b: T) -> u32 { 9 | A::from_b(b) 10 | } 11 | -------------------------------------------------------------------------------- /creusot-dev-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "creusot-dev-config" 3 | version.workspace = true 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | creusot-setup = { path = "../creusot-setup" } 9 | anyhow = "1.0" 10 | which = "7.0" 11 | -------------------------------------------------------------------------------- /tests/should_fail/bad_law.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait BadLaw { 5 | #[logic(law)] 6 | fn my_law(x: T); 7 | } 8 | 9 | impl BadLaw for () { 10 | fn my_law(_: T) {} 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_fail/result_param.stderr: -------------------------------------------------------------------------------- 1 | error: `result` is not allowed as a parameter name 2 | --> result_param.rs:6:1 3 | | 4 | 6 | pub fn result_arg(result: u32) {} 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1504.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(match result { 5 | Some(true) => true, 6 | _ => false, 7 | })] 8 | pub fn h() -> Option { 9 | Some(true) 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/486.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct HasMutRef<'a, T>(pub &'a mut T); 5 | 6 | #[ensures((^x.0)@ == 5)] 7 | pub fn test(x: HasMutRef<'_, u32>) { 8 | *x.0 = 5 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1762.stderr: -------------------------------------------------------------------------------- 1 | error: called program function `faux` in logic context 2 | --> 1762.rs:10:12 3 | | 4 | 10 | #[requires(faux())] // program function called in logic 5 | | ^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/simple_recursion.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[check(terminates)] 6 | fn recurses(b: bool) { 7 | if b { 8 | recurses(!b); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/terminates-calls-nonterminate.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[check(terminates)] 6 | fn i_terminate() { 7 | i_dont(); 8 | } 9 | 10 | fn i_dont() {} 11 | -------------------------------------------------------------------------------- /tests/should_fail/cycle.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(open)] 5 | pub fn f() { 6 | g(true); 7 | } 8 | 9 | #[logic(open)] 10 | pub fn g(x: bool) { 11 | if x { 12 | f(); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/non_ghost.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[check(terminates)] 5 | fn terminating() {} 6 | 7 | pub fn calls_terminating() { 8 | ghost! { 9 | terminating(); 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_fail/inexhaustive_match.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | enum Option { 4 | Some(T), 5 | None, 6 | } 7 | use Option::*; 8 | 9 | fn inexhaustive_match(x: Option<()>) { 10 | match x { 11 | None => (), 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/logic_prophetic_impl.stderr: -------------------------------------------------------------------------------- 1 | error: Expected `f` to be a logic function as specified by the trait declaration 2 | --> logic_prophetic_impl.rs:11:5 3 | | 4 | 11 | fn f() { 5 | | ^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1030.coma: -------------------------------------------------------------------------------- 1 | module M_test 2 | constant new: () = () 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | function test : () 9 | 10 | goal vc_test: [@expl:test ensures] new = new 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/eq_panic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Verifies that the inherited spec for PartialEq can actually be used 5 | 6 | pub fn omg(x: &T, y: &T) -> bool { 7 | x == y 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/pure_neq.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::Int, prelude::*}; 3 | 4 | #[logic(open)] 5 | #[ensures(result == !(x == y))] 6 | pub fn f(x: Option, y: Option) -> bool { 7 | pearlite! { x != y } 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1439.stderr: -------------------------------------------------------------------------------- 1 | error: Empty matches are forbidden in Pearlite, because Why3 types are always inhabited. 2 | --> 1439.rs:6:12 3 | | 4 | 6 | #[requires(match empty { })] 5 | | ^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_0.stderr: -------------------------------------------------------------------------------- 1 | error: called prophetic logic function `prophecy` in logic context 2 | --> 436_0.rs:15:23 3 | | 4 | 15 | b.g = snapshot! { prophecy(b) + 1 }; 5 | | ^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/loop.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f() { 4 | let mut a = 10; 5 | let b = &mut a; 6 | *b = 5; 7 | loop { 8 | if true { 9 | break; 10 | } 11 | } 12 | let _ = a == 15; 13 | } 14 | -------------------------------------------------------------------------------- /creusot-contracts-proc/src/creusot/derive.rs: -------------------------------------------------------------------------------- 1 | mod clone; 2 | mod deep_model; 3 | mod default; 4 | mod partial_eq; 5 | 6 | pub use clone::derive_clone; 7 | pub use deep_model::derive_deep_model; 8 | pub use default::derive_default; 9 | pub use partial_eq::derive_partial_eq; 10 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1762.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[check(ghost)] 5 | pub fn faux() -> bool { 6 | false 7 | } 8 | 9 | #[trusted] 10 | #[requires(faux())] // program function called in logic 11 | pub fn f() {} 12 | -------------------------------------------------------------------------------- /tests/should_fail/opaque.stderr: -------------------------------------------------------------------------------- 1 | error: Cannot make `"x::priv_symbol"` transparent in `"x::bad"` as it would call a less-visible item. 2 | --> opaque.rs:16:9 3 | | 4 | 16 | priv_symbol() 5 | | ^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test2.rs: -------------------------------------------------------------------------------- 1 | use creusot_contracts::prelude::*; 2 | 3 | #[logic] 4 | fn is_zero(v: Option) -> Int { 5 | pearlite! { 6 | match v { 7 | Some(0) => 1, 8 | None => 0, 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/box_borrow_resolve.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Check that the borrow inside `x` is resolved. 5 | #[ensures(result == *x)] 6 | pub fn borrow_in_box(x: Box<&mut i32>) -> &mut i32 { 7 | &mut **x 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/06.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub trait Ix { 4 | type Tgt; 5 | 6 | fn ix(&self, ix: usize) -> Self::Tgt; 7 | } 8 | 9 | pub fn test(a: &T) -> T::Tgt 10 | where 11 | T::Tgt: Eq, 12 | { 13 | a.ix(0) 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/09.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub trait Tr { 4 | type X; 5 | } 6 | 7 | pub fn test>(t: T::X) -> u32 { 8 | t + 0 9 | } 10 | 11 | pub fn test2>(t: T::X) -> U::X { 12 | t 13 | } 14 | -------------------------------------------------------------------------------- /why3/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(alloc_slice_into_array)] 2 | 3 | pub mod ce_models; 4 | pub mod coma; 5 | pub mod declaration; 6 | pub mod exp; 7 | pub mod name; 8 | pub mod printer; 9 | pub mod ty; 10 | 11 | pub use exp::Exp; 12 | pub use name::{Ident, Name, QName, Symbol}; 13 | -------------------------------------------------------------------------------- /ide: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | SCRIPTPATH=$(cd $(dirname "$BASH_SOURCE") && pwd) 4 | eval $(cargo run --bin dev-env) 5 | why3 \ 6 | --warn-off=unused_variable --warn-off=clone_not_abstract --warn-off=axiom_abstract \ 7 | --debug=coma_no_trivial \ 8 | ide -L "$SCRIPTPATH"/target $@ 9 | -------------------------------------------------------------------------------- /nix/z3.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | version, 4 | sha256, 5 | }: 6 | pkgs.z3.overrideAttrs { 7 | inherit version; 8 | 9 | src = pkgs.fetchFromGitHub { 10 | owner = "Z3Prover"; 11 | repo = "z3"; 12 | rev = "z3-${version}"; 13 | hash = sha256; 14 | }; 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_fail/alloc_max_size.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(false)] 5 | pub fn main() { 6 | ghost! { 7 | let x = [0usize; usize::MAX]; 8 | let _ = std::mem::size_of_val(&x); 9 | }; 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/impure_functions.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::*, prelude::*}; 3 | 4 | #[logic] 5 | fn x(v: &Vec) -> Int { 6 | pearlite! { v.len()@ } 7 | } 8 | 9 | pub fn y() { 10 | let _ = x(&Vec::<()>::new()); 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/terminates-calls-nonterminate.stderr: -------------------------------------------------------------------------------- 1 | error: called program function `i_dont` in program (terminates) context 2 | --> terminates-calls-nonterminate.rs:7:5 3 | | 4 | 7 | i_dont(); 5 | | ^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/265.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(open)] 5 | pub fn bool_to_bool(b: bool) -> bool { 6 | b 7 | } 8 | 9 | #[logic(open)] 10 | pub fn ex() { 11 | pearlite! { bool_to_bool(!true) }; 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/closures/04_generic_closure.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | extern crate creusot_contracts; 4 | 5 | fn generic_closure B>(f: F, a: A) -> B { 6 | f(a) 7 | } 8 | 9 | pub fn mapper(x: A) { 10 | let _ = generic_closure(|_a| (), x); 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1496.stderr: -------------------------------------------------------------------------------- 1 | error: Dereference of a raw pointer is forbidden in creusot: use `creusot_contracts::ghost::perm::Perm<*const T>` instead 2 | --> 1496.rs:4:14 3 | | 4 | 4 | unsafe { &*x } 5 | | ^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_2.stderr: -------------------------------------------------------------------------------- 1 | error: encountered a cycle during translation: Bad::None['_]; creusot_contracts::snapshot::Snapshot<&mut Bad<'_>>; Bad<'_>; Bad::Some['_]; 2 | --> 436_2.rs:5:5 3 | | 4 | 5 | None, 5 | | ^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/duplicate_specs.stderr: -------------------------------------------------------------------------------- 1 | error: duplicate extern specification for std::vec::Vec::::new 2 | --> duplicate_specs.rs:10:17 3 | | 4 | 10 | fn new() -> Vec; 5 | | ^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/macros.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: macros other than `pearlite!`, `proof_assert!` or `seq!` are unsupported in Pearlite code. 2 | --> macros.rs:6:5 3 | | 4 | 6 | panic!() 5 | | ^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1342.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::FSet, prelude::*}; 3 | 4 | #[logic(open)] 5 | #[variant(fset.len())] 6 | pub fn bar(fset: FSet) -> FSet { 7 | if fset.is_empty() { FSet::empty() } else { bar(FSet::empty()) } 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/691.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct Foo { 5 | bar: u32, 6 | } 7 | 8 | pub fn example() { 9 | let c = Foo { bar: 2u32 }; 10 | let _ = #[requires (c.bar == 2u32)] 11 | || (); 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unions.rs: -------------------------------------------------------------------------------- 1 | // Checks that unions don't cause a crash 2 | // FIXME: this is unsound, of course. 3 | 4 | extern crate creusot_contracts; 5 | 6 | pub union DummyUnion { 7 | _field1: usize, 8 | _field2: isize, 9 | } 10 | 11 | pub fn x(_: DummyUnion) {} 12 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/warn_unneeded_variant.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[variant(x)] 5 | pub fn variant_is_not_checked(x: u32) { 6 | if x != 0 { 7 | variant_is_not_checked(x); // Whoops 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_1.stderr: -------------------------------------------------------------------------------- 1 | error: called prophetic logic function `<&mut T as creusot_contracts::logic::ops::Fin>::fin` in logic context 2 | --> 436_1.rs:10:19 3 | | 4 | 10 | pearlite! { *(^x).g } 5 | | ^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/diagnostics/div_unimplemented.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | fn division(x: i32, y: i32) -> i32 { 7 | // FIXME(diagnostics): Why is the error reported twice? 8 | x / y 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/diagnostics/rem_unimplemented.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | fn remainder(x: i32, y: i32) -> i32 { 7 | // FIXME(diagnostics): Why is the error reported twice? 8 | x % y 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1312.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn foo99() -> impl Fn(Option) -> i32 { 4 | let _my_closure = |x: Option| match x { 5 | Some(y) => y, 6 | None => unreachable!("unwrapped None"), 7 | }; 8 | _my_closure 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/641.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(open)] 5 | pub fn test_law() {} 6 | 7 | #[logic(open)] 8 | pub fn test() -> bool { 9 | true 10 | } 11 | 12 | #[maintains(test())] 13 | pub fn test_maintains() {} 14 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/move_path.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn f() { 4 | let mut x = 1; 5 | 6 | let y = &mut x; 7 | let d = y; 8 | let z = d; 9 | 10 | let _ = *z = 2; 11 | 12 | // assert_eq!(x, 2); 13 | 14 | let _ = x == 2; 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/unnest.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[ensures(*result == **x)] 6 | #[ensures(^result == *^x)] 7 | #[ensures(^*x == ^^x)] 8 | pub fn unnest<'a, 'b: 'a>(x: &'a mut &'b mut u32) -> &'a mut u32 { 9 | *x 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/alloc_max_size.stderr: -------------------------------------------------------------------------------- 1 | error: called non-ghost function `std::mem::size_of_val` in ghost context 2 | --> alloc_max_size.rs:8:17 3 | | 4 | 8 | let _ = std::mem::size_of_val(&x); 5 | | ^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/logic_prophetic_impl.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait T { 5 | #[logic] 6 | fn f(); 7 | } 8 | 9 | impl T for () { 10 | #[logic(open(self), prophetic)] 11 | fn f() { 12 | () 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/nonreturning.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | fn f() -> ! { 6 | loop {} 7 | } 8 | 9 | #[allow(unreachable_code)] 10 | #[ensures(!b)] 11 | pub fn g(b: bool) { 12 | if b { 13 | f(); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/while_let.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn f() { 5 | let mut a = Some(10); 6 | let b = &mut a; 7 | 8 | #[invariant(true)] 9 | while let Some(_) = b { 10 | *b = None; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/one_side_update.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | struct MyInt(usize); 4 | 5 | pub fn f() { 6 | let mut a = MyInt(10); 7 | let b = &mut a; 8 | if true { 9 | let _ = a.0 == 10; 10 | } else { 11 | *b = MyInt(5); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/bug/borrowed_ghost.stderr: -------------------------------------------------------------------------------- 1 | error: Use of borrowed or uninitialized variable x 2 | --> borrowed_ghost.rs:7:22 3 | | 4 | 7 | *r = snapshot! { !x.inner() }; // r = (snapshot (not (inner x)), x) 5 | | ^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test3.rs: -------------------------------------------------------------------------------- 1 | use creusot_contracts::prelude::*; 2 | 3 | #[logic] 4 | pub fn has_zero(v: (Int, Int, Int)) -> Int { 5 | pearlite! { 6 | match v { 7 | (0, _, _) | (_, 0, _) | (_, _, 0) => 1, 8 | _ => 0 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/mc91.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[ensures(x <= 100u32 ==> result@ == 91 && 6 | x > 100u32 ==> result@ == x@ - 10)] 7 | pub fn mc91(x: u32) -> u32 { 8 | if x > 100 { x - 10 } else { mc91(mc91(x + 11)) } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/resolve_drop.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn f() { 5 | let mut x = 12; 6 | let b = Box::new(&mut x); 7 | **b += 1; 8 | proof_assert!(x@ == 13); 9 | // b is dropped here, but resolved earlier 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/bug/773.stderr: -------------------------------------------------------------------------------- 1 | error: Laws cannot have additional generic parameters or trait constraints 2 | --> 773.rs:13:5 3 | | 4 | 13 | / fn a(self) 5 | 14 | | where 6 | 15 | | Self: One; 7 | | |__________________^ 8 | 9 | error: aborting due to 1 previous error 10 | 11 | -------------------------------------------------------------------------------- /tests/should_fail/builtin_with_contract.stderr: -------------------------------------------------------------------------------- 1 | error: cannot specify both `creusot::builtin` and a contract on the same definition 2 | --> builtin_with_contract.rs:7:1 3 | | 4 | 7 | pub fn builtin_with_contract() {} 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/recursion_with_substitution.stderr: -------------------------------------------------------------------------------- 1 | error: Polymorphic recursion is not supported: recursive calls should have the same type parameters. 2 | --> recursion_with_substitution.rs:34:5 3 | | 4 | 34 | foo(0) 5 | | ^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/multiple_scopes.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | // make sure that local translation handles variable shadowing well 4 | pub fn multiple_scopes() { 5 | let mut _x = 1; 6 | let _y = 2; 7 | { 8 | let _y = 3; 9 | _x = _y; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/vector/07_read_write.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[requires(i@ < a@.len())] 6 | pub fn read_write(a: &mut Vec, i: usize, x: T) { 7 | a[i] = x; // a is slice 8 | assert!(a[i] == x); 9 | } 10 | -------------------------------------------------------------------------------- /nix/alt-ergo.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | version, 4 | sha256, 5 | }: 6 | pkgs.alt-ergo.overrideAttrs { 7 | inherit version; 8 | 9 | src = pkgs.fetchurl { 10 | url = "https://github.com/OCamlPro/alt-ergo/releases/download/v${version}/alt-ergo-${version}.tbz"; 11 | hash = sha256; 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/dead_term.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(opaque)] 5 | pub fn works() { 6 | dead 7 | } 8 | 9 | #[logic] 10 | pub fn fails1() { 11 | dead 12 | } 13 | 14 | #[trusted] 15 | #[logic] 16 | pub fn fails2() { 17 | dead 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_fail/tokens_new_not_in_main.stderr: -------------------------------------------------------------------------------- 1 | error: creusot_contracts::ghost::local_invariant::Tokens::<'_>::new can only be called in `main` 2 | --> tokens_new_not_in_main.rs:5:13 3 | | 4 | 5 | let _ = Tokens::new(); 5 | | ^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/217.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{ 4 | logic::{Int, Seq}, 5 | prelude::*, 6 | }; 7 | 8 | #[logic(open)] 9 | #[variant(c.len())] 10 | pub fn ex(c: Seq, a: Int) -> Int { 11 | if c.len() == 0 { 0 } else { ex(c.tail(), a) } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test1.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: Pattern matching literals on Int are unsupported by Pearlite. Consider using if-then-else instead. 2 | --> test1.rs:10:13 3 | | 4 | 10 | 0 => 0, 5 | | ^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/768.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct A { 5 | pub l: usize, 6 | pub r: usize, 7 | } 8 | 9 | impl A { 10 | #[logic(open)] 11 | pub fn with_l(self, l: usize) -> Self { 12 | A { l, ..self } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/recursion_logic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic] 5 | #[variant(x)] 6 | #[requires(x >= 0)] 7 | #[ensures(result == x)] 8 | pub fn variant_int(x: Int) -> Int { 9 | if x == 0 { 0 } else { 1 + variant_int(x - 1) } 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/02.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub trait A { 6 | #[ensures(result == true)] 7 | fn is_true(&self) -> bool; 8 | } 9 | 10 | #[ensures(result == true)] 11 | pub fn omg(a: T) -> bool { 12 | a.is_true() 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1538.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct Foo { 5 | bar: (), 6 | } 7 | 8 | #[logic] 9 | #[ensures(result == true)] 10 | pub fn baz(foo: Foo) -> bool { 11 | pearlite! { 12 | forall<_x: ()> foo.bar == () 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/463.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | pub fn test() { 4 | let c = { 5 | #[requires(x@ < 1000)] 6 | #[ensures(result@ == x@ + 1)] 7 | |x: usize| x + 1 8 | }; 9 | let y = c(2); 10 | proof_assert!(y@ == 3) 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/874.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::{vec, *}; 3 | 4 | pub fn can_extend() { 5 | let mut v = vec![1, 2, 3]; 6 | let w = vec![4, 5, 6]; 7 | v.extend(w); 8 | 9 | let z = vec![1, 2, 3, 4, 5, 6]; 10 | proof_assert!(z@.ext_eq(v@)); 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/logic_call.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | pub fn reflexive(x: T) -> bool { 7 | pearlite! { x == x } 8 | } 9 | 10 | #[ensures(reflexive(result))] 11 | pub fn dummy() -> u32 { 12 | 0 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test2.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: Pattern matching literals on Int are unsupported by Pearlite. Consider using if-then-else instead. 2 | --> test2.rs:7:13 3 | | 4 | 7 | Some(0) => 1, 5 | | ^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test4.rs: -------------------------------------------------------------------------------- 1 | use creusot_contracts::prelude::*; 2 | 3 | #[logic] 4 | pub fn has_zero(v: Option<(Option, Option)>) -> Int { 5 | pearlite! { 6 | match v { 7 | Some((Some(0), _)) | Some((_, Some(0))) => 1, 8 | _ => 0 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/call_in_contract.coma: -------------------------------------------------------------------------------- 1 | module M_impl_Foo_for_unit__g (* <() as Foo> *) 2 | constant f_unit: () = () 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | function g_unit : () 9 | 10 | goal vc_g_unit: [@expl:g ensures] f_unit = () 11 | end 12 | -------------------------------------------------------------------------------- /creusot/src/contracts_items.rs: -------------------------------------------------------------------------------- 1 | //! This modules groups together special items defined in [`creusot_contracts`]. 2 | //! 3 | //! This includes attributes like `#[creusot::logic]`, and intrinsics like `Snapshot`. 4 | 5 | mod attributes; 6 | mod intrinsics; 7 | 8 | pub(crate) use attributes::*; 9 | pub(crate) use intrinsics::*; 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1575.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Test handling of shifts by vcgen 5 | #[logic] 6 | #[requires(left@ < 8)] 7 | pub fn nth_bit_from_left_8(x: u8, left: usize) -> bool { 8 | let mask: u8 = 1u8 << (7usize - left); 9 | (x & mask) != 0u8 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1674.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn f(p: *const [usize]) { 5 | let q = p as *const usize; 6 | proof_assert!(p.addr_logic() == q.addr_logic()); 7 | let r = q as *const (); 8 | proof_assert!(q.addr_logic() == r.addr_logic()); 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1773.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub trait Tr { 4 | fn f(); 5 | 6 | fn g(x: [usize; N]) -> usize; 7 | } 8 | 9 | pub struct S; 10 | 11 | impl Tr<45> for S { 12 | fn f() {} 13 | 14 | fn g(x: [usize; 45]) -> usize { 15 | x.len() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/bug/400.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Tr { 5 | #[logic(law)] 6 | fn la(); 7 | 8 | #[logic] 9 | fn lo(); 10 | } 11 | 12 | impl Tr for () { 13 | #[logic] 14 | fn la() {} 15 | 16 | #[logic(law)] 17 | fn lo() {} 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/create_in_program.stderr: -------------------------------------------------------------------------------- 1 | error: cannot create a ghost variable in program context 2 | --> create_in_program.rs:5:14 3 | | 4 | 5 | let _g = Ghost::new(1); 5 | | ^^^^^^^^^^^^^ help: try wrapping this expression in `ghost!` instead: `ghost!(1)` 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1538.coma: -------------------------------------------------------------------------------- 1 | module M_baz 2 | type t_Foo = { bar: () } 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | constant foo : t_Foo 9 | 10 | predicate baz (foo: t_Foo) 11 | 12 | goal vc_baz: [@expl:baz ensures] (forall _x: (). foo.bar = ()) = true 13 | end 14 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/empty.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec f (return (x: ())) = (! bb0 9 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 10 | end 11 | -------------------------------------------------------------------------------- /tests/should_succeed/switch_struct.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub enum M { 4 | F { field1: u32 }, 5 | G { field2: T }, 6 | } 7 | 8 | pub fn test(o: M) -> bool { 9 | use M::*; 10 | match o { 11 | F { field1 } => field1 > 0, 12 | G { field2 } => field2 == 0, 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/call_in_contract.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Foo { 5 | #[logic] 6 | fn f() {} 7 | #[logic] 8 | fn g(); 9 | } 10 | 11 | impl Foo for () { 12 | #[logic] 13 | #[ensures(Self::f() == ())] 14 | fn g() {} 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/11.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic(open)] 6 | pub fn id(x: T) -> T { 7 | x 8 | } 9 | 10 | pub trait A { 11 | type T; 12 | 13 | #[ensures(id(x) == x)] 14 | fn f(x: Self::T); 15 | } 16 | 17 | pub fn test(_: T) {} 18 | -------------------------------------------------------------------------------- /ci/html/postscript.html: -------------------------------------------------------------------------------- 1 | 2 | 10 | -------------------------------------------------------------------------------- /tests/should_fail/diagnostics/index_unimplemented.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | struct S; 6 | 7 | // FIXME(diagnostics): the current desugaring of indexing does not yield a nice error message :( 8 | #[logic] 9 | fn indexing(x: S) { 10 | let _ = x[0]; 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1239.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | type tup2_Int_Int = { f0: int; f1: int } 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | function f : tup2_Int_Int 9 | 10 | goal vc_f: let x = 2 in let x'0 = 1 in [@expl:f ensures] { f0 = x'0; f1 = x } = { f0 = 1; f1 = 2 } 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/cc/arithmetic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::ops::NthBitLogic as _, prelude::*}; 3 | 4 | #[bitwise_proof] 5 | pub fn test() { 6 | proof_assert!(0u8.nth_bit(42) == false); 7 | proof_assert!(42u8.nth_bit(0) == false); 8 | proof_assert!(42u8.nth_bit(1) == true); 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/cast_ptr.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn f(p: *const T) { 5 | proof_assert!(p == (p as *mut T) as *const T) 6 | } 7 | 8 | #[ensures(result == p as *const T)] 9 | pub fn thin(p: *const [T]) -> *const T { 10 | p as *const T 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/unused_in_loop.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(result == 10u32)] 5 | pub fn unused_in_loop(b: bool) -> u32 { 6 | let x = 10; 7 | #[invariant(true)] 8 | loop { 9 | if b { 10 | break; 11 | } 12 | } 13 | x 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1410.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[warn(let_underscore_drop)] 5 | #[requires(f.precondition(()))] 6 | pub fn bar(mut f: F) { 7 | #[invariant(produced.len() == 0 ==> f.precondition(()))] 8 | for _ in 0..1 { 9 | f(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/or_pat.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic] 5 | #[ensures(x == (None, None) ==> result == 1i32)] 6 | pub fn f(x: (Option, Option)) -> i32 { 7 | match x { 8 | (Some(x), None) | (None, Some(x)) => x, 9 | _ => 1i32, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/slices/range.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(a@ == seq![0u32, 0u32, 0u32, 0u32])] 5 | #[ensures((^a)@ == seq![0u32, 1u32, 1u32, 0u32])] 6 | pub fn slice_range_inclusive(a: &mut [u32]) { 7 | let s = &mut a[1..=2]; 8 | s[0] = 1; 9 | s[1] = 1; 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/01.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | // The output should have `func2` cloning the interface of `func1` 3 | // but `func3` should only clone `func1` as its usage of `func1` is 4 | // internal. 5 | 6 | fn func1() {} 7 | 8 | fn func2() { 9 | func1() 10 | } 11 | 12 | pub fn func3() { 13 | func2() 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/weak_opacity.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic] 5 | #[ensures(result == 1)] 6 | fn f() -> Int { 7 | 1 8 | } 9 | 10 | #[logic(open)] 11 | #[ensures(result == 2)] 12 | pub fn g() -> Int { 13 | proof_assert!(f() == 1); 14 | let _ = f; 15 | 2 16 | } 17 | -------------------------------------------------------------------------------- /creusot-contracts/src/std/cell.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use std::cell::*; 3 | 4 | extern_spec! { 5 | impl UnsafeCell { 6 | #[check(ghost)] 7 | fn new(value: T) -> UnsafeCell; 8 | } 9 | 10 | impl UnsafeCell { 11 | #[check(ghost)] 12 | fn get(&self) -> *mut T; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /creusot/messages.ftl: -------------------------------------------------------------------------------- 1 | creusot_contractless_external_function = 2 | calling external function `{$name}` with no contract will yield an impossible precondition 3 | .label = function called here 4 | creusot_trusted_code = 5 | used the `#[trusted]` attribute 6 | creusot_dyn_experimental = 7 | support for trait objects (dyn) is limited and experimental 8 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/loops_in_terminates.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[check(terminates)] 6 | fn terminates_while_loop() { 7 | #[allow(while_true)] 8 | while true {} 9 | } 10 | 11 | #[check(terminates)] 12 | fn terminates_loop_loop() { 13 | loop {} 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/791.coma: -------------------------------------------------------------------------------- 1 | module M_i_love_floats 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec i_love_floats (return (x: ())) = (! bb0 9 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 10 | end 11 | -------------------------------------------------------------------------------- /tests/should_fail/const_default.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | // Check that we don't accidentally use the default value. 6 | pub trait Nat { 7 | const VALUE: usize = 0; 8 | } 9 | 10 | pub fn nat() { 11 | // Should fail 12 | proof_assert! { N::VALUE == 0usize } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1030.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct Test; 5 | 6 | impl Test { 7 | #[logic(open)] 8 | pub fn new() -> Test { 9 | Test 10 | } 11 | } 12 | 13 | #[logic(open)] 14 | #[ensures(result == Test::new())] 15 | pub fn test() -> Test { 16 | Test::new() 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/pair_bor_mut.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(if take_first { result == p.0 && ^p.1 == *p.1 } 5 | else { result == p.1 && ^p.0 == *p.0 } )] 6 | pub fn pair_bor_mut<'a, T>(p: (&'a mut T, &'a mut T), take_first: bool) -> &'a mut T { 7 | if take_first { p.0 } else { p.1 } 8 | } 9 | -------------------------------------------------------------------------------- /tests/should_fail/bug/ice-final-borrows.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // At some point, mutating an immutable borrow caused the code testing for final borrows 5 | // to crash. This test ensures that it does not happen again. 6 | 7 | #[requires(true)] 8 | pub fn mutates_immutable(x: &i32) { 9 | *x = 1; 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_fail/array.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: Array 2 | --> array.rs:9:12 3 | | 4 | 9 | #[requires([0, 1, 2, 3] == x)] 5 | | ^^^^^^^^^^^^ 6 | 7 | error: Unsupported expression: Repeat 8 | --> array.rs:13:12 9 | | 10 | 13 | #[requires([0; 4] == x)] 11 | | ^^^^^^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test3.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: Pattern matching literals on Int are unsupported by Pearlite. Consider using if-then-else instead. 2 | --> test3.rs:7:13 3 | | 4 | 7 | (0, _, _) | (_, 0, _) | (_, _, 0) => 1, 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/03.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | pub fn omg(_x: T) -> bool { 7 | true 8 | } 9 | 10 | #[ensures(omg(x))] 11 | fn prog(x: T) {} 12 | 13 | #[ensures(omg(0))] 14 | pub fn prog2() { 15 | prog(0); 16 | } 17 | 18 | #[ensures(omg((0, 0)))] 19 | pub fn prog3() {} 20 | -------------------------------------------------------------------------------- /creusot-args/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "creusot-args" 3 | version = "0.8.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | clap = { version = "4.5", features = ["derive", "env"] } 11 | serde = { version = "1.0", features = ["derive"] } 12 | 13 | -------------------------------------------------------------------------------- /creusot-setup/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "creusot-setup" 3 | version = "0.8.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | creusot-args = {path = "../creusot-args"} 9 | serde = { version = "1.0", features = ["derive"] } 10 | toml = { version = "0.8", features = ["preserve_order"] } 11 | directories = "6.0" 12 | which = "7.0" 13 | anyhow = "1.0" 14 | -------------------------------------------------------------------------------- /tests/should_fail/diagnostics/view_unimplemented.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | struct S; 6 | 7 | #[logic] 8 | fn views(x: S) { 9 | let _ = x.view(); 10 | } 11 | 12 | fn view_operator(x: S) { 13 | // FIXME(diagnostics): this error is printed twice, why? 14 | let _ = pearlite! { x@ }; 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/962.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(p.0@ == 1)] 5 | #[ensures(result@ == 2)] 6 | pub fn disjoint_captures(mut p: (i32, i32)) -> i32 { 7 | let p0 = &p.0; 8 | let mut clos = #[ensures(p.1@ == 1)] 9 | || { 10 | p.1 = 1; 11 | }; 12 | clos(); 13 | *p0 + p.1 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test4.stderr: -------------------------------------------------------------------------------- 1 | error: Unsupported expression: Pattern matching literals on Int are unsupported by Pearlite. Consider using if-then-else instead. 2 | --> test4.rs:7:13 3 | | 4 | 7 | Some((Some(0), _)) | Some((_, Some(0))) => 1, 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: aborting due to 1 previous error 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/789.coma: -------------------------------------------------------------------------------- 1 | module M_meta 2 | use creusot.prelude.Any 3 | use creusot.int.UInt64 4 | 5 | meta "compute_max_steps" 1000000 6 | 7 | meta "select_lsinst" "all" 8 | 9 | let rec meta' (_x: UInt64.t) (return (x: ())) = (! bb0 10 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/08.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{logic::Int, prelude::*}; 4 | 5 | // Ensure that different kinds of functions are translated to the 6 | // correct abstract symbol in Rust 7 | pub trait Tr { 8 | #[logic] 9 | fn logical(&self) -> Int; 10 | fn program(&self) {} 11 | } 12 | 13 | pub fn test(_: T) {} 14 | -------------------------------------------------------------------------------- /guide/src/basic_concepts/variants.md: -------------------------------------------------------------------------------- 1 | # Variants 2 | 3 | A `variant` clause can be attached either to a function like `ensures`, or `requires` or to a loop like `invariant`, it should contain a strictly decreasing expression which can prove the termination of the item it is attached to. 4 | 5 | 8 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1565.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Tr { 5 | #[logic] 6 | fn f(self) -> Int; 7 | } 8 | 9 | impl Tr for i32 { 10 | #[logic] 11 | fn f(self) -> Int { 12 | g() 13 | } 14 | } 15 | 16 | #[logic] 17 | pub fn g() -> Int 18 | where 19 | i32: Tr, 20 | { 21 | 1i32.f() 22 | } 23 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/206.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub struct A(Vec); 6 | 7 | #[logic] 8 | #[ensures(a.0@ == a.0@)] 9 | fn u2(a: A) {} 10 | 11 | #[logic(open(self))] 12 | pub fn u(a: A) { 13 | pearlite! { 14 | u2(a) 15 | } 16 | } 17 | 18 | #[ensures(u(*a) == (u(*a)))] 19 | pub fn ex(a: &A) {} 20 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/19_sealed.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Tr { 5 | #[logic] 6 | fn f(self, x: Int) -> Int; 7 | 8 | #[logic(open, sealed)] 9 | fn g(self, x: Int) -> Int { 10 | self.f(x) + 1 11 | } 12 | } 13 | 14 | #[ensures(x.g(y) == x.f(y) + 1)] 15 | pub fn p(x: T, y: Int) {} 16 | -------------------------------------------------------------------------------- /tests/should_succeed/type_constructors.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | mod a { 4 | #[allow(dead_code)] 5 | pub struct Y(pub super::b::X); 6 | } 7 | 8 | mod b { 9 | #[allow(dead_code)] 10 | pub enum X { 11 | A, 12 | B, 13 | C, 14 | } 15 | } 16 | 17 | pub fn f() { 18 | let _ = b::X::A; 19 | let _ = a::Y(b::X::B); 20 | } 21 | -------------------------------------------------------------------------------- /tests/should_fail/lints/contractless_external_function.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[deny(creusot::contractless_external_function)] 5 | #[requires(true)] 6 | pub fn f() { 7 | // We will probably never specify `transmute`, so it is a good target to showcase this lint 8 | let _x: i32 = unsafe { std::mem::transmute(1i32) }; 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/unsupported/1827/test1.rs: -------------------------------------------------------------------------------- 1 | // ISSUE 1827: Pattern matching on Int is unsupported by Pearlite 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | #[variant(arr.len())] 7 | fn sum(arr: Seq) -> Int { 8 | pearlite! { 9 | match arr.len() { 10 | 0 => 0, 11 | _ => arr[0] + sum(arr.pop_front()), 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unsized_quant.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic] 5 | pub fn f() -> bool { 6 | pearlite! { 7 | let len = |x: [i32]| x@.len(); 8 | forall { 9 | len[x] + len[y] >= 0 10 | } 11 | } 12 | } 13 | 14 | #[logic] 15 | #[ensures(f())] 16 | pub fn l() {} 17 | -------------------------------------------------------------------------------- /tests/should_succeed/sum.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires(n@ < 1000)] 5 | #[ensures(result@ == n@ * (n@ + 1) / 2)] 6 | pub fn sum_first_n(n: u32) -> u32 { 7 | let mut sum = 0; 8 | #[invariant(sum@ * 2 == produced.len() * (produced.len() + 1))] 9 | for i in 1..=n { 10 | sum += i; 11 | } 12 | sum 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/13_vec_macro.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::{vec, *}; 4 | 5 | pub fn x() { 6 | let v0: Vec = vec![]; 7 | proof_assert! { v0@.len() == 0 }; 8 | 9 | let v1 = vec![0; 2]; 10 | proof_assert! { v1@.len() == 2 }; 11 | 12 | let v2 = vec![1, 2, 3]; 13 | proof_assert! { v2@.len() == 3 }; 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/13_assoc_types.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub trait Model { 4 | type ModelTy; 5 | 6 | fn model(self) -> Self::ModelTy; 7 | } 8 | 9 | impl Model for &T { 10 | type ModelTy = T::ModelTy; 11 | 12 | #[allow(unconditional_recursion)] 13 | fn model(self) -> Self::ModelTy { 14 | (self).model() 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/mutual_recursion.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | mod m { 6 | #[super::check(terminates)] 7 | pub fn f1() { 8 | super::f2(); 9 | } 10 | } 11 | 12 | #[check(terminates)] 13 | fn f2() { 14 | f3(); 15 | } 16 | 17 | #[check(terminates)] 18 | fn f3() { 19 | m::f1(); 20 | } 21 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/181_ident.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{logic::Int, prelude::*}; 4 | 5 | // Bug #181 6 | #[logic(open)] 7 | pub fn max_int(a: Int, b: Int) -> Int { 8 | if a < b { b } else { a } 9 | } 10 | 11 | #[ensures(result@ == max_int(a@, b@))] 12 | pub fn max_usize(a: usize, b: usize) -> usize { 13 | if a < b { b } else { a } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/pure_neq.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | type t_Option_Int = None | Some int 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | constant x : t_Option_Int 9 | 10 | constant y : t_Option_Int 11 | 12 | predicate f (x: t_Option_Int) (y: t_Option_Int) 13 | 14 | goal vc_f: [@expl:f ensures] (x <> y) = (not x = y) 15 | end 16 | -------------------------------------------------------------------------------- /tests/should_succeed/cc/array.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub fn test_array() { 4 | let mut a = [1, 2].iter(); 5 | assert_eq!(a.next(), Some(&1)); 6 | assert_eq!(a.next(), Some(&2)); 7 | assert_eq!(a.next(), None); 8 | 9 | let mut b = ::std::iter::IntoIterator::into_iter([1]); 10 | assert_eq!(b.next(), Some(1)); 11 | assert_eq!(b.next(), None); 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/04.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | fn a(x: u32) -> bool { 7 | x > 0u32 8 | } 9 | 10 | #[logic] 11 | fn b(x: u32) -> bool { 12 | x > 10u32 && a(x) 13 | } 14 | 15 | #[logic] 16 | pub fn c(x: u32) -> bool { 17 | x < 50u32 && b(x) 18 | } 19 | 20 | #[requires(c(x))] 21 | pub fn f(x: u32) {} 22 | -------------------------------------------------------------------------------- /tests/should_succeed/simple_trigger.rs: -------------------------------------------------------------------------------- 1 | // CREUSOT_ARG=--simple-triggers=true 2 | extern crate creusot_contracts; 3 | 4 | use creusot_contracts::prelude::*; 5 | 6 | #[logic] 7 | #[requires(i >= 0)] 8 | #[variant(i)] 9 | #[ensures(i == 0 ==> result == 0)] 10 | pub fn id(i: Int) -> Int { 11 | if i == 0 { 0 } else { id(i - 1) + 1 } 12 | } 13 | 14 | #[ensures(id(1) == 1)] 15 | pub fn test() {} 16 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/default_function_non_logic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Foo { 5 | #[check(terminates)] 6 | fn f() {} 7 | #[check(terminates)] 8 | fn g(); 9 | } 10 | 11 | impl Foo for i32 { 12 | #[check(terminates)] 13 | fn g() { 14 | Self::f(); // this assumes f could call g 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/fake_ref.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use ::std::ops::Bound; 3 | 4 | // This generates "fake refs" for borrow checking that should be ignored otherwise 5 | pub fn range(range: Bound<&usize>) -> usize { 6 | match range { 7 | Bound::Included(&end) if end == 0 => 0, 8 | Bound::Excluded(&end) if end == 0 => 0, 9 | _ => 1, 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/cell/01_basic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{cell::PredCell, prelude::*}; 4 | 5 | #[requires(c@ == |z: u32| z@ % 2 == 0)] 6 | pub fn adds_two(c: &PredCell) { 7 | let v = c.get(); 8 | 9 | // To shut up overflow checking 10 | if v < 100000 { 11 | c.set(v + 2); 12 | } else { 13 | c.set(0); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/type_invariants.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{invariant::Invariant, prelude::*}; 3 | 4 | pub struct WithInvariant; 5 | 6 | impl Invariant for WithInvariant { 7 | #[logic(open)] 8 | fn invariant(self) -> bool { 9 | true 10 | } 11 | } 12 | 13 | pub fn id(x: WithInvariant) -> WithInvariant { 14 | x 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1204.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | #[requires(false)] 7 | #[variant(x)] 8 | pub fn evil(x: Int) -> Int { 9 | evil(-x) + 1 10 | } 11 | 12 | #[logic] 13 | #[ensures(false)] 14 | pub fn wrong() { 15 | proof_assert! {evil(1) == evil(-1) + 1}; 16 | proof_assert! {evil(-1) == evil(1) + 1} 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_1.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | struct S { 5 | g: Snapshot, 6 | } 7 | 8 | #[logic] 9 | fn prophecy(x: &mut S) -> bool { 10 | pearlite! { *(^x).g } 11 | } 12 | 13 | pub fn f() { 14 | let b = &mut S { g: snapshot! { true } }; 15 | b.g = snapshot! { !prophecy(b) }; 16 | proof_assert! { false } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/generic_deref_ghost.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | use std::ops::Deref; 5 | 6 | #[requires(T::deref.precondition((x,)))] 7 | #[ensures(T::deref.postcondition((x,), result))] 8 | pub fn deref_wrap(x: &T) -> &T::Target { 9 | &*x 10 | } 11 | 12 | pub fn bad(x: Ghost) -> i32 { 13 | *deref_wrap(&x) 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1239/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.025 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1504/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { "M_h": { "vc_h": { "prover": "cvc5@1.3.1", "time": 0.024 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1674/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.028 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/235/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.024 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/766.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::FMap, prelude::*}; 3 | 4 | pub trait Trait: 5 | DeepModel> 6 | { 7 | #[ensures(self.deep_model() == self.deep_model())] 8 | fn f(&mut self); 9 | 10 | fn goo(&mut self) { 11 | self.f() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/minus_assoc.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | use creusot.prelude.Any 3 | use mach.int.Int 4 | 5 | meta "compute_max_steps" 1000000 6 | 7 | meta "select_lsinst" "all" 8 | 9 | let rec f (return (x: ())) = (! bb0 10 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) 11 | [ return (result: ()) -> {[@expl:f ensures] 0 - (1 - 1) = 0} (! return {result}) ] 12 | end 13 | -------------------------------------------------------------------------------- /tests/should_succeed/immut/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.01 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/loop/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.015 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/prophecy/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.015 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/slices/02_std.rs: -------------------------------------------------------------------------------- 1 | // test some extern specs on slcies 2 | extern crate creusot_contracts; 3 | 4 | use creusot_contracts::prelude::*; 5 | 6 | #[requires(forall 0 <= i && i < s@.len() ==> s[i]@ == i)] 7 | #[requires(s@.len() == 5)] 8 | pub fn binary_search(s: &[u32]) -> usize { 9 | let ix = s.binary_search(&2).unwrap(); 10 | 11 | proof_assert! { ix@ < 5 }; 12 | ix 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/two_modules.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | mod mod1 { 4 | #[allow(dead_code)] 5 | pub enum T { 6 | A, 7 | B, 8 | C, 9 | } 10 | } 11 | 12 | mod mod2 { 13 | use crate::mod1; 14 | 15 | pub fn x(_t: mod1::T) -> bool { 16 | true 17 | } 18 | } 19 | 20 | use mod1::T::*; 21 | 22 | pub fn f() { 23 | mod2::x(B); 24 | } 25 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Install Creusot 3 | # Additional arguments can be stored in a file `INSTALL.opts`. For example: 4 | # $ cat "--external z3" > INSTALL.opts 5 | # $ ./INSTALL 6 | # To see a list of possible options, `./INSTALL --help`. 7 | if [ -f INSTALL.opts ] ; then 8 | ARGS=$(cat INSTALL.opts) 9 | else 10 | ARGS="" 11 | fi 12 | set -xe 13 | cargo run --bin creusot-install -- $ARGS $@ 14 | -------------------------------------------------------------------------------- /guide/src/trusted.md: -------------------------------------------------------------------------------- 1 | # Trusted 2 | 3 | The `trusted` marker lets Creusot trust the implementation and specs. 4 | More specifically, you can put `#[trusted]` on a function like the following: 5 | 6 | ```rust 7 | #[trusted] 8 | #[ensures(result == 42u32)] 9 | fn the_answer() -> u32 { 10 | trusted_super_oracle("the answer to life, the universe and everything") 11 | } 12 | ``` 13 | 14 | TODO: trusted traits 15 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_0.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | struct S { 5 | g: Snapshot, 6 | } 7 | 8 | #[logic(prophetic)] 9 | fn prophecy(x: &mut S) -> Int { 10 | pearlite! { *(^x).g } 11 | } 12 | 13 | pub fn f() { 14 | let b = &mut S { g: snapshot! { 1 } }; 15 | b.g = snapshot! { prophecy(b) + 1 }; 16 | proof_assert! { false } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/generic_deref_snap.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | use std::ops::Deref; 5 | 6 | #[requires(T::deref.precondition((x,)))] 7 | #[ensures(T::deref.postcondition((x,), result))] 8 | pub fn deref_wrap(x: &T) -> &T::Target { 9 | &*x 10 | } 11 | 12 | pub fn bad(x: Snapshot) -> i32 { 13 | *deref_wrap(&x) 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/simple_recursion.stderr: -------------------------------------------------------------------------------- 1 | error: Recursive function without a `#[variant]` clause 2 | --> simple_recursion.rs:6:1 3 | | 4 | 6 | fn recurses(b: bool) { 5 | | ^^^^^^^^^^^^^^^^^^^^ 6 | | 7 | note: Recursive call happens here 8 | --> simple_recursion.rs:8:9 9 | | 10 | 8 | recurses(!b); 11 | | ^^^^^^^^^^^^ 12 | 13 | error: aborting due to 1 previous error 14 | 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1438.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Tr: Sized { 5 | #[logic] 6 | fn foo(self); 7 | 8 | #[logic(open)] 9 | fn bar(self) {} 10 | } 11 | 12 | impl Tr for (T, U) 13 | where 14 | T: Tr, 15 | U: Tr, 16 | { 17 | #[logic(open(self))] 18 | fn foo(self) { 19 | self.bar() 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/pure_neq/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.023 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/04/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.028 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/empty/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.025 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/or_pat/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.015 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unary_op/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.025 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unions/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_x": { "vc_x": { "prover": "cvc5@1.3.1", "time": 0.027 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/match_int/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.028 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/resolve_drop/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.015 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/std_types/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_x": { "vc_x": { "prover": "cvc5@1.3.1", "time": 0.026 } } } 9 | } 10 | -------------------------------------------------------------------------------- /exercises/01_sum.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Prove that this function implements the sum of the first n natural numbers. 5 | // Hint: there exists a closed form of this sum 6 | pub fn sum_first_n(n: u32) -> u32 { 7 | let mut sum = 0; 8 | let mut i = 0; 9 | while i < n { 10 | i += 1; 11 | sum += i; 12 | } 13 | sum 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/minus_assoc/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.028 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/move_path/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.015 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unsized_quant/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_l": { "vc_l": { "prover": "cvc5@1.3.1", "time": 0.042 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/while_let/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.028 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/one_side_update/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.029 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/spec_tests.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | extern crate creusot_contracts; 4 | use creusot_contracts::prelude::*; 5 | 6 | pub enum T { 7 | A, 8 | B, 9 | } 10 | 11 | pub struct S(pub A, pub B); 12 | 13 | pub enum List { 14 | Cons(A, Box>), 15 | Nil, 16 | } 17 | 18 | #[ensures(T::A == T::B)] 19 | #[ensures(S(0u32, true) == S(1u32, false))] 20 | pub fn test_specs() {} 21 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/19_sealed/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { "M_p": { "vc_p_T": { "prover": "cvc5@1.3.1", "time": 0.03 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_succeed/type_constructors/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.029 } } } 9 | } 10 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1565.stderr: -------------------------------------------------------------------------------- 1 | error: Mutually recursive functions: when calling `::f`... 2 | --> 1565.rs:11:5 3 | | 4 | 11 | fn f(self) -> Int { 5 | | ^^^^^^^^^^^^^^^^^ 6 | | 7 | note: then `::f` might call `::f` via the call to `g`. 8 | --> 1565.rs:12:9 9 | | 10 | 12 | g() 11 | | ^^^ 12 | 13 | error: aborting due to 1 previous error 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/bug/492.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[ensures(*(result.0) == *x)] 6 | pub fn reborrow_tuple(x: &mut T) -> (&mut T, u32) { 7 | (x, 32) 8 | } 9 | 10 | #[ensures(false)] 11 | pub fn test() { 12 | let mut x = 5; 13 | let (res, _) = reborrow_tuple(&mut x); 14 | proof_assert!(^res == 5i32); 15 | *res = 10; 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_fail/bug/subregion.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | pub fn list_reversal_h(l: usize) -> usize { 5 | let mut r = 0; 6 | #[invariant(true)] 7 | while l != 0 { 8 | proof_assert!(false); 9 | let _x = r; 10 | let tmp = l; 11 | r = tmp; 12 | } 13 | // proof_assert!(false); 14 | return r; 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/ghost/disjoint_raw_ptr.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{ghost::perm::Perm, prelude::*}; 3 | 4 | pub fn foo() { 5 | let (p1, mut own1) = Perm::new(1i32); 6 | let (p2, own2) = Perm::new(1i32); 7 | 8 | ghost! { 9 | let _ = Perm::disjoint_lemma(&mut own1, &own2); 10 | }; 11 | proof_assert!(own1 != own2); 12 | proof_assert!(p1 != p2); 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/16_impl_cloning.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{logic::Seq, prelude::*}; 4 | 5 | pub struct Vec(pub std::vec::Vec); 6 | impl View for Vec { 7 | type ViewTy = Seq; 8 | #[logic(opaque)] 9 | fn view(self) -> Self::ViewTy { 10 | dead 11 | } 12 | } 13 | 14 | #[ensures(x@ == (*x)@)] 15 | pub fn test(x: &mut Vec) {} 16 | -------------------------------------------------------------------------------- /tests/should_fail/bug/400.stderr: -------------------------------------------------------------------------------- 1 | error: Method `lo` should not be a `#[logic(law)]`, as specified by the trait declaration 2 | --> 400.rs:17:5 3 | | 4 | 17 | fn lo() {} 5 | | ^^^^^^^ 6 | 7 | error: Expected `la` to be a `#[logic(law)]` as specified by the trait declaration 8 | --> 400.rs:14:5 9 | | 10 | 14 | fn la() {} 11 | | ^^^^^^^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/mutual_recursion_trait.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | trait Foo { 6 | #[check(terminates)] 7 | fn foo() {} 8 | } 9 | 10 | impl Foo for i32 { 11 | #[check(terminates)] 12 | fn foo() { 13 | bar(); 14 | } 15 | } 16 | 17 | #[check(terminates)] 18 | fn bar() { 19 | ::foo(); 20 | } 21 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1538/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 47, "time": 0.522 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_baz": { "vc_baz": { "prover": "cvc5@1.3.1", "time": 0.021 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/217/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_ex": { "vc_ex": { "prover": "cvc5@1.3.1", "time": 0.014 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/528/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_neq": { "vc_neq": { "prover": "cvc5@1.3.1", "time": 0.025 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/682.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[requires((*a)@ <= u64::MAX@ / 2)] 5 | #[ensures(^a > *a)] 6 | fn add_some(a: &mut u64) { 7 | *a += 1; 8 | } 9 | 10 | #[requires(*a == 3u64)] 11 | #[ensures(^a > *a)] 12 | pub fn foo(a: &mut u64) { 13 | let a_p: Snapshot = snapshot!(*a); 14 | add_some(a); 15 | proof_assert!(*a > *a_p); 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/761.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(result == x)] 5 | pub fn try_option(x: Option) -> Option { 6 | Some(x?) 7 | } 8 | 9 | #[ensures(result == x)] 10 | pub fn try_result(x: Result) -> Result { 11 | Ok(x?) 12 | } 13 | 14 | pub enum Empty {} 15 | 16 | pub fn elim_empty(x: Empty) { 17 | match x {} 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/match_int.rs: -------------------------------------------------------------------------------- 1 | #![allow(unreachable_patterns)] 2 | 3 | extern crate creusot_contracts; 4 | 5 | // Test that matching constant integer values works 6 | pub fn f() { 7 | match 1 { 8 | 0..10 => { 9 | assert!(true) 10 | } 11 | 5 | 6 => { 12 | assert!(false) 13 | } 14 | _ => { 15 | assert!(false) 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/mc91/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_mc91": { "vc_mc91": { "prover": "cvc5@1.3.1", "time": 0.047 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/resource_algebras/agree.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{ghost::resource::Resource, logic::ra::agree::Ag, prelude::*}; 3 | 4 | #[requires(x.id() == y.id())] 5 | #[ensures(x@ == y@)] 6 | pub fn agreement(x: &Resource>, y: &Resource>) { 7 | // this result is valid iff x@ == y@ 8 | // and it is valid by invariant 9 | let _ = x.join_shared(y); 10 | } 11 | -------------------------------------------------------------------------------- /creusot-install/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "creusot-install" 3 | version.workspace = true 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | clap = { version = "4.5", features = ["derive", "env"] } 9 | creusot-setup = {path = "../creusot-setup"} 10 | anyhow = "1.0" 11 | directories = "6.0" 12 | sha2 = "0.10" 13 | hex = "0.4" 14 | zip = { version = "2.2", default-features = false, features = ["deflate"] } 15 | -------------------------------------------------------------------------------- /exercises/04_all_zero.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Prove that after the call to this function the vector only contains zeroes 5 | // Also show that no elements were added or removed 6 | pub fn all_zero(v: &mut Vec) { 7 | let mut i = 0; 8 | let old_v = snapshot! { v }; 9 | 10 | while i < v.len() { 11 | v[i] = 0; 12 | i += 1; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_fail/opaque_unproveable.coma: -------------------------------------------------------------------------------- 1 | module M_test 2 | use creusot.prelude.Any 3 | 4 | predicate opaque 5 | 6 | meta "compute_max_steps" 1000000 7 | 8 | meta "select_lsinst" "all" 9 | 10 | let rec test (return (x: ())) = (! bb0 11 | [ bb0 = s0 [ s0 = {[@expl:assertion] opaque} s1 | s1 = return {_ret} ] ] [ & _ret: () = Any.any_l () ]) 12 | [ return (result: ()) -> (! return {result}) ] 13 | end 14 | -------------------------------------------------------------------------------- /tests/should_fail/sealed.stderr: -------------------------------------------------------------------------------- 1 | error: This trait methods overrides a sealed implementation. 2 | --> sealed.rs:21:5 3 | | 4 | 21 | fn g(self, x: Int) -> Int { 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: This sealed implementation is overriden. 8 | --> sealed.rs:9:5 9 | | 10 | 9 | fn g(self, x: Int) -> Int { 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1030/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1342/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_bar": { "vc_bar_T": { "prover": "cvc5@1.3.1", "time": 0.066 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/486/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.032 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/789/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_meta": { "vc_meta'": { "prover": "cvc5@1.3.1", "time": 0.024 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/fmap_indexing/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_foo": { "vc_foo": { "prover": "cvc5@1.3.1", "time": 0.054 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/replace/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.014 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/04_assoc_prec.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | extern crate creusot_contracts; 4 | 5 | use creusot_contracts::prelude::*; 6 | 7 | // TODO: these could be unit tests in the why3 crate 8 | 9 | #[ensures(5 == 3 ==> 2 + 1 == 3)] 10 | #[ensures(5 * 3 / 2 != 4 * (40 + 1))] 11 | #[ensures(x.0 == x.1)] 12 | pub fn respect_prec(x: (u32, u32)) {} 13 | 14 | #[ensures(0u32@ + 1u32@ == 0)] 15 | pub fn respect_assoc() {} 16 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/04.rs: -------------------------------------------------------------------------------- 1 | // NO_REPLAY 2 | 3 | extern crate creusot_contracts; 4 | 5 | use creusot_contracts::prelude::*; 6 | 7 | pub trait A { 8 | fn func1(&self, o: &Self) -> bool; 9 | fn func2(&self, o: &Self) -> bool; 10 | fn func3(&self, o: &Self) -> bool; 11 | } 12 | 13 | #[ensures(result == false)] 14 | pub fn user(a: &T, b: &T) -> bool { 15 | a.func1(b) && b.func2(a) && a.func3(b) 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/11/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test_T": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/unnest/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_unnest": { "vc_unnest": { "prover": "cvc5@1.3.1", "time": 0.016 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 100 2 | hard_tabs = false 3 | newline_style = "Auto" 4 | use_small_heuristics = "Max" 5 | reorder_imports = true 6 | reorder_modules = true 7 | remove_nested_parens = true 8 | fn_params_layout = "Tall" 9 | edition = "2024" 10 | style_edition = "2024" 11 | merge_derives = true 12 | use_try_shorthand = false 13 | use_field_init_shorthand = false 14 | force_explicit_abi = true 15 | imports_granularity = "Crate" 16 | -------------------------------------------------------------------------------- /tests/should_fail/bug/borrowed_ghost.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn use_borrowed() { 5 | let mut x = snapshot! { true }; 6 | let r = &mut x; // x = ?, r = (snapshot true, x) 7 | *r = snapshot! { !x.inner() }; // r = (snapshot (not (inner x)), x) 8 | // resolve r: x = snapshot (not (inner x)) 9 | proof_assert! { x.inner() == !x.inner() } // UNSOUND! 10 | } 11 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1208/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_impl_Q__mul": { "vc_mul": { "prover": "cvc5@1.3.1", "time": 0.02 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/168/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_max_int": { "vc_max_int": { "prover": "cvc5@1.3.1", "time": 0.013 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/173/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test_233": { "vc_test_233": { "prover": "cvc5@1.3.1", "time": 0.01 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/195/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_example": { "vc_example": { "prover": "cvc5@1.3.1", "time": 0.025 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/691/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_example": { "vc_example": { "prover": "cvc5@1.3.1", "time": 0.005 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/793/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_div_err": { "vc_div_err": { "prover": "cvc5@1.3.1", "time": 0.011 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/cc/arithmetic/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.049 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/02/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_program": { "vc_program": { "prover": "cvc5@1.3.1", "time": 0.024 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unary_op.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec f (return (x: ())) = (! bb0 9 | [ bb0 = any [ br0 -> {false = false} (! bb2) | br1 -> {false} (! bb1) ] | bb1 = {false} any | bb2 = return {_ret} ] 10 | [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/mapping_indexing/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_foo": { "vc_foo": { "prover": "cvc5@1.3.1", "time": 0.025 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/switch.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub enum Option { 4 | Some(T), 5 | None, 6 | } 7 | use Option::*; 8 | 9 | pub fn test(o: Option) -> bool { 10 | match o { 11 | Some(x) => x > 0, 12 | None => false, 13 | } 14 | } 15 | 16 | pub fn test2(o: (Option, u32)) -> u32 { 17 | match o.0 { 18 | Some(x) => x, 19 | None => o.1, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/11_array_types.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub struct UsesArray(pub [i64; 5]); 6 | 7 | #[requires(x.0@.len() > 0 && x.0@.len() < usize::MAX@)] 8 | pub fn omg(mut x: UsesArray) { 9 | x.0[0] = 5; 10 | 11 | proof_assert! { x.0[0]@ == 5}; 12 | } 13 | 14 | pub fn call_omg() { 15 | let arr = [3_i64; 5]; 16 | omg(UsesArray(arr)) 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/array.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | fn main() { 5 | let _ = [0; 8]; 6 | } 7 | 8 | // Checks that array expressions are not allowed in specificatiosn 9 | #[requires([0, 1, 2, 3] == x)] 10 | fn array_in_spec(x: [u32; 4]) {} 11 | 12 | // Checks that array reptitions are not allowed in specificatiosn 13 | #[requires([0; 4] == x)] 14 | fn repeat_in_spec(x: [u32; 4]) {} 15 | -------------------------------------------------------------------------------- /tests/should_fail/bug/459.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub enum A { 5 | Cons(Box), 6 | Nil, 7 | } 8 | 9 | impl DeepModel for A { 10 | type DeepModelTy = Int; 11 | #[logic(open)] 12 | fn deep_model(self) -> Self::DeepModelTy { 13 | match self { 14 | A::Cons(a) => *a.deep_model() + 1, 15 | A::Nil => 0, 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/non_terminating.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[check(ghost)] 5 | pub fn recursive() { 6 | ghost! { 7 | f(); 8 | 42 9 | }; 10 | } 11 | 12 | #[check(ghost)] 13 | fn f() { 14 | recursive(); 15 | } 16 | 17 | #[allow(unreachable_code)] 18 | pub fn looping() { 19 | let _g: Ghost = ghost! { 20 | loop {} 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /tests/should_fail/opaque_unproveable.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | mod x { 6 | use creusot_contracts::prelude::*; 7 | 8 | #[logic(open(self))] 9 | pub fn opaque() -> bool { 10 | true 11 | } 12 | } 13 | 14 | pub fn test() { 15 | // INTENT: Should not pass as the body of `x::opaque` is opaque (duh). 16 | proof_assert!(x::opaque()); 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/trait_item_types_mismatch.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[trusted] 5 | pub trait Trusted {} 6 | 7 | impl Trusted for () {} 8 | 9 | pub trait HasPredicate { 10 | #[logic(open(self))] 11 | fn my_predicate() -> bool { 12 | true 13 | } 14 | } 15 | 16 | impl HasPredicate for u32 { 17 | fn my_predicate() -> bool { 18 | false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/should_fail/unsafe.stderr: -------------------------------------------------------------------------------- 1 | error[E0133]: call to unsafe function `evil` is unsafe and requires unsafe block 2 | --> unsafe.rs:8:5 3 | | 4 | 8 | evil(); 5 | | ^^^^^^ call to unsafe function 6 | | 7 | = note: consult the function's documentation for information on how to avoid undefined behavior 8 | 9 | error: aborting due to 1 previous error 10 | 11 | For more information about this error, try `rustc --explain E0133`. 12 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/528.coma: -------------------------------------------------------------------------------- 1 | module M_neq 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec neq (a: bool) (b: bool) (return (x: bool)) = (! bb0 9 | [ bb0 = s0 [ s0 = [ &_ret <- a <> b ] s1 | s1 = return {_ret} ] ] 10 | [ & _ret: bool = Any.any_l () | & a: bool = a | & b: bool = b ]) [ return (result: bool) -> (! return {result}) ] 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/assoc_type/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_uses3": { "vc_uses3_T": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/module_paths/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/opaque/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/14_const_fns/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_omg": { "vc_omg": { "prover": "cvc5@1.3.1", "time": 0.027 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/vec_inv/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_vec": { "vc_vec": { "prover": "cvc5@1.3.1", "time": 0.048 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/division/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_divide": { "vc_divide": { "prover": "cvc5@1.3.1", "time": 0.05 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/forall.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::{logic::Int, prelude::*}; 4 | 5 | #[ensures(forall<_x:u32> true && true && true && true && true && true && true && true && true)] 6 | pub fn f() {} 7 | 8 | #[logic(open)] 9 | #[requires(a <= b)] 10 | #[ensures(true)] 11 | pub fn omg(a: Int, b: Int) -> bool { 12 | pearlite! { { 13 | exists a + c == b 14 | } } 15 | } 16 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/logic_call/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_dummy": { "vc_dummy": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/16_impl_cloning/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test_T": { "prover": "cvc5@1.3.1", "time": 0.033 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/type_constructors.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | use creusot.prelude.Any 3 | 4 | type t_X = A | B | C 5 | 6 | meta "compute_max_steps" 1000000 7 | 8 | meta "select_lsinst" "all" 9 | 10 | let rec f (return (x: ())) = (! bb0 11 | [ bb0 = s0 [ s0 = [ &_3 <- B ] s1 | s1 = return {_ret} ] ] [ & _ret: () = Any.any_l () | & _3: t_X = Any.any_l () ]) 12 | [ return (result: ()) -> (! return {result}) ] 13 | end 14 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/capture_non_copy_data.stderr: -------------------------------------------------------------------------------- 1 | error: cannot move a non-ghost variable into a `ghost!` block 2 | --> capture_non_copy_data.rs:5:12 3 | | 4 | 5 | ghost!(v); 5 | | ^ 6 | | 7 | note: variable defined here is not copy 8 | --> capture_non_copy_data.rs:4:30 9 | | 10 | 4 | pub fn capture_non_copy_data(v: Vec) { 11 | | ^ 12 | 13 | error: aborting due to 1 previous error 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/non_bool_assertion.stderr: -------------------------------------------------------------------------------- 1 | error[E0308]: mismatched types 2 | --> non_bool_assertion.rs:5:21 3 | | 4 | 5 | proof_assert! { 1 }; 5 | | ----------------^-- 6 | | | | 7 | | | expected `bool`, found `Int` 8 | | expected `bool` because of return type 9 | 10 | error: aborting due to 1 previous error 11 | 12 | For more information about this error, try `rustc --explain E0308`. 13 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/trait_def_and_impl_disagree.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | trait Tr { 6 | #[check(terminates)] 7 | fn f(); 8 | 9 | #[check(ghost)] 10 | fn g(); 11 | 12 | #[check(ghost)] 13 | fn h(); 14 | } 15 | 16 | impl Tr for i32 { 17 | fn f() {} 18 | 19 | #[check(terminates)] 20 | fn g() {} 21 | 22 | fn h() {} 23 | } 24 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/195.coma: -------------------------------------------------------------------------------- 1 | module M_example 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec example (_example_parameter: bool) (return (x: ())) = {[@expl:example requires] _example_parameter 9 | = _example_parameter} 10 | (! bb0 11 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 12 | end 13 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/545.coma: -------------------------------------------------------------------------------- 1 | module M_negative_is_negative 2 | use mach.int.Int 3 | use creusot.prelude.Any 4 | 5 | meta "compute_max_steps" 1000000 6 | 7 | meta "select_lsinst" "all" 8 | 9 | let rec negative_is_negative (return (x: ())) = (! bb0 10 | [ bb0 = s0 [ s0 = {[@expl:assertion] 0 > - 100} s1 | s1 = return {_ret} ] ] [ & _ret: () = Any.any_l () ]) 11 | [ return (result: ()) -> (! return {result}) ] 12 | end 13 | -------------------------------------------------------------------------------- /tests/should_succeed/ghost/loop_in_ghost.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(*result == x)] 5 | pub fn foo(x: u32) -> Ghost { 6 | ghost! { 7 | let mut y = 0; 8 | let mut i = x; 9 | #[variant(i)] 10 | #[invariant(y@ + i@ == x@)] 11 | while i > 0 { 12 | i -= 1; 13 | y += 1; 14 | } 15 | y 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/12_default_method.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub trait T { 6 | fn default(&self) -> u32 { 7 | 0 8 | } 9 | 10 | #[logic(open)] 11 | fn logic_default(self) -> bool { 12 | true 13 | } 14 | } 15 | 16 | impl T for u32 {} 17 | 18 | #[ensures(x.logic_default())] 19 | pub fn should_use_impl(x: u32) { 20 | x.default(); 21 | } 22 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/15_impl_interfaces/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_calls": { "vc_calls": { "prover": "cvc5@1.3.1", "time": 0.026 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/generated/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_use_foo": { "vc_use_foo": { "prover": "cvc5@1.3.1", "time": 0.046 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/type_invariants/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_id": { "vc_id": { "prover": "cvc5@1.3.1", "time": 0.029 } } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_fail/impure_functions.stderr: -------------------------------------------------------------------------------- 1 | error: called program function `std::vec::Vec::::len` in logic context 2 | --> impure_functions.rs:6:19 3 | | 4 | 6 | pearlite! { v.len()@ } 5 | | ^^^ 6 | 7 | error: called logic function `x` in program context 8 | --> impure_functions.rs:10:13 9 | | 10 | 10 | let _ = x(&Vec::<()>::new()); 11 | | ^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/02_derive.coma: -------------------------------------------------------------------------------- 1 | module M_impl_Clone_for_Lit__clone (* *) 2 | use creusot.prelude.Any 3 | 4 | meta "compute_max_steps" 1000000 5 | 6 | meta "select_lsinst" "all" 7 | 8 | let rec clone_Lit (self: ()) (return (x: ())) = (! bb0 9 | [ bb0 = s0 [ s0 = [ &_ret <- () ] s1 | s1 = return {_ret} ] ] [ & _ret: () = Any.any_l () ]) 10 | [ return (result: ()) -> (! return {result}) ] 11 | end 12 | -------------------------------------------------------------------------------- /tests/should_succeed/resource_algebras/excl.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{ghost::resource::Resource, logic::ra::excl::Excl, prelude::*}; 3 | 4 | #[ensures(x.id() != y.id())] 5 | #[ensures(*x == ^x)] 6 | pub fn exclusivity(x: &mut Resource>, y: &Resource>) { 7 | if x.id_ghost() == y.id_ghost() { 8 | x.valid_shared(y); 9 | assert!(false); // x * y cannot be valid 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/07.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | pub trait Ix { 4 | type Tgt; 5 | fn ix(&self) -> Self::Tgt; 6 | } 7 | 8 | impl Ix for i32 { 9 | type Tgt = (); 10 | 11 | fn ix(&self) -> ::Tgt { 12 | () 13 | } 14 | } 15 | 16 | pub fn test, T: Ix>(_a: &T::Tgt, _b: &G::Tgt) -> bool { 17 | true 18 | } 19 | 20 | pub fn test2(a: &i32) { 21 | a.ix() 22 | } 23 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/15_impl_interfaces.coma: -------------------------------------------------------------------------------- 1 | module M_calls 2 | use creusot.prelude.Any 3 | 4 | function x_unit (_x: ()) : () 5 | 6 | meta "compute_max_steps" 1000000 7 | 8 | meta "select_lsinst" "all" 9 | 10 | let rec calls (a: ()) (return (x: ())) = {[@expl:calls requires] x_unit a = ()} 11 | (! bb0 12 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 13 | end 14 | -------------------------------------------------------------------------------- /tests/should_fail/bad_law.stderr: -------------------------------------------------------------------------------- 1 | error: Laws cannot have additional generic parameters or trait constraints 2 | --> bad_law.rs:6:5 3 | | 4 | 6 | fn my_law(x: T); 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: Expected `my_law` to be a logic function as specified by the trait declaration 8 | --> bad_law.rs:10:5 9 | | 10 | 10 | fn my_law(_: T) {} 11 | | ^^^^^^^^^^^^^^^^^^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/ghost/deref_in_program.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn deref_ghost_in_program() { 5 | let g = ghost!(2); 6 | let _: &i32 = &*g; 7 | } 8 | 9 | pub fn deref_mut_ghost_in_program() { 10 | let mut g = ghost!(2); 11 | let _: &mut i32 = &mut *g; 12 | } 13 | 14 | pub fn into_inner_ghost_in_program() { 15 | let g = ghost!(2); 16 | let _: i32 = g.into_inner(); 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/opaque.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | // INTENT: Should produce an error message because we reference `priv_symbol` which is 4 | // less visible than we are opaque. 5 | 6 | pub mod x { 7 | use creusot_contracts::prelude::*; 8 | 9 | #[logic] 10 | fn priv_symbol() -> bool { 11 | true 12 | } 13 | 14 | #[logic(open(crate))] 15 | pub fn bad() -> bool { 16 | priv_symbol() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/vcgen/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.426 } 7 | ], 8 | "proofs": { 9 | "M_set_max": { 10 | "vc_set_max": { "prover": "alt-ergo@2.6.2", "time": 0.041 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /creusot-contracts/src/std/convert.rs: -------------------------------------------------------------------------------- 1 | use crate::prelude::*; 2 | use std::convert::*; 3 | 4 | extern_spec! { 5 | mod std { 6 | mod convert { 7 | trait From where Self: From { 8 | // #[requires(true)] 9 | fn from(value: T) -> Self; 10 | } 11 | } 12 | } 13 | 14 | impl From for T { 15 | #[ensures(result == self)] 16 | fn from(self) -> T; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_fail/cycle.stderr: -------------------------------------------------------------------------------- 1 | error: Mutually recursive functions: when calling `g`... 2 | --> cycle.rs:10:1 3 | | 4 | 10 | pub fn g(x: bool) { 5 | | ^^^^^^^^^^^^^^^^^ 6 | | 7 | note: then `g` calls `f`... 8 | --> cycle.rs:12:9 9 | | 10 | 12 | f(); 11 | | ^^^ 12 | note: finally `f` calls `g`. 13 | --> cycle.rs:6:5 14 | | 15 | 6 | g(true); 16 | | ^^^^^^^ 17 | 18 | error: aborting due to 1 previous error 19 | 20 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/181_ident/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_max_usize": { 10 | "vc_max_usize": { "prover": "cvc5@1.3.1", "time": 0.01 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/791/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_i_love_floats": { 10 | "vc_i_love_floats": { "prover": "cvc5@1.3.1", "time": 0.025 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/warn_unneeded_variant.stderr: -------------------------------------------------------------------------------- 1 | warning: variant will be ignored 2 | --> warn_unneeded_variant.rs:4:11 3 | | 4 | 4 | #[variant(x)] 5 | | ^ 6 | | 7 | note: This function is not a logical function, and is not marked with `#[terminates]`. 8 | --> warn_unneeded_variant.rs:5:1 9 | | 10 | 5 | pub fn variant_is_not_checked(x: u32) { 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | warning: 1 warning emitted 14 | 15 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/14_assoc_in_logic.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub trait Assoc { 6 | type Ty; 7 | } 8 | 9 | #[logic(opaque)] 10 | pub fn from_ty(_x: T::Ty) -> T { 11 | dead 12 | } 13 | 14 | #[logic(opaque)] 15 | pub fn to_ty(_x: T) -> T::Ty { 16 | dead 17 | } 18 | 19 | #[trusted] 20 | #[ensures(_a == from_ty(to_ty(_a)))] 21 | pub fn test(_a: T) {} 22 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1204.stderr: -------------------------------------------------------------------------------- 1 | warning: function cannot return without recursing 2 | --> 1204.rs:8:1 3 | | 4 | 8 | pub fn evil(x: Int) -> Int { 5 | | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing 6 | 9 | evil(-x) + 1 7 | | -------- recursive call site 8 | | 9 | = help: a `loop` may express intention better if this is on purpose 10 | = note: `#[warn(unconditional_recursion)]` on by default 11 | 12 | warning: 1 warning emitted 13 | 14 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/default_function_non_open.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub mod inner { 5 | use super::*; 6 | pub trait Foo { 7 | #[logic(open(self))] 8 | fn f() {} 9 | #[logic] 10 | fn g(); 11 | } 12 | } 13 | 14 | impl inner::Foo for i32 { 15 | #[logic(open(self))] 16 | fn g() { 17 | Self::f(); // this assumes f could call g 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/395/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_signed_division": { 10 | "vc_signed_division": { "prover": "cvc5@1.3.1", "time": 0.034 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/641/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test_maintains": { 10 | "vc_test_maintains": { "prover": "cvc5@1.3.1", "time": 0.024 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/fmap_indexing.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::FMap, prelude::*}; 3 | 4 | pub fn foo() { 5 | let mut map = snapshot!(FMap::empty()); 6 | map = snapshot!(map.insert(1, 3)); 7 | proof_assert!(map[1] == 3); 8 | map = snapshot!(map.insert(2, 42)); 9 | proof_assert!(map[1] == 3 && map[2] == 42); 10 | map = snapshot!(map.insert(1, 4)); 11 | proof_assert!(map[1] == 4 && map[2] == 42); 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/pair_bor_mut/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_pair_bor_mut": { 10 | "vc_pair_bor_mut_T": { "prover": "cvc5@1.3.1", "time": 0.014 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /creusot-metadata/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "creusot-metadata" 3 | version.workspace = true 4 | edition = "2024" 5 | publish = false 6 | 7 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 8 | 9 | [dependencies] 10 | indexmap = "2.7" 11 | 12 | [package.metadata.rust-analyzer] 13 | # This crate uses #[feature(rustc_private)]. 14 | # See https://github.com/rust-analyzer/rust-analyzer/pull/7891 15 | rustc_private = true 16 | -------------------------------------------------------------------------------- /pearlite-syn/src/print.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::ToTokens; 3 | 4 | pub struct TokensOrDefault<'a, T: 'a>(pub &'a Option); 5 | 6 | impl<'a, T> ToTokens for TokensOrDefault<'a, T> 7 | where 8 | T: ToTokens + Default, 9 | { 10 | fn to_tokens(&self, tokens: &mut TokenStream) { 11 | match self.0 { 12 | Some(t) => t.to_tokens(tokens), 13 | None => T::default().to_tokens(tokens), 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/generic_trait_predicate.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | pub trait CP { 6 | #[logic(open)] 7 | fn match_t() -> bool { 8 | pearlite! { Self::match_n::() } 9 | } 10 | 11 | #[logic] 12 | fn match_n() -> bool; 13 | } 14 | 15 | impl CP for (L, R) { 16 | #[logic(open)] 17 | fn match_n() -> bool { 18 | pearlite! { true } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/literals/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_float_operation": { 10 | "vc_float_operation": { "prover": "cvc5@1.3.1", "time": 0.03 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/05_annotations/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_assertion": { 10 | "vc_assertion_T": { "prover": "cvc5@1.3.1", "time": 0.026 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/unused_in_loop/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_unused_in_loop": { 10 | "vc_unused_in_loop": { "prover": "cvc5@1.3.1", "time": 0.026 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/bug/436_2.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | enum Bad<'a> { 5 | None, 6 | Some(Snapshot<&'a mut Bad<'a>>), 7 | } 8 | 9 | pub fn test_bad() { 10 | let mut x = Bad::None; 11 | let m = &mut x; 12 | let g = snapshot!(m); 13 | *m = Bad::Some(g); 14 | proof_assert!(*m == Bad::Some(g)); 15 | proof_assert!(^g == ^m); 16 | let _ = m; 17 | proof_assert!(^g == Bad::Some(g)); 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_fail/duplicate_specs.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // Fails because its already defined in `creusot-contracts` 5 | extern_spec! { 6 | mod std { 7 | mod vec { 8 | impl Vec { 9 | #[requires(true == true)] 10 | fn new() -> Vec; 11 | } 12 | } 13 | } 14 | } 15 | 16 | pub fn main() { 17 | let _: Vec = Vec::new(); 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/02_derive/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_impl_Clone_for_Lit__clone": { 10 | "vc_clone_Lit": { "prover": "cvc5@1.3.1", "time": 0.025 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1575/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_nth_bit_from_left_8": { 10 | "vc_nth_bit_from_left_8": { "prover": "cvc5@1.3.1", "time": 0.025 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/545/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_negative_is_negative": { 10 | "vc_negative_is_negative": { "prover": "cvc5@1.3.1", "time": 0.023 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/991/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_impl_Formula__love_and_hope": { 10 | "vc_love_and_hope": { "prover": "cvc5@1.3.1", "time": 0.03 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/box_borrow_resolve/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_borrow_in_box": { 10 | "vc_borrow_in_box": { "prover": "cvc5@1.3.1", "time": 0.033 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/02.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | // Here we want to ensure that `program` properly shares 6 | // the implementation of simple between itself and `uses_simple`. 7 | 8 | #[logic] 9 | pub fn simple() -> bool { 10 | true 11 | } 12 | 13 | #[logic] 14 | pub fn uses_simple() -> bool { 15 | simple() 16 | } 17 | 18 | #[requires(uses_simple())] 19 | #[ensures(simple())] 20 | pub fn program() {} 21 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/multiple_scopes.coma: -------------------------------------------------------------------------------- 1 | module M_multiple_scopes 2 | use creusot.int.Int32 3 | use creusot.prelude.Any 4 | 5 | meta "compute_max_steps" 1000000 6 | 7 | meta "select_lsinst" "all" 8 | 9 | let rec multiple_scopes (return (x: ())) = (! bb0 10 | [ bb0 = s0 [ s0 = [ &_y <- (3: Int32.t) ] s1 | s1 = return {_ret} ] ] 11 | [ & _ret: () = Any.any_l () | & _y: Int32.t = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 12 | end 13 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/recursion_logic/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_variant_int": { 10 | "vc_variant_int": { "prover": "cvc5@1.3.1", "time": 0.028 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/arc_and_rc.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use ::std::{rc::Rc, sync::Arc}; 4 | use creusot_contracts::prelude::*; 5 | 6 | pub fn rc() { 7 | let rc = Rc::new(1); 8 | proof_assert!(*rc@ == 1i32); 9 | let inner = rc.as_ref(); 10 | proof_assert!(inner@ == 1); 11 | } 12 | 13 | pub fn arc() { 14 | let arc = Arc::new(2); 15 | proof_assert!(*arc@ == 2i32); 16 | let inner = arc.as_ref(); 17 | proof_assert!(inner@ == 2); 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/641.coma: -------------------------------------------------------------------------------- 1 | module M_test_maintains 2 | use creusot.prelude.Any 3 | 4 | predicate test = true 5 | 6 | meta "compute_max_steps" 1000000 7 | 8 | meta "select_lsinst" "all" 9 | 10 | let rec test_maintains (return (x: ())) = {[@expl:test_maintains requires] test} 11 | (! bb0 12 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) 13 | [ return (result: ()) -> {[@expl:test_maintains ensures] test} (! return {result}) ] 14 | end 15 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/multiple_scopes/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_multiple_scopes": { 10 | "vc_multiple_scopes": { "prover": "cvc5@1.3.1", "time": 0.013 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_succeed/std_types.coma: -------------------------------------------------------------------------------- 1 | module M_x 2 | use creusot.prelude.Any 3 | use creusot.int.UInt32 4 | 5 | type t_Option_u32 = None | Some UInt32.t 6 | 7 | type t_MyType = { f0: t_Option_u32 } 8 | 9 | meta "compute_max_steps" 1000000 10 | 11 | meta "select_lsinst" "all" 12 | 13 | let rec x (_x: t_MyType) (return (x'0: ())) = (! bb0 14 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 15 | end 16 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/call_in_contract/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_impl_Foo_for_unit__g": { 10 | "vc_g_unit": { "prover": "cvc5@1.3.1", "time": 0.025 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/const_default.coma: -------------------------------------------------------------------------------- 1 | module M_nat 2 | use creusot.int.UInt64 3 | use creusot.prelude.Any 4 | 5 | constant const_VALUE : UInt64.t 6 | 7 | meta "compute_max_steps" 1000000 8 | 9 | meta "select_lsinst" "all" 10 | 11 | let rec nat_N (return (x: ())) = (! bb0 12 | [ bb0 = s0 [ s0 = {[@expl:assertion] const_VALUE = (0: UInt64.t)} s1 | s1 = return {_ret} ] ] 13 | [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 14 | end 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/570.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub struct S1 { 5 | pub f: i32, 6 | } 7 | 8 | pub struct S2 { 9 | pub s1: S1, 10 | } 11 | 12 | pub fn test_program(s: S2) { 13 | s.s1.f; 14 | } 15 | 16 | #[allow(unused)] 17 | pub fn test_assign(mut s: S2) -> S2 { 18 | s.s1.f = 2; 19 | s 20 | } 21 | 22 | #[allow(unused_must_use)] 23 | #[logic(open)] 24 | pub fn test_logic(s: S2) { 25 | s.s1.f; 26 | } 27 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/loops/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_while_loop_variant": { 10 | "vc_while_loop_variant": { "prover": "cvc5@1.3.1", "time": 0.026 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /verif 3 | nll-facts/ 4 | mir_dump/ 5 | 6 | # opam 7 | _opam 8 | 9 | # Creusot local config for development 10 | /.creusot-config 11 | INSTALL.opts 12 | 13 | # Creusot files 14 | *.creusot 15 | *.cmeta 16 | _creusot_erasure 17 | 18 | # Why3 Files 19 | /*.coma 20 | *.bak 21 | *~ 22 | 23 | # why3find 24 | META.json 25 | dune 26 | dune.why3find 27 | .why3find 28 | 29 | # macOS 30 | 31 | .DS_Store 32 | 33 | _opam/ 34 | 35 | # failed tests 36 | 37 | why3tests/failed 38 | -------------------------------------------------------------------------------- /creusot-contracts/tests/compile_test.rs: -------------------------------------------------------------------------------- 1 | // Test that we can build verified code without enabling unstable features 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | // Test that `ensures` removes loop invariants 6 | #[ensures(true)] 7 | pub fn f() { 8 | #[invariant(true)] 9 | for _ in 0..1 { 10 | #[creusot_contracts::invariant(true)] 11 | while false { 12 | #[::creusot_contracts::invariant(true)] 13 | loop {} 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/206/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_ex": { "vc_ex": { "prover": "cvc5@1.3.1", "time": 0.007 } }, 10 | "M_u2": { "vc_u2": { "prover": "cvc5@1.3.1", "time": 0.011 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/235.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | use mach.int.Int 3 | use creusot.prelude.Any 4 | 5 | meta "compute_max_steps" 1000000 6 | 7 | meta "select_lsinst" "all" 8 | 9 | let rec f (return (x: ())) = (! bb0 10 | [ bb0 = bb0 11 | [ bb0 = {[@expl:loop invariant] 0 <= 1} (! s0) [ s0 = any [ br0 -> {false} (! bb4) | br1 -> {true} (! bb0) ] ] ] 12 | | bb4 = return {_ret} ] [ & _ret: () = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 13 | end 14 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/weak_opacity.coma: -------------------------------------------------------------------------------- 1 | module M_f 2 | meta "compute_max_steps" 1000000 3 | 4 | meta "select_lsinst" "all" 5 | 6 | function f : int 7 | 8 | goal vc_f: [@expl:f ensures] 1 = 1 9 | end 10 | module M_g 11 | constant f: int = 1 12 | 13 | axiom f_spec: f = 1 14 | 15 | meta "compute_max_steps" 1000000 16 | 17 | meta "select_lsinst" "all" 18 | 19 | function g : int 20 | 21 | goal vc_g: f = 1 -> f = 1 && ([@expl:g ensures] 2 = 2) 22 | end 23 | -------------------------------------------------------------------------------- /tests/should_succeed/vector/09_capacity.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures((^v)@.len() == v@.len())] 5 | #[ensures(forall 0 <= i && i < v@.len() ==> (^v)[i] == v[i])] 6 | pub fn change_capacity(v: &mut Vec) { 7 | v.reserve(100); 8 | v.reserve_exact(200); 9 | v.shrink_to_fit(); 10 | v.shrink_to(1); 11 | } 12 | 13 | #[ensures((^v)@.len() == 0)] 14 | pub fn clear_vec(v: &mut Vec) { 15 | v.clear(); 16 | } 17 | -------------------------------------------------------------------------------- /nix/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | pkgs, 3 | pins, 4 | }: { 5 | pkgs = rec { 6 | alt-ergo = import ./alt-ergo.nix ({inherit pkgs;} // pins.alt-ergo); 7 | cvc4 = import ./cvc4.nix ({inherit pkgs;} // pins.cvc4); 8 | cvc5 = import ./cvc5.nix ({inherit pkgs;} // pins.cvc5); 9 | why3 = import ./why3.nix ({inherit pkgs;} // pins.why3); 10 | why3find = import ./why3find.nix ({inherit pkgs why3;} // pins.why3find); 11 | z3 = import ./z3.nix ({inherit pkgs;} // pins.z3); 12 | }; 13 | } 14 | -------------------------------------------------------------------------------- /tests/should_fail/sealed.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub trait Tr { 5 | #[logic] 6 | fn f(self, x: Int) -> Int; 7 | 8 | #[logic(open, sealed)] 9 | fn g(self, x: Int) -> Int { 10 | self.f(x) + 1 11 | } 12 | } 13 | 14 | impl Tr for Int { 15 | #[logic] 16 | fn f(self, x: Int) -> Int { 17 | self + x 18 | } 19 | 20 | #[logic] 21 | fn g(self, x: Int) -> Int { 22 | x 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/258/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_err": { "vc_err": { "prover": "cvc5@1.3.1", "time": 0.024 } }, 10 | "M_err2": { "vc_err2": { "prover": "cvc5@1.3.1", "time": 0.024 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/vector/01.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | #[ensures(forall 0 <= i && i < (^v)@.len() ==> (^v)[i] == 0u32)] 6 | #[ensures(v@.len() == (^v)@.len())] 7 | pub fn all_zero(v: &mut Vec) { 8 | let old_v = snapshot! { v }; 9 | #[invariant(v@.len() == old_v@.len())] 10 | #[invariant(forall 0 <= j && j < produced.len() ==> v[j] == 0u32)] 11 | for i in 0..v.len() { 12 | v[i] = 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/691.coma: -------------------------------------------------------------------------------- 1 | module M_example 2 | use creusot.int.UInt32 3 | use creusot.prelude.Any 4 | 5 | type t_Foo = { bar: UInt32.t } 6 | 7 | meta "compute_max_steps" 1000000 8 | 9 | meta "select_lsinst" "all" 10 | 11 | let rec example (return (x: ())) = (! bb0 12 | [ bb0 = s0 [ s0 = [ &c <- { bar = (2: UInt32.t) } ] s1 | s1 = return {_ret} ] ] 13 | [ & _ret: () = Any.any_l () | & c: t_Foo = Any.any_l () ]) [ return (result: ()) -> (! return {result}) ] 14 | end 15 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/module_paths.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | // Check that module paths are properly printed in coma. 4 | 5 | mod a { 6 | pub struct T(pub u32); 7 | } 8 | 9 | pub struct S(pub a::T); 10 | 11 | mod b { 12 | pub struct O(pub u32); 13 | 14 | pub mod c { 15 | pub struct T(pub crate::a::T); 16 | 17 | #[allow(dead_code)] 18 | pub struct U(super::O); 19 | } 20 | } 21 | 22 | pub fn test(_a: a::T, _b: S, _c: b::O, _d: b::c::T) {} 23 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/weak_opacity/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.025 } }, 10 | "M_g": { "vc_g": { "prover": "cvc5@1.3.1", "time": 0.026 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/partially_opaque/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 47, "time": 0.531 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_f": { "vc_f_A": { "prover": "cvc5@1.3.1", "time": 0.028 } }, 10 | "M_g": { "vc_g_B": { "prover": "cvc5@1.3.1", "time": 0.027 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/swap_borrows.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(result == (x.1, x.0))] 5 | fn swap(x: (T, T)) -> (T, T) { 6 | (x.1, x.0) 7 | } 8 | 9 | // The required permission Acc(_5.tuple_1.val_ref, read) cannot be obtained. 10 | pub fn f() { 11 | let (mut a, mut b) = (0, 0); 12 | let p = swap((&mut a, &mut b)); 13 | *p.0 = 10; 14 | 15 | proof_assert! { b == 10u32 }; 16 | proof_assert! { a == 0u32 }; 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/impl_trait.rs: -------------------------------------------------------------------------------- 1 | // WHY3PROVE 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | pub trait MyTrait { 6 | fn a(&self) -> bool; 7 | } 8 | 9 | impl MyTrait for () { 10 | #[ensures(result)] 11 | fn a(&self) -> bool { 12 | true 13 | } 14 | } 15 | 16 | pub fn returns_iterator() -> impl MyTrait { 17 | () 18 | } 19 | 20 | #[ensures(true)] 21 | pub fn main() { 22 | let x = returns_iterator().a(); 23 | 24 | proof_assert!(x); 25 | } 26 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/cast_ptr/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_f": { "vc_f_T": { "prover": "cvc5@1.3.1", "time": 0.027 } }, 10 | "M_thin": { "vc_thin_T": { "prover": "cvc5@1.3.1", "time": 0.025 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/simple_trigger/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_id": { "vc_id": { "prover": "cvc5@1.3.1", "time": 0.025 } }, 10 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.026 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/forall/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_f": { "vc_f": { "prover": "cvc5@1.3.1", "time": 0.01 } }, 10 | "M_omg": { "vc_omg": { "prover": "cvc5@1.3.1", "time": 0.009 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/specification/opaque.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | mod x { 5 | use creusot_contracts::prelude::*; 6 | 7 | #[logic(open)] 8 | pub fn transparent() -> bool { 9 | true 10 | } 11 | 12 | #[logic(open(crate))] 13 | pub fn transparent_crate() -> bool { 14 | true 15 | } 16 | } 17 | 18 | pub fn test() { 19 | proof_assert!(x::transparent()); 20 | proof_assert!(x::transparent_crate()); 21 | } 22 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/warn_unneeded_variant/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_variant_is_not_checked": { 10 | "vc_variant_is_not_checked": { "prover": "cvc5@1.3.1", "time": 0.01 } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /guide/highlight.js/src/languages/pearlite.js: -------------------------------------------------------------------------------- 1 | import { CREUSOT_TYPES, LITERALS, PEARLITE_KEYWORDS, TYPES, utils } from './rust.js'; 2 | 3 | export default function(hljs) { 4 | const UTILS = utils(hljs); 5 | const PEARLITE = UTILS.pearlite; 6 | return { 7 | name: 'Pearlite', 8 | aliases: [], 9 | literals: LITERALS, 10 | keywords: { 11 | keyword: PEARLITE_KEYWORDS, 12 | type: TYPES, 13 | 'creusot-type': CREUSOT_TYPES, 14 | }, 15 | contains: PEARLITE, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_fail/bug/1610-crash.rs: -------------------------------------------------------------------------------- 1 | // Test a crash when trying to implement collect 2 | // This test may become should_succeed in the future. 3 | extern crate creusot_contracts; 4 | use creusot_contracts::prelude::*; 5 | 6 | struct P(); 7 | 8 | impl ::std::iter::Iterator for P { 9 | type Item = (); 10 | fn next(&mut self) -> Option { 11 | None 12 | } 13 | 14 | fn collect>(self) -> B { 15 | std::iter::empty().collect() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/256/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_bug_256": { "vc_bug_256": { "prover": "cvc5@1.3.1", "time": 0.026 } }, 10 | "M_u8_safe": { "vc_u8_safe": { "prover": "cvc5@1.3.1", "time": 0.026 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/273/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_ex": { 10 | "vc_elim_Some": { "prover": "cvc5@1.3.1", "time": 0.025 }, 11 | "vc_ex": { "prover": "cvc5@1.3.1", "time": 0.009 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/463/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { 10 | "vc_closure0": { "prover": "cvc5@1.3.1", "time": 0.027 }, 11 | "vc_test": { "prover": "cvc5@1.3.1", "time": 0.024 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/clones/02.coma: -------------------------------------------------------------------------------- 1 | module M_program 2 | use creusot.prelude.Any 3 | 4 | predicate simple = true 5 | 6 | predicate uses_simple = simple 7 | 8 | meta "compute_max_steps" 1000000 9 | 10 | meta "select_lsinst" "all" 11 | 12 | let rec program (return (x: ())) = {[@expl:program requires] uses_simple} 13 | (! bb0 14 | [ bb0 = return {_ret} ] [ & _ret: () = Any.any_l () ]) 15 | [ return (result: ()) -> {[@expl:program ensures] simple} (! return {result}) ] 16 | end 17 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/06/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { 10 | "vc_ix_T": { "prover": "cvc5@1.3.1", "time": 0.03 }, 11 | "vc_test_T": { "prover": "cvc5@1.3.1", "time": 0.033 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/09/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test": { "vc_test_T": { "prover": "cvc5@1.3.1", "time": 0.029 } }, 10 | "M_test2": { "vc_test2_T": { "prover": "cvc5@1.3.1", "time": 0.025 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/quant.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{invariant::Invariant, prelude::*}; 3 | 4 | pub struct WithInvariant; 5 | 6 | impl Invariant for WithInvariant { 7 | #[logic(open)] 8 | fn invariant(self) -> bool { 9 | true 10 | } 11 | } 12 | 13 | #[logic(open)] 14 | #[ensures(forall x.invariant())] 15 | pub fn forall() {} 16 | 17 | #[logic(open)] 18 | #[ensures(exists<_x: WithInvariant> true)] 19 | pub fn exists() {} 20 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/168.coma: -------------------------------------------------------------------------------- 1 | module M_max_int 2 | use creusot.int.UInt64 3 | use creusot.prelude.Any 4 | 5 | constant const_MAX: UInt64.t = (18446744073709551615: UInt64.t) 6 | 7 | meta "compute_max_steps" 1000000 8 | 9 | meta "select_lsinst" "all" 10 | 11 | let rec max_int (return (x: UInt64.t)) = (! bb0 12 | [ bb0 = s0 [ s0 = [ &_ret <- const_MAX ] s1 | s1 = return {_ret} ] ] [ & _ret: UInt64.t = Any.any_l () ]) 13 | [ return (result: UInt64.t) -> (! return {result}) ] 14 | end 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/eq_panic/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_omg": { 10 | "vc_eq_ref_T": { "prover": "cvc5@1.3.1", "time": 0.01 }, 11 | "vc_omg_T": { "prover": "cvc5@1.3.1", "time": 0.01 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/printing.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | pub fn f() { 5 | print!("Hello "); 6 | println!("world!"); 7 | eprint!("Hello "); 8 | eprintln!("stderr!"); 9 | 10 | proof_assert!(1 + 1 == 2); // So we have something to prove 11 | 12 | // FIXME: not supported at the moment 13 | // print!("{} ", "Hello"); 14 | // println!("{}!", "world"); 15 | // eprint!("{} ", "Hello"); 16 | // eprintln!("{}!", "stderr"); 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/syntax/big_types/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_get_a1": { "vc_get_a1": { "prover": "cvc5@1.3.1", "time": 0.027 } }, 10 | "M_is_a1": { "vc_is_a1": { "prover": "cvc5@1.3.1", "time": 0.026 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/02/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_omg": { 10 | "vc_is_true_T": { "prover": "cvc5@1.3.1", "time": 0.024 }, 11 | "vc_omg_T": { "prover": "cvc5@1.3.1", "time": 0.029 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/vec_inv.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{invariant::Invariant, prelude::*}; 3 | 4 | pub struct SumTo10 { 5 | pub a: i32, 6 | pub b: i32, 7 | } 8 | 9 | impl Invariant for SumTo10 { 10 | #[logic(open)] 11 | fn invariant(self) -> bool { 12 | pearlite! { self.a@ + self.b@ == 10 } 13 | } 14 | } 15 | 16 | #[requires(x@.len() > 0)] 17 | pub fn vec(x: Vec<&mut SumTo10>) { 18 | proof_assert! { x[0].a@ + x[0].b@ == 10 }; 19 | } 20 | -------------------------------------------------------------------------------- /tests/should_fail/bad_borrow.stderr: -------------------------------------------------------------------------------- 1 | error[E0499]: cannot borrow `x` as mutable more than once at a time 2 | --> bad_borrow.rs:6:13 3 | | 4 | 5 | let a = &mut x; 5 | | ------ first mutable borrow occurs here 6 | 6 | let b = &mut x; 7 | | ^^^^^^ second mutable borrow occurs here 8 | 7 | 9 | 8 | *a += *b; 10 | | -------- first borrow later used here 11 | 12 | error: aborting due to 1 previous error 13 | 14 | For more information about this error, try `rustc --explain E0499`. 15 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/default_function_non_logic.stderr: -------------------------------------------------------------------------------- 1 | error: Mutually recursive functions: when calling `::g`... 2 | --> default_function_non_logic.rs:13:5 3 | | 4 | 13 | fn g() { 5 | | ^^^^^^ 6 | | 7 | note: then `::g` might call `::g` via the call to `Foo::f`. 8 | --> default_function_non_logic.rs:14:9 9 | | 10 | 14 | Self::f(); // this assumes f could call g 11 | | ^^^^^^^^^ 12 | 13 | error: aborting due to 1 previous error 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/recursion_through_contract.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | #[logic] 6 | fn with_proof_assert(x: Int) { 7 | proof_assert! { 8 | x == f1() 9 | } 10 | } 11 | 12 | #[logic] 13 | fn f1() -> Int { 14 | with_proof_assert(5); 15 | 3 16 | } 17 | 18 | #[logic] 19 | #[requires(x == f2())] 20 | fn with_requires(x: Int) {} 21 | 22 | #[logic] 23 | fn f2() -> Int { 24 | with_requires(5); 25 | 3 26 | } 27 | -------------------------------------------------------------------------------- /tests/should_succeed/all_zero/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 33, "time": 0.601 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 17, "time": 0.718 }, 6 | { "prover": "cvc4@1.8", "size": 45, "time": 0.45 } 7 | ], 8 | "proofs": { 9 | "M_all_zero": { 10 | "vc_all_zero": { "prover": "cvc5@1.3.1", "time": 0.032 }, 11 | "vc_elim_Cons": { "prover": "cvc5@1.3.1", "time": 0.027 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/1239.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // The WP transformation by `vcgen.rs` put the pair constructor 5 | // under the scope of the inner `let`, which caused accidental capture when we 6 | // were using strings as variables. 7 | #[logic(open)] 8 | #[ensures(result == (1, 2))] 9 | pub fn f() -> (Int, Int) { 10 | let x = 2; 11 | ( 12 | { 13 | let x = 1; 14 | x 15 | }, 16 | x, 17 | ) 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/271.rs: -------------------------------------------------------------------------------- 1 | #![allow(unreachable_patterns)] 2 | 3 | extern crate creusot_contracts; 4 | 5 | pub fn ex() { 6 | let a = 0; 7 | match a { 8 | _ => {} 9 | 0 => {} 10 | } 11 | } 12 | 13 | pub fn ex2() { 14 | let a = 0; 15 | match a { 16 | 0 | 1 => {} 17 | 1 => {} 18 | _ => {} 19 | } 20 | } 21 | 22 | pub fn ex3() { 23 | let a = 0; 24 | match a { 25 | 0 | 1 => {} 26 | 1 | 2 => {} 27 | _ => {} 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /tests/should_succeed/ghost/loop_in_ghost/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_foo": { 10 | "vc_foo": { "prover": "cvc5@1.3.1", "time": 0.022 }, 11 | "vc_new_u32": { "prover": "cvc5@1.3.1", "time": 0.029 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/projection_toggle.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[ensures(if toggle { result == a && ^b == *b } else { result == b && ^a == *a })] 5 | fn proj_toggle<'a, T: PartialEq>(toggle: bool, a: &'a mut T, b: &'a mut T) -> &'a mut T { 6 | if toggle { a } else { b } 7 | } 8 | 9 | pub fn f() { 10 | let mut a = 10; 11 | let mut b = 5; 12 | 13 | let x = proj_toggle(true, &mut a, &mut b); 14 | 15 | *x += 5; 16 | assert!(a == 15); 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/type_invariants/quant/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_exists": { "vc_exists": { "prover": "cvc5@1.3.1", "time": 0.025 } }, 10 | "M_forall": { "vc_forall": { "prover": "cvc5@1.3.1", "time": 0.027 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /why3/README.md: -------------------------------------------------------------------------------- 1 | # Why3 2 | 3 | A Rust library furnishing the Why3 AST used by the Creusot verifier, and its associated pretty printer. 4 | The library supports two input formats to why3: WhyML (`.mlw`), [Coma](https://coma.paulpatault.fr/) (`.coma`). 5 | 6 | As it stands the core Why3 `Exp` type is heavily burdened with tech debt associated to its evolution as an offsprout of creusot. 7 | I hope to clean this up incrementally, but if you are planning on using `why3` in a project, please contact me so I can reprioritize. 8 | 9 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/766/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_trait_Trait__goo": { 10 | "vc_f_Self": { "prover": "cvc5@1.3.1", "time": 0.026 }, 11 | "vc_goo_Self": { "prover": "cvc5@1.3.1", "time": 0.012 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/closures/09_fnonce_resolve/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_f": { 10 | "vc_closure0": { "prover": "cvc5@1.3.1", "time": 0.03 }, 11 | "vc_f": { "prover": "cvc5@1.3.1", "time": 0.023 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/lang/unions.coma: -------------------------------------------------------------------------------- 1 | module M_x 2 | use creusot.prelude.Any 3 | 4 | type t_DummyUnion 5 | 6 | predicate resolve_DummyUnion (_1: t_DummyUnion) 7 | 8 | meta "compute_max_steps" 1000000 9 | 10 | meta "select_lsinst" "all" 11 | 12 | let rec x (_1: t_DummyUnion) (return (x'0: ())) = (! bb0 13 | [ bb0 = s0 [ s0 = -{resolve_DummyUnion _1}- s1 | s1 = return {_ret} ] ] 14 | [ & _ret: () = Any.any_l () | & _1: t_DummyUnion = _1 ]) [ return (result: ()) -> (! return {result}) ] 15 | end 16 | -------------------------------------------------------------------------------- /tests/should_succeed/termination/default_impl.rs: -------------------------------------------------------------------------------- 1 | #![allow(incomplete_features)] 2 | #![feature(specialization)] 3 | 4 | extern crate creusot_contracts; 5 | use creusot_contracts::prelude::*; 6 | 7 | pub trait Foo { 8 | #[logic] 9 | fn f(); 10 | #[logic] 11 | fn g(); 12 | } 13 | default impl Foo for T { 14 | #[logic(open)] 15 | fn f() {} 16 | #[logic(open)] 17 | fn g() {} 18 | } 19 | 20 | impl Foo for () { 21 | #[logic(open)] 22 | fn g() { 23 | Self::f(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /guide/src/quickstart/editor_config.md: -------------------------------------------------------------------------------- 1 | From the root of your project, write the following in the `.vscode/settings.json` file: 2 | ```json 3 | { 4 | "rust-analyzer.check.overrideCommand": [ 5 | "cargo", 6 | "creusot", 7 | "--", 8 | "--message-format=json" 9 | ] 10 | } 11 | ``` 12 | 13 | For other editors, see to add the above option to your configuration. 14 | 15 | Note that you will probably want to enable this option _only_ in projects that use creusot. 16 | -------------------------------------------------------------------------------- /tests/should_fail/terminates/complicated_traits_recursion.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | extern crate creusot_contracts; 3 | use creusot_contracts::prelude::*; 4 | 5 | trait Foo { 6 | #[check(terminates)] 7 | fn foo() {} 8 | } 9 | 10 | impl Foo for i32 { 11 | #[check(terminates)] 12 | fn foo() { 13 | bar::>(std::iter::once(1i32)); 14 | } 15 | } 16 | 17 | #[check(terminates)] 18 | fn bar(_: I) 19 | where 20 | I: Iterator, 21 | I::Item: Foo, 22 | { 23 | I::Item::foo() 24 | } 25 | -------------------------------------------------------------------------------- /tests/should_fail/unsound_dyn.stderr: -------------------------------------------------------------------------------- 1 | warning: support for trait objects (dyn) is limited and experimental 2 | --> unsound_dyn.rs:17:42 3 | | 4 | 17 | proof_assert! { forall x.falso() == () } 5 | | ^ 6 | | 7 | = note: `#[warn(creusot::experimental)]` on by default 8 | 9 | error: forbidden dyn type: dyn False (dyn support is currently minimal, please open an issue to improve this feature) 10 | 11 | error: aborting due to 1 previous error; 1 warning emitted 12 | 13 | -------------------------------------------------------------------------------- /tests/should_succeed/closures/12_borrow_instances/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_test1": { "vc_test1_F": { "prover": "cvc5@1.3.1", "time": 0.03 } }, 10 | "M_test2": { "vc_test2_F": { "prover": "cvc5@1.3.1", "time": 0.026 } } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/should_succeed/traits/01/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_uses_generic": { 10 | "vc_from_b_T": { "prover": "cvc5@1.3.1", "time": 0.027 }, 11 | "vc_uses_generic_T": { "prover": "cvc5@1.3.1", "time": 0.028 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/trigger.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | 3 | use creusot_contracts::prelude::*; 4 | 5 | mod inner { 6 | use creusot_contracts::prelude::*; 7 | 8 | #[logic(open(self))] 9 | pub fn id(i: Int) -> Int { 10 | i 11 | } 12 | 13 | #[logic(open(self))] 14 | #[ensures(forall #[trigger(id(i), id(j))] i <= j ==> id(i) <= id(j))] 15 | pub fn id_mono() {} 16 | } 17 | use inner::*; 18 | 19 | #[ensures(id(5) >= id(2))] 20 | pub fn test() { 21 | snapshot!(id_mono); 22 | } 23 | -------------------------------------------------------------------------------- /tests/should_fail/bug/ice-final-borrows.stderr: -------------------------------------------------------------------------------- 1 | error[E0594]: cannot assign to `*x`, which is behind a `&` reference 2 | --> ice-final-borrows.rs:9:5 3 | | 4 | 9 | *x = 1; 5 | | ^^^^^^ `x` is a `&` reference, so it cannot be written to 6 | | 7 | help: consider changing this to be a mutable reference 8 | | 9 | 8 | pub fn mutates_immutable(x: &mut i32) { 10 | | +++ 11 | 12 | error: aborting due to 1 previous error 13 | 14 | For more information about this error, try `rustc --explain E0594`. 15 | -------------------------------------------------------------------------------- /tests/should_fail/trait_item_types_mismatch.stderr: -------------------------------------------------------------------------------- 1 | error: Expected implementation of trait `Trusted` for `()` to be marked as `#[trusted]` 2 | --> trait_item_types_mismatch.rs:7:1 3 | | 4 | 7 | impl Trusted for () {} 5 | | ^^^^^^^^^^^^^^^^^^^ 6 | 7 | error: Expected `my_predicate` to be a logic function as specified by the trait declaration 8 | --> trait_item_types_mismatch.rs:17:5 9 | | 10 | 17 | fn my_predicate() -> bool { 11 | | ^^^^^^^^^^^^^^^^^^^^^^^^^ 12 | 13 | error: aborting due to 2 previous errors 14 | 15 | -------------------------------------------------------------------------------- /tests/should_fail/unsound_dyn.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | // - Any `trait Tr` is implemented by `dyn Tr`, 5 | // - but `trait False` below has no valid implementation. 6 | // Contradiction. 7 | // 8 | // We prevent this by restricting the traits allowed in `dyn`. 9 | pub trait False { 10 | #[logic] 11 | #[ensures(false)] 12 | fn falso(&self); 13 | } 14 | 15 | #[ensures(false)] 16 | pub fn unsound() { 17 | proof_assert! { forall x.falso() == () } 18 | } 19 | -------------------------------------------------------------------------------- /tests/should_succeed/trigger/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 46, "time": 0.541 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_inner__id_mono": { 10 | "vc_id_mono": { "prover": "cvc5@1.3.1", "time": 0.025 } 11 | }, 12 | "M_test": { "vc_test": { "prover": "cvc5@1.3.1", "time": 0.027 } } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/trigger2.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(prophetic)] 5 | #[ensures(resolve(seq) ==> result)] 6 | fn resolve_seq(seq: Vec<&mut T>) -> bool { 7 | pearlite! { 8 | forall #[trigger(seq@[i])] 0 <= i && i < seq@.len() ==> 9 | *seq@[i] == ^seq@[i] 10 | } 11 | } 12 | 13 | #[logic(open(self), prophetic)] 14 | #[ensures(resolve(seq) ==> result)] 15 | pub fn resolve_seq2(seq: Vec<&mut T>) -> bool { 16 | resolve_seq(seq) 17 | } 18 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/564.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::prelude::*; 3 | 4 | #[logic(open)] 5 | #[requires(invariants())] 6 | pub fn emits_pure_eq() -> bool { 7 | pearlite! { 8 | (1i32 == 1i32) == true 9 | } 10 | } 11 | 12 | #[logic(open)] 13 | #[requires(invariants())] 14 | #[allow(unused_parens)] 15 | pub fn emits_pure_implies() -> bool { 16 | pearlite! { 17 | (1i32 == 1i32) ==> true 18 | } 19 | } 20 | 21 | #[logic] 22 | pub fn invariants() -> bool { 23 | true 24 | } 25 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/962/proof.json: -------------------------------------------------------------------------------- 1 | { 2 | "profile": [ 3 | { "prover": "cvc5@1.3.1", "size": 47, "time": 0.522 }, 4 | { "prover": "z3@4.15.3", "size": 30, "time": 0.165 }, 5 | { "prover": "alt-ergo@2.6.2", "size": 16, "time": 0.232 }, 6 | { "prover": "cvc4@1.8", "size": 40, "time": 0.506 } 7 | ], 8 | "proofs": { 9 | "M_disjoint_captures": { 10 | "vc_closure2": { "prover": "cvc5@1.3.1", "time": 0.033 }, 11 | "vc_disjoint_captures": { "prover": "cvc5@1.3.1", "time": 0.029 } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /tests/should_succeed/bug/vcgen.rs: -------------------------------------------------------------------------------- 1 | extern crate creusot_contracts; 2 | use creusot_contracts::{logic::FSet, prelude::*}; 3 | 4 | #[logic] 5 | #[requires(!s.is_empty())] 6 | #[variant(s.len())] 7 | #[ensures(s.contains(result))] 8 | #[ensures(forall s.contains(o) ==> o <= result )] 9 | pub fn set_max(s: FSet) -> Int { 10 | let x = s.peek(); 11 | let s = s.remove(x); 12 | 13 | if s.is_empty() { 14 | x 15 | } else { 16 | let rec = set_max(s); 17 | if x >= rec { x } else { rec } 18 | } 19 | } 20 | --------------------------------------------------------------------------------