Description
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 thatS: 'm
was implied by the reference toS
requiring lifetime'm
) - adding
where S: 'm
tocraft_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 ofSelf::craft
inside the function body
Some comments from the Discord (user Yandros FR-ES
):
Basically your
Updater
struct has an implicit bound ofS : 'm
to be well formed. In the "goodold 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 asSelf
) appears in the function signature.
Which does not happen in yourcraft_reply
function. This means that within the body of the function, the compiler does not know ifS : 'm
holds, and you thus can't name theSelf = 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 thatS : 'm
holds
(Thread starts here.)