Confused about lifetimes in `write_all_vectored`

The signature of the write_all_vectored method in AsyncWriteExt looks like,

 write_all_vectored(
    &'a mut self,
    bufs: &'a mut [IoSlice<'a>]
) -> WriteAllVectored<'a, Self>

When I try to use this, I get very confusing messages about my vector of slices not living long enough, but simultaneously being borrowed at the point where it's dropped. Discussing this with others, the impression I got was that it was a mistake for all these parameters to be using the same lifetime (the underlying poll version does not constrain the lifetimes) but I find it unlikely that a problem this overt could have got through testing and review.

Can anyone explain what's going on here? Is it possible to use this method in a dynamic-length async context without running into lifetime problems?

1 Like

For reference, the lifetimes have been like that since this method was first introduced:

https://github.com/rust-lang/futures-rs/pull/1741

I agree that the repeated use of 'a in argument position (especially &'a mut [IoSlice<'a>]) is a red flag. I guess there could be some reason that it's appropriate in this case, but I doubt it. In any case, it wasn't commented on in the PR.

Edit: One reason to think that reusing the same lifetime parameter here is not appropriate is that the corresponding (unstable) std method uses three different lifetime parameters.

1 Like

You should report this as a bug. The write_vectored in Tokio also does it correctly.

3 Likes

Is there any reason Tokio's write_vectored uses 'a twice in the arguments rather than having three lifetime parameters? That signature still seems unnecessarily restrictive to me.

Due to lifetime shortening, two and three lifetimes are exactly the same.

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.