cc #6004 and #3273
This is a rewrite of TLS to get towards not requiring `@` when using task local storage. Most of the rewrite is straightforward, although there are two caveats:
1. Changing `local_set` to not require `@` is blocked on #7673
2. The code in `local_pop` is some of the most unsafe code I've written. A second set of eyes should definitely scrutinize it...
The public-facing interface currently hasn't changed, although it will have to change because `local_data::get` cannot return `Option<T>`, nor can it return `Option<&T>` (the lifetime isn't known). This will have to be changed to be given a closure which yield `&T` (or as an Option). I didn't do this part of the api rewrite in this pull request as I figured that it could wait until when `@` is fully removed.
This also doesn't deal with the issue of using something other than functions as keys, but I'm looking into using static slices (as mentioned in the issues).
This patch is a step towards #6298. It extracts the graph abstraction from region inference into a library, and then ports the region inference to use it. It also adds a control-flow graph abstraction that will eventually be used by dataflow. The CFG code is not yet used, but I figured better to add it so as to make later rebasing etc easier.
00da76d r=cmr
6e75f2d r=cmr
This implements the trait for vector iterators, replacing the reverse
iterator types. The methods will stay, for implementing the future
reverse Iterable traits and convenience.
This can also be trivially implemented for circular buffers and other
variants of arrays like strings.
The `DoubleEndedIterator` trait will allow for implementing algorithms
like in-place reverse on generic mutable iterators.
The naming (`Range` vs. `Iterator`, `Bidirectional` vs. `DoubleEnded`)
can be bikeshedded in the future.
Indentation now works correctly on subsequent lines of a multi-line
comment, whether there are leaders (` * `) or not. (Formerly it was
incorrectly doing a two-space indent if there was no leader.)
By default, this no longer puts a ` * ` leader on `/*!` comments, as
that appears to be the current convention in the Rust source code, but
that can easily be re-enabled if desired:
let g:rust_bang_comment_leader = 1
This is a new doubly-linked list using owned nodes. In the forward direction, the list is linked with owned pointers, and the backwards direction is linked with &'static Node pointers.
This intends to replace the previous extra::DList that was using managed nodes and also featured freestanding nodes. The new List does not give access to the nodes, but means to implement all relevant linked-list methods.
The list supports pop_back, push_back, pop_front, push_front, front, back, iter, mut_iter, +more iterators, append, insert_ordered, and merge.
* Add a trait Deque for double ended sequences.
* Both List and Deque implement this trait. Rename Deque to ArrayDeque.
*The text has been updated to summarize resolved items*
## RFC Topics
### Resolved
* Should be in extra
* Representation for the backlinks
### Container Method Names and Trait Names and Type Names
* Location and name of trait `extra::collection::Deque`?
* Name of the ring buffer `extra::deque::ArrayDeque` ?
* Name of the doubly linked list `extra::dlist::List` ?
For container methods I think we have two options:
* Align with the existing methods on the vector. That would be `.push()`, `.pop()`, `.shift()`, `.unshift()`.
* Use the API described in https://github.com/mozilla/rust/wiki/Containers Obviously that's the way List is written right now.
Should we use `pop_front() -> Option<T>` or `pop_front() -> T` ?
### Benchmarks
Some basic bench numbers for List vs. Vec, Deque and *old DList*
This List implementation's performance is dominated by the allocation of Nodes required when pushing.
Iterate (by-ref) collection of 128 elements
test test_bench::bench_iter ... bench: 198 ns/iter (+/- 0)
test test_bench::bench_iter_mut ... bench: 294 ns/iter (+/- 0)
test test_bench::bench_iter_rev ... bench: 198 ns/iter (+/- 0)
test test_bench::bench_iter_mut_rev ... bench: 198 ns/iter (+/- 3)
test test_bench::bench_iter_vec ... bench: 101 ns/iter (+/- 0)
test test_bench::bench_iter_deque ... bench: 581 ns/iter (+/- 0)
test test_bench::bench_iter_dlist ... bench: 9262 ns/iter (+/- 273)
Sequence of `.push(elt)`, `.pop()` or equivalent at the tail end
test test_bench::bench_push_back_pop_back ... bench: 72 ns/iter (+/- 0)
test test_bench::bench_push_back_pop_back_vec ... bench: 5 ns/iter (+/- 0)
test test_bench::bench_push_back_pop_back_deque ... bench: 15 ns/iter (+/- 0)
test test_bench::bench_push_back_pop_back_dlist ... bench: 234 ns/iter (+/- 0)
An iterator that allows mutating the list is very useful but needs care
to not be unsound. ListIteration exposes only insert_before (used for
insert_ordered) and peek_next so far.
This is an owned sendable linked list which allows insertion and
deletion at both ends, with fast traversal through iteration, and fast
append/prepend.
It is indended to replace the previous managed DList with exposed list
nodes. It does not match it feature by feature, but DList could grow
more methods if needed.
This is much faster for strings, and eventually when there is a
buffered reader of some sort, will be much faster for files.
Reading example.json 100 times before was around 1.18s.
After:
- reading from string 0.68s
- reading from file 1.08s (extra time is all in io::Reader)
Also:
- fixes#7611 - error when parsing strings and we hit EOF
- updates definition of whitespace in json should only be the 4 ascii whitespace chars
All of the examples were still using `core::` instead of `std::` and needed a `use std::rand;` at the top to compile
Most of the examples had
`rng = rand::rng();`
instead of
`let mut rng = rand::rng();`
This implements the trait for vector iterators, replacing the reverse
iterator types. The methods will stay, for implementing the future
reverse Iterable traits and convenience.
This can also be trivially implemented for circular buffers and other
variants of arrays like strings and `SmallIntMap`/`SmallIntSet`.
The `DoubleEndedIterator` trait will allow for implementing algorithms
like in-place reverse on generic mutable iterators.
The naming (`Range` vs. `Iterator`, `Bidirectional` vs. `DoubleEnded`)
can be bikeshedded in the future.
This is much faster for strings, and eventually when there is a
buffered reader of some sort.
Reading example.json 100 times before was around 1.18s.
After:
- reading from string 0.68s
- reading from file 1.08s (extra time is all in io::Reader)