From ad47e0ca6dfdc030e0645f0364a34e629a6d67a7 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sun, 10 Jul 2022 02:09:55 +0900 Subject: [PATCH] Make Slab::new const on Rust 1.39+ --- Cargo.toml | 4 ++++ build.rs | 21 +++++++++++++++++++++ src/lib.rs | 25 +++++++++++++++++++++++-- tests/slab.rs | 6 ++++++ 4 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 540de1a..d120413 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,9 +21,13 @@ exclude = ["/.*"] std = [] default = ["std"] +[build-dependencies] +autocfg = "1" + [dependencies] serde = { version = "1.0.95", optional = true, default-features = false, features = ["alloc"] } [dev-dependencies] +rustversion = "1" serde = { version = "1", features = ["derive"] } serde_test = "1" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..28840e4 --- /dev/null +++ b/build.rs @@ -0,0 +1,21 @@ +fn main() { + let cfg = match autocfg::AutoCfg::new() { + Ok(cfg) => cfg, + Err(e) => { + // If we couldn't detect the compiler version and features, just + // print a warning. This isn't a fatal error: we can still build + // Tokio, we just can't enable cfgs automatically. + println!( + "cargo:warning=slab: failed to detect compiler features: {}", + e + ); + return; + } + }; + // Note that this is `no_`*, not `has_*`. This allows treating as the latest + // stable rustc is used when the build script doesn't run. This is useful + // for non-cargo build systems that don't run the build script. + if !cfg.probe_rustc_version(1, 39) { + println!("cargo:rustc-cfg=slab_no_const_vec_new"); + } +} diff --git a/src/lib.rs b/src/lib.rs index f207455..e369f46 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -219,14 +219,35 @@ impl Slab { /// The function does not allocate and the returned slab will have no /// capacity until `insert` is called or capacity is explicitly reserved. /// + /// This is `const fn` on Rust 1.39+. + /// /// # Examples /// /// ``` /// # use slab::*; /// let slab: Slab = Slab::new(); /// ``` - pub fn new() -> Slab { - Slab::with_capacity(0) + #[cfg(not(slab_no_const_vec_new))] + pub const fn new() -> Self { + Self { + entries: Vec::new(), + next: 0, + len: 0, + } + } + /// Construct a new, empty `Slab`. + /// + /// The function does not allocate and the returned slab will have no + /// capacity until `insert` is called or capacity is explicitly reserved. + /// + /// This is `const fn` on Rust 1.39+. + #[cfg(slab_no_const_vec_new)] + pub fn new() -> Self { + Self { + entries: Vec::new(), + next: 0, + len: 0, + } } /// Construct a new, empty `Slab` with the specified capacity. diff --git a/tests/slab.rs b/tests/slab.rs index 41360fa..fa89ebb 100644 --- a/tests/slab.rs +++ b/tests/slab.rs @@ -696,3 +696,9 @@ fn try_remove() { assert_eq!(slab.try_remove(key), None); assert_eq!(slab.get(key), None); } + +#[rustversion::since(1.39)] +#[test] +fn const_new() { + static _SLAB: Slab<()> = Slab::new(); +}