Repository: rust
Issue: Surprising diagnostics for E0623 lifetime mismatch
Labels: A-diagnostics,A-lifetimes,T-compiler,D-confusing

Given the following code: <!-- Please provide a link to play.rust-lang.org -->

```rust
use std::collections::HashMap;
use std::marker::PhantomData;

fn diff(
    keys: &[Option<&str>],
    maps: &(
        HashMap<Option<&str>, Vec<&mut Record>>,
        HashMap<Option<&str>, Vec<&mut Record>>,
    ),
) {
    for key in keys {
        let info = (maps.0.get(key), maps.1.get(key));
        if info.0 == info.1 {
            continue;
        }
    }
}

#[derive(Debug, PartialEq)]
struct Record<'a>(PhantomData<&'a ()>);

#[derive(Copy, Clone, Eq, PartialEq, Hash)]
enum Enum {
    Foo,
    Bar,
}
```

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f47c0f93783ccca97fa1a040ce78f668

The current output is:

```
error[[E0623]](https://doc.rust-lang.org/stable/error-index.html#E0623): lifetime mismatch
  --> src/lib.rs:13:22
   |
7  |         HashMap<Option<&str>, Vec<&mut Record>>,
   |                                        ------
8  |         HashMap<Option<&str>, Vec<&mut Record>>,
   |                                        ------ these two types are declared with different lifetimes...
...
13 |         if info.0 == info.1 {
   |                      ^^^^^^ ...but data from `maps` flows into `maps` here

error[[E0623]](https://doc.rust-lang.org/stable/error-index.html#E0623): lifetime mismatch
  --> src/lib.rs:13:22
   |
7  |         HashMap<Option<&str>, Vec<&mut Record>>,
   |                                        ------ these two types are declared with different lifetimes...
8  |         HashMap<Option<&str>, Vec<&mut Record>>,
   |                                        ------
...
13 |         if info.0 == info.1 {
   |                      ^^^^^^ ...but data from `maps` flows into `maps` here

For more information about this error, try `rustc --explain E0623`.
```

I'm not sure what the ideal output for this, but here are some improvement points:

* Showing what appears to be the same error twice
* The explanation of "data [..] flows into [..]" seems really weird considering this is just a comparison
* Why does the borrow checker care about the exact lifetimes for a comparison anyway?
* Maybe this should mention something about the inner `Record` lifetime
* Why is the error pointing at the `info.1` value, which is derived from a `maps` value, but also at the keys of `maps`?

Another case where I got quite confused:

```rust
use anyhow::Error;

#[tokio::main]
async fn main() {
    let store = Store { p1: Pool1 };
    let t = Pool2.begin();
    let mut store_mut = store.get_mut(&mut t);
    store_mut.bar().await.unwrap();
    ()
}

struct Store {
    p1: Pool1,
}

impl Store {
    fn get_mut<'t, 's: 't>(&'s self, t: &'t mut T<'t>) -> StoreMut<'s> {
        StoreMut {
            p1: &self.p1,
            t,
        }
    }
}

struct StoreMut<'a> {
    p1: &'a Pool1,
    t: &'a mut T<'a>,
}

impl<'a> StoreMut<'a> {
    async fn bar(&mut self) -> Result<(), Error> {
        Ok(())
    }
}

struct Pool1;

struct Pool2;

impl Pool2 {
    fn begin(&self) -> T<'static> {
        T { s: "foo" }
    }
}

struct T<'a> {
    s: &'a str,
}

impl<'a> T<'a> {
    fn finalize(self) {
        
    }
}
```

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=f50a36b183385f8247f688ca7dd5cb41

Which gave me the error:

```rust
error[[E0623]](https://doc.rust-lang.org/stable/error-index.html#E0623): lifetime mismatch
  --> src/main.rs:18:9
   |
17 |       fn get_mut<'t, 's: 't>(&'s self, t: &'t mut T<'t>) -> StoreMut<'s> {
   |                              --------     ------------- these two types are declared with different lifetimes...
18 | /         StoreMut {
19 | |             p1: &self.p1,
20 | |             t,
21 | |         }
   | |_________^ ...but data from `t` flows into `self` here
```

Seems really weird to say that data from `t` is flowing into `self` in this case.