Macro adhesion::contract [] [src]

macro_rules! contract {
    (
        $(#[$attribute: meta])*
        $(pub$(($access_modifier: ident))*)* fn $fn_name: ident $($tail: tt)*
    ) => { ... };
    (
        @after_bracket_generics,
        $(#[$attribute: meta])* $(pub$(($access_modifier: ident))*)* fn $fn_name: ident,
        {
            constr: [$($constr: tt)*],
        },
        $args: tt $( -> $return_type: ty)* where $($tail: tt)*
    ) => { ... };
    (
        @after_bracket_generics,
        $(#[$attribute: meta])* $(pub$(($access_modifier: ident))*)* fn $fn_name: ident,
        {
            constr: [$($constr: tt)*],
        },
        $args: tt $( -> $return_type: ty)*
        {
            $($block: tt)*
        }
        $($tail: tt)*
    ) => { ... };
    (
        @after_where_generics,
        $(#[$attribute: meta])* $(pub$(($access_modifier: ident))*)* fn $fn_name: ident,
        {
            constr: [$($constr: tt)*],
        },
        $args: tt $( -> $return_type: ty)*,
        {
            clause: [$($where_clause: tt)*],
            preds: $preds: tt,
        },
        {
            $($block: tt)*
        }
        $($tail: tt)*
    ) => { ... };
    (
        @repeat
    ) => { ... };
    (
        @repeat
        $($tail: tt)+
    ) => { ... };
}

Converts one or more fn definitions inside to be contracted functions that may have pre- and post-condition checks. The following blocks are valid:

  1. pre -- runs once before body.
  2. body -- the main part of the function. This is the reason the function exists!
  3. post -- runs once after body.
  4. double_check -- runs twice; after pre, and before post.

When every contract block is being utilized, the final order of the checks inserted into the contract definition are as follows:

  1. pre
  2. double_check
  3. body
  4. double_check
  5. post

No blocks in this macro are required, nor is any specific order required.

Examples

contract! {
    fn asdf(asda: bool, stuff: u64) -> bool {
        pre {
            assert!(stuff < 30, "pre-condition violation");
        }
        body {
            asda
        }
        post(return_value) {
            assert!(return_value == (stuff % 3 == 0), "post-condition violation");
        }
        double_check {
            assert!(stuff > 5, "double_check violation");
        }
    }
}

assert_that!(asdf(true, 7), panics); // post failure
assert_that!(asdf(true, 64), panics); // pre failure
assert_that!(asdf(false, 3), panics); // double_check failure
asdf(true, 6);
asdf(false, 7);
asdf(false, 11);
asdf(true, 24);