Commit graph

313 commits

Author SHA1 Message Date
Dylan DPC
6ea27010b5
Rollup merge of #70752 - yoshuawuyts:slice_fill, r=dtolnay
Add slice::fill

Adds the `slice::fill` method to fill a slice with an item. This replaces manual for loops where items are copied one-by-one. This is a counterpart to C++20's [`std::fill`](https://en.cppreference.com/w/cpp/algorithm/fill) function.

## Usage

```rust
let mut buf = vec![0; 10];
buf.fill(1);
assert_eq!(buf, vec![1; 10]);
```

## Performance

When compiling in release mode, for `[u8]` and `[u16]` this method will optimize to a `memset(3)` call ([godbolt](https://godbolt.org/z/85El_c)). The initial implementation relies on LLVM's optimizer to make it as fast as possible for any given input. But as @jonas-schievink [pointed out](https://twitter.com/sheevink/status/1245756597453885442) this can later be optimized through specialization to guarantee it has a specific performance profile.

## Why now?

Conversations about adding `slice::fill` are not new. In fact, https://github.com/rust-lang/rfcs/issues/2067 was opened 3 years ago about this exact topic. However discussion stranded while discussing implementation details, and it's not seen much forward motion since.

In ["The Hunt for the Fastest Zero"](https://travisdowns.github.io/blog/2020/01/20/zero.html) Travis Downs provides disects C++'s `std::fill` performance profile on gcc, comparing it among others to `memset(3)`. Even though `memset(3)` outperforms `std::fill` in their tests, the author notes the following:

>  That the optimization fails, perhaps unexpectedly, in some cases is unfortunate but it’s nice that you can fix it yourself. [...] Do we throw out modern C++ idioms, at least where performance matters, for example by replacing std::fill with memset? I don’t think so.

Much of the article focuses on how how to fix the performance of `std::fill` by providing specializations for specific input. In Rust we don't have any dedicated methods to fill slices with values, so it either needs to be optimized at the MIR layer, or more likely rely on LLVM's optimizer.

By adding a dedicated method for filling slices with values it opens up the ability for us to in the future guarantee that e.g. `Vec<u8>` will always optimize to `memset` even in debug mode. Or perhaps provide stronger guarantees about memory when zeroing values when a certain flag is passed. But regardless of that, it improves general ergonomics of working with slices by providing a dedicated method with documentation and examples.

## References
- [slice-fill prototype on docs.rs](https://docs.rs/slice-fill/1.0.1/slice_fill/)
- [The Hunt For The Fastest Zero](https://travisdowns.github.io/blog/2020/01/20/zero.html)
- [Safe memset for slices](https://github.com/rust-lang/rfcs/issues/2067)
- [C++20 std::fill](https://en.cppreference.com/w/cpp/algorithm/fill)
- [ASM output on Godbolt](https://godbolt.org/z/5-XU66)
2020-04-05 06:44:45 +02:00
Yoshua Wuyts
edabceb4a3 Add slice::fill 2020-04-05 01:44:02 +02:00
Linus Färnstrand
c831265940 Replace float module consts with assoc consts in documentation 2020-04-03 09:33:10 +02:00
Adam Perry
a7ab7b136e #[track_caller] on core::ops::{Index, IndexMut}. 2020-03-23 08:01:49 -07:00
Josh Stone
53be0ccbc9 Use subslice patterns in slice methods
For all of the methods that pick off the first or last element, we can
use subslice patterns to implement them directly, rather than relying on
deeper indexing function calls. At a minimum, this means the generated
code will rely less on inlining for performance, but in some cases it
also optimizes better.
2020-03-04 10:34:24 -08:00
Dylan DPC
02381db8e0
Rollup merge of #69581 - RalfJung:align_to_mut, r=Centril
fix aliasing violation in align_to_mut

Fixes https://github.com/rust-lang/rust/issues/68549

I decided to add the testcase here to make it all one PR, but if you prefer I can also add that test case in the Miri repo instead.
2020-02-29 18:54:02 +01:00
Ralf Jung
c34451ffb7 fix aliasing violation in align_to_mut 2020-02-29 14:53:20 +01:00
Matthias Krüger
9523c89f18 use is_empty() instead of len() == x to determine if structs are empty. 2020-02-28 15:16:27 +01:00
bors
87e494c4cd Auto merge of #67330 - golddranks:split_inclusive, r=kodraus
Implement split_inclusive for slice and str

# Overview
* Implement `split_inclusive` for `slice` and `str` and `split_inclusive_mut` for `slice`
* `split_inclusive` is a substring/subslice splitting iterator that includes the matched part in the iterated substrings as a terminator.
* EDIT: The behaviour has now changed, as per @KodrAus 's input, to the same semantics with the `split_terminator` function. I updated the examples below.
* Two examples below:
```Rust
    let data = "\nMäry häd ä little lämb\nLittle lämb\n";
    let split: Vec<&str> = data.split_inclusive('\n').collect();
    assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]);
```

```Rust
    let uppercase_separated = "SheePSharKTurtlECaT";
    let mut first_char = true;
    let split: Vec<&str> = uppercase_separated.split_inclusive(|c: char| {
        let split = !first_char && c.is_uppercase();
        first_char = split;
        split
    }).collect();
    assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]);
```

# Justification for the API
* I was surprised to find that stdlib currently only has splitting iterators that leave out the matched part. In my experience, wanting to leave a substring terminator as a part of the substring is a pretty common usecase.
* This API is strictly more expressive than the standard `split` API: it's easy to get the behaviour of `split` by mapping a subslicing operation that drops the terminator. On the other hand it's impossible to derive this behaviour from `split` without using hacky and brittle `unsafe` code. The normal way to achieve this functionality would be implementing the iterator yourself.
* Especially when dealing with mutable slices, the only way currently is to use `split_at_mut`. This API provides an ergonomic alternative that plays to the strengths of the iterating capabilities of Rust. (Using `split_at_mut` iteratively used to be a real pain before NLL, fortunately the situation is a bit better now.)

# Discussion items
* <s>Does it make sense to mimic `split_terminator` in that the final empty slice would be left off in case of the string/slice ending with a terminator? It might do, as this use case is naturally geared towards considering the matching part as a terminator instead of a separator.</s>
  * EDIT: The behaviour was changed to mimic `split_terminator`.
* Does it make sense to have `split_inclusive_mut` for `&mut str`?
2020-02-22 03:54:50 +00:00
Pyry Kontio
5c9dc57cb5 Don't return empty slice on last iteration with matched terminator. Test reverse iteration. 2020-02-09 23:49:44 +09:00
Pyry Kontio
86bf96291d Implement split_inclusive for slice and str, an splitting iterator that includes the matched part in the iterated substrings as a terminator. 2020-02-09 23:48:52 +09:00
Matthew Jasper
a81c59f9b8 Remove some unsound specializations 2020-02-01 09:11:41 +00:00
Martin Habovstiak
2c796ee77c Use NonNull in slice::Iter and slice::IterMut.
`ptr` of `slice::Iter` and `slice::IterMut` can never be null, but this
fact wasn't exploited for layout optimizations. By changing `ptr` from
`*<mutability> T` to `NonNull<T>`, the compiler can now optimize layout
of `Option<Iter<'a, T>>`.
2019-12-26 20:18:31 +01:00
Mark Rousskov
a06baa56b9 Format the world 2019-12-22 17:42:47 -05:00
Ross MacArthur
f7256d28d1
Require issue = "none" over issue = "0" in unstable attributes 2019-12-21 13:16:18 +02:00
Mark Rousskov
82184440ec Propagate cfg bootstrap 2019-12-18 12:16:19 -05:00
Oliver Scherer
5e17e39881 Require stable/unstable annotations for the constness of all stable functions with a const modifier 2019-12-13 11:27:02 +01:00
David Tolnay
95e00bfed8
Format libcore with rustfmt
This commit applies rustfmt with default settings to files in
src/libcore *that are not involved in any currently open PR* to minimize
merge conflicts. The list of files involved in open PRs was determined
by querying GitHub's GraphQL API with this script:
https://gist.github.com/dtolnay/aa9c34993dc051a4f344d1b10e4487e8

With the list of files from the script in `outstanding_files`, the
relevant commands were:

    $ find src/libcore -name '*.rs' | xargs rustfmt --edition=2018
    $ rg libcore outstanding_files | xargs git checkout --

Repeating this process several months apart should get us coverage of
most of the rest of libcore.
2019-11-26 23:02:11 -08:00
Mazdak Farrokhzad
379b19c17f
Rollup merge of #63793 - oli-obk:🧹, r=dtolnay
Have tidy ensure that we document all `unsafe` blocks in libcore

cc @rust-lang/libs

I documented a few and added ignore flags on the other files. We can incrementally document the files, but won't regress any files this way.
2019-11-07 14:27:20 +01:00
Oliver Scherer
02f9167f94 Have tidy ensure that we document all unsafe blocks in libcore 2019-11-06 11:04:42 +01:00
Ralf Jung
b1d0a68fd7 fix link to ptr docs 2019-11-05 13:22:43 +01:00
Ralf Jung
1a254e4f43 expand slice from_raw_part docs 2019-11-05 09:55:33 +01:00
Mara Bos
381c4425b7 Fix slice::as_ptr_range doctest. 2019-10-25 18:01:31 +02:00
Mara Bos
de9b660a40 Explain why pointer::add in slice::as_ptr_range is safe. 2019-10-25 15:46:42 +02:00
Mara Bos
f1b69b0a87 Add slice_ptr_range tracking issue number. 2019-10-25 14:33:07 +02:00
Mara Bos
4936f96d42 Add [T]::as_ptr_range() and [T]::as_mut_ptr_range().
See https://github.com/rust-lang/rfcs/pull/2791 for motivation.
2019-10-25 14:09:32 +02:00
Mark Rousskov
d0a6805b0e Allow unused attributes to avoid incremental bug 2019-10-04 11:11:58 -04:00
bors
e0436d912d Auto merge of #64600 - scottmcm:no-slice-tryfold-unroll, r=bluss
Remove manual unrolling from slice::Iter(Mut)::try_fold

While this definitely helps sometimes (particularly for trivial closures), it's also a pessimization sometimes, so it's better to leave this to (hypothetical) future LLVM improvements instead of forcing this on everyone.

I think it's better for the advice to be that sometimes you need to unroll manually than you sometimes need to not-unroll manually (like #64545).

---

For context see https://github.com/rust-lang/rust/pull/64572#issuecomment-532961046
2019-09-30 09:52:29 +00:00
Mark Rousskov
f359a94849 Snap cfgs to new beta 2019-09-25 08:42:46 -04:00
Oliver Scherer
7767e7fb16 Stabilize str::len, [T]::len, is_empty and str::as_bytes as const fn 2019-09-24 12:56:44 +02:00
Scott McMurray
6ac64abd6d Just delete the overrides now that they match the default implementations 2019-09-23 23:10:45 -07:00
Scott McMurray
92e91f7541 Remove manual unrolling from slice::Iter(Mut)::try_fold
While this definitely helps sometimes (particularly for trivial closures), it's also a pessimization sometimes, so it's better to leave this to (hypothetical) future LLVM improvements instead of forcing this on everyone.

I think it's better for the advice to be that sometimes you need to unroll manually than you sometimes need to not-unroll manually (like #64545).
2019-09-21 21:16:24 -07:00
Mateusz Mikuła
edabcddf4d Apply clippy::let_and_return suggestion 2019-08-22 12:02:02 +02:00
Mazdak Farrokhzad
60649e3a2e
Rollup merge of #63265 - JohnTitor:implement-nth-back-for-chunksexactmut, r=scottmcm
Implement `nth_back` for ChunksExactMut

This is a part of #54054.

r? @scottmcm
2019-08-20 16:26:37 +02:00
Lzu Tao
30ba4bd8e2 Use Result::unwrap_or_else instead of matching 2019-08-10 17:16:58 +00:00
Lzu Tao
93839c3fb4 Add an example to show how to insert item to a sorted vec 2019-08-10 16:31:38 +00:00
bors
d8f8be4636 Auto merge of #61937 - AaronKutch:master, r=scottmcm
Improve `ptr_rotate` performance, tests, and benches

The corresponding issue is #61784. I am not actually sure if miri can handle the test, but I can change the commit if necessary.
2019-08-09 04:41:20 +00:00
Aaron Kutch
ad7fdb6859 Improve ptr_rotate performance, tests, and benchmarks 2019-08-06 10:42:48 -05:00
Jake Goulding
571e22d7e8 Clarify align_to's requirements and obligations 2019-08-05 19:44:07 -04:00
Yuki Okushi
d3019d16b9 Implement nth_back for ChunksExactMut 2019-08-05 02:44:08 +09:00
Ralf Jung
9b5623f8bc fix links
relative links do not work because this is included in several places
2019-08-04 09:52:36 +02:00
Ralf Jung
3b9cda4693
Apply suggestions from code review
Co-Authored-By: Mazdak Farrokhzad <twingoow@gmail.com>
2019-08-03 13:45:15 +02:00
Ralf Jung
f44abba4ec clarify that unchecked indexing is UB even if the reference is never used 2019-08-03 12:46:20 +02:00
Mazdak Farrokhzad
cb8b491a65
Rollup merge of #62074 - wizAmit:feature/mut_chunks_nth_back, r=scottmcm
squash of all commits for nth_back on ChunksMut

wip nth_back for chunks_mut

working chunksmut

fixed nth_back for chunksmut

Signed-off-by: wizAmit <amitforfriends_dns@yahoo.com>

r? @timvermeulen
r? @scottmcm
2019-07-28 03:01:44 +02:00
bors
890881f8f4 Auto merge of #60340 - mgeier:cap-vs-capacity, r=alexcrichton
Rename .cap() methods to .capacity()

As mentioned in #60316, there are a few `.cap()` methods, which seem out-of-place because such methods are called `.capacity()` in the rest of the code.

This PR renames them to `.capacity()` but leaves `RawVec::cap()` in there for backwards compatibility.

I didn't try to mark the old version as "deprecated", because I guess this would cause too much noise.
2019-07-25 18:45:42 +00:00
Mark Rousskov
4264f8376a
Rollup merge of #62656 - RalfJung:contains-no-own, r=Dylan-DPC
explain how to search in slice without owned data

Cc https://github.com/rust-lang/rust/issues/62367
2019-07-23 12:51:05 -04:00
Ralf Jung
ad261f6852 avoid uninit_array! macro where it is not needed 2019-07-19 17:23:47 +02:00
Ralf Jung
e074db764a use const array repeat expressions for uninit_array 2019-07-19 14:47:56 +02:00
Mark Rousskov
831d33b8b0
Rollup merge of #62728 - DutchGhost:fix-double-wording, r=jonas-schievink
Fix repeated wording in slice documentation

Changes `of the slice of the slice` to `of the slice` in the chunk- and friends documentation of slices
2019-07-18 11:29:42 -04:00
Dodo
9341e90b44 found more repeated wording 2019-07-16 21:57:32 +02:00