Skip to content

compiler fails to suggest move closure #61909

Closed
@nikomatsakis

Description

@nikomatsakis

This example gives a fairly opaque error message (playground):

pub struct VecMap<E, KeyFn> {
    data: Vec<E>,
    key_fn: KeyFn,
}

impl<E, K, KeyFn> VecMap<E, KeyFn>
where
    KeyFn: Fn(&E) -> K,
    K: Ord,
{
    fn iter<'k>(&'k self, key: &'k K) -> impl Iterator<Item = &'k E> {
        let (start, max) = (0, 0);
        self.data[start..max].iter().take_while(|elem| (self.key_fn)(elem) == *key)
    }
}

We currently get:

error[E0597]: `self` does not live long enough
  --> src/lib.rs:13:57
   |
11 |     fn iter<'k>(&'k self, key: &'k K) -> impl Iterator<Item = &'k E> {
   |             --                           --------------------------- opaque type requires that `self` is borrowed for `'k`
   |             |
   |             lifetime `'k` defined here
12 |         let (start, max) = (0, 0);
13 |         self.data[start..max].iter().take_while(|elem| (self.key_fn)(elem) == *key)
   |                                                 ------  ^^^^ borrowed value does not live long enough
   |                                                 |
   |                                                 value captured here
14 |     }
   |     - `self` dropped here while still borrowed

But as of 1.34.0 we used to get:

error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function
  --> /home/nmatsakis/tmp/foo.rs:13:49
   |
13 |         self.data[start..max].iter().take_while(|elem| (self.key_fn)(elem) == *key)
   |                                                 ^^^^^^  ---- `self` is borrowed here
   |                                                 |
   |                                                 may outlive borrowed value `self`
help: to force the closure to take ownership of `self` (and any other referenced variables), use the `move` keyword
   |
13 |         self.data[start..max].iter().take_while(move |elem| (self.key_fn)(elem) == *key)
   |                                                 ^^^^^^^^^^^

(There are also errors about key that are similar.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-NLLArea: Non-lexical lifetimes (NLL)A-closuresArea: Closures (`|…| { … }`)A-diagnosticsArea: Messages for errors, warnings, and lintsA-suggestion-diagnosticsArea: Suggestions generated by the compiler applied by `cargo fix`C-enhancementCategory: An issue proposing an enhancement or a PR with one.D-newcomer-roadblockDiagnostics: Confusing error or lint; hard to understand for new users.D-verboseDiagnostics: Too much output caused by a single piece of incorrect code.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