#casts #cast-checks #cast #compiler

cast_checks

A procedural macro to check for invalid casts

7 releases

new 0.1.6 Apr 20, 2025
0.1.5 May 3, 2024
0.1.4 Oct 5, 2023
0.1.3 Jul 25, 2023
0.1.1 Mar 26, 2023

#683 in Rust patterns

Download history 30/week @ 2024-12-31 48/week @ 2025-01-07 74/week @ 2025-01-14 2/week @ 2025-01-21 122/week @ 2025-01-28 75/week @ 2025-02-04 115/week @ 2025-02-11 16/week @ 2025-02-18 16/week @ 2025-02-25 75/week @ 2025-03-04 196/week @ 2025-03-11 46/week @ 2025-03-18 33/week @ 2025-03-25 25/week @ 2025-04-01 58/week @ 2025-04-08 128/week @ 2025-04-15

251 downloads per month
Used in test-fuzz

MIT/Apache

11KB

cast_checks

A procedural macro to check for invalid casts

Like -C overflow-checks, cast_checks is enabled only for debug builds by default. To enable cast_checks for release builds, set the crate-level release feature.

How it works

cast_checks::enable essentially rewrites each expression of the form:

expr as T

to an expression involving try_into:

<_ as TryInto::< T >>::try_into( expr ).expect("invalid cast")

So when an invalid cast occurs, a message like the following results:

thread 'checked_truncation' panicked at 'invalid cast: TryFromIntError(())', cast_checks/tests/basic.rs:30:13

We say "essentially rewrites" because the actual generated code is slightly more complex. It uses Nikolai Vazquez's impls' trick to determine whether an appropriate TryInto implementation exists.

How to use

With a stable compiler

You must use cast_checks::enable as an outer attribute. Example:

#[cast_checks::enable]
fn as_u16(x: u64) -> u16 {
    x as u16
}

With a nightly compiler

We recommend enabling Rust features custom_inner_attributes and proc_macro_hygiene.

If you enable the custom_inner_attributes and proc_macro_hygiene features, you can use cast_checks::enable as an inner attribute. Example:

#![feature(custom_inner_attributes, proc_macro_hygiene)]

mod m {
    #![cast_checks::enable]

    /* items */
}

CAST_CHECKS_LOG

If you are concerned that some casts are not being checked, try setting CAST_CHECKS_LOG and passing the procmacro2_semver_exempt config flag when compiling, e.g.:

CAST_CHECKS_LOG=1 RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build

This will cause cast_checks to dump to standard output:

  • all rewritten locations
  • all modules whose contents are not visited because they are not inlined

Example:

cast_checks rewriting `x as u16` at src/lib.rs:3:0
cast_checks not descending into `mod c ;` at src/lib.rs:3:0

Note that CAST_CHECKS_LOG requires --cfg procmacro2_semver_exempt to be passed to rustc.

Dependencies

~190–620KB
~15K SLoC