[5/n] rustc: record the target type of every adjustment.
_This is part of a series ([prev](https://github.com/rust-lang/rust/pull/37404) | [next](https://github.com/rust-lang/rust/pull/37412)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments._
<hr>
The first commit rearranges `tcx.tables` so that all users go through `tcx.tables()`. This in preparation for per-body `Tables` where they will be requested for a specific `DefId`. Included to minimize churn.
The rest of the changes focus on adjustments, there are some renamings, but the main addition is the target type, always available in all cases (as opposed to just for unsizing where it was previously needed).
Possibly the most significant effect of this change is that figuring out the final type of an expression is now _always_ just one successful `HashMap` lookup (either the adjustment or, if that doesn't exist, the node type).
Fix some mistakes in HRTB docs
The example code for higher-ranked trait bounds on closures had an unnecessary `mut` which was confusing, and the text referred to an mutable reference which does not exist in the code (and isn't needed). Removed the `mut`s and fixed the text to better describe the actual error for the failing example.
Thanks to csd_ on IRC for pointing out these problems!
r? @steveklabnik
Add Iterator trait TrustedLen to enable better FromIterator / Extend
This trait attempts to improve FromIterator / Extend code by enabling it to trust the iterator to produce an exact number of elements, which means that reallocation needs to happen only once and is moved out of the loop.
`TrustedLen` differs from `ExactSizeIterator` in that it attempts to include _more_ iterators by allowing for the case that the iterator's len does not fit in `usize`. Consumers must check for this case (for example they could panic, since they can't allocate a collection of that size).
For example, chain can be TrustedLen and all numerical ranges can be TrustedLen. All they need to do is to report an exact size if it fits in `usize`, and `None` as the upper bound otherwise.
The trait describes its contract like this:
```
An iterator that reports an accurate length using size_hint.
The iterator reports a size hint where it is either exact
(lower bound is equal to upper bound), or the upper bound is `None`.
The upper bound must only be `None` if the actual iterator length is
larger than `usize::MAX`.
The iterator must produce exactly the number of elements it reported.
This trait must only be implemented when the contract is upheld.
Consumers of this trait must inspect `.size_hint()`’s upper bound.
```
Fixes#37232
detect extra region requirements in impls
The current "compare method" check fails to check for the "region obligations" that accrue in the fulfillment context. This branch switches that code to create a `FnCtxt` so that it can invoke the regionck code. Previous crater runs (I haven't done one with the latest tip) have found some small number of affected crates, so I went ahead and introduced a warning cycle. I will kick off a crater run with this branch shortly.
This is a [breaking-change] because previously unsound code was accepted. The crater runs also revealed some cases where legitimate code was no longer type-checking, so the branch contains one additional (but orthogonal) change. It improves the elaborator so that we elaborate region requirements more thoroughly. In particular, if we know that `&'a T: 'b`, we now deduce that `T: 'b` and `'a: 'b`.
I invested a certain amount of effort in getting a good error message. The error message looks like this:
```
error[E0276]: impl has stricter requirements than trait
--> traits-elaborate-projection-region.rs:33:5
|
21 | fn foo() where T: 'a;
| --------------------- definition of `foo` from trait
...
33 | fn foo() where U: 'a { }
| ^^^^^^^^^^^^^^^^^^^^^^^^ impl has extra requirement `U: 'a`
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #18937 <https://github.com/rust-lang/rust/issues/18937>
note: lint level defined here
--> traits-elaborate-projection-region.rs:12:9
|
12 | #![deny(extra_requirement_in_impl)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
```
Obviously the warning only prints if this is a _new_ error (that resulted from the bugfix). But all existing errors that fit this description are updated to follow the general template. In order to get the lint to preserve the span-labels and the error code, I separate out the core `Diagnostic` type (which encapsulates the error code, message, span, and children) from the `DiagnosticBuilder` (which layers on a `Handler` that can be used to report errors). I also extended `add_lint` with an alternative `add_lint_diagnostic` that takes in a full diagnostic (cc @jonathandturner for those changes). This doesn't feel ideal but feels like it's moving in the right direction =).
r? @pnkfelix
cc @arielb1
Fixes#18937
Add conversions from `io:ErrorKind` to `io::Error`
Filing to help with discussion around the possibility of doing this.
Current changes are clearly backwards incompatible, but I think adding a new function (with a bikeshed on naming) like `Error::new_str` should be possible (or some other way of specializing the string error message case) to fix#36658.
A way to remove otherwise unused locals from MIR
There is a certain amount of desire for a pass which cleans up the provably unused variables (no assignments or reads). There has been an implementation of such pass by @scottcarr, and another (two!) implementations by me in my own dataflow efforts.
PR like https://github.com/rust-lang/rust/pull/35916 proves that this pass is useful even on its own, which is why I cherry-picked it out from my dataflow effort.
@nikomatsakis previously expressed concerns over this pass not seeming to be very cheap to run and therefore unsuitable for regular cleanup duties. Turns out, regular cleanup of local declarations is not at all necessary, at least now, because majority of passes simply do not (or should not) care about them. That’s why it is viable to only run this pass once (perhaps a few more times in the future?) per function, right before translation.
r? @eddyb or @nikomatsakis
Use impl obligations as initial environment for specialization
This corrects a small regression in specialization that crept in, I think as part of the refactoring to introduce arenas. I also made an experiment (in the last commit) to cleanup the code to be more aggressive about normalization. As the commit log notes, I am not 100% sure that this is correct, but it feels safer, and I think that at worst it yields *more* ICEs (as opposed to admitting faulty code). I'll schedule a crater run to check beyond the testbase.
Fixes#37291.
r? @aturon
Optimize ObligationForest's NodeState handling.
This commit does the following.
- Changes `NodeState` from an enum to a `bitflags`. This makes it
possible to check against multiple possible values in a single bitwise
operation.
- Replaces all the hot `match`es involving `NodeState` with `if`/`else`
chains that ensure that cases are handled in the order of frequency.
- Partially inlines two functions, `find_cycles_from_node` and
`mark_as_waiting_from`, at two call sites in order to avoid function
unnecessary function calls on hot paths.
- Fully inlines and removes `is_popped`.
These changes speeds up rustc-benchmarks/inflate-0.1.0 by about 7% when
doing debug builds with a stage1 compiler.
r? @arielb1
This seems better because I want to avoid the situation where unresolved
inference variables make it into the environment. On the other hand, I
am not 100% sure that this is correct. My assumption was that the WF
check should ensure that this normalization can succeed. But it occurs
to me that the WF checks may need to make use of the `specializes`
predicate themselves, and hence we may have a kind of cycle here (this
is a bigger problem with spec in any case that we need to resolve).
On the other hand, this should just cause extra errors I think, so it
seems like a safe thing to attempt. Certainly all tests pass.
ICH: Hash expression spans if their source location is captured for panics.
Since the location of some expressions is captured in error message constants, it has an influence on machine code and consequently we need to take them into account by the incr. comp. hash. This PR makes this happen for `+, -, *, /, %` and for array indexing -- let me know if I forgot anything.
In the future we might want to change the codegen strategy for those error messages, so that they are stored in a separate object file with a stable symbol name, so that only this object file has to be regenerated when source locations change. This strategy would also eliminate unnecessary duplications due to monomorphization, as @arielb1 has pointed out on IRC. I opened https://github.com/rust-lang/rust/issues/37512, so we don't forget about this.
r? @nikomatsakis
Misc fixes for configure
Currently,
`./configure` at armv6 machines ends up with
```
configure: error: unknown CPU type: armv6l
```
`./configure` at armv7 machines **silently** produces build for armv6 (compatible, but suboptimal)
```
configure: CFG_BUILD := arm-unknown-linux-gnueabihf
```
Copyediting on documentation for write! and writeln!
Fix various sentence fragments, missing articles, and other grammatical issues in the documentation for write! and writeln!.
Also fix the links (and link names) for common return types.
(Noticed when preparing https://github.com/rust-lang/rust/pull/37472 ; posted separately to avoid mixing the new documentation with copyedits to existing documentation.)
Prevent exhaustive matching of Ordering to allow for future extension
The C++11 atomic memory model defines a `memory_order_consume` ordering which is generally equivalent to `memory_order_acquire` but can allow better code generation by avoiding memory barrier instructions. Most compilers (including LLVM) currently do not implement this ordering directly and instead treat it identically to `memory_order_acquire`, including adding a memory barrier instruction.
There is currently [work](http://open-std.org/Jtc1/sc22/wg21/docs/papers/2016/p0098r1.pdf) to support consume ordering in compilers, and it would be a shame if Rust did not support this. This PR therefore reserves a `__Nonexhaustive` variant in `Ordering` so that adding a new ordering is not a breaking change in the future.
This is a [breaking-change] since it disallows exhaustive matching on `Ordering`, however a search of all Rust code on Github shows that there is no code that does this. This makes sense since `Ordering` is typically only used as a parameter to an atomic operation.
More refactoring to obey platform abstraction lint
The most interesting things here are moving `std/sys/common` to `std/sys_common`, and `std/num/{f32,f64}.rs` to `std/{f32,f64}.rs`, and adding more documentation to `std/lib.rs`.
r? @alexcrichton
typeck: Fix error reporting of wrong entry function signatures
Expected and actual type were switched, this was introduced by
refactoring in 8eb12d91aa.
This commit partially inlines two functions, `find_cycles_from_node` and
`mark_as_waiting_from`, at two call sites in order to avoid function
unnecessary function calls on hot paths.
It also fully inlines and removes `is_popped`.
These changes speeds up rustc-benchmarks/inflate-0.1.0 by about 2% when
doing debug builds with a stage1 compiler.
Fix ICE when printing closures, and other similar types
Follow-up of https://github.com/rust-lang/rust/pull/37459, further fixes those problems.
Potentially actually fixes#36622, though @eddyb may want to not let that close if the rename of RUST_LOG is deemed part of that issue.
Potentially should be beta-nominated as well?
r? @eddyb
The new handling fixed a latent bug in the parser error handling where
it would only abort after the second error (when configured to stop
after the first error). This is because the check for `error_count != 0`
was occuring before the increment. Since the increment is tied to the
`emit()` call now this no longer occurs.
- correct indentation
- rename `from_cause` to `from_obligation_cause`
- break up `compare_impl_method` into fns
- delete some blank lines and correct comment