Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Known limitations

Formal verification provides strong guarantees about your code. Nevertheless, it is important to be aware of the limits of what one has specified. Creusot users should take note of the following limitations.

Some panics are allowed

The Vec methods that increase capacity (push, insert, extend, etc.) panic if the capacity overflows. The current contracts in creusot-contracts do not prevent this.

Because Vec is such a fundamental type, bounding its length is quite cumbersome. Moreover, you will probably run out of memory (another kind of failure that Creusot does not prevent) before the capacity overflows. There remains one notable blind spot: a Vec of a zero-sized type enables triggering this panic quite easily.

Architecture specificity

Creusot compiles code for some given target architecture, so the resulting proofs are only valid for that architecture.

An important consequence is that the sizes of many types are constants which depend on the architecture or compiler optimizations. In particular, this affects the value of usize::MAX and the sizes of repr(Rust) types. The latter are technically unspecified by The Rust Reference: Type Layout.

vec! macro

The vec! macro of Rust’s standard library uses special magic to initialize memory slightly more efficiently. Creusot does not support this magic, hence the version provided by the standard library is not supported in Creusot.

Instead, we provide the replacement macro creusot_contracts::std::vec::vec, which has the same semantics and can be used in Creusot, albeit being slightly less efficient (the content of the vector is first allocated in the stack, and then moved to the newly allocated vector, instead of being directly initialized in the heap). It needs to be explicitly imported in order to not conflict with Rust’s default implementation.