Repository: rust
Issue: Mixing `'static` and `'this` with iterators or vectors doesn't correctly shorten lifetime to the workable shorter version.
Labels: A-lifetimes,T-compiler,C-bug,T-types

<!--
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.
-->

This is either a borrow checker bug, a library bug, or a diagnostics bug. I don't know which one.

I tried this code:

```rust
use std::collections::HashMap;
use std::collections::BTreeSet;

struct DataRoot {
    entries: Vec<Entry>
}

impl DataRoot {
    pub fn columns<'this>(&'this self) -> impl Iterator<Item = &'this str> {
        let mut dynamic_columns = BTreeSet::new();

        for entry in &self.entries {
            dynamic_columns.extend(entry.dynamic_coluimns());
        }

        // This combines 'this and 'static, and I want the result to be 'this
        // (which is *shorter*)
        // This doesn't work for some reason, why? And what can be done about it?
        Entry::leading_columns()
            .chain(dynamic_columns.into_iter())
            .chain(Entry::trailing_columns())
    }

    pub fn columns2<'this>(&'this self) -> impl Iterator<Item = &'this str> {
        let mut dynamic_columns = BTreeSet::new();

        for entry in &self.entries {
            dynamic_columns.extend(entry.dynamic_coluimns());
        }

        // This doesn't work either!
        let mut values = vec![];
        values.extend(Entry::leading_columns());
        values.extend(dynamic_columns.into_iter());
        values.extend(Entry::trailing_columns());
        values.into_iter()
    }


    pub fn columns3(&self) -> impl Iterator<Item = String> {
        let mut dynamic_columns = BTreeSet::new();

        for entry in &self.entries {
            dynamic_columns.extend(entry.dynamic_coluimns());
        }

        // Okay, it makes no sense that this doesn't work.
        // * I turned it into String, so it is owned
        // * I collected into a vec and then returned that (which normally works)
        let v: Vec<_> = Entry::leading_columns()
            .chain(dynamic_columns.into_iter())
            .chain(Entry::trailing_columns())
            .map(|v| v.to_string()).collect();
        v.into_iter()
    }
}

struct Entry {
    // Various fixed fields here...

    // Other fields that are specific to this case, capture them dynamically
    // #[serde(flatten)]
    other: HashMap<String, String>
}

impl Entry {
    fn leading_columns() -> impl Iterator<Item = &'static str> {
        ["Crate name", "URL", "Maintained", "License", "Std"].into_iter()
    }

    fn dynamic_coluimns(&self) -> impl Iterator<Item = &str> {
        self.other.keys().map(|s| s.as_str())
    }

    fn trailing_columns() -> impl Iterator<Item = &'static str> {
        ["Notes"].into_iter()
    }
}
```

* [Playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9a835ca6bf717b5b893c00987c1aa968)
* [URLO discussion](https://users.rust-lang.org/t/mixing-static-and-this-in-iterator-chain/120370)

I expected to see this happen: One of the following:

* All three cases works, and `'static` is shortened to `'this`
* The compiler errors nudge you towards a solution to the issue rather than suggesting incorrect things like adding `+ 'this`

Ideally (if this can't be fixed so that it works) the compiler error should nudge you in the direction that [jendrikw](https://users.rust-lang.org/u/jendrikw) suggested on URLO:

```rust
Entry::leading_columns().map(|s: &'static str| -> &'this str {s})
    .chain(dynamic_columns.into_iter())
    .chain(Entry::trailing_columns().map(|s: &'static str| -> &'this str {s}))
```

Instead, this happened:

```rust
   Compiling playground v0.0.1 (/playground)
error: lifetime may not live long enough
  --> src/lib.rs:19:9
   |
9  |       pub fn columns<'this>(&'this self) -> impl Iterator<Item = &'this str> {
   |                      ----- lifetime `'this` defined here
...
19 | /         Entry::leading_columns()
20 | |             .chain(dynamic_columns.into_iter())
21 | |             .chain(Entry::trailing_columns())
   | |_____________________________________________^ returning this value requires that `'this` must outlive `'static`
   |
help: to declare that `impl Iterator<Item = &'this str>` captures data from argument `self`, you can add an explicit `'this` lifetime bound
   |
9  |     pub fn columns<'this>(&'this self) -> impl Iterator<Item = &'this str> + 'this {
   |                                                                            +++++++

error[E0521]: borrowed data escapes outside of method
  --> src/lib.rs:27:22
   |
24 |     pub fn columns2<'this>(&'this self) -> impl Iterator<Item = &'this str> {
   |                     -----  ----------- `self` is a reference that is only valid in the method body
   |                     |
   |                     lifetime `'this` defined here
...
27 |         for entry in &self.entries {
   |                      ^^^^^^^^^^^^^
   |                      |
   |                      `self` escapes the method body here
   |                      argument requires that `'this` must outlive `'static`

error[E0521]: borrowed data escapes outside of method
  --> src/lib.rs:43:22
   |
40 |     pub fn columns3(&self) -> impl Iterator<Item = String> {
   |                     -----
   |                     |
   |                     `self` is a reference that is only valid in the method body
   |                     let's call the lifetime of this reference `'1`
...
43 |         for entry in &self.entries {
   |                      ^^^^^^^^^^^^^
   |                      |
   |                      `self` escapes the method body here
   |                      argument requires that `'1` must outlive `'static`

For more information about this error, try `rustc --explain E0521`.
error: could not compile `playground` (lib) due to 3 previous errors
```

### 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.82.0 (f6e511eec 2024-10-15)
binary: rustc
commit-hash: f6e511eec7342f59a25f7c0534f1dbea00d01b14
commit-date: 2024-10-15
host: x86_64-unknown-linux-gnu
release: 1.82.0
LLVM version: 19.1.1
```

<!--
Include a backtrace in the code block by setting `RUST_BACKTRACE=1` in your
environment. E.g. `RUST_BACKTRACE=1 cargo build`.
-->
<details><summary>Backtrace</summary>
<p>
No crash, so not applicable?
</p>
</details>