• Stars
    star
    247
  • Rank 158,883 (Top 4 %)
  • Language
    Rust
  • Created almost 10 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Design by contract style assertions for Rust

LibHoare

Simple Rust support for design by contract-style assertions. Supports

  • preconditions (precond),
  • postconditions (postcond),
  • invariants (pre and post) (invariant).

Each macro takes a predicate given as a string parameter. Each macro is available in a debug_ version which only checks the assertion in debug builds, they should be zero overhead in non-debug builds. You can use result inside a postcondition to get the value returned by the function.

Preconditions are checked on entry to a function. Postconditions are checked when leaving the function by any path.

(The library is named for Tony, not Graydon. Or rather it is named for the logic which was named after Tony).

Using libhoare

You can use libhoare with Cargo by adding

[dependencies.hoare]
git = "https://github.com/nick29581/libhoare.git"

to your projects Cargo manifest.

Otherwise, download this repo, build it (see build instructions below), make sure the path to the compiled libhoare is on your library path in some way (one way of doing this is to export LD_LIBRARY_PATH=/path/to/libhoare/obj before building).

Then (whether or not you used Cargo), in your crate you will need the following boilerplate:

#![feature(plugin, custom_attribute)]

#![plugin(hoare)]

Then you can use the macros as shown below.

Examples:

#[precond="x > 0"]
#[postcond="result > 1"]
fn foo(x: int) -> int {
    let y = 45 / x;
    y + 1
}


struct Bar {
    f1: int,
    f2: int
}

#[invariant="x.f1 < x.f2"]
fn baz(x: &mut Bar) {
    x.f1 += 10;
    x.f2 += 10;
}

fn main() {
    foo(12);
    foo(26);
    // task '<main>' failed at 'precondition of foo (x > 0)'
    // foo(-3);

    let mut b = Bar { f1: 0, f2: 10 };
    baz(&mut b);
    b.f2 = 100;
    baz(&mut b);
    b.f2 = -5;
    // task '<main>' failed at 'invariant entering baz (x.f1 < x.f2)'
    // baz(&mut b);
}

You can use contracts on methods as well as functions, but they are not as well tested.

Contents

All the code for checking conditions is in libhoare. Currently, there is only a single file, lib.rs.

The test directory contains unit tests for the library.

The eg directory contains a few examples of how to use the library:

  • hello.rs is a very simple (hello world!) example of how to use an invariant (useful as a basic test case);
  • doc.rs contains the examples above, so we can check they compiler and run;
  • lexer.rs is a more realistic example of use - a simple (and certainly not industrial-strength) lexer for a very small language.

Building

To build libhoare from the top level of your checked out repo run

cargo build

(if using cargo) or

$RUSTC ./libhoare/lib.rs

This will create libhoare.rs in the current directory, you might want to specify an output file using -o.

To build the examples run eg.sh in the top level and to run the tests run tests.sh. Both of these assume that you have a sibling directory called obj and that you used

$RUSTC ./libhoare/lib.rs -o "../obj/libhoare.so"

to build libhoare. Examples are created in ../obj

TODO

  • add tests to RustCI
  • tests for debug_ versions of macros - what is the best way to test this?
  • better use of macro stuff? (I'm a total beginner at syntax extensions, this all could probably be implemented better).
  • better spans.
  • better names for scopes (<precondition> rather than <quote expansion>, etc. These appear in the user-visible error messages, so it would be nice if they could be informative).

Wish list:

  • object invariants (I think this would need compiler support, if it is possible at all. You would add [#invariant="..."] to a struct, enum, etc. and the invariant would be checked on entering and leaving every method defined in any impl for the object).

More Repositories

1

r4cppp

Rust for C++ programmers
Rust
3,348
star
2

derive-new

derive simple constructor functions for Rust structs
Rust
499
star
3

graphql

A Rust GraphQL server framework
Rust
237
star
4

xmas-elf

elf parser and navigation tool, pure Rust
Rust
152
star
5

rustaceans.org

Backing data for
150
star
6

ezio

Easy IO for Rust
Rust
103
star
7

portable-interoperable

Async fundamentals initiative: portable and interoperable
74
star
8

apr-intro

An alternate introdcution to the APR book
60
star
9

talks

Slides and artifacts for talks
57
star
10

stupid-stats

Tutorial and demo of rust compiler replacement tooling
Rust
54
star
11

proc-macro-rules

Macro-rules-style syntax matching for procedural macros
Rust
49
star
12

zero

A Rust library for zero-allocation parsing of binary data.
Rust
47
star
13

error-docs

Documentation of Rust error handling
46
star
14

darkly

Rust
40
star
15

callgraph.rs

Callgraphs for Rust programs
Rust
32
star
16

rfc-index

A curated index of Rust RFCs
Rust
26
star
17

find-work

find something Rusty to work on
Rust
20
star
18

big-book-ffi

The Big Book of Rust Interop
20
star
19

provide-any

Proposed API for type-driven member access
Rust
10
star
20

leb128

Implementation of LEB128 encoding in Rust
Rust
9
star
21

mentor-rfcs

A place to improve your RFC writing skills and collaborate on writing RFCs
9
star
22

async-io-traits

Async versions of io traits
Rust
8
star
23

tikv-bench

Rust
7
star
24

rust-dxr

Rust indexing in DXR
7
star
25

rustdoc-highlight

A Rust syntax highlighting library
Rust
5
star
26

box-error

A library for error handling using boxed errors
Rust
4
star
27

gh-velocity

measure the velocity of PRs landing in GitHub
Rust
3
star
28

clyde

wip
Rust
3
star
29

grpc-snoop

A tool to capture TiKV gRPC messages
Go
3
star
30

survey-processing

Utility code for processing Rust's annual survey
Rust
3
star
31

N

PL Semantics Tool
Python
3
star
32

parcom

Rust
2
star
33

tmit

This Month in TiKV
2
star
34

owned-buf

An owned buffer type for reading into possibly uninitialized memory
Rust
2
star
35

github-issues-import

Fork of IQAndreas/github-issues-import
Python
2
star
36

triage

Scripts for helping with Rust issue triage
JavaScript
2
star
37

rustc-perf-data

1
star
38

grpc-benchmark

Shell
1
star
39

macro-libs

Design a proc macro library for Rust
1
star
40

collections

having some fun implementing basic data structures in Rust
Rust
1
star
41

fmtfmt

very WIP ideas for a generic formatting tool
Rust
1
star
42

read-buf

Very sketchy experimentation with ReadBuf things
Rust
1
star
43

raft-proto

Rust
1
star
44

ios-apnea

experiments in ios apps (an apnea timer)
Swift
1
star
45

ray

Rust and JS ray tracers
Rust
1
star
46

grpc-rs-squashed

grpc-rs without any Git history
Rust
1
star
47

derive-display-rfc

repo for collaborating on an RFC for derive display
1
star