Currently, all switches in MIR are exhausitive, meaning that we can have
a lot of arms that all go to the same basic block, the extreme case
being an if-let expression which results in just 2 possible cases, be
might end up with hundreds of arms for large enums.
To improve this situation and give LLVM less code to chew on, we can
detect whether there's a pre-dominant target basic block in a switch
and then promote this to be the default target, not translating the
corresponding arms at all.
In combination with #33544 this makes unoptimized MIR trans of
nickel.rs as fast as using old trans and greatly improves the times for
optimized builds, which are only 30-40% slower instead of ~300%.
cc #33111
trivial tweaks to documentation (book)
These are small things I found while reading through The Book. The `<hash>` and `panic!` lines are simply to improve readability, while I believe the proceeding/following distinction is a bug (but might be a English dialect distinction?).
I've read `rust/CONTRIBUTING`, i'm not sure if there is anything I need to do other than submit this PR.
r? @steveklabnik
Add rustc_on_unimplemented for Index implementation on slice
Reopening of #31071.
It also extends the possibility of `#[rustc_on_unimplemented]` by providing a small type filter in order to find the ones which corresponds the most.
r? @pnkfelix
mk: Fix dependencies of unwind crate on musl
The libunwind.a library was accidentally only being included for the standard
library, not the new unwind crate which implements an unwinder.
Currently, to prepare for MIR trans, we break _all_ critical edges,
although we only actually need to do this for edges originating from a
call that gets translated to an invoke instruction in LLVM.
This has the unfortunate effect of undoing a bunch of the things that
SimplifyCfg has done. A particularly bad case arises when you have a
C-like enum with N variants and a derived PartialEq implementation.
In that case, the match on the (&lhs, &rhs) tuple gets translated into
nested matches with N arms each and a basic block each, resulting in N²
basic blocks. SimplifyCfg reduces that to roughly 2*N basic blocks, but
breaking the critical edges means that we go back to N².
In nickel.rs, there is such an enum with roughly N=800. So we get about
640K basic blocks or 2.5M lines of LLVM IR. LLVM takes a while to
reduce that to the final "disr_a == disr_b".
So before this patch, we had 2.5M lines of IR with 640K basic blocks,
which took about about 3.6s in LLVM to get optimized and translated.
After this patch, we get about 650K lines with about 1.6K basic blocks
and spent a little less than 0.2s in LLVM.
cc #33111
fix DFS for region error reporting
This was causing terrible error reports, because the algorithm was incorrectly identifying the constraints.
r? @eddyb
middle: reset loop labels while visiting closure
This should fix#31754 and follow-up #25343. Before the latter, the closure was visited twice in the context of the enclosing fn, which made even a single closure with a loop label emit a warning.
With this change, the closure is still visited within the context of the main fn (which is intended, since it is not a separate item) but resets the found loop labels while being visited.
Fixes: #31754
Note: I amended the test file from #25343, but I don't know if the original or amended test are effective, since as far as I could see, compiletest's run-pass tests do not check for zero warnings emitted?
/cc @Manishearth
mir: drop temps outside-in by scheduling the drops inside-out.
It was backwards all along, but only noticeable with multiple drops in one rvalue scope. Fixes#32433.
Split the type context into a global and a local (inference-only) one.
After this change, each `InferCtxt` creates its own local type interner for types with inference by-products.
Most of the code which handles both a global and a local interner uses `'gcx` and `'tcx` for them.
A reference to the type context in that situation (e.g. `infcx.tcx`) is `TyCtxt<'a, 'gcx, 'tcx>`.
The global type context which used to be `&'a TyCtxt<'tcx>` is now `TyCtxt<'a, 'tcx, 'tcx>`.
In order to minimize the number of extra lifetime parameters, many functions became methods.
Where possible (some inherent impls), lifetime parameters were added on the impl, not each method.
As inference by-products no longer escape their inference contexts, memory usage is lower.
Example of `-Z time-passes` excerpt for `librustc`, stage1 (~100MB gains):
Before "rustc: Split local type contexts interners from the global one.":
```
time: 0.395; rss: 335MB item-types checking
time: 15.392; rss: 472MB item-bodies checking
time: 0.000; rss: 472MB drop-impl checking
time: 1.140; rss: 478MB const checking
time: 0.139; rss: 478MB privacy checking
time: 0.024; rss: 478MB stability index
time: 0.072; rss: 478MB intrinsic checking
time: 0.038; rss: 478MB effect checking
time: 0.255; rss: 478MB match checking
time: 0.128; rss: 484MB liveness checking
time: 1.372; rss: 484MB rvalue checking
time: 1.404; rss: 597MB MIR dump
time: 0.809; rss: 599MB MIR passes
```
After:
```
time: 0.467; rss: 337MB item-types checking
time: 17.443; rss: 395MB item-bodies checking
time: 0.000; rss: 395MB drop-impl checking
time: 1.423; rss: 401MB const checking
time: 0.141; rss: 401MB privacy checking
time: 0.024; rss: 401MB stability index
time: 0.116; rss: 401MB intrinsic checking
time: 0.038; rss: 401MB effect checking
time: 0.382; rss: 401MB match checking
time: 0.132; rss: 407MB liveness checking
time: 1.678; rss: 407MB rvalue checking
time: 1.614; rss: 503MB MIR dump
time: 0.957; rss: 512MB MIR passes
```
**NOTE**: Functions changed to methods weren't re-indented to keep this PR easier to review.
Once approved, the changes will be mechanically performed.
However, indentation changes of function arguments are there - and I believe there's a way to hide whitespace-only changes in diffs on GitHub.
rustdoc: remove artificial indentation of doctest code
The indentation makes the examples look nicer when printed (when is this done?), but breaks tests using multi-line string literals.
Fixes: #25944