about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm/src/llvm
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-07-07 11:32:19 +0000
committerbors <bors@rust-lang.org>2024-07-07 11:32:19 +0000
commit382148d9a21ae0b506adf44fc1e55a410acde828 (patch)
tree25d225a8dac2ac514a67eb406d2b1098bf137365 /compiler/rustc_codegen_llvm/src/llvm
parent98dcbae5c9ac615d5acfbf42d42b19a77cb9ec11 (diff)
parent54556f49d368ba96a92fd6ec352cf6b12e9542ef (diff)
downloadrust-382148d9a21ae0b506adf44fc1e55a410acde828.tar.gz
rust-382148d9a21ae0b506adf44fc1e55a410acde828.zip
Auto merge of #123253 - ChayimFriedman2:extend-trusted, r=the8472
Specialize `TrustedLen` for `Iterator::unzip()`

Don't check the capacity every time (and also for `Extend` for tuples, as this is how `unzip()` is implemented).

I did this with an unsafe method on `Extend` that doesn't check for growth (`extend_one_unchecked()`). I've marked it as perma-unstable currently, although we may want to expose it in the future so collections outside of std can benefit from it. Then specialize `Extend for (A, B)` for `TrustedLen` to call it.

An alternative way of implementing this is to have a semi-public trait (`#[doc(hidden)]` public, so collections outside of core can implement it) for `extend()` inside tuples, and specialize it from collections. However:

 1. This looks more complex to me.
 2. This prohibits the option of exposing this somewhen to collections outside of std, as we never expose specializations.

A concern that may arise with the current approach is that implementing `extend_one_unchecked()` correctly must also incur implementing `extend_reserve()`, otherwise you can have UB. This is a somewhat non-local safety invariant. However, I believe this is fine, since to have actual UB you must have unsafe code inside your `extend_one_unchecked()` that makes incorrect assumption, *and* not implement `extend_reserve()`. I've also documented this requirement.

**Benchmark:**

Code:
```rust
#[bench]
fn unzip(b: &mut Bencher) {
    b.iter(|| {
        for _ in 0..10_000 {
            let v: (Vec<_>, VecDeque<_>) =
                (black_box(0u32)..black_box(1_000)).map(|i| (i, i * 2)).unzip();
            black_box(v);
        }
    });
}
```

Before:
```
unzip::unzip 14.17ms/iter  +/- 374.85µs
```
After:
```
unzip::unzip 5.33ms/iter  +/- 164.54µs
```
Diffstat (limited to 'compiler/rustc_codegen_llvm/src/llvm')
0 files changed, 0 insertions, 0 deletions