Repository: rust
Issue: Lifetime of input (key) to HashMap::get() gets entanged w/ that of its output (value)
Labels: A-lifetimes,A-collections,T-libs-api,C-bug

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

The following code:

```rust
use std::{borrow::Cow, collections::HashMap};

#[derive(Debug)]
struct Message(String);

impl Message {
    fn interface(&self) -> &str {
        &self.0
    }
}

#[derive(Debug)]
struct Proxy<'p>(Cow<'p, str>);

impl<'p> Proxy<'p> {
    fn interface(&self) -> &str {
        &self.0
    }
}

#[derive(Hash, Eq, PartialEq)]
struct ProxyKey<'key>(Cow<'key, str>);

impl From<&Proxy<'_>> for ProxyKey<'_> {
    fn from(proxy: &Proxy<'_>) -> Self {
        ProxyKey(Cow::from(proxy.interface().to_owned()))
    }
}

impl<'key> From<&'key Message> for ProxyKey<'key> {
    fn from(msg: &'key Message) -> Self {
        ProxyKey(Cow::from(msg.interface()))
    }
}

struct ProxyGroup<'p> {
    proxies: HashMap<ProxyKey<'static>, Proxy<'p>>,
}

impl<'p> ProxyGroup<'p> {
    pub fn new() -> Self {
        Self {
            proxies: HashMap::new(),
        }
    }

    pub fn add<'a: 'p>(&mut self, proxy: Proxy<'a>) {
        let key = ProxyKey::from(&proxy);
        self.proxies.insert(key, proxy);
    }

    pub fn handle_next_signal(&self) {
        let msg = Message(String::from("some.interface"));

        match self.get_proxy_for_msg(&msg) {
            Some(_) => Self::consume_msg(msg),,
            None => (),
        }
    }

    fn get_proxy_for_msg<'a, 'b>(&'a self, msg: &'b Message) -> Option<&'a Proxy<'p>> 
    where
        'p: 'a,
    {
        let key = ProxyKey::from(msg);

        self.proxies.get(&key)
    }

    fn consume_msg(_msg: Message) {}
}
```

Which I (and devs I consulted on the Discord and IRC) think should compile. However, it doesn't and you get the following error:

```
error[E0623]: lifetime mismatch
  --> src/main.rs:67:9
   |
61 |     fn get_proxy_for_msg<'a, 'b>(&'a self, msg: &'b Message) -> Option<&'a Proxy<'p>> 
   |                                  --------       ----------- these two types are declared with different lifetimes...
...
67 |         self.proxies.get(&key)
   |         ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `msg` flows into `self` here

error: aborting due to previous error
```

i-e for some reason the lifetime of the `key` get associated with lifetime of the `Proxy` value we get from the `HashMap::get` call. I think it's likely a compiler bug. Even it is not, it'd be great to get better diagnostics/error message from the compiler for this so I can tell what exactly is going wrong here.

[Here](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=4ff71eafa906f51f8d45e8c9f59fa308) is the playground link for trying this out conveniently.

**NB**: If I change the code to make use of iterator, it works:

```rust
    fn get_proxy_for_msg<'a, 'b>(&'a self, msg: &'b Message) -> Option<&'a Proxy<'p>>
    where
        'p: 'a,
    {
        let key = ProxyKey::from(msg);

        self.proxies
            .iter()
            .find(|&(k, _)| &key == k)
            .map(|(_, v)| v)
    }
```

[Playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=958b8e29b7563369434e5618ebcafebb).

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

`rustc --version --verbose`:
```
rustc 1.48.0 (7eac88abb 2020-11-16)
binary: rustc
commit-hash: 7eac88abb2e57e752f3302f02be5f3ce3d7adfb4
commit-date: 2020-11-16
host: x86_64-unknown-linux-gnu
release: 1.48.0
LLVM version: 11.0
```

Reproducible on nightly (bb178237c 2020-12-25) as well.