// run-rustfix #![allow(clippy::ptr_arg)] #![warn(clippy::unnecessary_to_owned)] use std::borrow::Cow; use std::ffi::{CStr, CString, OsStr, OsString}; use std::ops::Deref; #[derive(Clone)] struct X(String); impl Deref for X { type Target = [u8]; fn deref(&self) -> &[u8] { self.0.as_bytes() } } impl AsRef for X { fn as_ref(&self) -> &str { self.0.as_str() } } impl ToString for X { fn to_string(&self) -> String { self.0.to_string() } } impl X { fn join(&self, other: impl AsRef) -> Self { let mut s = self.0.clone(); s.push_str(other.as_ref()); Self(s) } } #[allow(dead_code)] #[derive(Clone)] enum FileType { Account, PrivateKey, Certificate, } fn main() { let c_str = CStr::from_bytes_with_nul(&[0]).unwrap(); let os_str = OsStr::new("x"); let path = std::path::Path::new("x"); let s = "x"; let array = ["x"]; let array_ref = &["x"]; let slice = &["x"][..]; let x = X(String::from("x")); let x_ref = &x; require_c_str(&Cow::from(c_str)); require_c_str(c_str); require_os_str(os_str); require_os_str(&Cow::from(os_str)); require_os_str(os_str); require_path(path); require_path(&Cow::from(path)); require_path(path); require_str(s); require_str(&Cow::from(s)); require_str(s); require_str(x_ref.as_ref()); require_slice(slice); require_slice(&Cow::from(slice)); require_slice(array.as_ref()); require_slice(array_ref.as_ref()); require_slice(slice); require_slice(x_ref); require_x(&Cow::::Owned(x.clone())); require_x(x_ref); require_deref_c_str(c_str); require_deref_os_str(os_str); require_deref_path(path); require_deref_str(s); require_deref_slice(slice); require_impl_deref_c_str(c_str); require_impl_deref_os_str(os_str); require_impl_deref_path(path); require_impl_deref_str(s); require_impl_deref_slice(slice); require_deref_str_slice(s, slice); require_deref_slice_str(slice, s); require_as_ref_c_str(c_str); require_as_ref_os_str(os_str); require_as_ref_path(path); require_as_ref_str(s); require_as_ref_str(&x); require_as_ref_slice(array); require_as_ref_slice(array_ref); require_as_ref_slice(slice); require_impl_as_ref_c_str(c_str); require_impl_as_ref_os_str(os_str); require_impl_as_ref_path(path); require_impl_as_ref_str(s); require_impl_as_ref_str(&x); require_impl_as_ref_slice(array); require_impl_as_ref_slice(array_ref); require_impl_as_ref_slice(slice); require_as_ref_str_slice(s, array); require_as_ref_str_slice(s, array_ref); require_as_ref_str_slice(s, slice); require_as_ref_slice_str(array, s); require_as_ref_slice_str(array_ref, s); require_as_ref_slice_str(slice, s); let _ = x.join(x_ref); let _ = slice.iter().copied(); let _ = slice.iter().copied(); let _ = [std::path::PathBuf::new()][..].iter().cloned(); let _ = [std::path::PathBuf::new()][..].iter().cloned(); let _ = slice.iter().copied(); let _ = slice.iter().copied(); let _ = [std::path::PathBuf::new()][..].iter().cloned(); let _ = [std::path::PathBuf::new()][..].iter().cloned(); let _ = check_files(&[FileType::Account]); // negative tests require_string(&s.to_string()); require_string(&Cow::from(s).into_owned()); require_string(&s.to_owned()); require_string(&x_ref.to_string()); // `X` isn't copy. require_slice(&x.to_owned()); require_deref_slice(x.to_owned()); // The following should be flagged by `redundant_clone`, but not by this lint. require_c_str(&CString::from_vec_with_nul(vec![0]).unwrap()); require_os_str(&OsString::from("x")); require_path(&std::path::PathBuf::from("x")); require_str(&String::from("x")); } fn require_c_str(_: &CStr) {} fn require_os_str(_: &OsStr) {} fn require_path(_: &std::path::Path) {} fn require_str(_: &str) {} fn require_slice(_: &[T]) {} fn require_x(_: &X) {} fn require_deref_c_str>(_: T) {} fn require_deref_os_str>(_: T) {} fn require_deref_path>(_: T) {} fn require_deref_str>(_: T) {} fn require_deref_slice>(_: U) {} fn require_impl_deref_c_str(_: impl Deref) {} fn require_impl_deref_os_str(_: impl Deref) {} fn require_impl_deref_path(_: impl Deref) {} fn require_impl_deref_str(_: impl Deref) {} fn require_impl_deref_slice(_: impl Deref) {} fn require_deref_str_slice, U, V: Deref>(_: T, _: V) {} fn require_deref_slice_str, V: Deref>(_: U, _: V) {} fn require_as_ref_c_str>(_: T) {} fn require_as_ref_os_str>(_: T) {} fn require_as_ref_path>(_: T) {} fn require_as_ref_str>(_: T) {} fn require_as_ref_slice>(_: U) {} fn require_impl_as_ref_c_str(_: impl AsRef) {} fn require_impl_as_ref_os_str(_: impl AsRef) {} fn require_impl_as_ref_path(_: impl AsRef) {} fn require_impl_as_ref_str(_: impl AsRef) {} fn require_impl_as_ref_slice(_: impl AsRef<[T]>) {} fn require_as_ref_str_slice, U, V: AsRef<[U]>>(_: T, _: V) {} fn require_as_ref_slice_str, V: AsRef>(_: U, _: V) {} // `check_files` is based on: // https://github.com/breard-r/acmed/blob/1f0dcc32aadbc5e52de6d23b9703554c0f925113/acmed/src/storage.rs#L262 fn check_files(file_types: &[FileType]) -> bool { for t in file_types { let path = match get_file_path(t) { Ok(p) => p, Err(_) => { return false; }, }; if !path.is_file() { return false; } } true } fn get_file_path(_file_type: &FileType) -> Result { Ok(std::path::PathBuf::new()) } fn require_string(_: &String) {}