| //@aux-build:proc_macros.rs | |
| #![warn(clippy::explicit_deref_methods)] | |
| #![allow(unused_variables, unused_must_use)] | |
| #![allow( | |
| clippy::borrow_deref_ref, | |
| suspicious_double_ref_op, | |
| noop_method_call, | |
| clippy::explicit_auto_deref, | |
| clippy::needless_borrow, | |
| clippy::no_effect, | |
| clippy::uninlined_format_args, | |
| clippy::unnecessary_literal_unwrap, | |
| clippy::deref_addrof | |
| )] | |
| use std::ops::{Deref, DerefMut}; | |
| extern crate proc_macros; | |
| fn concat(deref_str: &str) -> String { | |
| format!("{}bar", deref_str) | |
| } | |
| fn just_return(deref_str: &str) -> &str { | |
| deref_str | |
| } | |
| struct CustomVec(Vec<u8>); | |
| impl Deref for CustomVec { | |
| type Target = Vec<u8>; | |
| fn deref(&self) -> &Vec<u8> { | |
| &self.0 | |
| } | |
| } | |
| struct Aaa; | |
| impl Deref for Aaa { | |
| type Target = (); | |
| fn deref(&self) -> &Self::Target { | |
| todo!(); | |
| } | |
| } | |
| impl DerefMut for Aaa { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| todo!(); | |
| } | |
| } | |
| fn main() { | |
| let a: &mut String = &mut String::from("foo"); | |
| // these should require linting | |
| let b: &str = &*a; | |
| //~^ explicit_deref_methods | |
| let b: &mut str = &mut **a; | |
| //~^ explicit_deref_methods | |
| // both derefs should get linted here | |
| let b: String = format!("{}, {}", &*a, &*a); | |
| //~^ explicit_deref_methods | |
| //~| explicit_deref_methods | |
| println!("{}", &*a); | |
| //~^ explicit_deref_methods | |
| #[allow(clippy::match_single_binding)] | |
| match &*a { | |
| //~^ explicit_deref_methods | |
| _ => (), | |
| } | |
| let b: String = concat(&*a); | |
| //~^ explicit_deref_methods | |
| let b = just_return(a); | |
| //~^ explicit_deref_methods | |
| let b: String = concat(just_return(a)); | |
| //~^ explicit_deref_methods | |
| let b: &str = a.deref().deref(); | |
| let opt_a = Some(a.clone()); | |
| let b = opt_a.unwrap().deref(); | |
| Aaa::deref(&Aaa); | |
| Aaa::deref_mut(&mut Aaa); | |
| <Aaa as Deref>::deref(&Aaa); | |
| <Aaa as DerefMut>::deref_mut(&mut Aaa); | |
| let mut aaa = Aaa; | |
| Aaa::deref(&aaa); | |
| Aaa::deref_mut(&mut aaa); | |
| // following should not require linting | |
| let cv = CustomVec(vec![0, 42]); | |
| let c = cv.deref()[0]; | |
| let b: &str = &*a.deref(); | |
| let b: String = a.deref().clone(); | |
| let b: usize = a.deref_mut().len(); | |
| let b: &usize = &a.deref().len(); | |
| let b: &str = &*a; | |
| let b: &mut str = &mut *a; | |
| macro_rules! expr_deref { | |
| ($body:expr) => { | |
| $body.deref() | |
| }; | |
| } | |
| let b: &str = expr_deref!(a); | |
| let b: &str = expr_deref!(&*a); | |
| //~^ explicit_deref_methods | |
| proc_macros::external! { | |
| let a: &mut String = &mut String::from("foo"); | |
| let b: &str = a.deref(); | |
| } | |
| // Issue #15168 | |
| proc_macros::with_span! { | |
| span | |
| let a: &mut String = &mut String::from("foo"); | |
| let b: &str = a.deref(); | |
| } | |
| // The struct does not implement Deref trait | |
| #[derive(Copy, Clone)] | |
| struct NoLint(u32); | |
| impl NoLint { | |
| pub fn deref(self) -> u32 { | |
| self.0 | |
| } | |
| pub fn deref_mut(self) -> u32 { | |
| self.0 | |
| } | |
| } | |
| let no_lint = NoLint(42); | |
| let b = no_lint.deref(); | |
| let b = no_lint.deref_mut(); | |
| let _ = &*&"foo"; //~ explicit_deref_methods | |
| let mut x = String::new(); | |
| let _ = &&mut **&mut x; //~ explicit_deref_methods | |
| let _ = &&mut ***(&mut &mut x); //~ explicit_deref_methods | |
| } | |
| mod issue_15392 { | |
| use std::ops::{Deref, DerefMut}; | |
| struct Wrapper(String); | |
| impl Deref for Wrapper { | |
| type Target = str; | |
| fn deref(&self) -> &Self::Target { | |
| // forwarding is ok | |
| let res = Deref::deref(&self.0); | |
| // we let `deref_mut` pass as well | |
| let _ = DerefMut::deref_mut(&mut String::new()); | |
| res | |
| } | |
| } | |
| impl DerefMut for Wrapper { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| // forwarding is ok | |
| let res = DerefMut::deref_mut(&mut self.0); | |
| // we let `deref` pass as well | |
| let _ = Deref::deref(&String::new()); | |
| res | |
| } | |
| } | |
| struct A(String); | |
| struct AA(String); | |
| struct AB(String); | |
| impl Deref for A { | |
| type Target = str; | |
| fn deref(&self) -> &Self::Target { | |
| // in a top-level `Deref` impl, ok | |
| let _ = self.0.deref(); | |
| // in a top-level `Deref` impl, acceptable | |
| let _ = String::new().deref_mut(); | |
| #[allow(non_local_definitions)] | |
| impl Deref for AA { | |
| type Target = str; | |
| fn deref(&self) -> &Self::Target { | |
| // in a nested `Deref` impl, acceptable | |
| let _ = String::new().deref_mut(); | |
| // in a nested `Deref` impl, ok | |
| self.0.deref() | |
| } | |
| } | |
| // still in a top-level `Deref` impl, ok | |
| let _ = self.0.deref(); | |
| // still in a top-level `Deref` impl, acceptable | |
| let _ = String::new().deref_mut(); | |
| #[allow(non_local_definitions)] | |
| impl DerefMut for AA { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| // in a top-level `DerefMut` impl, acceptable | |
| let _ = self.0.deref(); | |
| // in a top-level `DerefMut` impl, ok | |
| self.0.deref_mut() | |
| } | |
| } | |
| // still in a top-level `Deref` impl, acceptable | |
| let _ = String::new().deref_mut(); | |
| // still in a top-level `Deref` impl, ok | |
| self.0.deref() | |
| } | |
| } | |
| impl DerefMut for A { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| // in a top-level `DerefMut` impl, acceptable | |
| let _ = self.0.deref(); | |
| // in a top-level `DerefMut` impl, ok | |
| let _ = self.0.deref_mut(); | |
| #[allow(non_local_definitions)] | |
| impl Deref for AB { | |
| type Target = str; | |
| fn deref(&self) -> &Self::Target { | |
| // in a nested `Deref` impl, acceptable | |
| let _ = String::new().deref_mut(); | |
| // in a nested `Deref` impl, ok | |
| Deref::deref(&self.0) | |
| } | |
| } | |
| // still in a top-level `DerefMut` impl, acceptable | |
| let _ = self.0.deref(); | |
| // still in a top-level `DerefMut` impl, ok | |
| let _ = self.0.deref_mut(); | |
| #[allow(non_local_definitions)] | |
| impl DerefMut for AB { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| // in a nested `DerefMut` impl, acceptable | |
| self.0.deref(); | |
| // in a nested `DerefMut` impl, ok | |
| self.0.deref_mut() | |
| } | |
| } | |
| // still in a top-level `DerefMut` impl, acceptable | |
| let _ = self.0.deref(); | |
| // still in a top-level `DerefMut` impl, ok | |
| self.0.deref_mut() | |
| } | |
| } | |
| } |