safety-guard

Crates.iosafety-guard
lib.rssafety-guard
version0.1.9
sourcesrc
created_at2019-03-12 19:21:03.330022
updated_at2019-04-06 17:49:41.810612
description#[safety] attribute to generate a corresponding doc entry and a debug assertion if a constraint is specified.
homepage
repositoryhttps://gitlab.com/tdiekmann/safety-guard
max_upload_size
id120337
size25,603
maintainers (github:rust-bus:maintainers)

documentation

https://docs.rs/safety-guard

README

Adds a #[safety] attribute for functions. The attribute adds a # Safety section to the documentation of the function and tests the given constraints in debug builds.

The attribute has four different forms:

  • #[safety("Description")]: Only the description is included in the documentation.
  • #[safety(assert(constraint), "Description")]: constraint must evaluate to true.
  • #[safety(eq(lhs, rhs), "Description")]: lhs and rhs needs to be equal
  • #[safety(ne(lhs, rhs), "Description")]: lhs and rhs must not be equal

A function with a #[safety] attribute must be marked as unsafe. Otherwise a compile error is generated.

If # Safety already exists in the documentation, the heading is not added.

Examples

#[safety(assert(lhs.checked_add(rhs).is_some()), "`lhs` + `rhs` must not overflow")]
unsafe fn add_unchecked(lhs: usize, rhs: usize) -> usize {
    lhs + rhs
}

generates

/// # Safety
/// - `lhs` + `rhs` must not overflow
unsafe fn add_unchecked(lhs: usize, rhs: usize) -> usize {
    debug_assert!(lhs.checked_add(rhs).is_some(), "`lhs` + `rhs` must not overflow");
    lhs + rhs
}

Without a constraint, only the documentation is added:

#[safety("`hash` must correspond to the `string`s hash value")]
unsafe fn add_string_with_hash(string: &str, hash: u64) -> u64 {
    // ...
}

generates

/// # Safety
/// - `hash` must correspond to the `string`s hash value
unsafe fn add_string_with_hash(string: &str, hash: u64) -> u64 {
    // ...
}

It is also possible to use multiple #[safety] attributes:

#[safety(eq(ptr as usize % layout.align(), 0), "`layout` must *fit* the `ptr`")]
#[safety(assert(new_size > 0), "`new_size` must be greater than zero")]
#[safety(
    "`new_size`, when rounded up to the nearest multiple of `layout.align()`, must not \
    overflow (i.e., the rounded value must be less than `usize::MAX`)."
)]
unsafe fn realloc(
    ptr: *mut u8,
    layout: Layout,
    new_size: usize,
) -> *mut u8 {
    // ...
}

However, the documentation is generated in reversed order:

/// # Safety
/// - `new_size`, when rounded up to the nearest multiple of `layout.align()`, must not
///   overflow (i.e., the rounded value must be less than `usize::MAX`).
/// - `new_size` must be greater than zero
/// - `layout` must *fit* the `ptr`
unsafe fn realloc(
    ptr: *mut u8,
    layout: Layout,
    new_size: usize,
) -> *mut u8 {
    debug_assert!(new_size > 0, "`new_size` must be greater than zero");
    debug_assert_eq!(ptr as usize % layout.align(), 0, "`layout` must *fit* the `ptr`");
    // ...
}
Commit count: 30

cargo fmt