How does borrowed data escapes outside of method? I'm truly confused

I'm not sure what I'm doing wrong.

I'm trying to create some failable traits that replicate a variety of Ops functionality. In my scenario I've created TryBuf (based off of Bytes's Buf trait), RefIntoTryBuf (generically get the TryBuf implementer), and TryPartialEq.

I have a generic implementer for TryPartialEq where as long as self and other implement RefIntoTryBuf everything should work.

Except it doesn't compile and I'm not sure why.

    Checking bbolt-nub v0.1.0 (/Users/abaxter/projects/better-bbolt/bbolt-nub)
error[E0521]: borrowed data escapes outside of method
   --> bbolt-nub/src/io/ops.rs:157:7
    |
136 |     fn try_eq(&self, other: &Rhs) -> crate::Result<bool, Self::Error> {
    |               -----
    |               |
    |               `self` is a reference that is only valid in the method body
    |               let's call the lifetime of this reference `'1`
...
157 | /       s_buf
158 | |         .try_advance(cmp_len)
159 | |         .change_context(OpsError::TryPartialEq)?;
    | |                                               ^
    | |                                               |
    | |_______________________________________________`self` escapes the method body here
    |                                                 argument requires that `'1` must outlive `'static`

error[E0521]: borrowed data escapes outside of method
   --> bbolt-nub/src/io/ops.rs:160:7
    |
136 |     fn try_eq(&self, other: &Rhs) -> crate::Result<bool, Self::Error> {
    |                      -----  - let's call the lifetime of this reference `'2`
    |                      |
    |                      `other` is a reference that is only valid in the method body
...
160 | /       o_buf
161 | |         .try_advance(cmp_len)
162 | |         .change_context(OpsError::TryPartialEq)?;
    | |                                               ^
    | |                                               |
    | |_______________________________________________`other` escapes the method body here
    |                                                 argument requires that `'2` must outlive `'static`

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

I don't see the escape, though?
try_eq<'a>(&'a self , other: &'a Rhs) create TryBufs with a lifetime of 'a.
The TryBufs get advanced, but nothing in the result is bound by 'a.

Annoyingly, what I'm doing works fine on the rust-playground.

My code is at better-bbolt/bbolt-nub at main · ambaxter/better-bbolt · GitHub

Notice that the error message is pointing at the change_context() call, which you left out of the playground.

I don't have a full explanation for the error, but I think it has something to do with

  • all of your errors are associated types, which means they can change depending on the types being used in the operations, and
  • change_context is a higher-order function,

together making it hard for the compiler to tell that the lifetime doesn't leak into the output. As a workaround, I would try replacing change_context with a plain match of the error and see if that is better behaved.

Oh my god. Thank you. This has been driving me insane for 2 days now.

I figured out the root cause! The Error associated type was missing the 'static lifetime requirement required by error-stack's Context trait.

1 Like