Returning Trait Object Containing Reference

I'm trying to construct a lock for a Data Access Object, which will require a reference to the data base's connection. The issue I'm having is that I'm trying to return a struct with a reference to something from &self, and getting conflicting lifetimes; playground here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9599ba025aa0510dbfc3b5be38add384

The basic part is here:

impl Dao for MysqlDao {
    fn lock<'a>(&self) -> Box<dyn DaoLock + 'a> {
        Box::new(MysqlLock { arg: &self.arg })
    }
}

Which gives me the following error:

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
  --> src/lib.rs:22:35
   |
22 |         Box::new(MysqlLock { arg: &self.arg })
   |                                   ^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 21:5...
  --> src/lib.rs:21:5
   |
21 | /     fn lock<'a>(&self) -> Box<dyn DaoLock + 'a> {
22 | |         Box::new(MysqlLock { arg: &self.arg })
23 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/lib.rs:22:35
   |
22 |         Box::new(MysqlLock { arg: &self.arg })
   |                                   ^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the method body at 21:13...
  --> src/lib.rs:21:13
   |
21 |     fn lock<'a>(&self) -> Box<dyn DaoLock + 'a> {
   |             ^^
note: ...so that the expression is assignable
  --> src/lib.rs:22:9
   |
22 |         Box::new(MysqlLock { arg: &self.arg })
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: expected  `std::boxed::Box<(dyn DaoLock<'_> + 'a)>`
              found  `std::boxed::Box<dyn DaoLock<'_>>`

Any/all lifetime parameters might be wrong... I was just trying to get it work. Thanks!

Your lifetime annotation needs to be listed on &self as well, because you need to continue borrowing self as long as the trait object exists. Also, consider using a more meaningful name than ’a, like ’conn to indicate it’s the lifetime of the connection:

trait Dao {
    fn lock<'conn>(&'conn self) -> Box<dyn DaoLock + 'conn>;
}

I made these changes on your playground link and it compiles now:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a0e417606824fe4186d784924d3046d0

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.