Skip to content

return_position_impl_trait_in_trait can not express static lifetime bound #117210

Open
@mikialex

Description

@mikialex

Code

I tried this code:

pub trait Test {
  fn log(&self);
}

struct A;
impl Test for A {
  fn log(&self) {
    todo!()
  }
}


pub trait MakeTest {
  fn make(&self) -> impl Test + 'static;
}

struct MakeTestA;

impl MakeTest for MakeTestA {
  fn make(&self) -> impl Test + 'static {
    A
  }
}

fn test(maker: impl MakeTest) -> impl Test + 'static {
  maker.make()
}

I expected to see this happen: compiled successfully

Instead, this happened: compiled with error

error[E0597]: `maker` does not live long enough
  --> src/lib.rs:26:3
   |
25 | fn test(maker: impl MakeTest) -> impl Test + 'static {
   |         ----- binding `maker` declared here
26 |   maker.make()
   |   ^^^^^-------
   |   |
   |   borrowed value does not live long enough
   |   argument requires that `maker` is borrowed for `'static`
27 | }
   | - `maker` dropped here while still borrowed

error[E0310]: the parameter type `impl MakeTest` may not live long enough
  --> src/lib.rs:26:3
   |
26 |   maker.make()
   |   ^^^^^^^^^^^^
   |   |
   |   the parameter type `impl MakeTest` must be valid for the static lifetime...
   |   ...so that the type `impl MakeTest` will meet its required lifetime bounds
   |
help: consider adding an explicit lifetime bound
   |
25 | fn test(maker: impl MakeTest + 'static) -> impl Test + 'static {
   |                              +++++++++

Some errors have detailed explanations: E0310, E0597.
For more information about an error, try `rustc --explain E0310`.

Version it worked on

It worked on nightly-2023-06-12 (at least, not the most recent one).

Version with regression

I'm testing in recent nightly 2023-10-21

Other info

I'm updating my project's nightly version and find it not work. I'm not sure if it's a real regression or if the return_position_impl_trait_in_trait's design has been changed.

Intuitively, I thought the above example should as the same as this one which works fine:

pub trait Test {
  fn log(&self);
}

struct A;
impl Test for A {
  fn log(&self) {
    todo!()
  }
}

pub trait MakeTest {
  type Test: Test + 'static;
  fn make(&self) -> Self::Test;
}

struct MakeTestA;

impl MakeTest for MakeTestA {
  type Test = A;

  fn make(&self) -> Self::Test {
    A
  }
}

fn test(maker: impl MakeTest) -> impl Test + 'static {
  maker.make()
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.C-bugCategory: This is a bug.F-return_position_impl_trait_in_trait`#![feature(return_position_impl_trait_in_trait)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions