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)
Remove "failed to resolve" and use the same format we use in other resolution errors "cannot find `name`".
```
error[E0433]: cannot find `nonexistent` in `existent`
--> $DIR/custom_attr_multisegment_error.rs:5:13
|
LL | #[existent::nonexistent]
| ^^^^^^^^^^^ could not find `nonexistent` in `existent`
```
Rehome 30 `tests/ui/issues/` tests to other subdirectories under `tests/ui/` [#3 of Batch #2]
Part of rust-lang/rust#133895
Methodology:
1. Refer to the previously written `tests/ui/SUMMARY.md`
2. Find an appropriate category for the test, using the original issue thread and the test contents.
3. Add the issue URL at the bottom (not at the top, as that would mess up stderr line numbers)
4. Rename the tests to make their purpose clearer
Inspired by the methodology that `@Kivooeo` was using.
r? `@jieyouxu`
When encountering an unmet trait bound, point at local type that doesn't implement the trait:
```
error[E0277]: the trait bound `Bar<T>: Foo` is not satisfied
--> $DIR/issue-64855.rs:9:19
|
LL | pub struct Bar<T>(<Self as Foo>::Type) where Self: ;
| ^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound
|
help: the trait `Foo` is not implemented for `Bar<T>`
--> $DIR/issue-64855.rs:9:1
|
LL | pub struct Bar<T>(<Self as Foo>::Type) where Self: ;
| ^^^^^^^^^^^^^^^^^
```
When looking for the field names and types of a given type, account for tuples. This allows suggestions for incorrectly nested field accesses and field name typos to trigger as intended. Previously these suggestions only worked on `ty::Adt`, including tuple structs which are no different to tuples, so they should behave the same in suggestions.
```
error[E0599]: no method named `get_ref` found for tuple `(BufReader<File>,)` in the current scope
--> $DIR/missing-field-access.rs:11:15
|
LL | let x = f.get_ref();
| ^^^^^^^ method not found in `(BufReader<File>,)`
|
help: one of the expressions' fields has a method of the same name
|
LL | let x = f.0.get_ref();
| ++
```
Previously, we included a redundant prefix on the panic message and a postfix of the location of the panic. The prefix didn't carry any additional information beyond "something failed", and the location of the panic is redundant with the diagnostic's span, which gets printed out even if its code is not shown.
```
error[E0080]: evaluation of constant value failed
--> $DIR/assert-type-intrinsics.rs:11:9
|
LL | MaybeUninit::<!>::uninit().assume_init();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation panicked: aborted execution: attempted to instantiate uninhabited type `!`
```
```
error[E0080]: evaluation of `Fail::<i32>::C` failed
--> $DIR/collect-in-dead-closure.rs:9:19
|
LL | const C: () = panic!();
| ^^^^^^^^ evaluation panicked: explicit panic
|
= note: this error originates in the macro
`$crate::panic::panic_2015` which comes from the expansion of the macro
`panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
```
error[E0080]: evaluation of constant value failed
--> $DIR/uninhabited.rs:41:9
|
LL | assert!(false);
| ^^^^^^^^^^^^^^ evaluation panicked: assertion failed: false
|
= note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
```
---
When the primary span for a const error is the same as the first frame in the const error report, skip it.
```
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| ^^^^^^^^^^^^^^ evaluation panicked: explicit panic
|
note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34}>`
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^ the failure occurred here
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
instead of
```
error[E0080]: evaluation of constant value failed
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^ explicit panic
|
note: inside `f::<{closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34}>`
--> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
|
LL | panic!()
| ^^^^^^^^
note: inside `_CONST`
--> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
|
LL | const _CONST: &[u8] = &f(&[], |_| {});
| ^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
---
Revert order of constant evaluation errors
Point at the code the user wrote first and std functions last.
```
error[E0080]: evaluation of constant value failed
--> $DIR/const-errs-dont-conflict-103369.rs:5:25
|
LL | impl ConstGenericTrait<{my_fn(1)}> for () {}
| ^^^^^^^^ evaluation panicked: Some error occurred
|
note: called from `my_fn`
--> $DIR/const-errs-dont-conflict-103369.rs:10:5
|
LL | panic!("Some error occurred");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
instead of
```
error[E0080]: evaluation of constant value failed
--> $DIR/const-errs-dont-conflict-103369.rs:10:5
|
LL | panic!("Some error occurred");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Some error occurred
|
note: called from `<() as ConstGenericTrait<{my_fn(1)}>>::{constant#0}`
--> $DIR/const-errs-dont-conflict-103369.rs:5:25
|
LL | impl ConstGenericTrait<{my_fn(1)}> for () {}
| ^^^^^^^^
= note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
```
Reword resolve errors caused by likely missing crate in dep tree
Reword label and add `help`:
```
error[E0432]: unresolved import `some_novel_crate`
--> f704.rs:1:5
|
1 | use some_novel_crate::Type;
| ^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `some_novel_crate`
|
= help: if you wanted to use a crate named `some_novel_crate`, use `cargo add some_novel_crate` to add it to your `Cargo.toml`
```
Fix#133137.
```
error[E0432]: unresolved import `some_novel_crate`
--> file.rs:1:5
|
1 | use some_novel_crate::Type;
| ^^^^^^^^^^^^^^^^ use of unresolved module or unlinked crate `some_novel_crate`
```
On resolve errors where there might be a missing crate, mention `cargo add foo`:
```
error[E0433]: failed to resolve: use of unresolved module or unlinked crate `nope`
--> $DIR/conflicting-impl-with-err.rs:4:11
|
LL | impl From<nope::Thing> for Error {
| ^^^^ use of unresolved module or unlinked crate `nope`
|
= help: if you wanted to use a crate named `nope`, use `cargo add nope` to add it to your `Cargo.toml`
```
This CL makes a number of small changes to dyn compatibility errors:
- "object safety" has been renamed to "dyn-compatibility" throughout
- "Convert to enum" suggestions are no longer generated when there
exists a type-generic impl of the trait or an impl for `dyn OtherTrait`
- Several error messages are reorganized for user readability
Additionally, the dyn compatibility error creation code has been
split out into functions.
cc #132713
cc #133267