Skip to main content

Int8Tier

Enum Int8Tier 

Source
pub enum Int8Tier {
    Scalar,
    Autovec,
    NeonSdot,
    WasmSimd128,
}
Expand description

An executable int8 dot-product route.

Every variant is exactly equal in i32 to Scalar on every input. NeonSdot exists only on aarch64 builds with the neon-dotprod feature and is dispatchable only where the CPU reports FEAT_DotProd at runtime.

Variants§

§

Scalar

Portable left-to-right checked-free scalar loop; the reference every tier must equal.

§

Autovec

Portable eight-lane loop, retained ONLY as an A/B datapoint: measured ~15x SLOWER than Scalar at m=1 on M4 Pro (NE-001) — the manual lane structure defeats LLVM’s autovectorizer, while the plain Scalar shape vectorizes to memory bandwidth. Never the dispatch default.

§

NeonSdot

Hand SDOT island (aarch64 + FEAT_DotProd), four 16-byte accumulator streams.

§

WasmSimd128

Hand SIMD128 island (wasm32 + simd128), four 16-byte accumulator streams.

The browser’s equivalent of Self::NeonSdot. Unlike aarch64, wasm has no int8 dot for the autovectorizer to find, so without this tier a browser runs the byte-at-a-time Scalar loop.

Implementations§

Source§

impl Int8Tier

Source

pub const fn as_str(self) -> &'static str

Stable machine-readable route name.

Examples found in repository?
examples/int8_shape_bench.rs (line 65)
62fn main() {
63    let tiers: Vec<Int8Tier> = Int8Tier::available();
64    println!("int8 shape bench — tiers available: {:?}", {
65        tiers.iter().map(|t| t.as_str()).collect::<Vec<_>>()
66    });
67    println!(
68        "interleaved rounds={ROUNDS} (+{WARMUP_ROUNDS} warmup); per-sample = mean over calls in one round; cv% over rounds"
69    );
70
71    for &m in &[1_usize, 16] {
72        println!(
73            "\n== m = {m} {} ==",
74            if m == 1 {
75                "(decode GEMV)"
76            } else {
77                "(seq-16 verify GEMM)"
78            }
79        );
80        for &(label, n, k) in SHAPES {
81            let calls: usize = (32 / m).max(2);
82            let weight = pseudo_random_f32(n * k, 0xbe0_0001 ^ (n as u64) << 20 ^ k as u64);
83            let x = pseudo_random_f32(m * k, 0xbe0_0002 ^ (m as u64) << 32 ^ k as u64);
84            let quantized = QuantizedMatrix::quantize(&weight, n, k);
85            let mut out = vec![0.0_f32; m * n];
86            let mut x_q = vec![0_i8; m * k];
87            let mut x_scales = vec![0.0_f32; m];
88
89            // One arm per route, all interleaved inside every round.
90            let mut f32_samples = Vec::with_capacity(ROUNDS);
91            let mut tier_samples: Vec<Vec<f64>> =
92                tiers.iter().map(|_| Vec::with_capacity(ROUNDS)).collect();
93
94            for round in 0..ROUNDS + WARMUP_ROUNDS {
95                // f32 arm
96                let start = Instant::now();
97                for _ in 0..calls {
98                    f32ref::linear(
99                        black_box(&x),
100                        black_box(&weight),
101                        None,
102                        m,
103                        k,
104                        n,
105                        black_box(&mut out),
106                    );
107                }
108                let f32_us = start.elapsed().as_secs_f64() * 1e6 / calls as f64;
109
110                // W8A8 arms, including dynamic activation quantization each call.
111                let mut this_round = Vec::with_capacity(tiers.len());
112                for &tier in &tiers {
113                    let start = Instant::now();
114                    for _ in 0..calls {
115                        for ((x_row, q_row), scale) in x
116                            .chunks_exact(k)
117                            .zip(x_q.chunks_exact_mut(k))
118                            .zip(x_scales.iter_mut())
119                        {
120                            *scale = quantize_row_q8(black_box(x_row), q_row);
121                        }
122                        linear_q8(
123                            black_box(&x_q),
124                            black_box(&x_scales),
125                            black_box(&quantized),
126                            None,
127                            m,
128                            black_box(&mut out),
129                            tier,
130                        );
131                    }
132                    this_round.push(start.elapsed().as_secs_f64() * 1e6 / calls as f64);
133                }
134
135                if round >= WARMUP_ROUNDS {
136                    f32_samples.push(f32_us);
137                    for (samples, sample) in tier_samples.iter_mut().zip(&this_round) {
138                        samples.push(*sample);
139                    }
140                }
141            }
142
143            let f32_stats = stats(&f32_samples);
144            // The f32 reference loops rows outermost, so it streams the weight matrix once per
145            // activation row (m times per call); the q8 kernel is weight-stationary and streams
146            // it exactly once per call. The column reports actual weight bytes moved per second.
147            let f32_bytes = (n * k * 4 * m) as f64;
148            println!(
149                "{label}  f32     {:9.1} us  cv {:4.1}%  ({:5.1} GB/s weight-stream)",
150                f32_stats.mean_us,
151                f32_stats.cv_percent,
152                f32_bytes / (f32_stats.mean_us * 1e-6) / 1e9,
153            );
154            for (tier, samples) in tiers.iter().zip(&tier_samples) {
155                let tier_stats = stats(samples);
156                let q8_bytes = (n * k) as f64;
157                let verdict = if tier_stats.cv_percent > 5.0 || f32_stats.cv_percent > 5.0 {
158                    "REFUSED (cv>5%)"
159                } else {
160                    ""
161                };
162                println!(
163                    "{label}  q8 {:9} {:9.1} us  cv {:4.1}%  ({:5.1} GB/s weight-stream)  x{:.2} vs f32 {verdict}",
164                    tier.as_str(),
165                    tier_stats.mean_us,
166                    tier_stats.cv_percent,
167                    q8_bytes / (tier_stats.mean_us * 1e-6) / 1e9,
168                    f32_stats.mean_us / tier_stats.mean_us,
169                );
170            }
171        }
172    }
173    println!(
174        "\nNOTE: ratios above compare routes inside this tree (self-comparison = maintenance),\nnever a pinned incumbent. cv%>5 rows are refused, not averaged."
175    );
176}
More examples
Hide additional examples
examples/int4_speed_gate.rs (line 64)
45fn main() {
46    // (label, n, k) for one microdecoder layer, at decode geometry m = 1.
47    const HIDDEN: usize = 1024;
48    const INTERMEDIATE: usize = 3072;
49    const Q_WIDTH: usize = 16 * 128;
50    const KV_WIDTH: usize = 8 * 128;
51    let projections: &[(&str, usize, usize)] = &[
52        ("q_proj", Q_WIDTH, HIDDEN),
53        ("k_proj", KV_WIDTH, HIDDEN),
54        ("v_proj", KV_WIDTH, HIDDEN),
55        ("o_proj", HIDDEN, Q_WIDTH),
56        ("gate_up", INTERMEDIATE * 2, HIDDEN),
57        ("down_proj", HIDDEN, INTERMEDIATE),
58    ];
59
60    // Fifteen depths x five layers is how often this body is walked per frame.
61    const ROUNDS: usize = 15 * 5;
62
63    let dispatched = Int8Tier::dispatch();
64    println!("dispatched int8 route: {}", dispatched.as_str());
65    println!("shapes: microdecoder layer at m=1, {ROUNDS} rounds (15 depths x 5 layers)\n");
66    // The ratio columns are SPEED ratios (q4's throughput relative to the q8 variant):
67    // t_q8 / t_q4, so 1.0 means parity and 0.05 means q4 runs at 5% of q8's speed.
68    println!(
69        "{:<10} {:>6} {:>6} {:>10} {:>10} {:>10} {:>9} {:>9}",
70        "proj", "n", "k", "q8-scalar", "q4-scalar", "q8-route", "spd/q8scl", "spd/route"
71    );
72
73    let mut total_q8_scalar = 0.0_f64;
74    let mut total_q4 = 0.0_f64;
75    let mut total_q8_route = 0.0_f64;
76
77    for &(label, n, k) in projections {
78        let weight = deterministic(n * k, 0x51ED_0000 + n as u64);
79        let activation = deterministic(k, 0xA0C7_0000 + k as u64);
80        let mut x_q = vec![0_i8; k];
81        let scale = quantize_row_q8(&activation, &mut x_q);
82
83        let q8 = QuantizedMatrix::quantize(&weight, n, k);
84        let q4 = QuantizedMatrixQ4::quantize(&weight, n, k);
85        let mut out = vec![0.0_f32; n];
86
87        // Warm the caches for whichever side runs first, so the ordering does not decide it.
88        linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, Int8Tier::Scalar);
89        linear_q4(&x_q, &[scale], &q4, None, 1, &mut out);
90
91        // INTERLEAVED repeats, reporting the minimum of each variant.
92        //
93        // A first attempt timed the three variants in sequential blocks and produced 98.60 ms for
94        // k_proj against 5.14 ms for v_proj — identical 1024x1024 shapes, 19x apart. That is
95        // scheduler and thermal noise, and it is precisely what doctrine #8's same-thermal-window
96        // rule exists to prevent. Interleaving puts all three variants in the same window on every
97        // repeat, and the minimum is the least noise-contaminated estimator of a deterministic
98        // kernel: noise only ever adds time.
99        const REPEATS: usize = 7;
100        let mut q8_scalar = f64::MAX;
101        let mut q4_ms = f64::MAX;
102        let mut q8_route = f64::MAX;
103        for _ in 0..REPEATS {
104            let started = Instant::now();
105            for _ in 0..ROUNDS {
106                linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, Int8Tier::Scalar);
107            }
108            q8_scalar = q8_scalar.min(started.elapsed().as_secs_f64() * 1000.0);
109
110            let started = Instant::now();
111            for _ in 0..ROUNDS {
112                linear_q4(&x_q, &[scale], &q4, None, 1, &mut out);
113            }
114            q4_ms = q4_ms.min(started.elapsed().as_secs_f64() * 1000.0);
115
116            let started = Instant::now();
117            for _ in 0..ROUNDS {
118                linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, dispatched);
119            }
120            q8_route = q8_route.min(started.elapsed().as_secs_f64() * 1000.0);
121        }
122
123        total_q8_scalar += q8_scalar;
124        total_q4 += q4_ms;
125        total_q8_route += q8_route;
126
127        println!(
128            "{label:<10} {n:>6} {k:>6} {q8_scalar:>9.2}m {q4_ms:>9.2}m {q8_route:>9.2}m {:>8.2}x {:>8.2}x",
129            q8_scalar / q4_ms,
130            q8_route / q4_ms
131        );
132    }
133
134    println!(
135        "\ntotals (one layer, {ROUNDS} rounds): q8-scalar {total_q8_scalar:.1} ms, \
136         q4-scalar {total_q4:.1} ms, q8-route {total_q8_route:.1} ms"
137    );
138    println!(
139        "int4 vs scalar int8 : {:.2}x  ({})",
140        total_q8_scalar / total_q4,
141        if total_q4 < total_q8_scalar {
142            "FASTER - the halved-bytes thesis holds at equal implementation quality"
143        } else {
144            "SLOWER - unpack cost exceeds the traffic saving even against scalar"
145        }
146    );
147    println!(
148        "int4 vs shipping int8: {:.2}x  ({})",
149        total_q8_route / total_q4,
150        if total_q4 < total_q8_route {
151            "FASTER - gate (a) PASSES; the listening gate is now worth running"
152        } else {
153            "SLOWER - gate (a) FAILS as built; int4 needs an in-register SIMD unpack to compete"
154        }
155    );
156
157    // Bytes are the thesis; report them so the ratio can be read against the traffic it saves.
158    let q8_bytes: usize = projections.iter().map(|(_, n, k)| n * k).sum();
159    println!(
160        "\nweight bytes per layer: q8 {:.1} MB, q4 {:.1} MB",
161        q8_bytes as f64 / 1e6,
162        q8_bytes as f64 / 2e6
163    );
164}
Source

pub fn available() -> Vec<Self>

Every tier this build can execute on the running silicon, scalar first.

Examples found in repository?
examples/int8_shape_bench.rs (line 63)
62fn main() {
63    let tiers: Vec<Int8Tier> = Int8Tier::available();
64    println!("int8 shape bench — tiers available: {:?}", {
65        tiers.iter().map(|t| t.as_str()).collect::<Vec<_>>()
66    });
67    println!(
68        "interleaved rounds={ROUNDS} (+{WARMUP_ROUNDS} warmup); per-sample = mean over calls in one round; cv% over rounds"
69    );
70
71    for &m in &[1_usize, 16] {
72        println!(
73            "\n== m = {m} {} ==",
74            if m == 1 {
75                "(decode GEMV)"
76            } else {
77                "(seq-16 verify GEMM)"
78            }
79        );
80        for &(label, n, k) in SHAPES {
81            let calls: usize = (32 / m).max(2);
82            let weight = pseudo_random_f32(n * k, 0xbe0_0001 ^ (n as u64) << 20 ^ k as u64);
83            let x = pseudo_random_f32(m * k, 0xbe0_0002 ^ (m as u64) << 32 ^ k as u64);
84            let quantized = QuantizedMatrix::quantize(&weight, n, k);
85            let mut out = vec![0.0_f32; m * n];
86            let mut x_q = vec![0_i8; m * k];
87            let mut x_scales = vec![0.0_f32; m];
88
89            // One arm per route, all interleaved inside every round.
90            let mut f32_samples = Vec::with_capacity(ROUNDS);
91            let mut tier_samples: Vec<Vec<f64>> =
92                tiers.iter().map(|_| Vec::with_capacity(ROUNDS)).collect();
93
94            for round in 0..ROUNDS + WARMUP_ROUNDS {
95                // f32 arm
96                let start = Instant::now();
97                for _ in 0..calls {
98                    f32ref::linear(
99                        black_box(&x),
100                        black_box(&weight),
101                        None,
102                        m,
103                        k,
104                        n,
105                        black_box(&mut out),
106                    );
107                }
108                let f32_us = start.elapsed().as_secs_f64() * 1e6 / calls as f64;
109
110                // W8A8 arms, including dynamic activation quantization each call.
111                let mut this_round = Vec::with_capacity(tiers.len());
112                for &tier in &tiers {
113                    let start = Instant::now();
114                    for _ in 0..calls {
115                        for ((x_row, q_row), scale) in x
116                            .chunks_exact(k)
117                            .zip(x_q.chunks_exact_mut(k))
118                            .zip(x_scales.iter_mut())
119                        {
120                            *scale = quantize_row_q8(black_box(x_row), q_row);
121                        }
122                        linear_q8(
123                            black_box(&x_q),
124                            black_box(&x_scales),
125                            black_box(&quantized),
126                            None,
127                            m,
128                            black_box(&mut out),
129                            tier,
130                        );
131                    }
132                    this_round.push(start.elapsed().as_secs_f64() * 1e6 / calls as f64);
133                }
134
135                if round >= WARMUP_ROUNDS {
136                    f32_samples.push(f32_us);
137                    for (samples, sample) in tier_samples.iter_mut().zip(&this_round) {
138                        samples.push(*sample);
139                    }
140                }
141            }
142
143            let f32_stats = stats(&f32_samples);
144            // The f32 reference loops rows outermost, so it streams the weight matrix once per
145            // activation row (m times per call); the q8 kernel is weight-stationary and streams
146            // it exactly once per call. The column reports actual weight bytes moved per second.
147            let f32_bytes = (n * k * 4 * m) as f64;
148            println!(
149                "{label}  f32     {:9.1} us  cv {:4.1}%  ({:5.1} GB/s weight-stream)",
150                f32_stats.mean_us,
151                f32_stats.cv_percent,
152                f32_bytes / (f32_stats.mean_us * 1e-6) / 1e9,
153            );
154            for (tier, samples) in tiers.iter().zip(&tier_samples) {
155                let tier_stats = stats(samples);
156                let q8_bytes = (n * k) as f64;
157                let verdict = if tier_stats.cv_percent > 5.0 || f32_stats.cv_percent > 5.0 {
158                    "REFUSED (cv>5%)"
159                } else {
160                    ""
161                };
162                println!(
163                    "{label}  q8 {:9} {:9.1} us  cv {:4.1}%  ({:5.1} GB/s weight-stream)  x{:.2} vs f32 {verdict}",
164                    tier.as_str(),
165                    tier_stats.mean_us,
166                    tier_stats.cv_percent,
167                    q8_bytes / (tier_stats.mean_us * 1e-6) / 1e9,
168                    f32_stats.mean_us / tier_stats.mean_us,
169                );
170            }
171        }
172    }
173    println!(
174        "\nNOTE: ratios above compare routes inside this tree (self-comparison = maintenance),\nnever a pinned incumbent. cv%>5 rows are refused, not averaged."
175    );
176}
Source

pub fn dispatch() -> Self

The route the int8 path dispatches by default, honoring the FTTS_INT8_TIER override.

The override exists for interleaved A/B measurement (scalar / autovec / neon-sdot); an unavailable or unrecognized override falls back to the measured default rather than panicking mid-synthesis. Until a per-shape KernelPlan lands, the default is NeonSdot where FEAT_DotProd exists, else Scalar. Measured on M4 Pro (2026-08-08, shape bench, noisy shared host, indicative): plain Scalar autovectorizes to ~50 GB/s and ties SDOT at m=1 — NE-INH-003 reconfirmed — while the hand-shaped Autovec lane loop defeats the vectorizer and loses ~15x; it stays only as an A/B datapoint.

Examples found in repository?
examples/int4_speed_gate.rs (line 63)
45fn main() {
46    // (label, n, k) for one microdecoder layer, at decode geometry m = 1.
47    const HIDDEN: usize = 1024;
48    const INTERMEDIATE: usize = 3072;
49    const Q_WIDTH: usize = 16 * 128;
50    const KV_WIDTH: usize = 8 * 128;
51    let projections: &[(&str, usize, usize)] = &[
52        ("q_proj", Q_WIDTH, HIDDEN),
53        ("k_proj", KV_WIDTH, HIDDEN),
54        ("v_proj", KV_WIDTH, HIDDEN),
55        ("o_proj", HIDDEN, Q_WIDTH),
56        ("gate_up", INTERMEDIATE * 2, HIDDEN),
57        ("down_proj", HIDDEN, INTERMEDIATE),
58    ];
59
60    // Fifteen depths x five layers is how often this body is walked per frame.
61    const ROUNDS: usize = 15 * 5;
62
63    let dispatched = Int8Tier::dispatch();
64    println!("dispatched int8 route: {}", dispatched.as_str());
65    println!("shapes: microdecoder layer at m=1, {ROUNDS} rounds (15 depths x 5 layers)\n");
66    // The ratio columns are SPEED ratios (q4's throughput relative to the q8 variant):
67    // t_q8 / t_q4, so 1.0 means parity and 0.05 means q4 runs at 5% of q8's speed.
68    println!(
69        "{:<10} {:>6} {:>6} {:>10} {:>10} {:>10} {:>9} {:>9}",
70        "proj", "n", "k", "q8-scalar", "q4-scalar", "q8-route", "spd/q8scl", "spd/route"
71    );
72
73    let mut total_q8_scalar = 0.0_f64;
74    let mut total_q4 = 0.0_f64;
75    let mut total_q8_route = 0.0_f64;
76
77    for &(label, n, k) in projections {
78        let weight = deterministic(n * k, 0x51ED_0000 + n as u64);
79        let activation = deterministic(k, 0xA0C7_0000 + k as u64);
80        let mut x_q = vec![0_i8; k];
81        let scale = quantize_row_q8(&activation, &mut x_q);
82
83        let q8 = QuantizedMatrix::quantize(&weight, n, k);
84        let q4 = QuantizedMatrixQ4::quantize(&weight, n, k);
85        let mut out = vec![0.0_f32; n];
86
87        // Warm the caches for whichever side runs first, so the ordering does not decide it.
88        linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, Int8Tier::Scalar);
89        linear_q4(&x_q, &[scale], &q4, None, 1, &mut out);
90
91        // INTERLEAVED repeats, reporting the minimum of each variant.
92        //
93        // A first attempt timed the three variants in sequential blocks and produced 98.60 ms for
94        // k_proj against 5.14 ms for v_proj — identical 1024x1024 shapes, 19x apart. That is
95        // scheduler and thermal noise, and it is precisely what doctrine #8's same-thermal-window
96        // rule exists to prevent. Interleaving puts all three variants in the same window on every
97        // repeat, and the minimum is the least noise-contaminated estimator of a deterministic
98        // kernel: noise only ever adds time.
99        const REPEATS: usize = 7;
100        let mut q8_scalar = f64::MAX;
101        let mut q4_ms = f64::MAX;
102        let mut q8_route = f64::MAX;
103        for _ in 0..REPEATS {
104            let started = Instant::now();
105            for _ in 0..ROUNDS {
106                linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, Int8Tier::Scalar);
107            }
108            q8_scalar = q8_scalar.min(started.elapsed().as_secs_f64() * 1000.0);
109
110            let started = Instant::now();
111            for _ in 0..ROUNDS {
112                linear_q4(&x_q, &[scale], &q4, None, 1, &mut out);
113            }
114            q4_ms = q4_ms.min(started.elapsed().as_secs_f64() * 1000.0);
115
116            let started = Instant::now();
117            for _ in 0..ROUNDS {
118                linear_q8(&x_q, &[scale], &q8, None, 1, &mut out, dispatched);
119            }
120            q8_route = q8_route.min(started.elapsed().as_secs_f64() * 1000.0);
121        }
122
123        total_q8_scalar += q8_scalar;
124        total_q4 += q4_ms;
125        total_q8_route += q8_route;
126
127        println!(
128            "{label:<10} {n:>6} {k:>6} {q8_scalar:>9.2}m {q4_ms:>9.2}m {q8_route:>9.2}m {:>8.2}x {:>8.2}x",
129            q8_scalar / q4_ms,
130            q8_route / q4_ms
131        );
132    }
133
134    println!(
135        "\ntotals (one layer, {ROUNDS} rounds): q8-scalar {total_q8_scalar:.1} ms, \
136         q4-scalar {total_q4:.1} ms, q8-route {total_q8_route:.1} ms"
137    );
138    println!(
139        "int4 vs scalar int8 : {:.2}x  ({})",
140        total_q8_scalar / total_q4,
141        if total_q4 < total_q8_scalar {
142            "FASTER - the halved-bytes thesis holds at equal implementation quality"
143        } else {
144            "SLOWER - unpack cost exceeds the traffic saving even against scalar"
145        }
146    );
147    println!(
148        "int4 vs shipping int8: {:.2}x  ({})",
149        total_q8_route / total_q4,
150        if total_q4 < total_q8_route {
151            "FASTER - gate (a) PASSES; the listening gate is now worth running"
152        } else {
153            "SLOWER - gate (a) FAILS as built; int4 needs an in-register SIMD unpack to compete"
154        }
155    );
156
157    // Bytes are the thesis; report them so the ratio can be read against the traffic it saves.
158    let q8_bytes: usize = projections.iter().map(|(_, n, k)| n * k).sum();
159    println!(
160        "\nweight bytes per layer: q8 {:.1} MB, q4 {:.1} MB",
161        q8_bytes as f64 / 1e6,
162        q8_bytes as f64 / 2e6
163    );
164}

Trait Implementations§

Source§

impl Clone for Int8Tier

Source§

fn clone(&self) -> Int8Tier

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Int8Tier

Source§

impl Debug for Int8Tier

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for Int8Tier

Source§

impl PartialEq for Int8Tier

Source§

fn eq(&self, other: &Int8Tier) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for Int8Tier

Auto Trait Implementations§

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

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

Source§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

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.