| //@aux-build:unnecessary_unwrap_unchecked_helper.rs | |
| //@aux-build:proc_macros.rs | |
| #![warn(clippy::unnecessary_unwrap_unchecked)] | |
| use proc_macros::{external, with_span}; | |
| #[rustfmt::skip] | |
| use unnecessary_unwrap_unchecked_helper::{lol, kek}; | |
| mod b { | |
| pub fn test_fn() -> Option<u32> { | |
| Some(0) | |
| } | |
| pub unsafe fn test_fn_unchecked() -> u32 { | |
| 0 | |
| } | |
| } | |
| fn test_fn() -> Option<u32> { | |
| Some(0) | |
| } | |
| unsafe fn test_fn_unchecked() -> u32 { | |
| 0 | |
| } | |
| struct A; | |
| impl A { | |
| fn a(&self) -> Option<u32> { | |
| Some(0) | |
| } | |
| unsafe fn a_unchecked(&self) -> u32 { | |
| 0 | |
| } | |
| fn an_assoc_fn() -> Option<u32> { | |
| Some(0) | |
| } | |
| unsafe fn an_assoc_fn_unchecked() -> u32 { | |
| 0 | |
| } | |
| } | |
| struct B; | |
| impl B { | |
| fn b(&self) -> Option<u32> { | |
| Some(0) | |
| } | |
| } | |
| impl B { | |
| unsafe fn b_unchecked(&self) -> u32 { | |
| 0 | |
| } | |
| } | |
| fn main() { | |
| let string_slice = unsafe { std::str::from_utf8_unchecked(&[]) }; | |
| //~^ unnecessary_unwrap_unchecked | |
| let a = unsafe { A::a_unchecked(&A) }; | |
| //~^ unnecessary_unwrap_unchecked | |
| let a = unsafe { | |
| let a = A; | |
| a.a_unchecked() | |
| }; | |
| //~^^ unnecessary_unwrap_unchecked | |
| let an_assoc_fn = unsafe { A::an_assoc_fn_unchecked() }; | |
| //~^ unnecessary_unwrap_unchecked | |
| let extern_fn = unsafe { unnecessary_unwrap_unchecked_helper::lol_unchecked() }; | |
| //~^ unnecessary_unwrap_unchecked | |
| let extern_fn_qualified = unsafe { unnecessary_unwrap_unchecked_helper::lol_unchecked() }; | |
| //~^ unnecessary_unwrap_unchecked | |
| let local_fn = unsafe { b::test_fn_unchecked() }; | |
| //~^ unnecessary_unwrap_unchecked | |
| // Don't lint: unlike `kek`, `kek_unchecked` isn't accessible from here | |
| let extern_pub_fn = unsafe { kek().unwrap_unchecked() }; | |
| // Don't lint: `B::b` and `B::b_unchecked` come from distinct impl blocks | |
| // (even though that wouldn't actually make the suggestion invalid in this case) | |
| let b = unsafe { | |
| let b = B; | |
| b.b().unwrap_unchecked() | |
| }; | |
| macro_rules! local { | |
| () => {{ | |
| unsafe { ::std::str::from_utf8(&[]).unwrap_unchecked() }; | |
| }}; | |
| } | |
| local!(); | |
| external! { | |
| unsafe { std::str::from_utf8(&[]).unwrap_unchecked() }; | |
| } | |
| with_span! { | |
| span | |
| unsafe { std::str::from_utf8(&[]).unwrap_unchecked() }; | |
| } | |
| } | |
| mod issue17349 { | |
| pub enum Foo { | |
| A, | |
| B, | |
| C, | |
| } | |
| impl Foo { | |
| pub const fn from_u8(value: u8) -> Option<Self> { | |
| match value { | |
| 0 => Some(Self::A), | |
| 1 => Some(Self::B), | |
| 2 => Some(Self::C), | |
| _ => None, | |
| } | |
| } | |
| /// # Safety | |
| /// | |
| /// The value must be either 0, 1 or 2 | |
| pub const unsafe fn from_u8_unchecked(value: u8) -> Self { | |
| // Don't lint from inside the `_unchecked` associated function itself | |
| unsafe { Self::from_u8(value).unwrap_unchecked() } | |
| } | |
| pub const fn to_bool(&self) -> Option<bool> { | |
| match self { | |
| Self::A => Some(false), | |
| Self::B => Some(true), | |
| Self::C => None, | |
| } | |
| } | |
| /// # Safety | |
| /// | |
| /// The value must be either `Self::A` or `Self::B` | |
| pub const unsafe fn to_bool_unchecked(&self) -> bool { | |
| // Don't lint from inside the `_unchecked` method itself | |
| unsafe { self.to_bool().unwrap_unchecked() } | |
| } | |
| } | |
| pub const fn from_u8(value: u8) -> Option<Foo> { | |
| Foo::from_u8(value) | |
| } | |
| /// # Safety | |
| /// | |
| /// The value must be either 0, 1 or 2 | |
| pub const unsafe fn from_u8_unchecked(value: u8) -> Foo { | |
| // Don't lint from inside the `_unchecked` function itself | |
| unsafe { from_u8(value).unwrap_unchecked() } | |
| } | |
| pub fn from_u16(value: u16) -> Option<Foo> { | |
| Foo::from_u8(u8::try_from(value).ok()?) | |
| } | |
| /// # Safety | |
| /// | |
| /// The value must be either 0, 1 or 2 | |
| pub unsafe fn from_u16_unchecked(value: u16) -> Foo { | |
| // Don't lint from inside the `_unchecked` function itself | |
| // even in the presence of intermediate bodies. | |
| let cl = || unsafe { from_u16(value).unwrap_unchecked() }; | |
| cl() | |
| } | |
| } |