Consider this code:
struct Updater<'m, S: Copy> {
store: &'m mut S,
}
impl<'m, S: Copy> Updater<'m, S> {
fn craft<T: Copy>(builder: &Vec<T>) {}
fn craft_reply<T: Copy>(update: Vec<T>)
{
Self::craft(&update)
}
}
It fails to compile on 1.50 and nightly 1.52.0-nightly (2021-03-10 f98721f) with:
Compiling playground v0.0.1 (/playground)
error[E0309]: the parameter type `S` may not live long enough
--> src/lib.rs:11:9
|
5 | impl<'m, S: Copy> Updater<'m, S> {
| -- help: consider adding an explicit lifetime bound...: `S: 'm +`
...
11 | Self::craft(&update)
| ^^^^^^^^^^^ ...so that the type `S` will meet its required lifetime bounds
error: aborting due to previous error
For more information about this error, try `rustc --explain E0309`.
error: could not compile `playground`
If I add a &self parameter to craft_reply(), it compiles. I cannot see what needs to be parameterised by the &self lifetime when it's not there, though.
Other things that work:
- using
impl<'m, S: Copy + 'm> (but I would have thought that S: 'm was implied by the reference to S requiring lifetime 'm)
- adding
where S: 'm to craft_reply()
- moving the associated functions out of the impl (but I like organising associated functions alongside the methods that use them)
- use
Updater::<'_, S>::craft instead of Self::craft inside the function body
Some comments from the Discord (user Yandros FR-ES):
Basically your Updater struct has an implicit bound of S : 'm to be well formed. In the "good old days", one had to write that bound explicitly in many many places. That was considered cumbersome, given that the existence of a &'m [mut] S type already implies this.
So the compiler was tweaked to elide this bound, when such as type (e.g., &'m [mut] S or a wrapper around it, such as Self) appears in the function signature.
Which does not happen in your craft_reply function. This means that within the body of the function, the compiler does not know if S : 'm holds, and you thus can't name the Self = Updater<'m, S> type which needs that bound to hold 😄
I'd consider that a bug (and I expect there to be some issue about it already): the outer impl block ought to already imply that S : 'm holds
(Thread starts here.)
Consider this code:
It fails to compile on 1.50 and nightly 1.52.0-nightly (2021-03-10 f98721f) with:
If I add a
&selfparameter tocraft_reply(), it compiles. I cannot see what needs to be parameterised by the&selflifetime when it's not there, though.Other things that work:
impl<'m, S: Copy + 'm>(but I would have thought thatS: 'mwas implied by the reference toSrequiring lifetime'm)where S: 'mtocraft_reply()Updater::<'_, S>::craftinstead ofSelf::craftinside the function bodySome comments from the Discord (user
Yandros FR-ES):(Thread starts here.)