1

Here is a minimal reproducible sample:

use std::fmt::{self, Debug, Formatter};

pub trait Apple {}

impl Debug for dyn Apple {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str("Apple")
    }
}

struct Basket<'a> {
    apples: Vec<Box<dyn Apple + 'a>>,
}

impl<'a> Basket<'a> {
    fn f(&self) {
        let x = format!("{:?}", self.apples);
    }
}
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/lib.rs:17:17
   |
17 |         let x = format!("{:?}", self.apples);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined on the impl at 15:6...
  --> src/lib.rs:15:6
   |
15 | impl<'a> Basket<'a> {
   |      ^^
note: ...so that the types are compatible
  --> src/lib.rs:17:17
   |
17 |         let x = format!("{:?}", self.apples);
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected `(&std::vec::Vec<std::boxed::Box<dyn Apple>>,)`
              found `(&std::vec::Vec<std::boxed::Box<(dyn Apple + 'a)>>,)`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> src/lib.rs:17:33
   |
17 |         let x = format!("{:?}", self.apples);
   |                                 ^^^^^^^^^^^
   = note: expected `std::fmt::Debug`
              found `std::fmt::Debug`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

format! should only borrow self.apples for a very short period of time (only borrow during its formatting process). However, it even requires self.apples to have the 'static lifetime.

EDIT: Now I see why is that, after kind help from comments and other answers. According to @Shepmaster's suggestion, I move this part of content into an answer.

ch271828n
  • 15,854
  • 5
  • 53
  • 88
  • Hi, interesting, not sure if this might help https://stackoverflow.com/questions/41270052/cannot-infer-an-appropriate-lifetime-for-autoref-due-to-conflicting-requirements – IronMan Sep 21 '20 at 04:25
  • 1
    Your example is not reproducible. If I supply a `trait Req {}` I get ``error[E0277]: `dyn Req` doesn't implement `std::fmt::Debug` ``, not the one you claim. The problem is in some other code than what is in the question. – trent Sep 21 '20 at 04:40
  • 1
    Not reroduced on stable and nightly channels, both 2018 and 2015 edition: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=dabaa88484570326ef48780dbc5c63fd – test failed in 1.08s Sep 21 '20 at 05:42
  • Now reproducible, **question is edited!** Thanks friends! – ch271828n Sep 21 '20 at 05:43
  • @chuigda_whitegive Thanks for your "non-reproducibile" sample! I find out where I am wrong. – ch271828n Sep 21 '20 at 05:51
  • @trentcl Question edited. Thanks! – ch271828n Sep 21 '20 at 05:54
  • @IronMan Seems a little bit different. Question edited. Thanks! – ch271828n Sep 21 '20 at 05:54
  • It's great that you have the solution to your question! You should post it as an answer rather than an edit to your question and then potentially accept that answer. That way, the question shows up as solved in search results, people can vote on your answer, and your solution can be more helpful to future people with the same problem. – Shepmaster Sep 21 '20 at 16:38
  • @Shepmaster Thanks for your suggestion! I have moved it. – ch271828n Sep 22 '20 at 01:24

2 Answers2

4

Because of default trait object lifetimes, impl Debug for dyn Apple is shorthand for impl Debug for dyn Apple + 'static.

To write an implementation for non-'static trait objects, you can override this default lifetime with an explicit one:

impl<'a> Debug for dyn Apple + 'a
mbrubeck
  • 869
  • 6
  • 5
0

I see the reason after @chuigda_whitegive 's "non-reproducible" sample:

This is wrong

pub trait Apple {}

impl Debug for dyn Apple {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        f.write_str("Apple")
    }
}

but should do this

pub trait Apple: Debug {}

I still do not understand, why I should not impl Debug for dyn Apple. It compiles in other cases and it sounds reasonable ("when debugging, we should output the Apple string").


EDIT

Now I see how to do a two-letter modification to the original question. One more anonymous lifetime and this compiles:

use std::fmt::{Debug, Formatter};

pub trait Apple {}

impl Debug for dyn Apple + '_ {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        f.write_str("Apple")
    }
}

struct Basket<'a> {
    apples: Vec<Box<dyn Apple + 'a>>,
}

impl<'a> Basket<'a> {
    fn f(&self) {
        let x = format!("{:?}", self.apples);
    }
}

For why this is the case, please see @Matt Brubeck 's answer.

ch271828n
  • 15,854
  • 5
  • 53
  • 88