Reduce the amount of untracked state in TyCtxt
Access to untracked global state may generate instances of #84970.
The GlobalCtxt contains the lowered HIR, the resolver outputs and interners.
By wrapping the resolver inside a query, we make sure those accesses are properly tracked.
As a no_hash query, all dependent queries essentially become `eval_always`,
what they should have been from the beginning.
Don't sort a `Vec` before computing its `DepTrackingHash`
Previously, we sorted the vec prior to hashing, making the hash
independent of the original (command-line argument) order. However, the
original vec was still always kept in the original order, so we were
relying on the rest of the compiler always working with it in an
'order-independent' way.
This assumption was not being upheld by the `native_libraries` query -
the order of the entires in its result depends on the order of entries
in `Options.libs`. This lead to an 'unstable fingerprint' ICE when the
`-l` arguments were re-ordered.
This PR removes the sorting logic entirely. Re-ordering command-line
arguments (without adding/removing/changing any arguments) seems like a
really niche use case, and correctly optimizing for it would require
additional work. By always hashing arguments in their original order, we
can entirely avoid a cause of 'unstable fingerprint' errors.
Emit a hard error when a panic occurs during const-eval
Previous, a panic during const evaluation would go through the
`const_err` lint. This PR ensures that such a panic always causes
compilation to fail.
Fix span of redundant generic arguments
Fixes#71563
Above issue is about lifetime arguments, but generic arguments also have same problem.
This PR fixes both help messages.
Use correct edition when parsing `:pat` matchers
As described in issue #85708, we currently do not properly decode
`SyntaxContext::root()` and `ExpnId::root()` from foreign crates. As a
result, when we decode a span from a foreign crate with
`SyntaxContext::root()`, we end up up considering it to have the edition
of the *current* crate, instead of the foreign crate where it was
originally created.
A full fix for this issue will be a fairly significant undertaking.
Fortunately, it's possible to implement a partial fix, which gives us
the correct edition-dependent behavior for `:pat` matchers when the
macro is loaded from another crate. Since we have the edition of the
macro's defining crate available, we can 'recover' from seeing a
`SyntaxContext::root()` and use the edition of the macro's defining
crate.
Any solution to issue #85708 must reproduce the behavior of this
targeted fix - properly preserving a foreign `SyntaxContext::root()`
means (among other things) preserving its edition, which by definition
is the edition of the foreign crate itself. Therefore, this fix moves us
closer to the correct overall solution, and does not expose any new
incorrect behavior to macros.
Use command line metadata path if provided
If the command-line has `--emit metadata=some/path/libfoo.rmeta` then
use that.
Closes#85356
I couldn't find any existing tests for the `--emit TYPE=PATH` command line syntax, so I wasn't sure how to test this aside from ad-hoc manual testing. Is there a ui test type for "generated output file with expected name"?
Merge CrateDisambiguator into StableCrateId
This simplifies the code and potentially improves performance by reducing the amount of hashed data.
Fixes https://github.com/rust-lang/rust/issues/85795
Make `Step` trait safe to implement
This PR makes a few modifications to the `Step` trait that I believe better position it for stabilization in the short term. In particular,
1. `unsafe trait TrustedStep` is introduced, indicating that the implementation of `Step` for a given type upholds all stated invariants (which have remained unchanged). This is gated behind a new `trusted_step` feature, as stabilization is realistically blocked on min_specialization.
2. The `Step` trait is internally specialized on the `TrustedStep` trait, which avoids a serious performance regression.
3. `TrustedLen` is implemented for `T: TrustedStep` as the latter's invariants subsume the former's.
4. The `Step` trait is no longer `unsafe`, as the invariants must not be relied upon by unsafe code (unless the type implements `TrustedStep`).
5. `TrustedStep` is implemented for all types that implement `Step` in the standard library and compiler.
6. The `step_trait_ext` feature is merged into the `step_trait` feature. I was unable to find any reasoning for the features being split; the `_unchecked` methods need not necessarily be stabilized at the same time, but I think it is useful to have them under the same feature flag.
All existing implementations of `Step` will be broken, as it is not possible to `unsafe impl` a safe trait. Given this trait only exists on nightly, I feel this breakage is acceptable. The blanket `impl<T: Step> TrustedLen for T` will likely cause some minor breakage, but this should be covered by the equivalent impl for `TrustedStep`.
Hopefully these changes are sufficient to place `Step` in decent position for stabilization, which would allow user-defined types to be used with `a..b` syntax.
Don't panic when failing to initialize incremental directory.
This removes a panic when rustc fails to initialize the incremental directory. This can commonly happen on various filesystems that don't support locking (often various network filesystems). Panics can be confusing and scary, and there are already plenty of issues reporting this.
This has been panicking since 1.22 due to I think #44502 which was a major rework of how things work. Previously, things were simpler and the [`load_dep_graph`](https://github.com/rust-lang/rust/blob/1.21.0/src/librustc_incremental/persist/load.rs#L43-L65) function would emit an error and then continue on without panicking. With 1.22, [`load_dep_graph`](https://github.com/rust-lang/rust/blob/1.22.0/src/librustc_incremental/persist/load.rs#L44) was changed so that it assumes it can load the data without errors. Today, the problem is that it calls [`prepare_session_directory`](fbf1b1a719/compiler/rustc_interface/src/passes.rs (L175-L179)) and then immediately calls `garbage_collect_session_directories` which will panic since the session is `IncrCompSession::NotInitialized`.
The solution here is to have `prepare_session_directory` return an error that must be handled so that compilation stops if it fails.
Some other options:
* Ignore directory lock failures.
* Print a warning on directory lock failure, but otherwise continue with incremental enabled.
* Print a warning on directory lock failure, and disable incremental.
* Provide a different locking mechanism.
Cargo ignores lock errors if locking is not supported, so that would be a precedent for the first option. These options would require quite a bit more changes, but I'm happy to entertain any of them, as I think they all have valid justifications.
There is more discussion on the many issues where this is reported: #49773, #59224, #66513, #76251. I'm not sure if this can be considered closing any of those, though, since I think there is some value in discussing if there is a way to avoid the error altogether. But I think it would make sense to at least close all but one to consolidate them.
As described in issue #85708, we currently do not properly decode
`SyntaxContext::root()` and `ExpnId::root()` from foreign crates. As a
result, when we decode a span from a foreign crate with
`SyntaxContext::root()`, we end up up considering it to have the edition
of the *current* crate, instead of the foreign crate where it was
originally created.
A full fix for this issue will be a fairly significant undertaking.
Fortunately, it's possible to implement a partial fix, which gives us
the correct edition-dependent behavior for `:pat` matchers when the
macro is loaded from another crate. Since we have the edition of the
macro's defining crate available, we can 'recover' from seeing a
`SyntaxContext::root()` and use the edition of the macro's defining
crate.
Any solution to issue #85708 must reproduce the behavior of this
targeted fix - properly preserving a foreign `SyntaxContext::root()`
means (among other things) preserving its edition, which by definition
is the edition of the foreign crate itself. Therefore, this fix moves us
closer to the correct overall solution, and does not expose any new
incorrect behavior to macros.
A bit more polish on const eval errors
This PR adds a bit more polish to the const eval errors:
- a slight improvement to the PME messages from #85633: I mentioned there that the erroneous item's paths were dependent on the environment, and could be displayed fully qualified or not. This can obscure the items when they come from a dependency. This PR uses the pretty-printing code ensuring the items' paths are not trimmed.
- whenever there are generics involved in an item where const evaluation errors out, the error message now displays the instance and its const arguments, so that we can see which instantiated item and compile-time values lead to the error.
So we get this slight improvement for our beloved `stdarch` example, on nightly:
```
error[E0080]: evaluation of constant value failed
--> ./stdarch/crates/core_arch/src/macros.rs:8:9
|
8 | assert!(IMM >= MIN && IMM <= MAX, "IMM value not in expected range");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'IMM value not in expected range', /rustc/9111b8ae9793f18179a1336417618fc07a9cac85/library/core/src/../../stdarch/crates/core_arch/src/macros.rs:8:9
|
```
to this PR's:
```
error[E0080]: evaluation of `core::core_arch::macros::ValidateConstImm::<51_i32, 0_i32, 15_i32>::VALID` failed
--> ./stdarch/crates/core_arch/src/macros.rs:8:9
|
8 | assert!(IMM >= MIN && IMM <= MAX, "IMM value not in expected range");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'IMM value not in expected range', ./stdarch/crates/core_arch/src/macros.rs:8:9
|
```
with this PR.
Of course this is an idea from Oli, so maybe r? `@oli-obk` if they have the time.
const-eval: disallow unwinding across functions that `!fn_can_unwind()`
Following https://github.com/rust-lang/miri/pull/1776#discussion_r633074343, so r? `@RalfJung`
This PR turns `unwind` in `StackPopCleanup::Goto` into a new enum `StackPopUnwind`, with a `NotAllowed` variant to indicate that unwinding is not allowed. This variant is chosen based on `rustc_middle::ty::layout::fn_can_unwind()` in `eval_fn_call()` when pushing the frame. A check is added in `unwind_to_block()` to report UB if unwinding happens across a `StackPopUnwind::NotAllowed` frame.
Tested with Miri `HEAD` with [minor changes](https://github.com/rust-lang/miri/compare/HEAD..9cf3c7f0d86325a586fbcbf2acdc9232b861f1d8) and the rust-lang/miri#1776 branch with [these changes](d866c1c52f..626638fbfe).
Fix incorrect suggestions for E0605
Fixes#84598. Here is a simplified version of the problem presented in issue #84598:
```Rust
#![allow(unused_variables)]
#![allow(dead_code)]
trait T { fn t(&self) -> i32; }
unsafe fn foo(t: *mut dyn T) {
(t as &dyn T).t();
}
fn main() {}
```
The current output is:
```
error[E0605]: non-primitive cast: `*mut (dyn T + 'static)` as `&dyn T`
--> src/main.rs:7:5
|
7 | (t as &dyn T).t();
| ^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
|
7 | (&t as &dyn T).t();
| ^
```
This is incorrect, though: The cast will _not_ be valid when writing `&t` instead of `t`:
```
error[E0277]: the trait bound `*mut (dyn T + 'static): T` is not satisfied
--> t4.rs:7:6
|
7 | (&t as &dyn T).t();
| ^^ the trait `T` is not implemented for `*mut (dyn T + 'static)`
|
= note: required for the cast to the object type `dyn T`
```
The correct suggestion is `&*t`, which I have implemented in this pull request. Of course, this suggestion will always require an unsafe block, but arguably, that's what the user really wants if they're trying to cast a pointer to a reference.
In any case, claiming that the cast will be valid after implementing the suggestion is overly optimistic, as the coercion logic doesn't seem to resolve all nested obligations, i.e. the cast may still be invalid after implementing the suggestion. I have therefore rephrased the suggestion slightly ("consider borrowing the value" instead of "borrow the value for the cast to be valid").
Additionally, I have fixed another incorrect suggestion not mentioned in #84598, which relates to casting immutable references to mutable ones:
```rust
fn main() {
let mut x = 0;
let m = &x as &mut i32;
}
```
currently leads to
```
error[E0605]: non-primitive cast: `&i32` as `&mut i32`
--> t5.rs:3:13
|
3 | let m = &x as &mut i32;
| ^^^^^^^^^^^^^^ invalid cast
|
help: borrow the value for the cast to be valid
|
3 | let m = &mut &x as &mut i32;
| ^^^^
```
which is obviously incorrect:
```
error[E0596]: cannot borrow data in a `&` reference as mutable
--> t5.rs:3:13
|
3 | let m = &mut &x as &mut i32;
| ^^^^^^^ cannot borrow as mutable
```
I've changed the suggestion to a note explaining the problem:
```
error[E0605]: non-primitive cast: `&i32` as `&mut i32`
--> t5.rs:3:13
|
3 | let m = &x as &mut i32;
| ^^^^^^^^^^^^^^ invalid cast
|
note: this reference is immutable
--> t5.rs:3:13
|
3 | let m = &x as &mut i32;
| ^^
note: trying to cast to a mutable reference type
--> t5.rs:3:19
|
3 | let m = &x as &mut i32;
| ^^^^^^^^
```
In this example, it would have been even nicer to suggest replacing `&x` with `&mut x`, but this would be much more complex because we would have to take apart the expression to be cast (currently, we only look at its type), and `&x` could be stored in a variable, where such a suggestion would not even be directly applicable:
```rust
fn main() {
let mut x = 0;
let r = &x;
let m = r as &mut i32;
}
```
My solution covers this case, too.