]> git.lizzy.rs Git - rust.git/blobdiff - tests/ui/explicit_auto_deref.rs
Move MSRV tests into the lint specific test files
[rust.git] / tests / ui / explicit_auto_deref.rs
index 1cc77c1b08f94f62fa4e64c29f43db9b2f7ca58d..deedafad153b97ae0edd6d777637516d65c33410 100644 (file)
@@ -1,14 +1,18 @@
 // 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 {
@@ -48,6 +52,7 @@ fn callable_t(&self) -> Self::T {
 }
 
 fn f_str(_: &str) {}
+fn f_string(_: &String) {}
 fn f_t<T>(_: T) {}
 fn f_ref_t<T: ?Sized>(_: &T) {}
 
@@ -55,10 +60,16 @@ fn f_str_t<T>(_: &str, _: 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.
 
@@ -158,4 +169,101 @@ enum E2<'a, T: ?Sized> {
     }
     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
+    };
 }