Skip to main content

ScratchPool

Struct ScratchPool 

Source
pub struct ScratchPool<T>
where T: ScratchElement,
{ /* private fields */ }
Expand description

A pool of reusable, aligned scratch buffers for a specific element type.

Send but not Sync — designed for thread_local! storage.

§Usage

ⓘ
use mnemosyne_arena::scratch::ScratchPool;

thread_local! {
    static POOL: ScratchPool<f64> = ScratchPool::new();
}

POOL.with(|pool| {
    pool.with_scratch(1024, |scratch| {
        // scratch: &mut [f64] of exactly 1024 elements, 64-byte aligned
    });
});

Implementations§

Source§

impl<T> ScratchPool<T>
where T: ScratchElement,

Source

pub fn with_scratch<R>(&self, n: usize, f: impl FnOnce(&mut [T]) -> R) -> R

Provides a mutable aligned scratch slice of exactly n elements to the closure. Borrow depth is released when the closure returns.

If a pool slot is available, the closure receives a direct &mut [T] into the pooled buffer (zero-copy). If all slots are exhausted (nested recursive calls), a temporary buffer is allocated instead.

Examples found in repository?
examples/book_scratch_pool.rs (lines 31-42)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub fn with_scratch_bounded<R>( &self, n: usize, f: impl FnOnce(&mut [T]) -> R, ) -> R

Like with_scratch, but records the request for release.

Each depth’s largest-ever request becomes that slot’s provision; a later release may reclaim everything a slot holds above it. The two forms share the slot storage, so a pool can be driven through either (or both) — only the provisions differ.

§Panics

Panics if f panics and leaves self.borrow_depth at u8::MAX, where the depth increment would wrap; with_scratch has the same bound via slot exhaustion, so this is not a new failure mode.

Examples found in repository?
examples/book_scratch_pool.rs (line 77)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub unsafe fn with_scratch_uninit<R>( &self, n: usize, f: impl FnOnce(*mut [T]) -> R, ) -> R

Like with_scratch but provides uninitialized memory via a raw pointer. The caller must initialize all elements.

§Safety

Every element of the returned slice must be initialized before any safe read on the same allocation.

Source§

impl<T> ScratchPool<T>
where T: ScratchElement,

Source

pub fn release(&self) -> [usize; 4]

Reclaims every slot’s storage above its recorded provision.

With with_scratch_bounded as the only entry point, a provision is the largest request ever seen at that depth; the slot keeps capacity for it (warm reuse stays allocation-free) and surrenders everything above — growth headroom included, so the retained steady state is exactly the working set. Slots whose provision is zero are dropped entirely. A slot is reclaimed only when its depth is idle; busy slots are skipped, never torn from under a live borrow.

The intended quiescent rhythm: run transforms normally, then call this when the workload idles — not on every with_scratch exit, which would reintroduce the churn the pool exists to remove. Provisions persist, so repeated release/idle cycles converge; a smaller steady-state working set needs reset.

Returns the per-slot capacities after reclamation. A slot that is currently borrowed reports its provision instead: its live capacity is not observable without deriving a reference under an existing exclusive borrow, the same aliasing capacity exists to avoid.

Examples found in repository?
examples/book_scratch_pool.rs (line 80)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub fn reset(&self)

Clears the recorded provisions so a later release reclaims every slot entirely.

For a full working-set changeover (a consumer tearing down one workload and starting another): reset, then run the new workload through with_scratch_bounded, then release. Slots that are not idle keep their buffers; the next release sees their cleared provisions and reclaims them.

Examples found in repository?
examples/book_scratch_pool.rs (line 86)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub fn prewarm(&self, min_capacity: usize)

Ensures the primary slot has capacity for at least min_capacity elements, growing it if necessary. No-op when the pool is borrowed.

Source

pub fn preload(&self, sizes: &[usize])

Prewarms multiple slots in one call.

sizes[i] specifies the minimum capacity for slot i (depth i). Out-of-range indices or a borrowed slot are silently skipped. Entries of 0 skip that slot.

Source

pub fn shrink_all_slots(&self)

Releases all slot allocations when not borrowed. No-op when borrowed.

Source§

impl<T> ScratchPool<T>
where T: ScratchElement,

Source

pub fn borrow_depth(&self) -> u8

Returns the current borrow depth (0 = fully available).

Source

pub fn capacity(&self) -> usize

Returns the capacity of the first slot (primary buffer).

Callable at any time, including from inside a live Self::with_scratch borrow of that same slot. The figure is read from a mirror maintained outside the slot’s UnsafeCell, so the accessor never derives a reference that could alias the exclusive one the borrow holds — the reentrant call is sound rather than merely undetected, and it neither panics nor reports a stale value.

Every slot carries such a mirror; see Self::total_capacity_bytes for the sum across all of them.

Examples found in repository?
examples/book_scratch_pool.rs (line 79)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub fn is_available(&self) -> bool

Returns true when the pool has at least one slot available for a new borrow (borrow_depth < MAX_POOL_SLOTS).

Source

pub fn slot_capacity(&self, idx: usize) -> usize

Returns the backing capacity of slot idx, or 0 when idx is out of range. Callable at any time including during a live borrow.

Source

pub fn total_capacity_bytes(&self) -> usize

Sum of backing capacities across all slots, in bytes.

Source§

impl<T> ScratchPool<T>
where T: ScratchElement,

Source

pub const fn new() -> ScratchPool<T>

Creates a new empty scratch pool (zero allocation at construction).

Examples found in repository?
examples/book_scratch_pool.rs (line 27)
22fn main() {
23    // Construct a pool locally and use it directly (not thread_local! here
24    // to avoid the clippy::missing_const_for_thread_local false positive on
25    // 1.97.0 — see ATLAS-MNEMOSYNE-CI-1).  In production callers store the
26    // pool in thread_local! storage so it persists between calls.
27    let f64_pool: ScratchPool<f64> = ScratchPool::new();
28    let f32_pool: ScratchPool<f32> = ScratchPool::new();
29
30    // Simple single-level scratch use: compute a dot product via a temp buffer.
31    f64_pool.with_scratch(1024, |scratch| {
32        for (i, slot) in scratch.iter_mut().enumerate() {
33            *slot = i as f64;
34        }
35        let partial: f64 = scratch.iter().sum();
36        println!(
37            "sum of 0..1024 via scratch: {} (expected {})",
38            partial,
39            (0..1024usize).sum::<usize>() as f64,
40        );
41        assert_eq!(partial, (0..1024usize).sum::<usize>() as f64);
42    });
43
44    // Nested borrows: outer scratch holds the signal; inner holds a window.
45    f64_pool.with_scratch(256, |signal| {
46        for (i, s) in signal.iter_mut().enumerate() {
47            *s = (i as f64).sin();
48        }
49        f64_pool.with_scratch(16, |window| {
50            window.copy_from_slice(&signal[..16]);
51            let dp = dot_product(window, &signal[..16]);
52            println!("windowed dot-product: {dp:.6}");
53            assert!(dp.is_finite());
54        });
55    });
56
57    // F32 pool: same API, different element type.
58    f32_pool.with_scratch(64, |buf| {
59        buf.fill(1.0_f32);
60        let total: f32 = buf.iter().sum();
61        println!("f32 scratch sum: {total}");
62        assert_eq!(total, 64.0_f32);
63    });
64
65    // Banked scratch keeps multiple related roles in one const-generic group,
66    // which matches transform pipelines that need independent temporary views
67    // without falling back to the system allocator.
68    let bank: ScratchBank<f64, 2> = ScratchBank::new();
69    bank.with_scratch::<1, _>(32, |scratch| {
70        scratch.fill(3.5);
71        assert!(scratch.iter().all(|v| *v == 3.5));
72    });
73
74    // Bounded provisioning retains the working set while making geometric
75    // growth headroom reclaimable at a consumer-selected quiescent point.
76    let bounded_pool: ScratchPool<u32> = ScratchPool::new();
77    bounded_pool.with_scratch_bounded(1024, |_| {});
78    bounded_pool.with_scratch_bounded(1025, |_| {});
79    assert_eq!(bounded_pool.capacity(), 2048);
80    let retained = bounded_pool.release();
81    println!(
82        "bounded release: capacity={} -> retained={}",
83        2048, retained[0]
84    );
85    assert_eq!(retained[0], 1025);
86    bounded_pool.reset();
87    assert_eq!(bounded_pool.release()[0], 0);
88
89    println!("MAX_POOL_SLOTS = {MAX_POOL_SLOTS} (max concurrent nested borrows)");
90    println!("all scratch-pool assertions passed");
91}
Source

pub fn with_slot_capacity(capacity: usize) -> ScratchPool<T>

Creates a new scratch pool with pre-allocated capacity per slot.

Trait Implementations§

Source§

impl<T> Default for ScratchPool<T>
where T: ScratchElement,

Source§

fn default() -> ScratchPool<T>

Returns the “default value” for a type. Read more
Source§

impl<T> Send for ScratchPool<T>
where T: ScratchElement,

Auto Trait Implementations§

§

impl<T> !Freeze for ScratchPool<T>

§

impl<T> !RefUnwindSafe for ScratchPool<T>

§

impl<T> !Sync for ScratchPool<T>

§

impl<T> Unpin for ScratchPool<T>
where [UnsafeCell<AlignedVec<T>>; 4]: Unpin,

§

impl<T> UnsafeUnpin for ScratchPool<T>

§

impl<T> UnwindSafe for ScratchPool<T>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.