This effectively reverses <https://github.com/rust-lang/rust/commit/4284edc>.
At that time, I thought GetQueryVTable might be useful for other kinds of
static lookup in the future, but after various other simplifications and
cleanups that now seems less likely, and this style is more consistent with
other vtable-related functions.
The different parts of this function used to be split across different crates,
but nowadays they are both in `rustc_query_impl`, so they can be combined.
This commit also hoists the vtable lookup to a closure in
`make_dep_kind_vtable_for_query`, to reduce the amount of code that deals with
`GetQueryVTable`, and to make the inner function more consistent with other
functions in `execution`.
In the serial compiler, we should never be trying to force a query node that
has a cached value, because we would have already marked the node red or green
when putting its value in cache.
In the parallel compiler, we immediately re-check the cache while holding the
state shard lock anyway, and trying to avoid that lock doesn't seem worthwhile.
This assertion and its comment are much visually heavier than the part of the
function that actually performs important work.
This assertion is also useless, because the `codegen_unit` query does not have
a `force_from_dep_node_fn` in its DepKindVTable, so the assertion would never
be reached even in the situation it is trying to guard against.
This assertion is also redundant, because we have plenty of incremental tests
that fail if the corresponding calls to `tcx.ensure_ok().codegen_unit(..)` are
removed.
Remove the `anon` query modifier
Prior experiments:
- https://github.com/rust-lang/rust/pull/152268
- https://github.com/rust-lang/rust/pull/153996
[Zulip thread: *Removing the `anon` query modifier*](https://rust-lang.zulipchat.com/#narrow/channel/582699-t-compiler.2Fquery-system/topic/Removing.20the.20.60anon.60.20query.20modifier/with/580760962)
---
There are currently three queries that use the `anon` modifier:
- `check_representability`
- `check_representability_adt_ty`
- `erase_and_anonymize_regions_ty`
It seems that none of them are using `anon` in an essential way.
According to comments and tests, the *representability* queries mainly care about not being eligible for forcing (despite having a recoverable key type), so that if a cycle does occur then the entire cycle will be on the query stack. Replacing `anon` with a new `no_force` modifier gives a modest perf improvement.
The `erase_and_anonymize_regions_ty` query appears to be using `anon` to reduce the dep-graph overhead of a query that is expected to not call any other queries (and thus have no dependencies). Replacing `anon` with either `no_hash` or nothing appears to give only a very small perf hit on `cargo` benchmarks, which is justified by the fact that it lets us remove a lot of machinery for anonymous queries.
We still need to retain some of the machinery for anonymous *tasks*, because the non-query task `DepKind::TraitSelect` still uses it.
---
I have some ideas for a follow-up that will reduce dep-graph overhead by replacing *all* zero-dependency nodes with a singleton node, but I want to keep that separate in case it causes unexpected issues and needs to be bisected or reverted.
Make `par_slice` consistent with single-threaded execution
rust-lang/rust#152375 removed this consistency by switching from order preserving join to scope, which does not preserve order as stated in `par_fns` as well. This also makes `par_slice` behavior consistent with `par_fns`.
According to its comment, this query was only using `anon` to save a little bit
of work for a dep graph node that is expected to have no dependencies.
Benchmarks indicate that the perf loss, if any, is small enough to be justified
by the fact that we can now remove support for `anon` queries.
Adding `no_hash` appears to give marginally better perf results.
These queries appear to have been using `anon` for its side-effect of making
them ineligible for forcing.
According to their comments and also `tests/incremental/issue-61323.rs`, these
queries want to avoid forcing so that if a cycle does occur, the whole cycle
will be on the query stack for the cycle handler to find.
Start migrating `DecorateDiagCompat::Builtin` items to `DecorateDiagCompat::Dynamic`
Part of https://github.com/rust-lang/rust/issues/153099.
End goal being to completely remove the two steps currently required by `DecorateDiagCompat::Builtin` and remove duplicated types.
r? @JonathanBrouwer
don't suggest non-deriveable traits for unions
Fixesrust-lang/rust#137587
Before, the compiler suggested adding `#[derive(Debug)]` (other traits too) for unions,
which is misleading because some traits can't be automatically derived.
Only traits that are still suggested are Copy and Clone.
I noticed the error label changed after removing the suggestion. I hope this isn't a big deal, but let me know if that's an issue.
original example:
```rs
union Union {
member: usize,
}
impl PartialEq<u8> for Union {
fn eq(&self, rhs: &u8) -> bool {
unsafe { self.member == (*rhs).into() }
}
}
fn main() {
assert_eq!(Union { member: 0 }, 0);
}
```
before:
```
error[E0277]: `Union` doesn't implement `Debug`
--> src\main.rs:13:5
|
13 | assert_eq!(Union { member: 0 }, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `Union`
|
= note: add `#[derive(Debug)]` to `Union` or manually `impl Debug for Union`
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider annotating `Union` with `#[derive(Debug)]`
|
2 + #[derive(Debug)]
3 | union Union {
|
```
after (the message doesn't suggest adding #[derive(Debug)] to unions)
```
error[E0277]: `Union` doesn't implement `Debug`
--> src\main.rs:13:5
|
13 | assert_eq!(Union { member: 0 }, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
|
help: the trait `Debug` is not implemented for `Union`
--> src\main.rs:2:1
|
2 | union Union {
| ^^^^^^^^^^^
= note: manually `impl Debug for Union`
```
Allow passing `expr` metavariable as `cfg` predicate
This PR allows expanding `expr` metavariables inside the configuration predicates of `cfg` and `cfg_attr` invocations.
For example, the following code will now compile:
```rust
macro_rules! mac {
($e:expr) => {
#[cfg_attr($e, inline)]
#[cfg($e)]
fn func() {}
#[cfg(not($e))]
fn func() {
panic!()
}
}
}
mac!(any(unix, feature = "foo"));
```
There is currently no `macro_rules` fragment specifier that can represent all valid `cfg` predicates. `meta` comes closest, but excludes `true` and `false`. By fixing that, this change makes it easier to write declarative macros that parse `cfg` or `cfg_attr` invocations, for example https://github.com/rust-lang/rust/pull/146281/.
@rustbot label T-lang needs-fcp A-attributes A-cfg A-macros
Emit fewer errors for incorrect rtn and `=` -> `:` typos in bindings
Make all existing `:` -> `=` typo suggestions verbose and tweak the suggested code.
Stash parse errors when pasing rtn that doesn't use `(..)`.
Emit single error on `Foo::bar(qux)` that looks like rtn in incorrect position and suggest `Foo::bar(..)`.
```
error: return type notation not allowed in this position yet
--> $DIR/let-binding-init-expr-as-ty.rs:18:10
|
LL | struct K(S::new(()));
| ^^^^^^^^^^
|
help: furthermore, argument types not allowed with return type notation
|
LL - struct K(S::new(()));
LL + struct K(S::new(..));
|
```
On incorrect rtn in let binding type for an existing inherent associated function, suggest `:` -> `=` to turn the "type" into a call expression. (Fixrust-lang/rust#134087)
```
error: expected type, found associated function call
--> $DIR/let-binding-init-expr-as-ty.rs:29:12
|
LL | let x: S::new(());
| ^^^^^^^^^^
|
help: use `=` if you meant to assign
|
LL - let x: S::new(());
LL + let x = S::new(());
|
```
Stash parse errors when pasing rtn that doesn't use `(..)`.
Emit single error on `Foo::bar(qux)` that looks like rtn in incorrect position and suggest `Foo::bar(..)`.
```
error: return type notation not allowed in this position yet
--> $DIR/let-binding-init-expr-as-ty.rs:18:10
|
LL | struct K(S::new(()));
| ^^^^^^^^^^
|
help: furthermore, argument types not allowed with return type notation
|
LL - struct K(S::new(()));
LL + struct K(S::new(..));
|
```
On incorrect rtn in let binding type for an existing inherent associated function, suggest `:` -> `=` to turn the "type" into a call expression.
```
error: expected type, found associated function call
--> $DIR/let-binding-init-expr-as-ty.rs:29:12
|
LL | let x: S::new(());
| ^^^^^^^^^^
|
help: use `=` if you meant to assign
|
LL - let x: S::new(());
LL + let x = S::new(());
|
```
Guard patterns: lowering to THIR
This pr implements lowering of guard patterns to THIR
r? @Nadrieril
cc @max-niederman
Tracking issue: rust-lang/rust#129967
Fix typos and markdown errors
This PR fixes some typos and markdown errors I found while writing rust-lang/rust#153697.
I've split it out to reduce the size of that PR.
Remove redundant `is_dyn_thread_safe` checks
Refactor uses of `FromDyn` to reduce number of redundant `is_dyn_thread_safe` checks by replacing `FromDyn::from` with `check_dyn_thread_safe` in tandem with existing `FromDyn::derive` so that the users would avoid redundancy in the future.
PR is split up into multiple commits for an easier review.
coretests: Expand ieee754 parsing and printing tests to f16
Use `float_test!` to cover all types, with a note about f128 missing the traits. Also includes some minor reorganization.
ty-aware delayed AST -> HIR lowering
This PR implements a prototype of ty-aware delayed AST -> HIR lowering. Part of rust-lang/rust#118212.
r? @petrochenkov
# Motivation
When lowering delegation in perfect scenario we would like to access the ty-level information, in particular, queries like `generics_of`, `type_of`, `fn_sig` for proper HIR generation with less hacks. For example, we do not want to generate more lifetimes than needed, because without ty-level queries we do not know which delegee's lifetimes are late-bound. Next, consider recursive delegations, for their proper support without ty we would have to either duplicate generics inheritance code in AST -> HIR lowering or create stubs for parts of the HIR and materialize them later. We already use those queries when interacting with external crates, however when dealing with compilation of a local crate we should use resolver for similar purposes. Finally, access to ty-level queries is expected to help supporting delegation to inherent impls, as we can not resolve such calls during AST -> HIR stage.
# Benefits
We eliminate almost all code that uses resolver in delegation lowering:
- Attributes inheritance is done without copying attributes from AST at resolve stage
- Fn signatures are obtained from `tcx.fn_sig`
- Param counts are also obtained from `tcx.fn_sig`
- `is_method` function now uses `tcx.associated_item` instead of resolver
- Generics are now inherited through `get_external_generics` that uses `tcx.generics_of`. Generics for recursive delegations should also work
- `DelegationIds` that stored paths for recursive delegations is removed, we now use only `delegee_id`
- Structs that were used for storing delegation-related information in resolver are almost fully removed
- `ast_index` is no more used
# Next steps
- Remove creating generic params through AST cloning, proper const types propagation
- Inherent impls
# High level design overview
## Queries
We store ids of delayed items to lower in `Crate` struct. During first stage of lowering, owners that correspond to delayed items are filled with `MaybeOwner::Phantom`.
Next, we define two new queries: `lower_delayed_owner`, `delayed_owner` and a function `force_delayed_owners_lowering`.
The first query is used when lowering known (which is in `delayed_ids`) delayed owner.
The second is fed with children that were obtained during lowering of a delayed owner (note that the result of lowering of a single `LocalDefId` is not a single `MaybeOwner`, its a list of `(LocalDefId, MaybeOwner)` where the first `MaybeOwner` corresponds to delayed `LocalDefId` and others to children that were obtained during lowering (i.e. generic params)). By default `delayed_owner` returns `MaybeOwner::Phantom`. As we do not want to predict the whole list of children which will be obtained after lowering of a single delayed item, we need to store those children somewhere. There are several options:
- Make the return type of `lower_delayed_owner` to be `FxIndexMap<LocalDefId, MaybeOwner>` and search children here. Search will be either linear or we can introduce a map somewhere which will track parent-child relations between a single delayed `LocalDefId` and its children.
- Try to make query that will lower all delayed items in a loop and return a complete map of all delayed `LocalDefIds` and their children. In this case there will be problems with delayed items that require information about other delayed items.
By using proposed queries we handle the second concern, and in case of acyclic dependencies between delayed ids it automatically works, moreover we use queries as cache for delayed `MaybeOwners`. The only invariant here is that queries which are invoked during delayed AST -> HIR lowering of some `LocalDefId` should not in any way access children of other, yet unlowered, delayed `LocalDefId`, they should firstly materialize it.
The `force_delayed_owners_lowering` forces lowering of all delayed items and now integrated in `hir_crate_items` query.
## Resolver for lowering
> ~Currently the `resolver_for_lowering` is stolen in `lower_to_hir` function, however we want to prolong its life until all delayed `LocalDefIds` are materialized. For this purpose we borrow `resolver_for_lowering` in `lower_to_hir` and drop it after forcing materialization of all delayed `LocalDefId` in `rustc_interface::run_required_analyses`.~
We split resolver for lowering into two parts: the first part is a readonly part that came to us from resolve, the second part is a mutable part that can be used to add or overwrite values in the readonly part. Such splitted resolver is used during delayed lowering, as we can't steal it.
## AST index
Lowering uses an AST index. It is created in `lower_to_hir` function and it references parts of AST. We want to avoid reindexing AST on every delayed `LocalDefId` lowering, however now it is not clear how to properly do it. As delayed HIR lowering is used only for delegation unstable feature it should not affect other use-cases of the compiler. But it will be reworked sooner or later.
Fix whitespace after fragment specifiers in macro pretty printing
When a macro-generating-macro captures fragment specifier tokens (like `$x:ident`) as `tt` metavariables and replays them before a keyword (like `where`), the pretty printer concatenates them into an invalid fragment specifier (e.g. `$x:identwhere` instead of `$x:ident where`).
This happens because `tt` captures preserve the original token spacing. When the fragment specifier name (e.g. `ident`) was originally the last token before a closing delimiter, it retains `JointHidden` spacing. The `print_tts` function only checks `space_between` for `Spacing::Alone` tokens, so `JointHidden` tokens skip the space check entirely, causing adjacent identifier-like tokens to merge.
The fix adds a check in `print_tts` to insert a space between adjacent identifier-like tokens (identifiers and keywords) regardless of the original spacing, preventing them from being concatenated into invalid tokens.
This is similar to the existing `space_between` mechanism that prevents token merging for `Spacing::Alone` tokens, extended to also handle `Joint`/`JointHidden` cases where two identifier-like tokens would merge.
## Example
**before** (`rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)`):
```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:macro-fragment-specifier-whitespace.pp
// Test that fragment specifier names in macro definitions are properly
// separated from the following keyword/identifier token when pretty-printed.
// This is a regression test for a bug where `$x:ident` followed by `where`
// was pretty-printed as `$x:identwhere` (an invalid fragment specifier).
macro_rules! outer {
($d:tt $($params:tt)*) =>
{
#[macro_export] macro_rules! inner
{ ($($params)* where $d($rest:tt)*) => {}; }
};
}
#[macro_export]
macro_rules! inner { ($x:identwhere $ ($rest : tt)*) => {}; }
fn main() {}
```
**after** (this branch):
```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:macro-fragment-specifier-whitespace.pp
// Test that fragment specifier names in macro definitions are properly
// separated from the following keyword/identifier token when pretty-printed.
// This is a regression test for a bug where `$x:ident` followed by `where`
// was pretty-printed as `$x:identwhere` (an invalid fragment specifier).
macro_rules! outer {
($d:tt $($params:tt)*) =>
{
#[macro_export] macro_rules! inner
{ ($($params)* where $d($rest:tt)*) => {}; }
};
}
#[macro_export]
macro_rules! inner { ($x:ident where $ ($rest : tt)*) => {}; }
fn main() {}
```
Notice the `$x:identwhere` in the before — an invalid fragment specifier that causes a hard parse error. The after correctly separates it as `$x:ident where`.
Insert space after float literal ending with `.` in pretty printer
The pretty printer was collapsing unsuffixed float literals (like `0.`) with adjacent dot tokens, producing ambiguous or invalid output:
- `0. ..45.` (range) became `0...45.`
- `0. ..=360.` (inclusive range) became `0...=360.`
- `0. .to_string()` (method call) became `0..to_string()`
The fix inserts a space after an unsuffixed float literal ending with `.` when it appears as the start expression of a range operator or the receiver of a method call or field access, preventing the trailing dot from merging with the following `.`, `..`, or `..=` token. This is skipped when the expression is already parenthesized, since the closing `)` naturally provides separation.
## Example
**before** (`rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)`):
```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pp-exact
fn main() {
let _ = 0...45.;
let _ = 0...=360.;
let _ = 0...;
let _ = 0..to_string();
}
```
**after** (this branch):
```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pp-exact
fn main() {
let _ = 0. ..45.;
let _ = 0. ..=360.;
let _ = 0. ..;
let _ = 0. .to_string();
}
```
Notice `0...45.` (ambiguous — looks like deprecated `...` inclusive range) becomes `0. ..45.` (clear: float `0.` followed by range `..`). Similarly `0..to_string()` (parsed as range) becomes `0. .to_string()` (method call on float).
Preserve braces around `self` in use tree pretty printing
The AST pretty printer strips braces from single-item `use` sub-groups, simplifying `use foo::{Bar}` to `use foo::Bar`. However, when the single item is `self`, this produces `use foo::self` which is not valid Rust (E0429) — the grammar requires `use foo::{self}`.
This affects both `stringify!` and `rustc -Zunpretty=expanded`, causing `cargo expand` output to be unparseable when a crate uses `use path::{self}` imports (a common pattern in the ecosystem).
The fix checks whether the single nested item's path starts with `self` before stripping braces. If so, the braces are preserved.
## Example
**before** (`rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)`):
```rust
#![feature(prelude_import)]
//@ pp-exact
//@ edition:2021
#![allow(unused_imports)]
extern crate std;
#[prelude_import]
use std::prelude::rust_2021::*;
// Braces around `self` must be preserved, because `use foo::self` is not valid Rust.
use std::io::self;
use std::fmt::{self, Debug};
fn main() {}
```
**after** (this branch):
```rust
#![feature(prelude_import)]
//@ pp-exact
//@ edition:2021
#![allow(unused_imports)]
extern crate std;
#[prelude_import]
use std::prelude::rust_2021::*;
// Braces around `self` must be preserved, because `use foo::self` is not valid Rust.
use std::io::{self};
use std::fmt::{self, Debug};
fn main() {}
```
Notice the `use std::io::self` (invalid, E0429) in the before becomes `use std::io::{self}` in the after.
Updates derive_where and removes workaround
Updates dependency on `derive-where` that fixes issue https://github.com/ModProg/derive-where/issues/136 and removes the following workaround:
```
// FIXME(derive-where#136): Need to use separate `derive_where` for
// `Copy` and `Ord` to prevent the emitted `Clone` and `PartialOrd`
// impls from incorrectly relying on `T: Copy` and `T: Ord`.
```
r? lcnr
Rewrite `query_ensure_result`.
It currently uses chaining which is concise but hard to read. There are up to four implicit matches occurring after the call to `execute_query_fn`.
- The first `map` on `Option<Erased<Result<T, ErrorGuaranteed>>>`.
- The second `map` on `Option<Result<T, ErrorGuaranteed>>`.
- The third `map` on `Result<T, ErrorGuaranteed>`.
- The `unwrap_or` on `Option<Result<(), ErrorGuaranteed>>`.
This commit rewrites it to use at most two matches.
- An explicit match on `Option<Erased<Result<T, ErrorGuaranteed>>>`.
- An explicit match on `Result<T, ErrorGuaranteed>`.
This is easier to read. It's also more efficient, though the code isn't hot enough for that to matter.
r? @Zalathar