#![feature(try_blocks)] #![allow(unreachable_code)] #![allow(dead_code)] #![allow(clippy::unnecessary_wraps)] fn some_func(a: Option) -> Option { a?; a } fn some_other_func(a: Option) -> Option { if a.is_none() { return None; } else { return Some(0); } unreachable!() } pub enum SeemsOption { Some(T), None, } impl SeemsOption { pub fn is_none(&self) -> bool { match *self { SeemsOption::None => true, SeemsOption::Some(_) => false, } } } fn returns_something_similar_to_option(a: SeemsOption) -> SeemsOption { if a.is_none() { return SeemsOption::None; } a } pub struct CopyStruct { pub opt: Option, } impl CopyStruct { #[rustfmt::skip] pub fn func(&self) -> Option { (self.opt)?; self.opt?; let _ = Some(self.opt?); let _ = self.opt?; self.opt } } #[derive(Clone)] pub struct MoveStruct { pub opt: Option>, } impl MoveStruct { pub fn ref_func(&self) -> Option> { self.opt.as_ref()?; self.opt.clone() } pub fn mov_func_reuse(self) -> Option> { self.opt.as_ref()?; self.opt } pub fn mov_func_no_use(self) -> Option> { self.opt.as_ref()?; Some(Vec::new()) } pub fn if_let_ref_func(self) -> Option> { let v: &Vec<_> = self.opt.as_ref()?; Some(v.clone()) } pub fn if_let_mov_func(self) -> Option> { let v = self.opt?; Some(v) } } fn func() -> Option { fn f() -> Option { Some(String::new()) } f()?; Some(0) } fn func_returning_result() -> Result { Ok(1) } fn result_func(x: Result) -> Result { let _ = x?; 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::(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 { func_returning_result()?; Ok(1) } fn err_immediate_return_and_do_something() -> Result { func_returning_result()?; do_something(); Ok(1) } // No warning fn no_immediate_return() -> Result { if let Err(err) = func_returning_result() { do_something(); return Err(err); } Ok(1) } // No warning fn mixed_result_and_option() -> Option { if let Err(err) = func_returning_result() { return Some(err); } None } // No warning fn else_if_check() -> Result { 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 { 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) -> Option { let b: Option = try { if a.is_none() { return None; } 32 }; b.or(Some(128)) } fn issue6828_nested_body() -> Option { try { fn f2(a: Option) -> Option { a?; 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 { let _: Option = try { let Some(_) = Some(42) else { return None; }; 123 }; Some(42) } fn issue11983(option: &Option) -> 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, } 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 v = bar.foo.owned.clone()?; Some(()) }