// run-rustfix
+#![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::too_many_arguments,
+ clippy::borrow_deref_ref,
+ clippy::let_unit_value
)]
trait CallableStr {
}
fn f_str(_: &str) {}
+fn f_string(_: &String) {}
fn f_t<T>(_: T) {}
fn f_ref_t<T: ?Sized>(_: &T) {}
fn f_box_t<T>(_: &Box<T>) {}
+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.
}
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<U, T: core::ops::Deref<Target = U>>(x: &T) -> &U {
+ &**x
+ }
+
+ let _ = |x: &'static Box<dyn Iterator<Item = u32>>| -> &'static dyn Iterator<Item = u32> { &**x };
+ fn ret_any(x: &Box<dyn std::any::Any>) -> &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
+ };
}