blob: a44c46c145c6cb5edaac3e99a3c6ea313a4361fd [file] [log] [blame]
#![allow(dead_code)]
#![warn(clippy::manual_filter_map)]
#![allow(clippy::redundant_closure)] // FIXME suggestion may have redundant closure
#![allow(clippy::useless_vec)]
#![allow(clippy::struct_field_names)]
fn main() {
// is_some(), unwrap()
let _ = (0..).filter_map(|a| to_opt(a));
// ref pattern, expect()
let _ = (0..).filter_map(|a| to_opt(a));
// is_ok(), unwrap_or()
let _ = (0..).filter_map(|a| to_res(a).ok());
let _ = (1..5)
.filter_map(|y| *to_ref(to_opt(y)));
let _ = (1..5)
.filter_map(|y| *to_ref(to_opt(y)));
let _ = (1..5)
.filter_map(|y| to_ref(to_res(y)).ok());
let _ = (1..5)
.filter_map(|y| to_ref(to_res(y)).ok());
}
#[rustfmt::skip]
fn simple_equal() {
iter::<Option<&u8>>().find_map(|x| x.cloned());
iter::<&Option<&u8>>().find_map(|x| x.cloned());
iter::<&Option<String>>().find_map(|x| x.as_deref());
iter::<Option<&String>>().find_map(|y| to_ref(y).cloned());
iter::<Result<u8, ()>>().find_map(|x| x.ok());
iter::<&Result<u8, ()>>().find_map(|x| x.ok());
iter::<&&Result<u8, ()>>().find_map(|x| x.ok());
iter::<Result<&u8, ()>>().find_map(|x| x.cloned().ok());
iter::<&Result<&u8, ()>>().find_map(|x| x.cloned().ok());
iter::<&Result<String, ()>>().find_map(|x| x.as_deref().ok());
iter::<Result<&String, ()>>().find_map(|y| to_ref(y).cloned().ok());
}
fn no_lint() {
// no shared code
let _ = (0..).filter(|n| *n > 1).map(|n| n + 1);
// very close but different since filter() provides a reference
let _ = (0..).filter(|n| to_opt(n).is_some()).map(|a| to_opt(a).unwrap());
// similar but different
let _ = (0..).filter(|n| to_opt(n).is_some()).map(|n| to_res(n).unwrap());
let _ = (0..)
.filter(|n| to_opt(n).map(|n| n + 1).is_some())
.map(|a| to_opt(a).unwrap());
}
fn iter<T>() -> impl Iterator<Item = T> {
std::iter::empty()
}
fn to_opt<T>(_: T) -> Option<T> {
unimplemented!()
}
fn to_res<T>(_: T) -> Result<T, ()> {
unimplemented!()
}
fn to_ref<'a, T>(_: T) -> &'a T {
unimplemented!()
}
struct Issue8920<'a> {
option_field: Option<String>,
result_field: Result<String, ()>,
ref_field: Option<&'a usize>,
}
fn issue_8920() {
let mut vec = vec![Issue8920 {
option_field: Some(String::from("str")),
result_field: Ok(String::from("str")),
ref_field: Some(&1),
}];
let _ = vec
.iter()
.filter_map(|f| f.option_field.clone());
let _ = vec
.iter()
.filter_map(|f| f.ref_field.cloned());
let _ = vec
.iter()
.filter_map(|f| f.ref_field.copied());
let _ = vec
.iter()
.filter_map(|f| f.result_field.clone().ok());
let _ = vec
.iter()
.filter_map(|f| f.result_field.as_ref().ok());
let _ = vec
.iter()
.filter_map(|f| f.result_field.as_deref().ok());
let _ = vec
.iter_mut()
.filter_map(|f| f.result_field.as_mut().ok());
let _ = vec
.iter_mut()
.filter_map(|f| f.result_field.as_deref_mut().ok());
let _ = vec
.iter()
.filter_map(|f| f.result_field.to_owned().ok());
}
fn issue8010() {
#[derive(Clone)]
enum Enum {
A(i32),
B,
}
let iter = [Enum::A(123), Enum::B].into_iter();
let _x = iter.clone().filter_map(|x| match x { Enum::A(s) => Some(s), _ => None });
let _x = iter.clone().filter(|x| matches!(x, Enum::B)).map(|x| match x {
Enum::A(s) => s,
_ => unreachable!(),
});
let _x = iter
.clone()
.filter_map(|x| match x { Enum::A(s) => Some(s), _ => None });
#[allow(clippy::unused_unit)]
let _x = iter
.clone()
.filter(|x| matches!(x, Enum::B))
.map(|x| if let Enum::B = x { () } else { unreachable!() });
}