Skip to main content

bump_scope/
bump.rs

1use core::{
2    alloc::Layout,
3    ffi::CStr,
4    fmt::{self, Debug},
5    mem::MaybeUninit,
6    panic::{RefUnwindSafe, UnwindSafe},
7};
8
9#[cfg(feature = "alloc")]
10use core::{mem::ManuallyDrop, ptr::NonNull};
11
12#[cfg(feature = "nightly-clone-to-uninit")]
13use core::clone::CloneToUninit;
14
15use crate::{
16    BumpBox, BumpClaimGuard, BumpScope, BumpScopeGuard, Checkpoint, ErrorBehavior,
17    alloc::{AllocError, Allocator},
18    chunk::ChunkSize,
19    maybe_default_allocator,
20    owned_slice::OwnedSlice,
21    polyfill::{transmute_mut, transmute_ref, transmute_value},
22    raw_bump::RawBump,
23    settings::{BumpAllocatorSettings, BumpSettings, False, MinimumAlignment, SupportedMinimumAlignment},
24    stats::{AnyStats, Stats},
25    traits::{
26        self, BumpAllocator, BumpAllocatorCore, BumpAllocatorScope, BumpAllocatorTyped, BumpAllocatorTypedScope,
27        MutBumpAllocatorTypedScope,
28    },
29};
30
31#[cfg(feature = "panic-on-alloc")]
32use crate::panic_on_error;
33
34#[cfg(feature = "alloc")]
35use crate::alloc::Global;
36
37macro_rules! make_type {
38    ($($allocator_parameter:tt)*) => {
39        /// The bump allocator.
40        ///
41        /// # Generic parameters
42        /// - **`A`** — the base allocator, defaults to `Global` when the `alloc` feature is enabled
43        /// - **`S`** — the bump allocator settings, see [`settings`](crate::settings)
44        ///
45        /// # Overview
46        /// All of the mentioned methods that do allocations panic if the base allocator returned an error.
47        /// For every such panicking method, there is a corresponding `try_`-prefixed version that returns a `Result` instead.
48        ///
49        /// #### Create a `Bump` ...
50        /// - without allocating a chunk: <code>[new]\([_in][new_in])</code> / <code>[default]</code>
51        /// - provide a size hint: <code>[with_size]\([_in][with_size_in])</code>
52        /// - provide a minimum capacity: <code>[with_capacity]\([_in][with_capacity_in])</code>
53        ///
54        /// [new]: Bump::new
55        /// [new_in]: Bump::new_in
56        /// [default]: Bump::default
57        /// [with_size]: Bump::with_size
58        /// [with_size_in]: Bump::with_size_in
59        /// [with_capacity]: Bump::with_capacity
60        /// [with_capacity_in]: Bump::with_capacity_in
61        ///
62        /// #### Allocate ...
63        /// - sized values: [`alloc`], [`alloc_with`], [`alloc_default`], [`alloc_zeroed`]
64        /// - strings: [`alloc_str`], <code>[alloc_fmt](BumpAllocatorTypedScope::alloc_fmt)([_mut](MutBumpAllocatorTypedScope::alloc_fmt_mut))</code>
65        /// - c strings: [`alloc_cstr`], [`alloc_cstr_from_str`], <code>[alloc_cstr_fmt](BumpAllocatorTypedScope::alloc_cstr_fmt)([_mut](MutBumpAllocatorTypedScope::alloc_cstr_fmt_mut))</code>
66        /// - slices: <code>alloc_slice_{[copy](BumpAllocatorTypedScope::alloc_slice_copy), [clone](BumpAllocatorTypedScope::alloc_slice_clone), [move](BumpAllocatorTypedScope::alloc_slice_move), [fill](BumpAllocatorTypedScope::alloc_slice_fill), [fill_with](BumpAllocatorTypedScope::alloc_slice_fill_with)}</code>,
67        ///   [`alloc_zeroed_slice`]
68        /// - slices from an iterator: [`alloc_iter`], [`alloc_iter_exact`], [`alloc_iter_mut`], [`alloc_iter_mut_rev`]
69        /// - uninitialized values: [`alloc_uninit`], [`alloc_uninit_slice`], [`alloc_uninit_slice_for`]
70        ///
71        ///   which can then be conveniently initialized by the [`init*` methods of `BumpBox`](crate::BumpBox#bumpbox-has-a-lot-of-methods).
72        /// - results: [`alloc_try_with`], [`alloc_try_with_mut`]
73        /// - via clone *(nightly only)*: [`alloc_clone`]
74        ///
75        /// #### Free memory using ...
76        /// - scopes: [`scoped`], [`scoped_aligned`], [`scope_guard`]
77        /// - checkpoints: [`checkpoint`], [`reset_to`]
78        /// - reset: [`reset`]
79        /// - dealloc: [`dealloc`]
80        ///
81        /// #### Configure allocator settings ...
82        /// - [`with_settings`], [`borrow_with_settings`], [`borrow_mut_with_settings`]
83        ///
84        /// ## Collections
85        /// A `Bump` (and [`BumpScope`]) can be used to allocate collections of this crate...
86        /// ```
87        /// use bump_scope::{Bump, BumpString};
88        /// let bump: Bump = Bump::new();
89        ///
90        /// let mut string = BumpString::new_in(&bump);
91        /// string.push_str("Hello,");
92        /// string.push_str(" world!");
93        /// ```
94        ///
95        /// ... and collections from crates that use `allocator_api2`'s `Allocator` like [hashbrown](https://docs.rs/hashbrown)'s [`HashMap`](https://docs.rs/hashbrown/latest/hashbrown/struct.HashMap.html):
96        ///
97        /// *This requires the `allocator-api2-02` feature OR the `nightly-allocator-api` feature along with hashbrown's `nightly` feature.*
98        // NOTE: This code is tested in `crates/test-hashbrown/lib.rs`.
99        // It's not tested here because using hashbrown requires us to either have both the crate features for a nightly allocator api in bump-scope and hashbrown or neither.
100        // This could be solved by making bump-scope's "nightly-allocator-api" depend on "hashbrown/nightly" but that currently breaks tools like cargo-hack and cargo-minimal-versions.
101        /// ```
102        /// # /*
103        /// use bump_scope::Bump;
104        /// use hashbrown::HashMap;
105        ///
106        /// let bump: Bump = Bump::new();
107        /// let mut map = HashMap::new_in(&bump);
108        /// map.insert("tau", 6.283);
109        /// # */
110        /// # ()
111        /// ```
112        ///
113        /// On nightly and with the feature `nightly-allocator-api` you can also allocate collections from `std` that have an allocator parameter:
114        #[cfg_attr(feature = "nightly-allocator-api", doc = "```")]
115        #[cfg_attr(not(feature = "nightly-allocator-api"), doc = "```no_run")]
116        /// # /*
117        /// # those features are already been enabled by a `doc(test(attr`
118        /// # but we still want it here for demonstration
119        /// #![feature(allocator_api, btreemap_alloc)]
120        /// # */
121        /// # #[cfg(feature = "nightly-allocator-api")] fn main() {
122        /// use bump_scope::Bump;
123        /// use std::collections::{VecDeque, BTreeMap, LinkedList};
124        ///
125        /// let bump: Bump = Bump::new();
126        /// let vec = Vec::new_in(&bump);
127        /// let queue = VecDeque::new_in(&bump);
128        /// let map = BTreeMap::new_in(&bump);
129        /// let list = LinkedList::new_in(&bump);
130        /// # let _: Vec<i32, _> = vec;
131        /// # let _: VecDeque<i32, _> = queue;
132        /// # let _: BTreeMap<i32, i32, _> = map;
133        /// # let _: LinkedList<i32, _> = list;
134        /// # }
135        /// # #[cfg(not(feature = "nightly-allocator-api"))] fn main() {}
136        /// ```
137        ///
138        /// [`alloc`]: BumpAllocatorTypedScope::alloc
139        /// [`alloc_with`]: BumpAllocatorTypedScope::alloc_with
140        /// [`alloc_default`]: BumpAllocatorTypedScope::alloc_default
141        /// [`alloc_zeroed`]: crate::zerocopy_08::BumpAllocatorTypedScopeExt::alloc_zeroed
142        ///
143        /// [`alloc_str`]: BumpAllocatorTypedScope::alloc_str
144        ///
145        /// [`alloc_cstr`]: BumpAllocatorTypedScope::alloc_cstr
146        /// [`alloc_cstr_from_str`]: BumpAllocatorTypedScope::alloc_cstr_from_str
147        ///
148        /// [`alloc_zeroed_slice`]: crate::zerocopy_08::BumpAllocatorTypedScopeExt::alloc_zeroed_slice
149        ///
150        /// [`alloc_iter`]: BumpAllocatorTypedScope::alloc_iter
151        /// [`alloc_iter_exact`]: BumpAllocatorTypedScope::alloc_iter_exact
152        /// [`alloc_iter_mut`]: MutBumpAllocatorTypedScope::alloc_iter_mut
153        /// [`alloc_iter_mut_rev`]: MutBumpAllocatorTypedScope::alloc_iter_mut_rev
154        ///
155        /// [`alloc_uninit`]: BumpAllocatorTypedScope::alloc_uninit
156        /// [`alloc_uninit_slice`]: BumpAllocatorTypedScope::alloc_uninit_slice
157        /// [`alloc_uninit_slice_for`]: BumpAllocatorTypedScope::alloc_uninit_slice_for
158        ///
159        /// [`alloc_try_with`]: Bump::alloc_try_with
160        /// [`alloc_try_with_mut`]: Bump::alloc_try_with_mut
161        ///
162        /// [`alloc_clone`]: BumpAllocatorTypedScope::alloc_clone
163        ///
164        /// [`scoped`]: crate::traits::BumpAllocator::scoped
165        /// [`scoped_aligned`]: crate::traits::BumpAllocator::scoped_aligned
166        /// [`scope_guard`]: crate::traits::BumpAllocator::scope_guard
167        ///
168        /// [`checkpoint`]: BumpAllocatorCore::checkpoint
169        /// [`reset_to`]: BumpAllocatorCore::reset_to
170        ///
171        /// [`reset`]: Bump::reset
172        /// [`dealloc`]: BumpAllocatorTyped::dealloc
173        ///
174        /// [`aligned`]: BumpAllocatorScope::aligned
175        ///
176        /// [`with_settings`]: Bump::with_settings
177        /// [`borrow_with_settings`]: Bump::borrow_with_settings
178        /// [`borrow_mut_with_settings`]: Bump::borrow_with_settings
179        ///
180        /// # Gotcha
181        ///
182        /// Having live allocations and entering bump scopes at the same time requires a `BumpScope`.
183        /// This is due to the way lifetimes work, since `Bump` returns allocations with the lifetime
184        /// of its own borrow instead of a separate lifetime like `BumpScope` does.
185        ///
186        /// So you can't do this:
187        /// ```compile_fail,E0502
188        /// # use bump_scope::Bump;
189        /// let mut bump: Bump = Bump::new();
190        ///
191        /// let one = bump.alloc(1);
192        ///
193        /// bump.scoped(|bump| {
194        ///     // whatever
195        ///     # _ = bump;
196        /// });
197        /// # _ = one;
198        /// ```
199        /// But you can make the code work by converting the `Bump` it to a [`BumpScope`] first using [`as_mut_scope`]:
200        /// ```
201        /// # use bump_scope::Bump;
202        /// let mut bump: Bump = Bump::new();
203        /// let bump = bump.as_mut_scope();
204        ///
205        /// let one = bump.alloc(1);
206        ///
207        /// bump.scoped(|bump| {
208        ///     // whatever
209        ///     # _ = bump;
210        /// });
211        /// # _ = one;
212        /// ```
213        ///
214        /// [`as_mut_scope`]: Bump::as_mut_scope
215        #[repr(transparent)]
216        pub struct Bump<$($allocator_parameter)*, S = BumpSettings>
217        where
218            A: Allocator,
219            S: BumpAllocatorSettings,
220        {
221            pub(crate) raw: RawBump<A, S>,
222        }
223    };
224}
225
226maybe_default_allocator!(make_type);
227
228// Sending Bumps when nothing is allocated is fine.
229// When something is allocated Bump is borrowed and sending is not possible.
230unsafe impl<A, S> Send for Bump<A, S>
231where
232    A: Allocator,
233    S: BumpAllocatorSettings,
234{
235}
236
237impl<A, S> UnwindSafe for Bump<A, S>
238where
239    A: Allocator + UnwindSafe,
240    S: BumpAllocatorSettings,
241{
242}
243
244impl<A, S> RefUnwindSafe for Bump<A, S>
245where
246    A: Allocator + RefUnwindSafe,
247    S: BumpAllocatorSettings,
248{
249}
250
251impl<A, S> Drop for Bump<A, S>
252where
253    A: Allocator,
254    S: BumpAllocatorSettings,
255{
256    fn drop(&mut self) {
257        unsafe { self.raw.manually_drop() }
258    }
259}
260
261impl<A, S> Debug for Bump<A, S>
262where
263    A: Allocator,
264    S: BumpAllocatorSettings,
265{
266    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267        AnyStats::from(self.stats()).debug_format("Bump", f)
268    }
269}
270
271impl<A, S> Default for Bump<A, S>
272where
273    A: Allocator + Default,
274    S: BumpAllocatorSettings<GuaranteedAllocated = False>,
275{
276    #[inline(always)]
277    fn default() -> Self {
278        Self::new()
279    }
280}
281
282/// Methods for a `Bump` with a default base allocator.
283impl<A, S> Bump<A, S>
284where
285    A: Allocator + Default,
286    S: BumpAllocatorSettings,
287{
288    /// Constructs a new `Bump` without allocating.
289    ///
290    /// # Examples
291    /// ```
292    /// use bump_scope::Bump;
293    ///
294    /// let bump: Bump = Bump::new();
295    /// # _ = bump;
296    /// ```
297    #[must_use]
298    #[inline(always)]
299    pub fn new() -> Self {
300        Self::new_in(Default::default())
301    }
302
303    /// Constructs a new `Bump` with a size hint for the first chunk.
304    ///
305    /// If you want to ensure a specific capacity, use [`with_capacity`](Self::with_capacity) instead.
306    ///
307    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
308    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
309    /// After that, the size of `[usize; 2]` is subtracted.
310    ///
311    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
312    ///
313    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
314    /// Such a change is not considered semver breaking.
315    ///
316    /// # Panics
317    /// Panics if the allocation fails.
318    ///
319    /// # Examples
320    /// ```
321    /// use bump_scope::Bump;
322    ///
323    /// // `Bump` with a roughly 1 Mebibyte sized chunk
324    /// let bump_1mib: Bump = Bump::with_size(1024 * 1024);
325    /// # _ = bump_1mib;
326    /// ```
327    #[must_use]
328    #[inline(always)]
329    #[cfg(feature = "panic-on-alloc")]
330    pub fn with_size(size: usize) -> Self {
331        panic_on_error(Self::generic_with_size(size))
332    }
333
334    /// Constructs a new `Bump` with a size hint for the first chunk.
335    ///
336    /// If you want to ensure a specific capacity, use [`try_with_capacity`](Self::try_with_capacity) instead.
337    ///
338    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
339    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
340    /// After that, the size of `[usize; 2]` is subtracted.
341    ///
342    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
343    ///
344    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
345    /// Such a change is not considered semver breaking.
346    ///
347    /// # Errors
348    /// Errors if the allocation fails.
349    ///
350    /// # Examples
351    /// ```
352    /// use bump_scope::Bump;
353    ///
354    /// // `Bump` with a roughly 1 Mebibyte sized chunk
355    /// let bump_1mib: Bump = Bump::try_with_size(1024 * 1024)?;
356    /// # _ = bump_1mib;
357    /// # Ok::<(), bump_scope::alloc::AllocError>(())
358    /// ```
359    #[inline(always)]
360    pub fn try_with_size(size: usize) -> Result<Self, AllocError> {
361        Self::generic_with_size(size)
362    }
363
364    #[inline]
365    pub(crate) fn generic_with_size<E: ErrorBehavior>(size: usize) -> Result<Self, E> {
366        Self::generic_with_size_in(size, Default::default())
367    }
368
369    /// Constructs a new `Bump` with at least enough space for `layout`.
370    ///
371    /// To construct a `Bump` with a size hint use <code>[with_size](Bump::with_size)</code> instead.
372    ///
373    /// # Panics
374    /// Panics if the allocation fails.
375    ///
376    /// # Examples
377    /// ```
378    /// use bump_scope::Bump;
379    /// use core::alloc::Layout;
380    ///
381    /// let layout = Layout::array::<u8>(1234).unwrap();
382    /// let bump: Bump = Bump::with_capacity(layout);
383    /// assert!(bump.stats().capacity() >= layout.size());
384    /// ```
385    #[must_use]
386    #[inline(always)]
387    #[cfg(feature = "panic-on-alloc")]
388    pub fn with_capacity(layout: Layout) -> Self {
389        panic_on_error(Self::generic_with_capacity(layout))
390    }
391
392    /// Constructs a new `Bump` with at least enough space for `layout`.
393    ///
394    /// To construct a `Bump` with a size hint use <code>[try_with_size](Bump::try_with_size)</code> instead.
395    ///
396    /// # Errors
397    /// Errors if the allocation fails.
398    ///
399    /// # Examples
400    /// ```
401    /// use bump_scope::Bump;
402    /// use core::alloc::Layout;
403    ///
404    /// let layout = Layout::array::<u8>(1234).unwrap();
405    /// let bump: Bump = Bump::try_with_capacity(layout)?;
406    /// assert!(bump.stats().capacity() >= layout.size());
407    /// # Ok::<(), bump_scope::alloc::AllocError>(())
408    /// ```
409    #[inline(always)]
410    pub fn try_with_capacity(layout: Layout) -> Result<Self, AllocError> {
411        Self::generic_with_capacity(layout)
412    }
413
414    #[inline]
415    pub(crate) fn generic_with_capacity<E: ErrorBehavior>(layout: Layout) -> Result<Self, E> {
416        Self::generic_with_capacity_in(layout, Default::default())
417    }
418}
419
420/// Methods that are always available.
421impl<A, S> Bump<A, S>
422where
423    A: Allocator,
424    S: BumpAllocatorSettings,
425{
426    /// Constructs a new `Bump` without allocating.
427    ///
428    /// # Examples
429    /// ```
430    /// use bump_scope::Bump;
431    /// use bump_scope::alloc::Global;
432    ///
433    /// let bump: Bump = Bump::new_in(Global);
434    /// # _ = bump;
435    /// ```
436    #[must_use]
437    #[inline(always)]
438    pub const fn new_in(allocator: A) -> Self {
439        Self {
440            raw: RawBump::new(allocator),
441        }
442    }
443
444    /// Constructs a new `Bump` with a size hint for the first chunk.
445    ///
446    /// If you want to ensure a specific capacity, use [`with_capacity_in`](Self::with_capacity_in) instead.
447    ///
448    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
449    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
450    /// After that, the size of `[usize; 2]` is subtracted.
451    ///
452    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
453    ///
454    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
455    /// Such a change is not considered semver breaking.
456    ///
457    /// # Panics
458    /// Panics if the allocation fails.
459    ///
460    /// # Examples
461    /// ```
462    /// use bump_scope::Bump;
463    /// use bump_scope::alloc::Global;
464    ///
465    /// // `Bump` with a roughly 1 Mebibyte sized chunk
466    /// let bump_1mib: Bump = Bump::with_size_in(1024 * 1024, Global);
467    /// # _ = bump_1mib;
468    /// ```
469    #[must_use]
470    #[inline(always)]
471    #[cfg(feature = "panic-on-alloc")]
472    pub fn with_size_in(size: usize, allocator: A) -> Self {
473        panic_on_error(Self::generic_with_size_in(size, allocator))
474    }
475
476    /// Constructs a new `Bump` with a size hint for the first chunk.
477    ///
478    /// If you want to ensure a specific capacity, use [`try_with_capacity`](Self::try_with_capacity) instead.
479    ///
480    /// An effort is made to ensure the size requested from the base allocator is friendly to an allocator that uses size classes and stores metadata alongside allocations.
481    /// To achieve this, the requested size is rounded up to either the next power of two or the next multiple of `0x1000`, whichever is smaller.
482    /// After that, the size of `[usize; 2]` is subtracted.
483    ///
484    /// If the base allocator returns a memory block that is larger than requested, then the chunk will use the extra space.
485    ///
486    /// **Disclaimer:** The way in which the chunk layout is calculated might change.
487    /// Such a change is not considered semver breaking.
488    ///
489    /// # Errors
490    /// Errors if the allocation fails.
491    ///
492    /// # Examples
493    /// ```
494    /// use bump_scope::Bump;
495    /// use bump_scope::alloc::Global;
496    ///
497    /// // `Bump` with a roughly 1 Mebibyte sized chunk
498    /// let bump_1mib: Bump = Bump::try_with_size_in(1024 * 1024, Global)?;
499    /// # _ = bump_1mib;
500    /// # Ok::<(), bump_scope::alloc::AllocError>(())
501    /// ```
502    #[inline(always)]
503    pub fn try_with_size_in(size: usize, allocator: A) -> Result<Self, AllocError> {
504        Self::generic_with_size_in(size, allocator)
505    }
506
507    #[inline]
508    pub(crate) fn generic_with_size_in<E: ErrorBehavior>(size: usize, allocator: A) -> Result<Self, E> {
509        Ok(Self {
510            raw: RawBump::with_size(
511                ChunkSize::<S::Up>::from_hint(size).ok_or_else(E::capacity_overflow)?,
512                allocator,
513            )?,
514        })
515    }
516
517    /// Constructs a new `Bump` with at least enough space for `layout`.
518    ///
519    /// To construct a `Bump` with a size hint use <code>[with_size_in](Bump::with_size_in)</code> instead.
520    ///
521    /// # Panics
522    /// Panics if the allocation fails.
523    ///
524    /// # Examples
525    /// ```
526    /// use bump_scope::Bump;
527    /// use bump_scope::alloc::Global;
528    /// use core::alloc::Layout;
529    ///
530    /// let layout = Layout::array::<u8>(1234).unwrap();
531    /// let bump: Bump = Bump::with_capacity_in(layout, Global);
532    /// assert!(bump.stats().capacity() >= layout.size());
533    /// # Ok::<(), bump_scope::alloc::AllocError>(())
534    /// ```
535    #[must_use]
536    #[inline(always)]
537    #[cfg(feature = "panic-on-alloc")]
538    pub fn with_capacity_in(layout: Layout, allocator: A) -> Self {
539        panic_on_error(Self::generic_with_capacity_in(layout, allocator))
540    }
541
542    /// Constructs a new `Bump` with at least enough space for `layout`.
543    ///
544    /// To construct a `Bump` with a size hint use <code>[try_with_size_in](Bump::try_with_size_in)</code> instead.
545    ///
546    /// # Errors
547    /// Errors if the allocation fails.
548    ///
549    /// # Examples
550    /// ```
551    /// use bump_scope::Bump;
552    /// use bump_scope::alloc::Global;
553    /// use core::alloc::Layout;
554    ///
555    /// let layout = Layout::array::<u8>(1234).unwrap();
556    /// let bump: Bump = Bump::try_with_capacity_in(layout, Global)?;
557    /// assert!(bump.stats().capacity() >= layout.size());
558    /// # Ok::<(), bump_scope::alloc::AllocError>(())
559    /// ```
560    #[inline(always)]
561    pub fn try_with_capacity_in(layout: Layout, allocator: A) -> Result<Self, AllocError> {
562        Self::generic_with_capacity_in(layout, allocator)
563    }
564
565    #[inline]
566    pub(crate) fn generic_with_capacity_in<E: ErrorBehavior>(layout: Layout, allocator: A) -> Result<Self, E> {
567        Ok(Self {
568            raw: RawBump::with_size(
569                ChunkSize::<S::Up>::from_capacity(layout).ok_or_else(E::capacity_overflow)?,
570                allocator,
571            )?,
572        })
573    }
574
575    // This needs `&mut self` to make sure that no allocations are alive.
576    /// Deallocates every chunk but the newest, which is also the biggest.
577    ///
578    /// ```
579    /// use bump_scope::Bump;
580    ///
581    /// let mut bump: Bump = Bump::with_size(512);
582    ///
583    /// // won't fit in the first chunk
584    /// bump.alloc_uninit_slice::<u8>(600);
585    ///
586    /// let chunks = bump.stats().small_to_big().collect::<Vec<_>>();
587    /// assert_eq!(chunks.len(), 2);
588    /// assert!(chunks[0].size() < chunks[1].size());
589    /// assert_eq!(chunks[0].allocated(), 0);
590    /// assert_eq!(chunks[1].allocated(), 600);
591    /// let last_chunk_size = chunks[1].size();
592    ///
593    /// bump.reset();
594    ///
595    /// let chunks = bump.stats().small_to_big().collect::<Vec<_>>();
596    /// assert_eq!(chunks.len(), 1);
597    /// assert_eq!(chunks[0].size(), last_chunk_size);
598    /// assert_eq!(chunks[0].allocated(), 0);
599    /// ```
600    #[inline(always)]
601    pub fn reset(&mut self) {
602        self.raw.reset();
603    }
604
605    /// Returns a type which provides statistics about the memory usage of the bump allocator.
606    #[must_use]
607    #[inline(always)]
608    pub fn stats(&self) -> Stats<'_, S> {
609        self.as_scope().stats()
610    }
611
612    /// Returns this `&Bump` as a `&BumpScope`.
613    #[must_use]
614    #[inline(always)]
615    pub fn as_scope(&self) -> &BumpScope<'_, A, S> {
616        unsafe { transmute_ref(self) }
617    }
618
619    /// Returns this `&mut Bump` as a `&mut BumpScope`.
620    #[must_use]
621    #[inline(always)]
622    pub fn as_mut_scope(&mut self) -> &mut BumpScope<'_, A, S> {
623        unsafe { transmute_mut(self) }
624    }
625
626    /// Converts this `Bump` into a `Bump` with new settings.
627    ///
628    /// Not every setting can be converted to. This function will fail to compile if:
629    /// - `NewS::UP != S::UP`
630    /// - `NewS::GUARANTEED_ALLOCATED > S::GUARANTEED_ALLOCATED`
631    /// - `NewS::CLAIMABLE < S::CLAIMABLE`
632    #[inline]
633    pub fn with_settings<NewS>(self) -> Bump<A, NewS>
634    where
635        NewS: BumpAllocatorSettings,
636    {
637        self.raw.ensure_satisfies_settings::<NewS>();
638        unsafe { transmute_value(self) }
639    }
640
641    /// Borrows this `Bump` with new settings.
642    ///
643    /// Not every settings can be converted to. This function will fail to compile if:
644    /// - `NewS::MIN_ALIGN != S::MIN_ALIGN`
645    /// - `NewS::UP != S::UP`
646    /// - `NewS::GUARANTEED_ALLOCATED > S::GUARANTEED_ALLOCATED`
647    /// - `NewS::CLAIMABLE != S::CLAIMABLE`
648    #[inline]
649    pub fn borrow_with_settings<NewS>(&self) -> &Bump<A, NewS>
650    where
651        NewS: BumpAllocatorSettings,
652    {
653        self.raw.ensure_satisfies_settings_for_borrow::<NewS>();
654        unsafe { transmute_ref(self) }
655    }
656
657    /// Borrows this `Bump` mutably with new settings.
658    ///
659    /// Not every settings can be converted to. This function will fail to compile if:
660    /// - `NewS::MIN_ALIGN < S::MIN_ALIGN`
661    /// - `NewS::UP != S::UP`
662    /// - `NewS::GUARANTEED_ALLOCATED != S::GUARANTEED_ALLOCATED`
663    /// - `NewS::CLAIMABLE != S::CLAIMABLE`
664    #[inline]
665    pub fn borrow_mut_with_settings<NewS>(&mut self) -> &mut Bump<A, NewS>
666    where
667        NewS: BumpAllocatorSettings,
668    {
669        self.raw.ensure_satisfies_settings_for_borrow_mut::<NewS>();
670        unsafe { transmute_mut(self) }
671    }
672}
673
674#[cfg(feature = "alloc")]
675impl<S> Bump<Global, S>
676where
677    S: BumpAllocatorSettings,
678{
679    /// Converts this `Bump` into a raw pointer.
680    ///
681    /// ```
682    /// use bump_scope::Bump;
683    ///
684    /// let bump: Bump = Bump::new();
685    /// let ptr = bump.into_raw();
686    /// let bump: Bump = unsafe { Bump::from_raw(ptr) };
687    ///
688    /// bump.alloc_str("Why did i do this?");
689    /// ```
690    #[inline]
691    #[must_use]
692    pub fn into_raw(self) -> NonNull<()> {
693        let this = ManuallyDrop::new(self);
694        unsafe { (&raw const this.raw).read().into_raw() }
695    }
696
697    /// Converts the raw pointer that was created with [`into_raw`](Bump::into_raw) back into a `Bump`.
698    ///
699    /// # Safety
700    /// - `ptr` must have been created with `Self::into_raw`.
701    /// - This function must only be called once with this `ptr`.
702    /// - The settings must match the original ones.
703    #[inline]
704    #[must_use]
705    pub unsafe fn from_raw(ptr: NonNull<()>) -> Self {
706        Self {
707            raw: unsafe { RawBump::from_raw(ptr) },
708        }
709    }
710}
711
712impl<'b, A, S> From<&'b Bump<A, S>> for &'b BumpScope<'b, A, S>
713where
714    A: Allocator,
715    S: BumpAllocatorSettings,
716{
717    #[inline(always)]
718    fn from(value: &'b Bump<A, S>) -> Self {
719        value.as_scope()
720    }
721}
722
723impl<'b, A, S> From<&'b mut Bump<A, S>> for &'b mut BumpScope<'b, A, S>
724where
725    A: Allocator,
726    S: BumpAllocatorSettings,
727{
728    #[inline(always)]
729    fn from(value: &'b mut Bump<A, S>) -> Self {
730        value.as_mut_scope()
731    }
732}
733
734/// Methods that forward to traits.
735// Documentation is in the forwarded to methods.
736#[allow(clippy::missing_errors_doc, clippy::missing_safety_doc)]
737impl<A, S> Bump<A, S>
738where
739    A: Allocator,
740    S: BumpAllocatorSettings,
741{
742    traits::forward_methods! {
743        self: self
744        access: {self.as_scope()}
745        access_mut: {self.as_mut_scope()}
746        lifetime: '_
747    }
748}
749
750/// Additional `alloc` methods that are not available in traits.
751impl<A, S> Bump<A, S>
752where
753    A: Allocator,
754    S: BumpAllocatorSettings,
755{
756    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
757    ///
758    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
759    ///
760    /// There is also [`alloc_try_with_mut`](Self::alloc_try_with_mut), optimized for a mutable reference.
761    ///
762    /// # Panics
763    /// Panics if the allocation fails.
764    ///
765    /// # Examples
766    #[cfg_attr(feature = "nightly-tests", doc = "```")]
767    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
768    /// # #![feature(offset_of_enum)]
769    /// # use core::mem::offset_of;
770    /// # use bump_scope::Bump;
771    /// # let bump: Bump = Bump::new();
772    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Ok(123) });
773    /// assert_eq!(result.unwrap(), 123);
774    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
775    /// ```
776    #[cfg_attr(feature = "nightly-tests", doc = "```")]
777    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
778    /// # use bump_scope::Bump;
779    /// # let bump: Bump = Bump::new();
780    /// let result = bump.alloc_try_with(|| -> Result<i32, i32> { Err(123) });
781    /// assert_eq!(result.unwrap_err(), 123);
782    /// assert_eq!(bump.stats().allocated(), 0);
783    /// ```
784    #[inline(always)]
785    #[cfg(feature = "panic-on-alloc")]
786    #[expect(clippy::missing_errors_doc)]
787    pub fn alloc_try_with<T, E>(&self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'_, T>, E> {
788        self.as_scope().alloc_try_with(f)
789    }
790
791    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
792    ///
793    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
794    ///
795    /// There is also [`try_alloc_try_with_mut`](Self::try_alloc_try_with_mut), optimized for a mutable reference.
796    ///
797    /// # Errors
798    /// Errors if the allocation fails.
799    ///
800    /// # Examples
801    #[cfg_attr(feature = "nightly-tests", doc = "```")]
802    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
803    /// # #![feature(offset_of_enum)]
804    /// # use core::mem::offset_of;
805    /// # use bump_scope::Bump;
806    /// # let bump: Bump = Bump::new();
807    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Ok(123) })?;
808    /// assert_eq!(result.unwrap(), 123);
809    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
810    /// # Ok::<(), bump_scope::alloc::AllocError>(())
811    /// ```
812    #[cfg_attr(feature = "nightly-tests", doc = "```")]
813    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
814    /// # use bump_scope::Bump;
815    /// # let bump: Bump = Bump::new();
816    /// let result = bump.try_alloc_try_with(|| -> Result<i32, i32> { Err(123) })?;
817    /// assert_eq!(result.unwrap_err(), 123);
818    /// assert_eq!(bump.stats().allocated(), 0);
819    /// # Ok::<(), bump_scope::alloc::AllocError>(())
820    /// ```
821    #[inline(always)]
822    pub fn try_alloc_try_with<T, E>(
823        &self,
824        f: impl FnOnce() -> Result<T, E>,
825    ) -> Result<Result<BumpBox<'_, T>, E>, AllocError> {
826        self.as_scope().try_alloc_try_with(f)
827    }
828
829    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
830    ///
831    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
832    ///
833    /// This is just like [`alloc_try_with`](Self::alloc_try_with), but optimized for a mutable reference.
834    ///
835    /// # Panics
836    /// Panics if the allocation fails.
837    ///
838    /// # Examples
839    #[cfg_attr(feature = "nightly-tests", doc = "```")]
840    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
841    /// # #![feature(offset_of_enum)]
842    /// # use core::mem::offset_of;
843    /// # use bump_scope::Bump;
844    /// # let mut bump: Bump = Bump::new();
845    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) });
846    /// assert_eq!(result.unwrap(), 123);
847    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
848    /// ```
849    #[cfg_attr(feature = "nightly-tests", doc = "```")]
850    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
851    /// # use bump_scope::Bump;
852    /// # let mut bump: Bump = Bump::new();
853    /// let result = bump.alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) });
854    /// assert_eq!(result.unwrap_err(), 123);
855    /// assert_eq!(bump.stats().allocated(), 0);
856    /// ```
857    #[inline(always)]
858    #[cfg(feature = "panic-on-alloc")]
859    #[expect(clippy::missing_errors_doc)]
860    pub fn alloc_try_with_mut<T, E>(&mut self, f: impl FnOnce() -> Result<T, E>) -> Result<BumpBox<'_, T>, E> {
861        self.as_mut_scope().alloc_try_with_mut(f)
862    }
863
864    /// Allocates the result of `f` in the bump allocator, then moves `E` out of it and deallocates the space it took up.
865    ///
866    /// This can be more performant than allocating `T` after the fact, as `Result<T, E>` may be constructed in the bump allocators memory instead of on the stack and then copied over.
867    ///
868    /// This is just like [`try_alloc_try_with`](Self::try_alloc_try_with), but optimized for a mutable reference.
869    ///
870    /// # Errors
871    /// Errors if the allocation fails.
872    ///
873    /// # Examples
874    #[cfg_attr(feature = "nightly-tests", doc = "```")]
875    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
876    /// # #![feature(offset_of_enum)]
877    /// # use core::mem::offset_of;
878    /// # use bump_scope::Bump;
879    /// # let mut bump: Bump = Bump::new();
880    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Ok(123) })?;
881    /// assert_eq!(result.unwrap(), 123);
882    /// assert_eq!(bump.stats().allocated(), offset_of!(Result<i32, i32>, Ok.0) + size_of::<i32>());
883    /// # Ok::<(), bump_scope::alloc::AllocError>(())
884    /// ```
885    #[cfg_attr(feature = "nightly-tests", doc = "```")]
886    #[cfg_attr(not(feature = "nightly-tests"), doc = "```ignore")]
887    /// # use bump_scope::Bump;
888    /// # let mut bump: Bump = Bump::new();
889    /// let result = bump.try_alloc_try_with_mut(|| -> Result<i32, i32> { Err(123) })?;
890    /// assert_eq!(result.unwrap_err(), 123);
891    /// assert_eq!(bump.stats().allocated(), 0);
892    /// # Ok::<(), bump_scope::alloc::AllocError>(())
893    /// ```
894    #[inline(always)]
895    pub fn try_alloc_try_with_mut<T, E>(
896        &mut self,
897        f: impl FnOnce() -> Result<T, E>,
898    ) -> Result<Result<BumpBox<'_, T>, E>, AllocError> {
899        self.as_mut_scope().try_alloc_try_with_mut(f)
900    }
901}