#![feature(closure_lifetime_binder)] #![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 _: &str = &*{ String::new() }; let _: &str = &mut *{ String::new() }; 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); } let s = &"str"; let _ = || return *s; let _ = || -> &'static str { return *s }; struct X; struct Y(X); impl core::ops::Deref for Y { type Target = X; fn deref(&self) -> &Self::Target { &self.0 } } let _: &X = &*{ Y(X) }; let _: &X = &*match 0 { #[rustfmt::skip] 0 => { Y(X) }, _ => panic!(), }; let _: &X = &*if true { Y(X) } else { panic!() }; fn deref_to_u>(x: &T) -> &U { &**x } let _ = |x: &'static Box>| -> &'static dyn Iterator { &**x }; fn ret_any(x: &Box) -> &dyn std::any::Any { &**x } let x = String::new(); let _: *const str = &*x; struct S7([u32; 1]); impl core::ops::Deref for S7 { type Target = [u32; 1]; fn deref(&self) -> &Self::Target { &self.0 } } let x = S7([0]); let _: &[u32] = &*x; let c1 = |_: &Vec<&u32>| {}; let x = &&vec![&1u32]; c1(*x); let _ = for<'a, 'b> |x: &'a &'a Vec<&'b u32>, b: bool| -> &'a Vec<&'b u32> { if b { return *x; } *x }; trait WithAssoc { type Assoc: ?Sized; fn to_assoc(&self) -> &Self::Assoc { panic!() } } impl WithAssoc for String { type Assoc = str; } fn takes_assoc(_: &T::Assoc) -> T { unimplemented!() } let _: String = takes_assoc(&*String::new()); // Issue #9901 fn takes_ref(_: &i32) {} takes_ref(*Box::new(&0i32)); // Issue #10384 impl<'a> WithAssoc for &'a u32 { type Assoc = dyn core::fmt::Display; fn to_assoc(&self) -> &Self::Assoc { *self } } fn return_dyn_assoc<'a>(x: &'a &'a u32) -> &'a <&'a u32 as WithAssoc>::Assoc { *x } // Issue #11366 let _: &mut u32 = match &mut Some(&mut 0u32) { Some(x) => &mut *x, None => panic!(), }; // Issue #11474 #[derive(Clone, Copy)] struct Wrap(T); impl core::ops::Deref for Wrap { type Target = T; fn deref(&self) -> &T { &self.0 } } impl core::ops::DerefMut for Wrap { fn deref_mut(&mut self) -> &mut T { &mut self.0 } } union U { u: T, } #[derive(Clone, Copy)] struct S8 { x: &'static str, } unsafe { let mut x = U { u: core::mem::ManuallyDrop::new(S8 { x: "" }), }; let _ = &mut (*x.u).x; let _ = &mut (*{ x.u }).x; let _ = &mut ({ *x.u }).x; let mut x = U { u: Wrap(core::mem::ManuallyDrop::new(S8 { x: "" })), }; let _ = &mut (**x.u).x; let _ = &mut (**{ x.u }).x; let _ = &mut ({ **x.u }).x; let mut x = U { u: Wrap(S8 { x: "" }) }; let _ = &mut (*x.u).x; let _ = &mut (*{ x.u }).x; let _ = &mut ({ *x.u }).x; } } mod issue_12969 { use std::ops::Deref; struct Wrapper(T); impl Deref for Wrapper { type Target = T; fn deref(&self) -> &T { &self.0 } } fn foo(_bar: &str) {} fn bar() { let wrapped_bar = Wrapper(""); foo(&*wrapped_bar); } } mod issue_9841 { fn takes_array_ref(array: &&[T; N]) { takes_slice(*array) } fn takes_array_ref_ref(array: &&&[T; N]) { takes_slice(**array) } fn takes_slice(slice: &[T]) { todo!() } }