Skip to content

A Rust crate that defines the ToBoundedStatic and IntoBoundedStatic traits

License

Notifications You must be signed in to change notification settings

fujiapple852/bounded-static

Folders and files

NameName
Last commit message
Last commit date

Latest commit

b2e32db · Feb 22, 2025
Aug 7, 2024
Feb 22, 2025
Aug 7, 2024
Feb 14, 2022
Jun 23, 2024
Jul 28, 2024
Feb 17, 2022
Jun 23, 2024
Nov 21, 2024

Repository files navigation

ci Documentation Crate

Bounded Static

This crate defines the ToBoundedStatic and IntoBoundedStatic traits, the ToStatic macro and provides impls for common types. This crate has zero-dependencies, is no_std friendly and forbids unsafe code.

As described in the Common Rust Lifetime Misconceptions:

T: 'static should be read as "T is bounded by a 'static lifetime" not "T has a 'static lifetime".

The traits ToBoundedStatic and IntoBoundedStatic can be used to convert any suitable T and &T to an owned T such that T: 'static. Both traits define an associated type which is bounded by 'static and provide a method to convert to that bounded type.

The macros ToStatic can be used to automatically derive ToBoundedStatic and IntoBoundedStatic for any struct or enum that can be converted to a form that is bounded by 'static.

Refer to the crate documentation for details and examples.

FAQ

When is this useful?

This is useful for data structures which directly or indirectly contain Cow<T> types that must be supplied to a function which requires the 'static bound (i.e. std::thread::spawn):

#[derive(Debug, PartialEq, ToStatic)]
struct Foo<'a> {
    foo: Cow<'a, str>,
    bar: Vec<Bar<'a>>
}
#[derive(Debug, PartialEq, ToStatic)]
enum Bar<'a> {
    First,
    Second(Cow<'a, str>),
}

fn main() {
    let value = String::from("data");
    let foo = Foo {
        foo: Cow::from(&value),
        bar: vec![Bar::First, Bar::Second(Cow::from(&value))]
    };
    let foo_static = foo.into_static();
    std::thread::spawn(move || {
        assert_eq!(foo_static.foo, "data");
        assert_eq!(foo_static.bar, vec![Bar::First, Bar::Second("data".into())])
    }).join().unwrap();
}

How does this differ from the ToOwned trait?

The ToOwned trait defines an associated type Owned which is not bound by 'static and therefore the follow will not compile:

use std::borrow::Cow;

fn main() {
    #[derive(Clone)]
    struct Foo<'a> {
        foo: Cow<'a, str>,
    }

    fn ensure_static<T: 'static>(_: T) {}

    let s = String::from("data");
    let foo = Foo { foo: Cow::from(&s) };
    ensure_static(foo.to_owned())
}

Results in the following error:

error[E0597]: `s` does not live long enough
  --> src/lib.rs:12:36
   |
12 |     let foo = Foo { foo: Cow::from(&s) };
   |                          ----------^^-
   |                          |         |
   |                          |         borrowed value does not live long enough
   |                          argument requires that `s` is borrowed for `'static`
13 |     ensure_static(foo.to_owned())
14 | }
   | - `s` dropped here while still borrowed

Replacing Clone with ToStatic and using into_static() (or to_static() as needed) allows the example to compile:

use std::borrow::Cow;

fn main() {

    #[derive(ToStatic)]
    struct Foo<'a> {
        foo: Cow<'a, str>,
    }

    fn ensure_static<T: 'static>(_: T) {}

    let s = String::from("data");
    let foo = Foo { foo: Cow::from(&s) };
    ensure_static(foo.into_static())
}

License

bounded-static is distributed under the terms of the Apache License (Version 2.0).

See LICENSE for details.

Copyright 2022