// run-rustfix #![warn(clippy::explicit_auto_deref)] #![allow( dead_code, unused_braces, clippy::borrowed_box, clippy::needless_borrow, clippy::needless_return, clippy::ptr_arg, clippy::redundant_field_names, clippy::too_many_arguments, clippy::borrow_deref_ref, clippy::let_unit_value )] trait CallableStr { type T: Fn(&str); fn callable_str(&self) -> Self::T; } impl CallableStr for () { type T = fn(&str); fn callable_str(&self) -> Self::T { fn f(_: &str) {} f } } impl CallableStr for i32 { type T = <() as CallableStr>::T; fn callable_str(&self) -> Self::T { ().callable_str() } } trait CallableT { type T: Fn(&U); fn callable_t(&self) -> Self::T; } impl CallableT for () { type T = fn(&U); fn callable_t(&self) -> Self::T { fn f(_: &U) {} f:: } } impl CallableT for i32 { type T = <() as CallableT>::T; fn callable_t(&self) -> Self::T { ().callable_t() } } fn f_str(_: &str) {} fn f_string(_: &String) {} fn f_t(_: T) {} fn f_ref_t(_: &T) {} fn f_str_t(_: &str, _: T) {} fn f_box_t(_: &Box) {} extern "C" { fn var(_: u32, ...); } fn main() { let s = String::new(); let _: &str = &*s; let _ = &*s; // Don't lint. Inferred type would change. let _: &_ = &*s; // Don't lint. Inferred type would change. f_str(&*s); f_t(&*s); // Don't lint. Inferred type would change. f_ref_t(&*s); // Don't lint. Inferred type would change. f_str_t(&*s, &*s); // Don't lint second param. let b = Box::new(Box::new(Box::new(5))); let _: &Box = &**b; let _: &Box<_> = &**b; // Don't lint. Inferred type would change. f_box_t(&**b); // Don't lint. Inferred type would change. let c = |_x: &str| (); c(&*s); let c = |_x| (); c(&*s); // Don't lint. Inferred type would change. fn _f(x: &String) -> &str { &**x } fn _f1(x: &String) -> &str { { &**x } } fn _f2(x: &String) -> &str { &**{ x } } fn _f3(x: &Box>>) -> &Box { &***x } fn _f4( x: String, f1: impl Fn(&str), f2: &dyn Fn(&str), f3: fn(&str), f4: impl CallableStr, f5: <() as CallableStr>::T, f6: ::T, f7: &dyn CallableStr, f8: impl CallableT, f9: <() as CallableT>::T, f10: >::T, f11: &dyn CallableT, ) { f1(&*x); f2(&*x); f3(&*x); f4.callable_str()(&*x); f5(&*x); f6(&*x); f7.callable_str()(&*x); f8.callable_t()(&*x); f9(&*x); f10(&*x); f11.callable_t()(&*x); } struct S1<'a>(&'a str); let _ = S1(&*s); struct S2<'a> { s: &'a str, } let _ = S2 { s: &*s }; struct S3<'a, T: ?Sized>(&'a T); let _ = S3(&*s); // Don't lint. Inferred type would change. struct S4<'a, T: ?Sized> { s: &'a T, } let _ = S4 { s: &*s }; // Don't lint. Inferred type would change. enum E1<'a> { S1(&'a str), S2 { s: &'a str }, } impl<'a> E1<'a> { fn m1(s: &'a String) { let _ = Self::S1(&**s); let _ = Self::S2 { s: &**s }; } } let _ = E1::S1(&*s); let _ = E1::S2 { s: &*s }; enum E2<'a, T: ?Sized> { S1(&'a T), S2 { s: &'a T }, } let _ = E2::S1(&*s); // Don't lint. Inferred type would change. let _ = E2::S2 { s: &*s }; // Don't lint. Inferred type would change. let ref_s = &s; let _: &String = &*ref_s; // Don't lint reborrow. f_string(&*ref_s); // Don't lint reborrow. struct S5 { foo: u32, } let b = Box::new(Box::new(S5 { foo: 5 })); let _ = b.foo; let _ = (*b).foo; let _ = (**b).foo; struct S6 { foo: S5, } impl core::ops::Deref for S6 { type Target = S5; fn deref(&self) -> &Self::Target { &self.foo } } let s6 = S6 { foo: S5 { foo: 5 } }; let _ = (*s6).foo; // Don't lint. `S6` also has a field named `foo` let ref_str = &"foo"; let _ = f_str(*ref_str); let ref_ref_str = &ref_str; let _ = f_str(**ref_ref_str); fn _f5(x: &u32) -> u32 { if true { *x } else { return *x; } } f_str(&&*ref_str); // `needless_borrow` will suggest removing both references f_str(&&**ref_str); // `needless_borrow` will suggest removing only one reference let x = &&40; unsafe { var(0, &**x); } }