├── 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 |
--------------------------------------------------------------------------------