| //@aux-build:proc_macros.rs | |
| #![feature(try_blocks)] | |
| #![deny(clippy::try_err)] | |
| #![allow( | |
| clippy::unnecessary_wraps, | |
| clippy::needless_question_mark, | |
| clippy::needless_return_with_question_mark | |
| )] | |
| extern crate proc_macros; | |
| use proc_macros::{external, inline_macros}; | |
| use std::io; | |
| use std::task::Poll; | |
| // Tests that a simple case works | |
| // Should flag `Err(err)?` | |
| pub fn basic_test() -> Result<i32, i32> { | |
| let err: i32 = 1; | |
| // To avoid warnings during rustfix | |
| if true { | |
| return Err(err); | |
| //~^ try_err | |
| } | |
| Ok(0) | |
| } | |
| // Tests that `.into()` is added when appropriate | |
| pub fn into_test() -> Result<i32, i32> { | |
| let err: u8 = 1; | |
| // To avoid warnings during rustfix | |
| if true { | |
| return Err(err.into()); | |
| //~^ try_err | |
| } | |
| Ok(0) | |
| } | |
| // Tests that tries in general don't trigger the error | |
| pub fn negative_test() -> Result<i32, i32> { | |
| Ok(nested_error()? + 1) | |
| } | |
| // Tests that `.into()` isn't added when the error type | |
| // matches the surrounding closure's return type, even | |
| // when it doesn't match the surrounding function's. | |
| pub fn closure_matches_test() -> Result<i32, i32> { | |
| let res: Result<i32, i8> = Some(1) | |
| .into_iter() | |
| .map(|i| { | |
| let err: i8 = 1; | |
| // To avoid warnings during rustfix | |
| if true { | |
| return Err(err); | |
| //~^ try_err | |
| } | |
| Ok(i) | |
| }) | |
| .next() | |
| .unwrap(); | |
| Ok(res?) | |
| } | |
| // Tests that `.into()` isn't added when the error type | |
| // doesn't match the surrounding closure's return type. | |
| pub fn closure_into_test() -> Result<i32, i32> { | |
| let res: Result<i32, i16> = Some(1) | |
| .into_iter() | |
| .map(|i| { | |
| let err: i8 = 1; | |
| // To avoid warnings during rustfix | |
| if true { | |
| return Err(err.into()); | |
| //~^ try_err | |
| } | |
| Ok(i) | |
| }) | |
| .next() | |
| .unwrap(); | |
| Ok(res?) | |
| } | |
| fn nested_error() -> Result<i32, i32> { | |
| Ok(1) | |
| } | |
| #[inline_macros] | |
| fn calling_macro() -> Result<i32, i32> { | |
| // macro | |
| inline!( | |
| match $(Ok::<_, i32>(5)) { | |
| Ok(_) => 0, | |
| Err(_) => return Err(1), | |
| //~^ try_err | |
| } | |
| ); | |
| // `Err` arg is another macro | |
| inline!( | |
| match $(Ok::<_, i32>(5)) { | |
| Ok(_) => 0, | |
| Err(_) => return Err(inline!(1)), | |
| //~^ try_err | |
| } | |
| ); | |
| Ok(5) | |
| } | |
| // We don't want to lint in external macros | |
| external! { | |
| pub fn try_err_fn() -> Result<i32, i32> { | |
| let err: i32 = 1; | |
| // To avoid warnings during rustfix | |
| if true { Err(err)? } else { Ok(2) } | |
| } | |
| } | |
| fn main() {} | |
| #[inline_macros] | |
| pub fn macro_inside(fail: bool) -> Result<i32, String> { | |
| if fail { | |
| return Err(inline!(inline!(String::from("aasdfasdfasdfa")))); | |
| //~^ try_err | |
| } | |
| Ok(0) | |
| } | |
| pub fn poll_write(n: usize) -> Poll<io::Result<usize>> { | |
| if n == 0 { | |
| return Poll::Ready(Err(io::ErrorKind::WriteZero.into())) | |
| //~^ try_err | |
| } else if n == 1 { | |
| return Poll::Ready(Err(io::Error::new(io::ErrorKind::InvalidInput, "error"))) | |
| //~^ try_err | |
| }; | |
| Poll::Ready(Ok(n)) | |
| } | |
| pub fn poll_next(ready: bool) -> Poll<Option<io::Result<()>>> { | |
| if !ready { | |
| return Poll::Ready(Some(Err(io::ErrorKind::NotFound.into()))) | |
| //~^ try_err | |
| } | |
| Poll::Ready(None) | |
| } | |
| // Tests that `return` is not duplicated | |
| pub fn try_return(x: bool) -> Result<i32, i32> { | |
| if x { | |
| return Err(42); | |
| //~^ try_err | |
| } | |
| Ok(0) | |
| } | |
| // Test that the lint is suppressed in try block. | |
| pub fn try_block() -> Result<(), i32> { | |
| let _: Result<_, i32> = try { | |
| Err(1)?; | |
| }; | |
| Ok(()) | |
| } |