| #![warn(clippy::iter_on_empty_collections)] | |
| #![allow(clippy::iter_next_slice)] | |
| fn array() { | |
| assert_eq!(std::iter::empty().next(), Option::<i32>::None); | |
| //~^ iter_on_empty_collections | |
| assert_eq!(std::iter::empty().next(), Option::<&mut i32>::None); | |
| //~^ iter_on_empty_collections | |
| assert_eq!(std::iter::empty().next(), Option::<&i32>::None); | |
| //~^ iter_on_empty_collections | |
| assert_eq!(std::iter::empty().next(), Option::<i32>::None); | |
| //~^ iter_on_empty_collections | |
| assert_eq!(std::iter::empty().next(), Option::<&mut i32>::None); | |
| //~^ iter_on_empty_collections | |
| assert_eq!(std::iter::empty().next(), Option::<&i32>::None); | |
| //~^ iter_on_empty_collections | |
| // Don't trigger on non-iter methods | |
| let _: Option<String> = None.clone(); | |
| let _: [String; 0] = [].clone(); | |
| // Don't trigger on match or if branches | |
| let _ = match 123 { | |
| 123 => [].iter(), | |
| _ => ["test"].iter(), | |
| }; | |
| let _ = if false { ["test"].iter() } else { [].iter() }; | |
| let smth = Some(vec![1, 2, 3]); | |
| // Don't trigger when the empty collection iter is relied upon for its concrete type | |
| // But do trigger if it is just an iterator, despite being an argument to a method | |
| for i in smth.as_ref().map_or([].iter(), |s| s.iter()).chain(std::iter::empty()) { | |
| //~^ iter_on_empty_collections | |
| println!("{i}"); | |
| } | |
| // Same as above, but for empty collection iters with extra layers | |
| for i in smth.as_ref().map_or({ [].iter() }, |s| s.iter()) { | |
| println!("{y}", y = i + 1); | |
| } | |
| // Same as above, but for regular function calls | |
| for i in Option::map_or(smth.as_ref(), [].iter(), |s| s.iter()) { | |
| println!("{i}"); | |
| } | |
| // Same as above, but when there are no predicates that mention the collection iter type. | |
| let mut iter = [34, 228, 35].iter(); | |
| let _ = std::mem::replace(&mut iter, [].iter()); | |
| } | |
| macro_rules! in_macros { | |
| () => { | |
| assert_eq!([].into_iter().next(), Option::<i32>::None); | |
| assert_eq!([].iter_mut().next(), Option::<&mut i32>::None); | |
| assert_eq!([].iter().next(), Option::<&i32>::None); | |
| assert_eq!(None.into_iter().next(), Option::<i32>::None); | |
| assert_eq!(None.iter_mut().next(), Option::<&mut i32>::None); | |
| assert_eq!(None.iter().next(), Option::<&i32>::None); | |
| }; | |
| } | |
| // Don't trigger on a `None` that isn't std's option | |
| mod custom_option { | |
| enum CustomOption { | |
| Some(i32), | |
| None, | |
| } | |
| impl CustomOption { | |
| fn iter(&self) {} | |
| fn iter_mut(&mut self) {} | |
| fn into_iter(self) {} | |
| } | |
| use CustomOption::*; | |
| pub fn custom_option() { | |
| None.iter(); | |
| None.iter_mut(); | |
| None.into_iter(); | |
| } | |
| } | |
| fn main() {} |