Avoid ICEing miri on layout query cycles
Miri has special logic for catching panics during interpretation. Raising a fatal error in rustc uses unwinding to abort compilation. Thus miri ends up catching that fatal error and thinks it saw an ICE. While we should probably change that to ignore `Fatal` payloads, I think it's also neat to continue compilation after a layout query cycle 😆
Query cycles now (in addition to reporting an error just like before), return `Err(Cycle)` instead of raising a fatal error. This allows the interpreter to wind down via the regular error paths.
r? `@RalfJung` for a first round, feel free to reroll for the compiler team once the miri side looks good
Implement negative bounds for internal testing purposes
Implements partial support the `!` negative polarity on trait bounds. This is incomplete, but should allow us to at least be able to play with the feature.
Not even gonna consider them as a public-facing feature, but I'm implementing them because would've been nice to have in UI tests, for example in #110671.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
Make some simple queries no longer cache on disk
I don't think we need to cache queries with really simple local providers, like loading hir and accessing an attr
r? `@ghost`
Tweak await span to not contain dot
Fixes a discrepancy between method calls and await expressions where the latter are desugared to have a span that *contains* the dot (i.e. `.await`) but method call identifiers don't contain the dot. This leads to weird suggestions suggestions in borrowck -- see linked issue.
Fixes#110761
This mostly touches a bunch of tests to tighten their `await` span.
Remove `QueryEngine` trait
This removes the `QueryEngine` trait and `Queries` from `rustc_query_impl` and replaced them with function pointers and fields in `QuerySystem`. As a side effect `OnDiskCache` is moved back into `rustc_middle` and the `OnDiskCache` trait is also removed.
This has a couple of benefits.
- `TyCtxt` is used in the query system instead of the removed `QueryCtxt` which is larger.
- Function pointers are more flexible to work with. A variant of https://github.com/rust-lang/rust/pull/107802 is included which avoids the double indirection. For https://github.com/rust-lang/rust/pull/108938 we can name entry point `__rust_end_short_backtrace` to avoid some overhead. For https://github.com/rust-lang/rust/pull/108062 it avoids the duplicate `QueryEngine` structs.
- `QueryContext` now implements `DepContext` which avoids many `dep_context()` calls in `rustc_query_system`.
- The `rustc_driver` size is reduced by 0.33%, hopefully that means some bootstrap improvements.
- This avoids the unsafe code around the `QueryEngine` trait.
r? `@cjgillot`
I was curious about how many `Encodable`/`Decodable` derives we have.
Some grepping revealed that it's over 500 of each, but the number of
`Encodable` ones was higher, which was weird. Most of the
`Encodable`-only ones were in `hir.rs`. This commit removes them all,
plus some other unnecessary derives in that file and others that I found
via trial and error.
Rewrite MemDecoder around pointers not a slice
This is basically https://github.com/rust-lang/rust/pull/109910 but I'm being a lot more aggressive. The pointer-based structure means that it makes a lot more sense to absorb more complexity into `MemDecoder`, most of the diff is just complexity moving from one place to another.
The primary argument for this structure is that we only incur a single bounds check when doing multi-byte reads from a `MemDecoder`. With the slice-based implementation we need to do those with `data[position..position + len]` , which needs to account for `position + len` wrapping. It would be possible to dodge the first bounds check if we stored a slice that starts at `position`, but that would require updating the pointer and length on every read.
This PR also embeds the failure path in a separate function, which means that this PR should subsume all the perf wins observed in https://github.com/rust-lang/rust/pull/109867.
Use `?0` notation for ty/ct/int/float/region vars
Aligns the notation for infer vars that T-types and friends most often uses for inference variables with the notation in the compiler (which is kinda a sigil nightmare IMO: `_#`) by adopting `?0` style infer vars.
This mostly affects debug output since verbose infer vars shouldn't show up in user-facing places.
Does this need an MCP? It's debug output, so I'm thinking no, but happy to open one. 🤔
r? types
Consider polarity in new solver
It's kinda ugly to have a polarity check in all of the builtin impls -- I guess I could consider the polarity at the top of assemble-builtin but that would require adding a polarity fn to `GoalKind`...
🤷 putting this up just so i dont forget, since it's needed to bootstrap core during coherence (this alone does not allow core to bootstrap though, additional work is needed!)
r? ``@lcnr``
Add `impl_tag!` macro to implement `Tag` for tagged pointer easily
r? `@Nilstrieb`
This should also lifts the need to think about safety from the callers (`impl_tag!` is robust (ish, see the macro issue)) and removes the possibility of making a "weird" `Tag` impl.
Switch to `EarlyBinder` for `explicit_item_bounds`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `explicit_item_bounds` query and removes `bound_explicit_item_bounds`.
r? `@compiler-errors` (hope it's okay to request you, since you reviewed #110299 and #110498😃)
Add size asserts for MIR `SourceScopeData` & `VarDebugInfo`
There's vectors of both of these in `mir::Body`, so might as well track them.
(I was pondering adding something to one or the other, so wanted this to see the memory impact.)
Run various queries from other queries instead of explicitly in phases
These are just legacy leftovers from when rustc didn't have a query system. While there are more cleanups of this sort that can be done here, I want to land them in smaller steps.
This phased order of query invocations was already a lie, as any query that looks at types (e.g. the wf checks run before) can invoke e.g. const eval which invokes borrowck, which invokes typeck, ...
Report allocation errors as panics
OOM is now reported as a panic but with a custom payload type (`AllocErrorPanicPayload`) which holds the layout that was passed to `handle_alloc_error`.
This should be review one commit at a time:
- The first commit adds `AllocErrorPanicPayload` and changes allocation errors to always be reported as panics.
- The second commit removes `#[alloc_error_handler]` and the `alloc_error_hook` API.
ACP: https://github.com/rust-lang/libs-team/issues/192Closes#51540Closes#51245
Evaluate place expression in `PlaceMention`
https://github.com/rust-lang/rust/pull/102256 introduces a `PlaceMention(place)` MIR statement which keep trace of `let _ = place` statements from surface rust, but without semantics.
This PR proposes to change the behaviour of `let _ =` patterns with respect to the borrow-checker to verify that the bound place is live.
Specifically, consider this code:
```rust
let _ = {
let a = 5;
&a
};
```
This passes borrowck without error on stable. Meanwhile, replacing `_` by `_: _` or `_p` errors with "error[E0597]: `a` does not live long enough", [see playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c448d25a7c205dc95a0967fe96bccce8).
This PR *does not* change how `_` patterns behave with respect to initializedness: it remains ok to bind a moved-from place to `_`.
The relevant test is `tests/ui/borrowck/let_underscore_temporary.rs`. Crater check found no regression.
For consistency, this PR changes miri to evaluate the place found in `PlaceMention`, and report eventual dangling pointers found within it.
r? `@RalfJung`
Print ty placeholders pretty
Makes anon placeholders print like `!0` instead of `Placeholder { ... }`.
```
rustc_trait_selection::solve::compute_well_formed_goal goal=Goal{
predicate: !0,
param_env: ParamEnv{
caller_bounds: [
Binder(TraitPredicate(<!0 as std::marker::Copy>, polarity: Positive), []),
Binder(TraitPredicate(<!0 as std::clone::Clone>, polarity: Positive), []),
Binder(TraitPredicate(<!0 as std::marker::Sized>, polarity: Positive), []),
],
reveal: UserFacing,
constness: NotConst,
}
}
```
cc `@BoxyUwU` who might care about this formatting decision
Stable hash tag (discriminant) of `GenericArg`
This is a continuation of my quest of removing `transmute` if generic args and types (#110496, #110599).
r? `@compiler-errors`
Add offset_of! macro (RFC 3308)
Implements https://github.com/rust-lang/rfcs/pull/3308 (tracking issue #106655) by adding the built in macro `core::mem::offset_of`. Two of the future possibilities are also implemented:
* Nested field accesses (without array indexing)
* DST support (for `Sized` fields)
I wrote this a few months ago, before the RFC merged. Now that it's merged, I decided to rebase and finish it.
cc `@thomcc` (RFC author)
instead of merging everything into a single bag.
If it's acceptable from performance point of view, then it's more clear to keep this stuff organized more in accordance with its use.
Allow to feed a value in another query's cache and remove `WithOptConstParam`
I used it to remove `WithOptConstParam` queries, as an example.
The idea is that a query (here `typeck(function)`) can write into another query's cache (here `type_of(anon const)`). The dependency node for `type_of` would depend on all the current dependencies of `typeck`.
There is still an issue with cycles: if `type_of(anon const)` is accessed before `typeck(function)`, we will still have the usual cycle. The way around this issue is to `ensure` that `typeck(function)` is called before accessing `type_of(anon const)`.
When replayed, we may the following cases:
- `typeck` is green, in that case `type_of` is green too, and all is right;
- `type_of` is green, `typeck` may still be marked as red (it depends on strictly more things than `type_of`) -> we verify that the saved value and the re-computed value of `type_of` have the same hash;
- `type_of` is red, then `typeck` is red -> it's the caller responsibility to ensure `typeck` is recomputed *before* `type_of`.
As `anon consts` have their own `DefPathData`, it's not possible to have the def-id of the anon-const point to something outside the original function, but the general case may have to be resolved before using this device more broadly.
There is an open question about loading from the on-disk cache. If `typeck` is loaded from the on-disk cache, the side-effect does not happen. The regular `type_of` implementation can go and fetch the correct value from the decoded `typeck` results, and the dep-graph will check that the hashes match, but I'm not sure we want to rely on this behaviour.
I specifically allowed to feed the value to `type_of` from inside a call to `type_of`. In that case, the dep-graph will check that the fingerprints of both values match.
This implementation is still very sensitive to cycles, and requires that we call `typeck(function)` before `typeck(anon const)`. The reason is that `typeck(anon const)` calls `type_of(anon const)`, which calls `typeck(function)`, which feeds `type_of(anon const)`, and needs to build the MIR so needs `typeck(anon const)`. The latter call would not cycle, since `type_of(anon const)` has been set, but I'd rather not remove the cycle check.
Don't transmute `&List<GenericArg>` <-> `&List<Ty>`
In #93505 we allowed safely transmuting between `&List<GenericArg<'_>>` and `&List<Ty<'_>>`. This was possible because `GenericArg` is a tagged pointer and the tag for types is `0b00`, such that a `GenericArg` with a type inside has the same layout as `Ty`.
While this was meant as an optimization, it doesn't look like it was actually any perf or max-rss win (see https://github.com/rust-lang/rust/pull/94799#issuecomment-1064340003, https://github.com/rust-lang/rust/pull/94841, https://github.com/rust-lang/rust/pull/110496#issuecomment-1513799140).
Additionally the way it was done is quite fragile — `unsafe` code was not properly documented or contained in a module, types were not marked as `repr(C)` (making the transmutes possibly unsound). All of this makes the code maintenance harder and blocks other possible optimizations (as an example I've found out about these `transmutes` when my change caused them to sigsegv compiler).
Thus, I think we can safely (pun intended) remove those transmutes, making maintenance easier, optimizations possible, code less cursed, etc.
r? `@compiler-errors`
Add `rustc_fluent_macro` to decouple fluent from `rustc_macros`
Fluent, with all the icu4x it brings in, takes quite some time to compile. `fluent_messages!` is only needed in further downstream rustc crates, but is blocking more upstream crates like `rustc_index`. By splitting it out, we allow `rustc_macros` to be compiled earlier, which speeds up `x check compiler` by about 5 seconds (and even more after the needless dependency on `serde_json` is removed from `rustc_data_structures`).
Switch to `EarlyBinder` for `collect_return_position_impl_trait_in_trait_tys`
Part of the work to finish https://github.com/rust-lang/rust/issues/105779.
This PR adds `EarlyBinder` to the return type of the `collect_return_position_impl_trait_in_trait_tys` query and removes `bound_return_position_impl_trait_in_trait_tys`.
r? `@lcnr`