In general having all these different structs for "origins" is not
great, since equating types can cause obligations and vice-versa. I
think we should gradually collapse these things. We almost certainly
also need to invest a big more energy into the `error_reporting` code to
rationalize it: this PR does kind of the minimal effort in that
direction.
[8/n] rustc: clean up lookup_item_type and remove TypeScheme.
_This is part of a series ([prev](https://github.com/rust-lang/rust/pull/37676) | [next]()) 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>
* `tcx.tcache` -> `tcx.item_types`
* `TypeScheme` (grouping `Ty` and `ty::Generics`) is removed
* `tcx.item_types` entries no longer duplicated in `tcx.tables.node_types`
* `tcx.lookup_item_type(def_id).ty` -> `tcx.item_type(def_id)`
* `tcx.lookup_item_type(def_id).generics` -> `tcx.item_generics(def_id)`
* `tcx.lookup_generics(def_id)` -> `tcx.item_generics(def_id)`
* `tcx.lookup_{super_,}predicates(def_id)` -> `tcx.item_{super_,}predicates(def_id)`
Replace syntax's SmallVector with AccumulateVec
This adds a new type to data_structures, `SmallVec`, which wraps `AccumulateVec` with support for re-allocating onto the heap (`SmallVec::reserve`). `SmallVec` is then used to replace the implementation of `SmallVector` in libsyntax.
r? @eddyb
Fixes#37371. Using `SmallVec` instead of libsyntax's `SmallVector` will provide the `N = 2/4` case easily (just needs a few more `Array` impls).
cc @nnethercote, probably interested in this area
Don't provide hint to add lifetime on impl items
``` rust
use std::str::FromStr;
pub struct Foo<'a> {
field: &'a str,
}
impl<'a> FromStr for Foo<'a> {
type Err = ();
fn from_str(path: &str) -> Result<Self, ()> {
Ok(Foo { field: path })
}
}
```
would give the following hint:
``` nocode
help: consider using an explicit lifetime parameter as shown: fn from_str(path: &'a str) -> Result<Self, ()>
--> <anon>:9:5
|
9 | fn from_str(path: &str) -> Result<Self, ()> {
| ^
```
which is never correct, since then there will be a lifetime mismatch between the `impl` and the trait.
Remove this hint for all `impl` items.
Re: #37363.
Don't provide hint to add lifetime on impl items that implement a trait.
```rust
use std::str::FromStr;
pub struct Foo<'a> {
field: &'a str,
}
impl<'a> FromStr for Foo<'a> {
type Err = ();
fn from_str(path: &str) -> Result<Self, ()> {
Ok(Foo { field: path })
}
}
```
would give the following hint:
```nocode
help: consider using an explicit lifetime parameter as shown: fn from_str(path: &'a str) -> Result<Self, ()>
--> <anon>:9:5
|
9 | fn from_str(path: &str) -> Result<Self, ()> {
| ^
```
which is never correct, since then there will be a lifetime mismatch
between the impl and the trait.
Remove this hint for impl items that implement a trait.
[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).
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
- correct indentation
- rename `from_cause` to `from_obligation_cause`
- break up `compare_impl_method` into fns
- delete some blank lines and correct comment
Most of the Rust community agrees that the vec! macro is clearer when
called using square brackets [] instead of regular brackets (). Most of
these ocurrences are from before macros allowed using different types of
brackets.
There is one left unchanged in a pretty-print test, as the pretty
printer still wants it to have regular brackets.
This avoids 4% of malloc calls when compiling
rustc-benchmarks/issue-32278-big-array-of-strings, and 1--2% for other
benchmarks. A small win, but an easy one.
prefer `if let` to match with `None => { }` arm in some places
In #34268 (8531d581), we replaced matches of None to the unit value `()`
with `if let`s in places where it was deemed that this made the code
unambiguously clearer and more idiomatic. In #34638 (d37edef9), we did
the same for matches of None to the empty block `{}`.
A casual observer, upon seeing these commits fly by, might suppose that
the matter was then settled, that no further pull requests on this
utterly trivial point of style could or would be made. Unless ...
It turns out that sometimes people write the empty block with a space in
between the braces. Who knew?
`#[may_dangle]` attribute
`#[may_dangle]` attribute
Second step of #34761. Last big hurdle before we can work in earnest towards Allocator integration (#32838)
Note: I am not clear if this is *also* a syntax-breaking change that needs to be part of a breaking-batch.
In #34268 (8531d581), we replaced matches of None to the unit value `()`
with `if let`s in places where it was deemed that this made the code
unambiguously clearer and more idiomatic. In #34638 (d37edef9), we did
the same for matches of None to the empty block `{}`.
A casual observer, upon seeing these commits fly by, might suppose that
the matter was then settled, that no further pull requests on this
utterly trivial point of style could or would be made. Unless ...
It turns out that sometimes people write the empty block with a space in
between the braces. Who knew?
Use a distinct error code for "if may be missing an else clause"
Introduce the possibility of assigning distinct error codes to the various origin types of E0308. Start by assigning E0317 for the "IfExpressionWithNoElse" case, and write a long diagnostic specific to this case.
Fixes#36596
normalize types every time HR regions are erased
Associated type normalization is inhibited by higher-ranked regions.
Therefore, every time we erase them, we must re-normalize.
I was meaning to introduce this change some time ago, but we used
to erase regions in generic context, which broke this terribly (because
you can't always normalize in a generic context). That seems to be gone
now.
Ensure this by having a `erase_late_bound_regions_and_normalize`
function.
Fixes#37109 (the missing call was in mir::block).
r? @eddyb
Associated type normalization is inhibited by higher-ranked regions.
Therefore, every time we erase them, we must re-normalize.
I was meaning to introduce this change some time ago, but we used
to erase regions in generic context, which broke this terribly (because
you can't always normalize in a generic context). That seems to be gone
now.
Ensure this by having a `erase_late_bound_regions_and_normalize`
function.
Fixes#37109 (the missing call was in mir::block).
Fixing now incorrect Hash impl for TransItem.
Using as_ptr() rather than a pointer cast for string formatting.
Fixing Borrow and Lift impls for Substs.
Move usages of tcx.mk_substs to Substs::new iterator-based version.
Speed up `plug_leaks`
Profiling shows that `plug_leaks` and the functions it calls are hot on some benchmarks. It's very common that `skol_map` is empty in this function, and we can specialize `plug_leaks` in that case for some big speed-ups.
The PR has two commits. I'm fairly confident that the first one is correct -- I traced through the code to confirm that the `fold_regions` and `pop_skolemized` calls are no-ops when `skol_map` is empty, and I also temporarily added an assertion to check that `result` ends up having the same value as `value` in that case. This commit is responsible for most of the improvement.
I'm less confident about the second commit. The call to `resolve_type_vars_is_possible` can change `value` when `skol_map` is empty... but testing suggests that it doesn't matter if the call is
omitted.
So, please check both patches carefully, especially the second one!
Here are the speed-ups for the first commit alone.
stage1 compiler (built with old rustc, using glibc malloc), doing debug builds:
```
futures-rs-test 4.710s vs 4.538s --> 1.038x faster (variance: 1.009x, 1.005x)
issue-32062-equ 0.415s vs 0.368s --> 1.129x faster (variance: 1.009x, 1.010x)
issue-32278-big 1.884s vs 1.808s --> 1.042x faster (variance: 1.020x, 1.017x)
jld-day15-parse 1.907s vs 1.668s --> 1.143x faster (variance: 1.011x, 1.007x)
piston-image-0. 13.024s vs 12.421s --> 1.049x faster (variance: 1.004x, 1.012x)
rust-encoding-0 3.335s vs 3.276s --> 1.018x faster (variance: 1.021x, 1.028x)
```
stage2 compiler (built with new rustc, using jemalloc), doing debug builds:
```
futures-rs-test 4.167s vs 4.065s --> 1.025x faster (variance: 1.006x, 1.018x)
issue-32062-equ 0.383s vs 0.343s --> 1.118x faster (variance: 1.012x, 1.016x)
issue-32278-big 1.680s vs 1.621s --> 1.036x faster (variance: 1.007x, 1.007x)
jld-day15-parse 1.671s vs 1.478s --> 1.131x faster (variance: 1.016x, 1.004x)
piston-image-0. 11.336s vs 10.852s --> 1.045x faster (variance: 1.003x, 1.006x)
rust-encoding-0 3.036s vs 2.971s --> 1.022x faster (variance: 1.030x, 1.032x)
```
I've omitted the benchmarks for which the change was negligible.
And here are the speed-ups for the first and second commit in combination.
stage1 compiler (built with old rustc, using glibc malloc), doing debug
builds:
```
futures-rs-test 4.684s vs 4.498s --> 1.041x faster (variance: 1.012x, 1.012x)
issue-32062-equ 0.413s vs 0.355s --> 1.162x faster (variance: 1.019x, 1.006x)
issue-32278-big 1.869s vs 1.763s --> 1.060x faster (variance: 1.013x, 1.018x)
jld-day15-parse 1.900s vs 1.602s --> 1.186x faster (variance: 1.010x, 1.003x)
piston-image-0. 12.907s vs 12.352s --> 1.045x faster (variance: 1.005x, 1.006x)
rust-encoding-0 3.254s vs 3.248s --> 1.002x faster (variance: 1.063x, 1.045x)
```
stage2 compiler (built with new rustc, using jemalloc), doing debug builds:
```
futures-rs-test 4.183s vs 4.046s --> 1.034x faster (variance: 1.007x, 1.004x)
issue-32062-equ 0.380s vs 0.340s --> 1.117x faster (variance: 1.020x, 1.003x)
issue-32278-big 1.671s vs 1.616s --> 1.034x faster (variance: 1.031x, 1.012x)
jld-day15-parse 1.661s vs 1.417s --> 1.172x faster (variance: 1.013x, 1.005x)
piston-image-0. 11.347s vs 10.841s --> 1.047x faster (variance: 1.007x, 1.010x)
rust-encoding-0 3.050s vs 3.000s --> 1.017x faster (variance: 1.016x, 1.012x)
```
@eddyb: `git blame` suggests that you should review this. Thanks!
This commit avoids the `resolve_type_vars_if_possible` call in
`plug_leaks` when `skol_map` is empty, which is the common case. It also
changes the signature of `plug_leaks` slightly to avoid the need for a
`clone` of `value`. These changes give speed-ups of up a few percent on
some of the rustc-benchmarks.
This commit avoids the `fold_regions` call in `plug_leaks` when
`skol_map` is empty, which is the common case. This gives speed-ups of
up to 1.14x on some of the rustc-benchmarks.
Introduce the possibility of assigning distinct error codes to the various origin types of E0308. Start by assigning E0317 for the "IfExpressionWithNoElse" case, and write a long diagnostic specific to this case.
Fixes#36596
Be more specific when type parameter shadows primitive type
When a type parameter shadows a primitive type, the error message
was non obvious. For example, given the file `file.rs`:
```rust
trait Parser<T> {
fn parse(text: &str) -> Option<T>;
}
impl<bool> Parser<bool> for bool {
fn parse(text: &str) -> Option<bool> {
Some(true)
}
}
fn main() {
println!("{}", bool::parse("ok").unwrap_or(false));
}
```
The output was:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool a
|
= note: expected type `bool`
= note: found type `bool`
error: aborting due to previous error
```
We now show extra information about the type:
```bash
% rustc file.rs
error[E0308]: mismatched types
--> file.rs:7:14
|
7 | Some(true)
| ^^^^ expected type parameter, found bool a
|
= note: expected type `bool` (type parameter)
= note: found type `bool` (bool)
error: aborting due to previous error
```
Fixes#35030