Skip to content

Suggest borrowing from argument when return type is a borrow without an applicable lifetime #85843

Closed
@estebank

Description

@estebank

Given:

pub struct Super {
    pub super_name: String,
    pub real_name: String,
    pub power: u16,
}

pub struct Group {
    pub name: String,
    pub members: Vec<Super>,
}

pub fn find_largest_group(groups: Vec<Group>) -> Option<&Group> {
    groups
        .iter()
        .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
}

we currently display:

error[E0106]: missing lifetime specifier
 --> src/solutions.rs:3:57
  |
3 | pub fn find_largest_group(groups: Vec<Group>) -> Option<&Group> {
  |                                                         ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
  |
3 | pub fn find_largest_group(groups: Vec<Group>) -> Option<&'static Group> {
  |                                                         ^^^^^^^^

Suggesting 'static lifetimes is usually not what we want to do, and certainly not as the only suggestion.

Someone might try instead to write

pub fn find_largest_group<'a>(groups: Vec<Group>) -> Option<&'a Group> {
    groups
        .iter()
        .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
}

which would display

error[E0515]: cannot return value referencing function parameter `groups`
  --> src/foo.rs:13:5
   |
13 |       groups
   |       ^-----
   |       |
   |  _____`groups` is borrowed here
   | |
14 | |         .iter()
15 | |         .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
   | |____________________________________________________________________________________^ returns a value referencing data owned by the current function

In both cases we should (somehow) suggest the user to borrow the argument:

pub fn find_largest_group(groups: &Vec<Group>) -> Option<&Group> {
    groups
        .iter()
        .max_by(|&g1, &g2| g1.members.len().partial_cmp(&g2.members.len()).unwrap())
}

For the first step, it might be difficult, we might have to do some analysis we are not currently doing to figure out from which argument we should be borrowing from. For the second step we already know that groups is borrowed and something from it is being returned, which should make suggesting to change the argument straightforward.

Taken from https://blog.frankel.ch/start-rust/1/

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsD-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.T-compilerRelevant to the compiler 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