const panic with formatting

Overview

Rust crates-io api-docs

For panicking with formatting in const contexts.

This library exists because the panic macro was stabilized for use in const contexts in Rust 1.57.0, without formatting support.

All of the types that implement the PanicFmt trait can be formatted in panics.

Examples

Basic

use const_panic::concat_panic;

const FOO: u32 = 10;
const BAR: u32 = 0;
const _: () = assert_non_zero(FOO, BAR);

#[track_caller]
const fn assert_non_zero(foo: u32, bar: u32) {
    if foo == 0 || bar == 0 {
        concat_panic!("\nneither foo nor bar can be zero!\nfoo: ", foo, "\nbar: ", bar)
    }
}

The above code fails to compile with this error:

error[E0080]: evaluation of constant value failed
 --> src/lib.rs:17:15
  |
8 | const _: () = assert_non_zero(FOO, BAR);
  |               ^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at '
neither foo nor bar can be zero!
foo: 10
bar: 0', src/lib.rs:8:15

Custom types

Panic formatting for custom types can be done in these ways (in increasing order of verbosity):

  • Using the impl_panicfmt macro (requires the default-enabled "non_basic" feature)
  • Using the flatten_panicvals macro (requires the default-enabled "non_basic" feature)
  • Manually implementing the PanicFmt trait as described in its docs.

This example uses the impl_panicfmt approach.

use const_panic::concat_panic;

const LAST: u8 = {
    Foo{
        x: &[],
        y: Bar(false, true),
        z: Qux::Left(23),
    }.pop().1
};

impl Foo<'_> {
    /// Pops the last element
    ///
    /// # Panics
    ///
    /// Panics if `self.x` is empty
    #[track_caller]
    const fn pop(mut self) -> (Self, u8) {
        if let [rem @ .., last] = self.x {
            self.x = rem;
            (self, *last)
        } else {
            concat_panic!(
                "\nexpected a non-empty Foo, found: \n",
                // uses alternative Debug formatting for `self`,
                // otherwise this would use regular Debug formatting.
                alt_debug: self
            )
        }
    }
}

struct Foo<'a> {
    x: &'a [u8],
    y: Bar,
    z: Qux,
}

// You need to replace non-static lifetimes with `'_` here.
const_panic::impl_panicfmt! {
    impl Foo<'_>;

    struct Foo {
        x: &[u8],
        y: Bar,
        z: Qux,
    }
}

struct Bar(bool, bool);

const_panic::impl_panicfmt! {
    impl Bar;

    struct Bar(bool, bool);
}

enum Qux {
    Up,
    Down { x: u32, y: u32 },
    Left(u64),
}

const_panic::impl_panicfmt!{
    impl Qux;

    enum Qux {
        Up,
        Down { x: u32, y: u32 },
        Left(u64),
    }
}

The above code fails to compile with this error:

error[E0080]: evaluation of constant value failed
  --> src/lib.rs:57:5
   |
7  | /     Foo{
8  | |         x: &[],
9  | |         y: Bar(false, true),
10 | |         z: Qux::Left(23),
11 | |     }.pop().1
   | |___________^ the evaluated program panicked at '
expected a non-empty Foo, found: 
Foo {
    x: [],
    y: Bar(
        false,
        true,
    ),
    z: Left(
        23,
    ),
}', src/lib.rs:11:7

Limitations

Arguments to the formatting/panicking macros must have a fully inferred concrete type, because const_panic macros use duck typing to call methods on those arguments.

One effect of that limitation is that you will have to pass suffixed integer literals (eg: 100u8) when those integers aren't inferred to be a concrete type.

Cargo features

  • "non_basic"(enabled by default): Enables support for formatting structs, enums, and arrays.

Without this feature, you can effectively only format primitive types (custom types can manually implement formatting with more difficulty).

Plans

Adding a derive macro, under an opt-in "derive" feature.

No-std support

const_panic is #![no_std], it can be used anywhere Rust can be used.

Minimum Supported Rust Version

This requires Rust 1.57.0, because it uses the panic macro in a const context.

You might also like...
Asserts const generic expressions at build-time.

build_assert build_assert allows you to make assertions at build-time. Unlike assert and some implementations of compile-time assertions, such as stat

Cross-platform Rust library for coloring and formatting terminal output
Cross-platform Rust library for coloring and formatting terminal output

Coloring terminal output Documentation term-painter is a cross-platform (i.e. also non-ANSI terminals) Rust library for coloring and formatting termin

 create and test the style and formatting of text in your terminal applications
create and test the style and formatting of text in your terminal applications

description: create and test the style and formatting of text in your terminal applications docs: https://docs.rs/termstyle termstyle is a library tha

English formatting for unsigned integer IDs

English formatting for unsigned integers. Useful for encoding large IDs in a human-readable and recognizable format.

Fmt-rfcs - RFCs for Rust formatting guidelines and changes to Rustfmt

Rust code formatting RFCs This repository exists to decide on a code style for Rust code, to be enforced by the Rustfmt tool. Accepted RFCs live in th

Vari (Väri) is a Rust library for formatting strings with colors and cosmetic stuff to the terminal.
Vari (Väri) is a Rust library for formatting strings with colors and cosmetic stuff to the terminal.

Vari Vari (Väri) is a Rust library for formatting strings with colors and cosmetic stuff to the terminal. Like Rich library for Python. Väri means "co

This crate provides high-performance formatting and parsing routines for ISO8061 timestamps

ISO8061 Timestamp This crate provides high-performance formatting and parsing routines for ISO8061 timestamps, primarily focused on UTC values but wit

Monorepo for dprint—a pluggable and configurable code formatting platform

dprint Monorepo for dprint—a pluggable and configurable code formatting platform. This project is under active early development. I recommend you chec

Wealthy Rich ported to Rust! This aims to be a crate for rich text and beautiful formatting in the terminal

Wealthy Rich ported to Rust! This aims to be a crate for rich text and beautiful formatting in the terminal

Fast, minimal, feature-rich, extended formatting syntax for Rust!

Formatting Tools Fast, minimal, feature-rich, extended formatting syntax for Rust! Features include: Arbitrary expressions inside the formatting brace

🍅 A command-line tool to get and set values in toml files while preserving comments and formatting

tomato Get, set, and delete values in TOML files while preserving comments and formatting. That's it. That's the feature set. I wrote tomato to satisf

Custom formatting for Rust.

custom-format This crate extends the standard formatting syntax with custom format specifiers, by providing custom formatting macros. It uses : (a spa

Sleek is a CLI tool for formatting SQL. It helps you maintain a consistent style across your SQL code, enhancing readability and productivity.

Sleek: SQL Formatter ✨ Sleek is a CLI tool for formatting SQL. It helps you maintain a consistent style across your SQL code, enhancing readability an

A crate providing a tracing-subscriber layer for formatting events so Datadog can parse them

Datadog Formatting Layer A crate providing a tracing-subscriber layer for formatting events so Datadog can parse them. Features Provides a layer for t

⚡️Highly efficient data and string formatting library for Rust.

⚡️Highly efficient data and string formatting library for Rust. 🔎 Overview Pad and format string slices and generic vectors efficiently with minimal

Social media style compact number formatting for rust.

prettty-num Format integers into a compact social media style format, similar to using Intl.NumberFormat("en", { notation: "compact" }); as a number f

Comments
  • Avoid `clippy::equatable_if_let`

    Avoid `clippy::equatable_if_let`

    I'm not sure why there was a let to begin with, I hope this wasn't a workaround for something. This "fix" would avoid triggering a false-positive of clippy::equatable_if_let.

    See https://github.com/rust-lang/rust-clippy/issues/9066.

    opened by daxpedda 4
Releases(0.2.7)
  • 0.2.7(Nov 28, 2022)

    This release adds a concat_ macro, for concatenating PanicFmt values into a &'static str.

    Changelog

    0.2.7

    Added concat_ macro, which requires "non_basic" feature.

    Added TypeDelim::{close, open} methods.

    Made ArrayString::as_bytes take constant time when the "rust_1_64" feature is enabled.

    Made "derive" feature enable "non_basic" feature.

    Added konst_kernel = 0.3 dependency, enabled by "non_basic" feature.

    Source code(tar.gz)
    Source code(zip)
  • 0.2.5(Oct 10, 2022)

    Adds char, slice-of-char, and core::str::Utf8Error formatting support.

    Changelog

    0.2.5

    Added "rust_1_64" feature, which enables formatting impls which require newer versions.

    Added core::str::Utf8Error formatting (requires "rust_1_64" feature)

    Added formatting support for char and slices of char.

    Source code(tar.gz)
    Source code(zip)
  • 0.2.0(Nov 20, 2021)

    This release adds a PanicFmt derive, generic type support to impl_panicfmt macro, hexadecimal/binary formatting, and a concat_assert assertion macro.

    Changelog

    0.2

    0.2.0

    Added concat_assert macro.

    Added PanicFmt derive macro.

    Added "derive" crate feature, to enable the PanicFmt derive.

    Made breaking changes to impl_panicfmt to allow generic implementations with type and const parameters.

    Added NumberFmt enum, for choosing how numbers are formatted.

    Added FmtArg::{BIN, ALT_BIN, HEX. ALT_HEX} associated constants.

    Added FmtArg::{set_hex, set_bin} methods.

    Added PanicVal::from_short_str constructor.

    Added support for binary and hexadecimal formatting in macros.

    Added PackedFmtArg type (which requires the non_basic feature).

    Added const_panic::fmt::SHORT_STRING_CAP constant with the capacity of a ShortString.

    Changed PanicVal such that only strings can be left or right padded.

    Removed the PanicVal::{set_leftpad, set_rightpad} methods.

    Declared const_panic_proc_macros crate, depended by const_panic when the "derive" feature is enabled.

    0.1

    0.1.1

    Added PanicFmt-based formatting for these types(all of which require the "non_basic" feature):

    • Options of integer, bool, and &str
    • Options of arrays and slices (of integer, bool, and &str)
    • NonZero* integers, and Options of them
    • NonNull, and Options of them
    • *const T and *mut T
    • std::cmp::Ordering, and Options of them
    • std::sync::atomic::Ordering
    • std::ops::Range* types, parameterized with usize.
    • ()
    • std::marker::PhantomData
    • std::marker::PhantomPinned
    • StdWrapper

    Added these macros:

    • unwrap_ok
    • unwrap_err
    • unwrap_some

    Fixed signature of to_panicvals for arrays and slices of PanicVals, by adding a FmtArg parameter.

    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Oct 23, 2021)

    This initial release comes with the ability to do const panics with formatting. The types that can be formatted are all the primitive types, and user-defined types that implement formatting by using the macros from this crate.

    Source code(tar.gz)
    Source code(zip)
Owner
null
English formatting for unsigned integer IDs

English formatting for unsigned integers. Useful for encoding large IDs in a human-readable and recognizable format.

Khonsu Labs 4 Sep 10, 2022
Const equivalents of many [`bytemuck`] functions, and a few additional const functions.

Const equivalents of many bytemuck functions, and a few additional const functions. constmuck uses bytemuck's traits, so any type that implements thos

null 6 Nov 4, 2021
😱 Panic messages for humans.

human-panic Panic messages for humans. Handles panics by calling std::panic::set_hook to make errors nice for humans. Documentation Crates.io Why? Whe

Rust CLI WG 997 Jan 1, 2023
A panic hook for wasm32-unknown-unknown that logs panics with console.error

console_error_panic_hook This crate lets you debug panics on wasm32-unknown-unknown by providing a panic hook that forwards panic messages to console.

Rust and WebAssembly 241 Jan 3, 2023
Playboy is a Nintendo Gameboy emulator for the Panic Playdate written in Rust

Playboy Playboy is a Nintendo Gameboy emulator for the Panic Playdate! Building Playdate isn't exactly a Tier 1 platform for Rust :) As a result, the

Adam Soutar 121 Jan 5, 2023
Utf8 to utf16 conversion functions for use in const contexts

const-utf16 utf8 to utf16 conversion functions useable in const contexts. Use const HELLO_WORLD_UTF16: &[u16]= const_utf16::encode!("Hello, world!");

Ryan Levick 16 Dec 8, 2021
Statically sized matrix using a definition with const generics

Statically sized matrix using a definition with const generics

DenTaku 3 Aug 2, 2022
Rust Uint crate using const-generics

Rust uint crate using const-generics Implements [Uint<BITS, LIMBS>], the ring of numbers modulo $2^{\mathtt{BITS}}$ . It requires two generic argument

Remco Bloemen 63 Dec 29, 2022
An alternative to `qcell` and `ghost-cell` that instead uses const generics

Purpose This crate is another attempt at the ghost-cell / qcell saga of cell crates. This provides an alternative to std::cell::RefCell that can allow

SpencerBeige 5 Feb 9, 2023
Extension trait to chunk iterators into const-length arrays.

const-chunks This crate provides an extension trait that lets you chunk iterators into constant-length arrays using const generics. See the docs for m

Louis Gariépy 6 Jun 12, 2023