Skip to content

Implicit lifetime bound on impl type parameter not applied to associated function #83014

Closed
@detly

Description

@detly

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.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-implied-boundsArea: Implied bounds / inferred outlives-boundsC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-typesRelevant to the types team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions