Repository: rust
Issue: Trait projection plus return type hinders coercion of function argument
Labels: T-compiler,C-bug,fixed-by-next-solver

[I tried this code:](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=112b24cf9395fd2102dd4aabf9c8ec3e)

```rust
// For indirection
pub trait With {
    type F;
}

impl With for i32 {
    type F = fn(&str);
}

// A function item to coerce
fn f(_: &str) {}

fn main() {
    // Tuple constructor fails
    let _: V<i32> = V(f);
    pub struct V<T: With>(<T as With>::F);

    // Trait projection in variant fails
    pub enum E3<T: With> { Var(<T as With>::F), }
    let _: E3<i32> = E3::Var(f);
}
```

I expected to see this happen: Successful compilation due to the function item coercing to a function pointer.

Instead, this happened: E0271 due to coercion not applying through the trait projection:
```
error[[E0271]](https://doc.rust-lang.org/stable/error-index.html#E0271): type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
  [--> src/main.rs:16:21
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#)   |
16 |     let _: V<i32> = V(f);
   |                     ^^^^ type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
   |
note: expected this to be `for<'r> fn(&'r str)`
  [--> src/main.rs:7:14
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#)   |
7  |     type F = fn(&str);
   |              ^^^^^^^^
   = note: expected fn pointer `for<'r> fn(&'r str)`
                 found fn item `for<'r> fn(&'r str) {f}`

error[[E0271]](https://doc.rust-lang.org/stable/error-index.html#E0271): type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
  [--> src/main.rs:21:22
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#)   |
21 |     let _: E3<i32> = E3::Var(f);
   |                      ^^^^^^^^^^ type mismatch resolving `<i32 as With>::F == for<'r> fn(&'r str) {f}`
   |
note: expected this to be `for<'r> fn(&'r str)`
  [--> src/main.rs:7:14
](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=eff917c8034cf4f25f51a32ae093abab#)   |
7  |     type F = fn(&str);
   |              ^^^^^^^^
   = note: expected fn pointer `for<'r> fn(&'r str)`
                 found fn item `for<'r> fn(&'r str) {f}`
```

### Further notes

**Edit** This doesn't really seem to be about constructors, but functions more generally; see below.

<details>
<summary>Pre-edit notes</summary>

As can be seen in the playground link, the coercion applies for
* Ascripted bindings
* Function arguments (normal functions vs generated constructors)
* Actual tuples
* Bracketed struct and bracket variant fields

The last bullet also [did not work in Rust 1.19 and prior,](https://rust.godbolt.org/z/W94Mfx1x6) but this was fixed by #42807.  So technically this could be considered a dupe of #31260 as "coercion sites are not consistent between struct tuples and structs" is still true.

</details>

Coercion also applies if the indirection through the trait is not present.

### Meta

Discovered on the playground
* Stable version: 1.60.0
* Beta version: 1.61.0-beta.1 (2022-04-05 0f231250ba7fe3a3f98a)
* Nightly version: 1.62.0-nightly (2022-04-08 f4a7ce997a1d7546d2b7)

@rustbot modify labels: T-compiler