Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
estebank opened this issue May 31, 2021 · 0 comments · Fixed by #117914
Closed
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@estebank
Copy link
Contributor

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/

@estebank estebank added A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. labels May 31, 2021
estebank added a commit to estebank/rust that referenced this issue Nov 14, 2023
When we encounter a function with a return type that has an anonymous
lifetime with no argument to borrow from, besides suggesting the
`'static` lifetime we now also suggest changing the arguments to be
borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
estebank added a commit to estebank/rust that referenced this issue Nov 14, 2023
When we encounter a function with a return type that has an anonymous
lifetime with no argument to borrow from, besides suggesting the
`'static` lifetime we now also suggest changing the arguments to be
borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
estebank added a commit to estebank/rust that referenced this issue Nov 15, 2023
When we encounter a function with a return type that has an anonymous
lifetime with no argument to borrow from, besides suggesting the
`'static` lifetime we now also suggest changing the arguments to be
borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
estebank added a commit to estebank/rust that referenced this issue Nov 16, 2023
When we encounter a function with a return type that has an anonymous
lifetime with no argument to borrow from, besides suggesting the
`'static` lifetime we now also suggest changing the arguments to be
borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Dec 12, 2023
On borrow return type, suggest borrowing from arg or owned return type

When we encounter a function with a return type that has an anonymous lifetime with no argument to borrow from, besides suggesting the `'static` lifetime we now also suggest changing the arguments to be borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
@bors bors closed this as completed in b7a23bc Dec 12, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Dec 12, 2023
Rollup merge of rust-lang#117914 - estebank:issue-85843, r=wesleywiser

On borrow return type, suggest borrowing from arg or owned return type

When we encounter a function with a return type that has an anonymous lifetime with no argument to borrow from, besides suggesting the `'static` lifetime we now also suggest changing the arguments to be borrows or changing the return type to be an owned type.

```
error[E0106]: missing lifetime specifier
  --> $DIR/variadic-ffi-6.rs:7:6
   |
LL | ) -> &usize {
   |      ^ expected named lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
   |
LL | ) -> &'static usize {
   |       +++++++
help: instead, you are more likely to want to change one of the arguments to be borrowed...
   |
LL |     x: &usize,
   |        +
help: ...or alternatively, to want to return an owned value
   |
LL - ) -> &usize {
LL + ) -> usize {
   |
```

Fix rust-lang#85843.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions D-newcomer-roadblock Diagnostics: Confusing error or lint; hard to understand for new users. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant