refactor rustc_hir_typeck/src/op.rs
Fixesrust-lang/rust#64297
This is a refactoring PR with no logic or behaviour changes. I tried to improve readability of op.rs, which had a few very large functions using some suboptimal syntax. I broke these up into smaller helpers.
Rollup of 3 pull requests
Successful merges:
- rust-lang/rust#153038 (core::sync: rename `Exclusive` to `SyncView` and make improvements)
- rust-lang/rust#154955 (Fix pattern types rendering in rustdoc)
- rust-lang/rust#155026 (Move `maybe_loop_headers` out of `rustc_middle`.)
Move `maybe_loop_headers` out of `rustc_middle`.
`rustc_middle` is enormous and it's always good to move things out of it where possible. `maybe_loop_headers` is easy to move because it has a single use in `jump_threading.rs`.
r? @WaffleLapkin
Fix pattern types rendering in rustdoc
Closesrust-lang/rust#150889 .
`core` was rendering local pattern-type impls through `clean_ty`, which formatted `rustc_hir::TyPat` with derived Debug, while inlined docs go through `clean_middle_ty` and get the pretty-printed `rustc_middle::ty::Pattern`.
Lower local HIR pattern types before formatting so both paths share the same canonical pattern printer and stop exposing `TyPat { ... }` in implementors.
#### Current result:
<img width="1133" height="738" alt="截屏2026-04-07 22 47 26" src="https://github.com/user-attachments/assets/bb5f8942-30b1-400a-a0a0-f581da5bb59f" />
core::sync: rename `Exclusive` to `SyncView` and make improvements
This PR implements the renaming of `core::sync::Exclusive` to `SyncView` as decided in rust-lang/rust#98407. To preserve the ability to search for the old name, it adds `Exclusive` as a `doc_alias`.
It also makes the following additional changes:
- Converting the `get_mut` method to being an instance of `AsMut::as_mut`. In the process, it makes both the new `impl AsMut` and the existing `impl AsRef` `const`, and it also renames `get_pin_mut` to `as_pin_mut` for consistency. This direction follows a suggestion from rust-lang/rust#98407.
- Adding an `as_pin` method that can only be used when the wrapped type implements `Sync`, to complete the square of access methods.
- Making as many of the existing `impl`s `const` as possible; this involved making the existing `impl Default` no longer derived.
- Adding `impl`s for `AsyncFnOnce`, `AsyncFnMut`, and `AsyncFn`, akin to the existing `impls` for `FnOnce`, `FnMut`, and `Fn`.
It does not yet do the following, which may be desirable:
- Fixing/improving the documentation to address the concern pointed out in rust-lang/rust#146245.
It previously did the following, but this was removed after discussion:
- Adding an `impl` for (`const`) `Iterator`, which felt in line with the existing `impl`s for `Future` and `Coroutine`.
Rollup of 10 pull requests
Successful merges:
- rust-lang/rust#150316 (Do not use non-wf input expectations from fudge when checking function calls)
- rust-lang/rust#152859 (`-Znext-solver` use the trait object's own bounds instead of goal when considering builtin object bounds)
- rust-lang/rust#154856 (Fix linking two dylibs together when both depend on profiler_builtins)
- rust-lang/rust#153888 (Avoid stack overflow in FindExprBySpan)
- rust-lang/rust#154991 (Fix ICE in next-solver TransmuteFrom candidate)
- rust-lang/rust#154995 (min/max_by tests: also check result)
- rust-lang/rust#155004 (core/num: Fix feature name for unstable `integer_extend_truncate` functions)
- rust-lang/rust#155007 (renaming method is_impl_trait to is_opaque)
- rust-lang/rust#155009 (meta: Add checkboxes to unsresolved questions in issue templates)
- rust-lang/rust#155017 (Update tracking issue number of future-incompatibility lint `unstable_syntax_pre_expansion`)
Update tracking issue number of future-incompatibility lint `unstable_syntax_pre_expansion`
Issue rust-lang/rust#65860 has never been a proper tracking issue, it has always been a normal issue that reported a pass→fail regression which was subsequently fixed and which elicited a discussion spanning 50 comments. Years later the formerly offending errors were reintroduced as warnings which link to said issue (see section *Pre-History* in issue rust-lang/rust#154045 for details).
A few weeks ago I closed this issue (https://github.com/rust-lang/rust/issues/65860#issuecomment-4083652176) in favor of a new super focused & structured tracking issue, rust-lang/rust#154045. That means people now have to jump through hoops to arrive at the new tracking issue which is less than ideal (it's very likely that this user had to do so: https://github.com/rust-lang/rust/issues/154045#issuecomment-4207339422), let's fix that.
Part of rust-lang/rust#154045.
meta: Add checkboxes to unsresolved questions in issue templates
These frequently have links to comments on closed PRs, meaning it can looks like issues have been resolved even if that isn't the case. Add checkboxes to make it more clear when a conclusion has been reached.
min/max_by tests: also check result
These tests were recently added in https://github.com/rust-lang/rust/pull/154761. IMO there's no reason to ignore the actual result of the function in the test, so let's also assert that this is correct.
Fix ICE in next-solver TransmuteFrom candidate
Treat TransmuteFrom goals with non-region inference variables as ambiguous before running transmutability, matching the old solver.
Closesrust-lang/rust#153370 .
Avoid stack overflow in FindExprBySpan
Fixesrust-lang/rust#153583.
Deeply nested `?` desugarings can build a very deep HIR expression spine.
When `FindExprBySpan` walks that expression during error reporting, the
recursive `visit_expr` traversal can overflow the stack before rustc emits the
actual diagnostic.
This wraps the recursive expression walk in `ensure_sufficient_stack`, which
lets the compiler report the expected E0277 instead of crashing.
Added a UI regression test for a deeply nested `?` chain.
Do not use non-wf input expectations from fudge when checking function calls
cc https://github.com/rust-lang/rust/issues/149379
r? lcnr
# FCP: Do not use non-wf input expectations from fudge when checking function calls
## What is fudging?
https://github.com/rust-lang/rust/blob/71e00273c0921e1bc850ae8cc4161fbb44cfa848/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L168-L170
Consider this coercion site:
`let _: Box<dyn Fn(&str) -> usize> = Box::new(|s| s.len());`
We rely on the expectation to eagerly infer the type of `s` to be `&str`. However, `dyn Fn(&str) -> usize` is not a valid type as the argument of `Box::new`, as it is not `Sized`.
*Fudging* is the mechanism we use to propagate the expectation through the `Box::new` call without constraining its generic parameter.
Fudging computes the expected argument types by acting as if we're able to propagate the expected return type directly through the function, without any coercions on the return site.
Given that we may actually want to coerce afterwards, we cannot actually commit any constraints here. We therefore compute the expectations for the function arguments in a `probe` and rely on *fudging* to be able to name any inference variables created inside of the probe.
After the fudging step, we weaken the resulting expectation if it is an unsized type in the following lines:
https://github.com/rust-lang/rust/blob/71e00273c0921e1bc850ae8cc4161fbb44cfa848/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L354https://github.com/rust-lang/rust/blob/71e00273c0921e1bc850ae8cc4161fbb44cfa848/compiler/rustc_hir_typeck/src/expectation.rs#L77-L89
Because function arguments must be `Sized`, this weakening prevents us from applying wrong, unsized coercions to them.
## How fudging currently goes wrong
We have an opened issue for tracking such cases: https://github.com/rust-lang/rust/issues/149379.
Broadly, the failures seem to fall into two buckets.
### We may end up with non–well-formed expectations
Fudging can produce an expected type that is not well-formed.
That would eventually result in an error failing the well-formedness check, either when we do the coercion with the expected argument types, or when we select the remaining obligations.
```rust
fn foo<T>(x: (T, ())) -> Box<T> {
Box::new(x.0)
}
fn main() {
// We use `(dyn Send, ())` as the expectation the argument.
let _: Box<dyn Send> = foo(((), ()));
}
```
### Weakening fudged expectation is not covering all the cases
```rust
fn field_to_box<T>(x: &(T,)) -> &T {
&x.0
}
fn main() {
// `Expectation::rvalue_hint` only checks whether the whole argument
// itself is `Sized`. It does not check whether the function requires
// its generic parameters to be `Sized`.
let _: &dyn Send = field_to_box(&(1,));
}
```
## What this PR fixes
### One of the problematic cases of the issue
This PR fixes the first case, by simply checking well-formedness of the each expected argument types inside the fudge scope.
This is a reasonable change because:
- Non well-formed expectation would result in a well-formedness error so not using such expectation wouldn't make any previously compiled code being not compiled anymore
- Dropping a non well-formed expectation does not mean we stop providing expectations for argument coercions altogether.
If fudging fails, we still fall back to using the types from the function signature as expectations in the usual path:
https://github.com/rust-lang/rust/blob/71e00273c0921e1bc850ae8cc4161fbb44cfa848/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs#L330-L336
#### Related tests
- Fixes [tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-1.rs](https://github.com/rust-lang/rust/pull/150316/commits/5668ad597d8293dcfd8917ca6e8f78d2c06555d3#diff-1468a6d8495f7adfb4a64508f002bb934c13d13871662de6efd60433649401fd)
### Limited for `-Znext-solver`
Separately (and not directly tied to the above issue), this PR also fixes a next-solver regression tracked at: https://github.com/rust-lang/trait-system-refactor-initiative/issues/259.
That regression was introduced by https://github.com/rust-lang/rust/pull/149320, which started normalizing expected function input types inside the fudge scope.
Because all inference-variable relationships and pending obligations are dropped out when we exit the fudge scope, we drop the ambiguous goal used to normalize, leaving us with an unconstrained inference variable in the expectation.
This PR fixes that by normalizing the expectation outside the fudge scope, so the resulting normalization obligations are preserved to the `InferCtxt`'s `ObligationCtxt`.
#### Related tests
- Fixes [tests/ui/traits/next-solver/fudge-inference/do-not-drop-ambig-normalization.rs](https://github.com/rust-lang/rust/pull/150316/files#diff-42e97f178fbdee7c3405ae12409eb0bca4eec92488971c703b26c083eadf728a)
## Does this PR break anything
I don't think there should be any breakage affecting the old solver.
The separate expectation normalization change only affecting the new solver does break an existing [test](https://github.com/rust-lang/rust/pull/150316/files#diff-3b946a09e063aad2a4fa6b0893508d5ffab78763b8465abfe1f689d349fda815).
This is unfortunate but I think this change should be done because
- The broken test also doesn't compile with the old solver
- The expectation normalization change is necessary to compile stuff supported on stable
## What this PR doesn't fix
This PR doesn't fix the second case -- *Weakening fudged expectation is not covering all the cases*.
@lcnr has [suggested](https://rust-lang.zulipchat.com/#narrow/channel/144729-t-types/topic/expectations.20from.20fudging.20are.20a.20mess.20.23149379/near/560625205) the following solution for that problem:
> check whether a function where-bound errors without an out coercion, if so, weaken the expectation to `ExpectRvalueLikeUnsized`
I experimented with this and it works well in many cases.
However, on the old solver, checking where-bounds cannot reliably be treated as speculative: if we hit an overflow while checking the where-bounds, the old solver can fail the entire compilation rather than merely treating the check as failed and relaxing the expectation.
Since this second class of issues affects both the old solver and the next-solver, it seems preferable to keep the conservative behavior for now, at least until the next-solver is stabilized, rather than introducing a next-solver-only relaxation that might create new regressions and complicate stabilization efforts.
#### Related tests
- Does NOT Fix [tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-89299.rs](https://github.com/rust-lang/rust/pull/150316/files#diff-fdcfa8ab660c052dbe246db279d167ea8a309bfe10ca6163f7fa1836be2b30d6)
- Does NOT Fix [tests/ui/coercion/fudge-inference/expectated-input-not-satisfying-fn-bounds-issue-149881.rs](https://github.com/rust-lang/rust/pull/150316/files#diff-1ccbb181cbf164841ca5af350ecf903c802a4854bda309e83e91c3b917809a55)
- Does NOT Fix [tests/ui/coercion/fudge-inference/fn-ret-trait-object-propagated-to-inputs-issue-149379-3.rs](https://github.com/rust-lang/rust/pull/150316/files#diff-b12e01cc3c265db42f135d67425d8b2bd0d9c44c680b3e8c49d1f845a0b25d09)
Treat TransmuteFrom goals with non-region inference variables as ambiguous before running transmutability, instead of computing layouts for unresolved types. The old solver already treated these goals as ambiguous, so only the next solver could hit this ICE.
`rustc_middle` is enormous and it's always good to move things out of it
where possible. `maybe_loop_headers` is easy to move because it has a
single use in `jump_threading.rs`.
Rollup of 6 pull requests
Successful merges:
- rust-lang/rust#154912 (Remove `BuiltinLintDiag`)
- rust-lang/rust#154598 (test `#[naked]` with `#[link_section = "..."]` on windows)
- rust-lang/rust#154719 (Hexagon inline asm: add reg_pair, vreg, vreg_pair, and qreg register classes)
- rust-lang/rust#154057 (Parenthesize block-like expressions in index base of pretty printer)
- rust-lang/rust#154893 (make `expected_literal` positive)
- rust-lang/rust#155002 (Clarify that `core::range` ranges do not have special syntax)
Parenthesize block-like expressions in index base of pretty printer
The AST pretty printer produces invalid Rust when a block expression is the base of an index operation inside a macro expansion. This is a gap in the parenthesization fix from rust-lang/rust#119105 — the `FixupContext` approach handles statement position but not the case where a block-index is nested inside another expression.
The following is a correct program:
```rust
macro_rules! block_arr {
() => {{ [0u8; 4] }};
}
macro_rules! as_slice {
() => {{ &block_arr!()[..] }};
}
fn main() { let _: &[u8] = as_slice!(); }
```
But `rustc -Zunpretty=expanded` produces output that is not valid Rust, because the closing brace of `{ [0u8; 4] }` creates a statement boundary, causing the parser to treat `[..]` as a separate expression:
```rust
fn main() { let _: &[u8] = { &{ [0u8; 4] }[..] }; }
```
```
error: expected one of `.`, `;`, `?`, `}`, or an operator, found `[`
```
Fixed output after this change:
```rust
fn main() { let _: &[u8] = { &({ [0u8; 4] })[..] }; }
```
Since `{ ... }[...]` never parses as indexing a block regardless of context, the fix unconditionally parenthesizes "complete" expressions (block, match, if, loop, etc.) when they appear as the base of an index operation.
test `#[naked]` with `#[link_section = "..."]` on windows
As a part of https://github.com/rust-lang/rust/pull/147811 I ran into that we actually don't match (current) LLVM output.
r? @mati865
These frequently have links to comments on closed PRs, meaning it can
looks like issues have been resolved even if that isn't the case. Add
checkboxes to make it more clear when a conclusion has been reached.
Use fine grained component-wise span tracking in use trees
This often produces nicer spans and even doesn't need a Span field anymore (not that I expect the unused field to affect any perf, but still neat).
Cargo submodule update
11 commits in a357df4c26fc14514e66aae2a269456b5545c7db..101549dddbd2b08e806f50154e3aa4cb3374cc21
2026-04-03 16:47:15 +0000 to 2026-04-08 12:51:20 +0000
- Never include use extra-filename in build scripts (rust-lang/cargo#16855)
- fix(toml): Force script edition warnings on quiet (rust-lang/cargo#16848)
- GitHub fast path uses `http_async` (rust-lang/cargo#16847)
- feat(manifest): allow git dependency alongside alternate registry (rust-lang/cargo#16810)
- fix(auth): add auth scheme hint to token rejected error for alt registries (rust-lang/cargo#16794)
- Warn on invalid jobserver file descriptors (rust-lang/cargo#16843)
- docs(unstable): List the minimum required MSRV for 'public' field (rust-lang/cargo#16841)
- feat(lints): Emit unused_dependencies lint (rust-lang/cargo#16600)
- fix(tree): clarify error message when `-i` is used without a package name (rust-lang/cargo#16818)
- fix: Typo in target.<cfg>.linker (rust-lang/cargo#16839)
- Send Content-Type header with cargo publish requests (rust-lang/cargo#16832)
r? ghost
When a macro expands to a call whose callee is a block (or other
"complete" expression like `match`, `if`, `loop`), the AST pretty
printer emits the callee without parentheses. In statement position
the closing brace ends the expression and the argument list is parsed
as a separate tuple expression, producing a parse error.
match exhaustiveness: Show the guard exhaustivity note only when it's the guards alone that cause non-exhaustiveness
Only show the "match arms with guards don't count towards exhaustivity" note when removing all guards would make the match exhaustive, but also in the cases when the match contains arms without guards. Previously, this note was shown only if all arms had guards, but even if the patterns themselves were insufficient to cover all valid values of a type.
Do this by rerunning the exhaustiveness analysis with guards stripped to determine whether the guards are actually the cause of non-exhaustiveness. This only happens on an actual exhaustiveness error, so should not be a performance concern.
This will make a program like:
```rust
fn main() {
let some_condition = true;
let some_option: Option<u8> = None;
let _res = match some_option {
Some(val) if some_condition => val,
None => 0,
};
}
```
produce the note ”match arms with guards don't count towards exhaustivity” that previously would not have been appearing.
Closesrust-lang/rust#104653 as I think this addresses the spirit of that issue. I don’t believe it’s necessary to be any more elaborate in the diagnostics here?