Repository: rust
Issue: Source of lifetime coercion is not reported starting in 1.63
Labels: A-diagnostics,A-lifetimes,P-high,T-compiler,regression-from-stable-to-stable,C-bug,WG-diagnostics

When the lifetime of a value is coerced to a longer one due to the use of an associated function or trait member and the previous lifetime used by other call sites is no longer sufficient, rustc no longer includes any mention of the coercion site (and includes a red herring that forces one to go chasing after the wrong goose). This makes it much, much harder to figure out why code is not working as all the locations rustc mentions are perfectly fine and have nothing to do with the actual cause of the error.

### Code

```rust
use std::path::{Path, PathBuf};

enum PolyStr<'a> {
    Str(&'a str),
}

impl<'a> From<&'static str> for PolyStr<'static> {
    fn from(s: &'static str) -> Self {
        PolyStr::Str(s)
    }
}

#[derive(Default)]
struct Ffcommand<'a> {
    inputs: Vec<&'a Path>,
    output: Option<PolyStr<'a>>,
}

impl<'a> Ffcommand<'a> {
    pub fn run(&self) -> bool {
        true
    }

    pub fn input(mut self, p: &'a Path) -> Self {
        self.inputs.push(p);
        self
    }

    pub fn output<P>(mut self, p: P) -> Self
    where
        P: Into<PolyStr<'a>> + 'a
    {
        self.output = Some(p.into());
        self
    }
}

#[derive(Default)]
struct Ffinfo<'a> {
    cmd: Ffcommand<'a>,
    path: PathBuf,
}

impl Ffinfo<'_> {
    fn foo(&self) -> bool {
        let cmd = Ffcommand::default()
            .input(&self.path)
            // uncomment the next line to see the error
            // .output("pipe:1")
            ;
            
        cmd.run()
    }
}

fn main() {
    let mut info = Ffinfo::default();
    info.path = PathBuf::from("./hello.world");
    info.foo();
}

```

When the commented-out line is added back in, rustc will emit the following error:

```
error[[E0521]](https://doc.rust-lang.org/beta/error-index.html#E0521): borrowed data escapes outside of associated function
  --> src/main.rs:46:19
   |
45 |       fn foo(&self) -> bool {
   |              -----
   |              |
   |              `self` is a reference that is only valid in the associated function body
   |              let's call the lifetime of this reference `'1`
46 |           let cmd = Ffcommand::default()
   |  ___________________^
47 | |             .input(&self.path)
   | |                              ^
   | |                              |
   | |______________________________`self` escapes the associated function body here
   |                                argument requires that `'1` must outlive `'static`

For more information about this error, try `rustc --explain E0521`.
error: could not compile `playground` due to previous error
```

[Try on playground](https://play.rust-lang.org/?version=beta&mode=debug&edition=2021&gist=e27d357e44b18e36503950ba53524c4f).

The error message points to `self` and `.input()` as the locations pertaining to this error, when in fact the error stems entirely from the usage of `.output()`, which coerces the lifetime to `'static` due to the trait impl, at the same time as `.input()`, which doesn't last as long.

rustc stable (1.62) emits the following error message instead, which is infinitely more helpful:

```
error[[E0759]](https://doc.rust-lang.org/stable/error-index.html#E0759): `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src/main.rs:47:20
   |
45 |     fn foo(&self) -> bool {
   |            ----- this data with an anonymous lifetime `'_`...
46 |         let cmd = Ffcommand::default()
47 |             .input(&self.path)
   |                    ^^^^^^^^^^ ...is used here...
48 |             .output("pipe:1")
   |              ------ ...and is required to live as long as `'static` here

For more information about this error, try `rustc --explain E0759`.
error: could not compile `playground` due to previous error
```

Notice that here the correct call sites (`.input()` and `.output()`) are mentioned. In particular, the fact that `.output()` is where `'static` is required is clearly mentioned, making it easy to figure out what is going on.

Needless to say, this is a highly stripped-down example for illustration purposes. It took me perhaps half-an-hour to chase down the actual issue in a real codebase; IIRC the `.output()` equivalent was part of the original code and `.input()` was added some months later, and there were a lot of false trails to chase down before finding the `.output()` lifetime coercion.


### Version it worked on

<!--
Provide the most recent version this worked on, for example:

It most recently worked on: Rust 1.47
-->

It most recently worked on: 1.62.0

### Version with regression

<!--
Provide the version you are using that has the regression.
-->

`rustc --version --verbose`: 
```
1.63.0-beta.5 2022-07-10 93ef0cd7fd86d3d05cee
```

<!--
Did the compiler crash? If so, please provide a backtrace.
-->

<!--
If you know when this regression occurred, please add a line like below, replacing `{channel}` with one of stable, beta, or nightly.

@rustbot modify labels: +regression-from-stable-to-beta -regression-untriaged
-->