Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nested impl trait in return position (ITRP) forces argument lifetimes to be 'static #115849

Closed
ajwerner opened this issue Sep 14, 2023 · 2 comments
Labels
C-bug Category: This is a bug.

Comments

@ajwerner
Copy link

I tried this code (playground):

trait Goal {}

impl Goal for () {}

struct Holder<'a, T: ?Sized> {
    r: &'a T,
}

struct StaticHolder<T> {
    t: T,
}

fn make_goal<'a, T: 'a>(_s: &'a StaticHolder<T>) -> impl Goal + 'static {
    ()
}

fn outer() -> impl Goal {
    let s = String::from("hello world");
    let h = Holder { r: s.as_str() };
    let s = StaticHolder { t: h };
    make_goal(&s)
}

fn main() {
    outer();
}

I expected it to work. The value returned from make_goal is impl Goal + 'static, so i should be able to return it from outer.

Instead, this happened:

error[[E0597]](https://doc.rust-lang.org/stable/error_codes/E0597.html): `s` does not live long enough
  --> src/main.rs:19:25
   |
18 |     let s = String::from("hello world");
   |         - binding `s` declared here
19 |     let h = Holder { r: s.as_str() };
   |                         ^^^^^^^^^^ borrowed value does not live long enough
20 |     let s = StaticHolder { t: h };
21 |     make_goal(&s)
   |     ------------- argument requires that `s` is borrowed for `'static`
22 | }
   | - `s` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

Meta

I compiled in the playground using 1.72.0 and 1.74.0.

@ajwerner ajwerner added the C-bug Category: This is a bug. label Sep 14, 2023
@rustbot rustbot added the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 14, 2023
@traviscross
Copy link
Contributor

traviscross commented Sep 16, 2023

Here's a minimized version:

struct Ref<'a>(&'a ());

fn capture<'o, T>(_x: T) -> impl Send + 'o {}

fn outlives<'o, T: 'o>(_t: T) {}
fn test<'o>(x: ()) -> impl Send + 'o {
    outlives::<'o, _>(capture::<'o, Ref<'_>>(Ref(&x))); // OK.
    capture::<'o, Ref<'_>>(Ref(&x))
//                             ^^
// ERROR: borrowed value does not live long enough.
}

Playground link

This is another manifestation of #42940.

As it applies here, it's not that the argument lifetimes need to be 'static, it's that they have to be able to be named in a way that's valid outside of the function. Consider, e.g., that this is accepted:

trait Captures<T> {}
impl<T, U: ?Sized> Captures<T> for U {}

struct Ref<'a>(&'a ());

fn capture<'o, T>(_x: T) -> impl Send + 'o {}

fn outlives<'o, T: 'o>(_t: T) {}
fn test<'o, 'b>(x: &'b ()) -> impl Send + Captures<&'b ()> + 'o {
    outlives::<'o, _>(capture::<'o, Ref<'b>>(Ref(x))); // OK.
    capture::<'o, Ref<'b>>(Ref(x)) // OK.
}

Playground link

A full analysis of this issue is available here.

@aliemjay
Copy link
Member

This is another manifestation of #42940.

Agree. Closing as a duplicate of #42940. Thanks for reporting!

@aliemjay aliemjay closed this as not planned Won't fix, can't repro, duplicate, stale Sep 16, 2023
@fmease fmease removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

5 participants