Update substring search to use the Two Way algorithm
To improve our substring search performance, revive the two way searcher
and adapt it to the Pattern API.
Fixes#25483, a performance bug: that particular case now completes faster
in optimized rust than in ruby (but they share the same order of magnitude).
Many thanks to @gereeter who helped me understand the reverse case
better and wrote the comment explaining `next_back` in the code.
I had quickcheck to fuzz test forward and reverse searching thoroughly.
The two way searcher implements both forward and reverse search,
but not double ended search. The forward and reverse parts of the two
way searcher are completely independent.
The two way searcher algorithm has very small, constant space overhead,
requiring no dynamic allocation. Our implementation is relatively fast,
especially due to the `byteset` addition to the algorithm, which speeds
up many no-match cases.
A bad case for the two way algorithm is:
```
let haystack = (0..10_000).map(|_| "dac").collect::<String>();
let needle = (0..100).map(|_| "bac").collect::<String>());
```
For this particular case, two way is not much faster than the naive
implementation it replaces.
This commit finalizes the work of the past commits by fully moving the fulfillment context into
the InferCtxt, cleaning up related context interfaces, removing the Typer and ClosureTyper
traits and cleaning up related intefaces
Update all uses of FulfillmentContext to be ones obtained via
an InferCtxt. This is another step of flattening the type
checking context into a single piece of state.
This was originally motivated by checking for HRTB hygiene, but I found several other bugs on the way.
This does not fix the biggest user of ty_walk, which is dtorck - I would prefer to coordinate that with @pnkfelix.
r? @eddyb
This fixes two false positives for the unconditional recursion lint, when functions use themselves (or almost-themselves) internally, without actually being recursive.
````rust
fn main() { let _ = main; }
```
```rust
trait Bar {
fn method<T: Bar>(&self, x: &T) {
x.method(x)
}
}
```
This catches the case when a trait defines a default method that calls
itself, but on a type that isn't necessarily `Self`, e.g. there's no
reason that `T = Self` in the following, so the call isn't necessarily
recursive (`T` may override the call).
trait Bar {
fn method<T: Bar>(&self, x: &T) {
x.method(x)
}
}
Fixes#26333.
Namely:
* Change parameter `old` to read `current` so it is clearer what the argument refers to (originally
suggested `expected`, but shot down by Steve);
* Add some formatting and fix some mistakes like referring to the method as `swap` rather than
`compare_and_swap`.
Namely:
* Change parameter `old` to read `current` so it is clearer what the argument refers to (originally
suggested `expected`, but shot down by Steve);
* Add some formatting and fix some mistakes like referring to the method as `swap` rather than
`compare_and_swap`.
In Chapter 5.9 (References and Borrowing), there is an example [at the very end](https://doc.rust-lang.org/stable/book/references-and-borrowing.html#use-after-free) which shows that declaring a reference before declaring the variable that it points to results in a compilation error. The book does not really mention why this happens though -- in the sections before, it has described how different scopes affects the lifetime of resources, but there is no mention of how resources within the same scope work.
This confused me a little, so I asked on #rust and got the answer that the resources are destroyed in the reverse order that they are declared, but the book makes no mention of it (as far as I can find) -- except in Chapter 5.21 (Drop), where it says:
> When `x` goes out of scope at the end of `main()`, the code for `Drop` will run. `Drop` has one method, which is also called `drop()`. It takes a mutable reference to `self`.
>
> That’s it! The mechanics of `Drop` are very simple, but there are some subtleties. For example, values are dropped in the opposite order they are declared. [...]
---
I feel like Chapter 5.9 (References and Borrowing) is probably the best place to put this information (as I have done in my additions), since it deals with other types of referencing and borrowing. However, since English is not my native language, the wording of my additions perhaps are a little "off" -- any feedback on them is appreciated.