delegation: fix cycles during delayed lowering
This PR forces lowering of delayed owners after `hir_crate_items`, as some diagnostics use `hir_crate_items` which results in query cycle which is then hangs calling `def_path_str` again and again. Fixesrust-lang/rust#154169. Part of rust-lang/rust#118212.
r? @petrochenkov
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.
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
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.
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
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).
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?
Fix ICE in next-solver dyn-compatibility check
The next solver treated error-containing dispatchability goals as proven and misclassified the trait as dyn compatible. Short-circuit receivers with type errors so object-method confirmation stays on the normal error path.
Tracking issue: rust-lang/rust#130516Closes: rust-lang/rust#151311
Don't store `pattern_ty` in `TestableCase`
This field's only remaining use was in an assertion, but we can perform the same assertion earlier when constructing `TestableCase::Range`.
---
For background, the `pattern_ty` field was introduced in https://github.com/rust-lang/rust/pull/136435 to replace a reference to the full THIR pattern node. Since then, most uses of `pattern_ty` were removed by https://github.com/rust-lang/rust/pull/150238.
Fix private fields diagnostics and improve error messages
Fixesrust-lang/rust#151408
while the best solution may be check whether the code is under user's control, e.g. in the same workspace. but if user does not provide some fields, mention other private fields seems weird, see the test case:
```console
LL | let _ = std::collections::HashMap {};
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: private field `base` that was not provided
```
since we already suggested to use associated function to construct, it's better to remove the note.
this fix only provide note on private fields when `did.is_local()` or user have already provide some fields.
remove unnecessary variables and delimiter check
Zulip discussion: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp/topic/question.20about.20lex_token_tree_open_delim.20in.20rustc_parse/with/580552157
In `lex_token_tree_open_delim`, after calling `self.lex_token_trees(/* is_delimited */ true)`:
- If the delimiters are well-balanced, the value popped from the stack will always equal to `open_delim` and `pre_span`.
- If the delimiters are not balanced, `self.lex_token_trees(/* is_delimited */ true)` will return an error so this branch will not be reached
Therefore `open_delimiter` and `open_delimiter_span` can be removed.
Test `tests/ui/parser` all passed
Use convergent attribute to funcs for GPU targets
On targets with convergent operations, we need to add the convergent attribute to all functions that run convergent operations. Following clang, we can conservatively apply the attribute to all functions when compiling for such a target and rely on LLVM optimizing away the attribute in cases where it is not necessary.
This affects the amdgpu and nvptx targets.
cc @kjetilkjeka, @kulst for nvptx
cc @ZuseZ4
r? @nnethercote, as you already reviewed this in the other PR
Split out from rust-lang/rust#149637, the part here should be uncontroversial.
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 existing `FixupContext` parenthesization machinery — the 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.