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

incorrect suggestion for while_let_on_iterator #1924

Closed
tspiteri opened this issue Aug 4, 2017 · 3 comments · Fixed by #6966
Closed

incorrect suggestion for while_let_on_iterator #1924

tspiteri opened this issue Aug 4, 2017 · 3 comments · Fixed by #6966
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. S-needs-discussion Status: Needs further discussion before merging or work can be started T-middle Type: Probably requires verifiying types

Comments

@tspiteri
Copy link
Contributor

tspiteri commented Aug 4, 2017

For the snippet below, clippy suggests changing while let Some(i) = self.s.next() into for i in self.s { .. }, but that results in a "cannot move out of borrowed content" error. In this case, for i in &mut self.s { .. } would work.

pub struct S {
    i: i32,
}
impl Iterator for S {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        if self.i > 0 {
            self.i -= 1;
            Some(self.i)
        } else {
            None
        }
    }
}

pub struct T {
    s: S,
}
impl Iterator for T {
    type Item = i32;
    fn next(&mut self) -> Option<i32> {
        while let Some(i) = self.s.next() {
            if i < 3 || i > 7 {
                return Some(i);
            }
        }
        None
    }
}

#[test]
fn test() {
    let s = S { i: 9 };
    let mut t = T { s };
    assert_eq!(t.next(), Some(8));
    assert_eq!(t.next(), Some(2));
    assert_eq!(t.next(), Some(1));
    assert_eq!(t.next(), Some(0));
    assert_eq!(t.next(), None);
}
@oli-obk oli-obk added the S-needs-discussion Status: Needs further discussion before merging or work can be started label Aug 4, 2017
@oli-obk
Copy link
Contributor

oli-obk commented Aug 4, 2017

Hmm... I can't repro on master. @llogiq was this fixed by your PR? Should we extend it to support this case and suggest a for loop over &mut self.s?

Imo the while let loop is better here, since it clearly shows the intent that not all elements of the iterator are consumed.

@oli-obk
Copy link
Contributor

oli-obk commented Aug 4, 2017

Actually... We should probably detect this very pattern and suggest self.s.filter(|i| *i < 3 || *i > 7).next()

@oli-obk oli-obk added E-medium Call for participation: Medium difficulty level problem and requires some initial experience. A-lint Area: New lints T-middle Type: Probably requires verifiying types labels Aug 4, 2017
@tspiteri
Copy link
Contributor Author

tspiteri commented Aug 4, 2017

About the filter suggestion:

  1. It would need to be (&mut self.s).filter rather than self.s.filter, otherwise you get "cannot move out of borrowed content".
  2. While that would work in this reduced test case, it would not work if for example the filter expression uses another member of self, as self would be borrowed mutably and the filter body would try to borrow self again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. S-needs-discussion Status: Needs further discussion before merging or work can be started T-middle Type: Probably requires verifiying types
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants