| #![feature(try_blocks)] |
| #![allow(unreachable_code)] |
| #![allow(dead_code)] |
| #![allow(clippy::unnecessary_wraps)] |
| |
| fn some_func(a: Option<u32>) -> Option<u32> { |
| if a.is_none() { |
| return None; |
| } |
| |
| a |
| } |
| |
| fn some_other_func(a: Option<u32>) -> Option<u32> { |
| if a.is_none() { |
| return None; |
| } else { |
| return Some(0); |
| } |
| unreachable!() |
| } |
| |
| pub enum SeemsOption<T> { |
| Some(T), |
| None, |
| } |
| |
| impl<T> SeemsOption<T> { |
| pub fn is_none(&self) -> bool { |
| match *self { |
| SeemsOption::None => true, |
| SeemsOption::Some(_) => false, |
| } |
| } |
| } |
| |
| fn returns_something_similar_to_option(a: SeemsOption<u32>) -> SeemsOption<u32> { |
| if a.is_none() { |
| return SeemsOption::None; |
| } |
| |
| a |
| } |
| |
| pub struct CopyStruct { |
| pub opt: Option<u32>, |
| } |
| |
| impl CopyStruct { |
| #[rustfmt::skip] |
| pub fn func(&self) -> Option<u32> { |
| if (self.opt).is_none() { |
| return None; |
| } |
| |
| if self.opt.is_none() { |
| return None |
| } |
| |
| let _ = if self.opt.is_none() { |
| return None; |
| } else { |
| self.opt |
| }; |
| |
| let _ = if let Some(x) = self.opt { |
| x |
| } else { |
| return None; |
| }; |
| |
| self.opt |
| } |
| } |
| |
| #[derive(Clone)] |
| pub struct MoveStruct { |
| pub opt: Option<Vec<u32>>, |
| } |
| |
| impl MoveStruct { |
| pub fn ref_func(&self) -> Option<Vec<u32>> { |
| if self.opt.is_none() { |
| return None; |
| } |
| |
| self.opt.clone() |
| } |
| |
| pub fn mov_func_reuse(self) -> Option<Vec<u32>> { |
| if self.opt.is_none() { |
| return None; |
| } |
| |
| self.opt |
| } |
| |
| pub fn mov_func_no_use(self) -> Option<Vec<u32>> { |
| if self.opt.is_none() { |
| return None; |
| } |
| Some(Vec::new()) |
| } |
| |
| pub fn if_let_ref_func(self) -> Option<Vec<u32>> { |
| let v: &Vec<_> = if let Some(ref v) = self.opt { |
| v |
| } else { |
| return None; |
| }; |
| |
| Some(v.clone()) |
| } |
| |
| pub fn if_let_mov_func(self) -> Option<Vec<u32>> { |
| let v = if let Some(v) = self.opt { |
| v |
| } else { |
| return None; |
| }; |
| |
| Some(v) |
| } |
| } |
| |
| fn func() -> Option<i32> { |
| fn f() -> Option<String> { |
| Some(String::new()) |
| } |
| |
| if f().is_none() { |
| return None; |
| } |
| |
| Some(0) |
| } |
| |
| fn func_returning_result() -> Result<i32, i32> { |
| Ok(1) |
| } |
| |
| fn result_func(x: Result<i32, i32>) -> Result<i32, i32> { |
| let _ = if let Ok(x) = x { x } else { return x }; |
| |
| if x.is_err() { |
| return x; |
| } |
| |
| // No warning |
| let y = if let Ok(x) = x { |
| x |
| } else { |
| return Err(0); |
| }; |
| |
| // issue #7859 |
| // no warning |
| let _ = if let Ok(x) = func_returning_result() { |
| x |
| } else { |
| return Err(0); |
| }; |
| |
| // no warning |
| if func_returning_result().is_err() { |
| return func_returning_result(); |
| } |
| |
| // no warning |
| let _ = if let Err(e) = x { Err(e) } else { Ok(0) }; |
| |
| // issue #11283 |
| // no warning |
| #[warn(clippy::question_mark_used)] |
| { |
| if let Err(err) = Ok(()) { |
| return Err(err); |
| } |
| |
| if Err::<i32, _>(0).is_err() { |
| return Err(0); |
| } else { |
| return Ok(0); |
| } |
| |
| unreachable!() |
| } |
| |
| Ok(y) |
| } |
| |
| // see issue #8019 |
| pub enum NotOption { |
| None, |
| First, |
| AfterFirst, |
| } |
| |
| fn obj(_: i32) -> Result<(), NotOption> { |
| Err(NotOption::First) |
| } |
| |
| fn f() -> NotOption { |
| if obj(2).is_err() { |
| return NotOption::None; |
| } |
| NotOption::First |
| } |
| |
| fn do_something() {} |
| |
| fn err_immediate_return() -> Result<i32, i32> { |
| if let Err(err) = func_returning_result() { |
| return Err(err); |
| } |
| Ok(1) |
| } |
| |
| fn err_immediate_return_and_do_something() -> Result<i32, i32> { |
| if let Err(err) = func_returning_result() { |
| return Err(err); |
| } |
| do_something(); |
| Ok(1) |
| } |
| |
| // No warning |
| fn no_immediate_return() -> Result<i32, i32> { |
| if let Err(err) = func_returning_result() { |
| do_something(); |
| return Err(err); |
| } |
| Ok(1) |
| } |
| |
| // No warning |
| fn mixed_result_and_option() -> Option<i32> { |
| if let Err(err) = func_returning_result() { |
| return Some(err); |
| } |
| None |
| } |
| |
| // No warning |
| fn else_if_check() -> Result<i32, i32> { |
| if true { |
| Ok(1) |
| } else if let Err(e) = func_returning_result() { |
| Err(e) |
| } else { |
| Err(-1) |
| } |
| } |
| |
| // No warning |
| #[allow(clippy::manual_map)] |
| #[rustfmt::skip] |
| fn option_map() -> Option<bool> { |
| if let Some(a) = Some(false) { |
| Some(!a) |
| } else { |
| None |
| } |
| } |
| |
| pub struct PatternedError { |
| flag: bool, |
| } |
| |
| // No warning |
| fn pattern() -> Result<(), PatternedError> { |
| let res = Ok(()); |
| |
| if let Err(err @ PatternedError { flag: true }) = res { |
| return Err(err); |
| } |
| |
| res |
| } |
| |
| fn main() {} |
| |
| // `?` is not the same as `return None;` if inside of a try block |
| fn issue8628(a: Option<u32>) -> Option<u32> { |
| let b: Option<u32> = try { |
| if a.is_none() { |
| return None; |
| } |
| 32 |
| }; |
| b.or(Some(128)) |
| } |
| |
| fn issue6828_nested_body() -> Option<u32> { |
| try { |
| fn f2(a: Option<i32>) -> Option<i32> { |
| if a.is_none() { |
| return None; |
| // do lint here, the outer `try` is not relevant here |
| // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867 |
| } |
| Some(32) |
| } |
| 123 |
| } |
| } |
| |
| // should not lint, `?` operator not available in const context |
| const fn issue9175(option: Option<()>) -> Option<()> { |
| if option.is_none() { |
| return None; |
| } |
| //stuff |
| Some(()) |
| } |
| |
| fn issue12337() -> Option<i32> { |
| let _: Option<i32> = try { |
| let Some(_) = Some(42) else { |
| return None; |
| }; |
| 123 |
| }; |
| Some(42) |
| } |
| |
| fn issue11983(option: &Option<String>) -> Option<()> { |
| // Don't lint, `&Option` dose not impl `Try`. |
| let Some(v) = option else { return None }; |
| |
| let opt = Some(String::new()); |
| // Don't lint, `branch` method in `Try` takes ownership of `opt`, |
| // and `(&opt)?` also doesn't work since it's `&Option`. |
| let Some(v) = &opt else { return None }; |
| let mov = opt; |
| |
| Some(()) |
| } |
| |
| struct Foo { |
| owned: Option<String>, |
| } |
| struct Bar { |
| foo: Foo, |
| } |
| #[allow(clippy::disallowed_names)] |
| fn issue12412(foo: &Foo, bar: &Bar) -> Option<()> { |
| // Don't lint, `owned` is behind a shared reference. |
| let Some(v) = &foo.owned else { |
| return None; |
| }; |
| // Don't lint, `owned` is behind a shared reference. |
| let Some(v) = &bar.foo.owned else { |
| return None; |
| }; |
| // lint |
| let Some(v) = bar.foo.owned.clone() else { |
| return None; |
| }; |
| Some(()) |
| } |