diff options
| author | Samuel Moelius <samuel.moelius@trailofbits.com> | 2022-11-04 16:01:44 +0000 |
|---|---|---|
| committer | Samuel Moelius <samuel.moelius@trailofbits.com> | 2022-11-04 16:02:12 +0000 |
| commit | f27ca5c00a96d2dbd1e2b5dceee918d829891bc1 (patch) | |
| tree | 411c245fa7bc1d7f4ea58c97158d984a156589b0 | |
| parent | 704e00cb75ef5be2080d21be0965afd938d6fbec (diff) | |
| download | rust-f27ca5c00a96d2dbd1e2b5dceee918d829891bc1.tar.gz rust-f27ca5c00a96d2dbd1e2b5dceee918d829891bc1.zip | |
Fix #9771 (`unnecessary_to_owned` false positive)
| -rw-r--r-- | clippy_lints/src/methods/unnecessary_to_owned.rs | 18 | ||||
| -rw-r--r-- | tests/ui/unnecessary_to_owned.fixed | 29 | ||||
| -rw-r--r-- | tests/ui/unnecessary_to_owned.rs | 29 |
3 files changed, 72 insertions, 4 deletions
diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 4b4f2f47b1d..460bd1cfbd3 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -19,7 +19,6 @@ use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitP use rustc_semver::RustcVersion; use rustc_span::{sym, Symbol}; use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause}; -use std::cmp::max; use super::UNNECESSARY_TO_OWNED; @@ -263,11 +262,22 @@ fn check_other_call_arg<'tcx>( if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef); if trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id; let receiver_ty = cx.typeck_results().expr_ty(receiver); - if can_change_type(cx, maybe_arg, receiver_ty); // We can't add an `&` when the trait is `Deref` because `Target = &T` won't match // `Target = T`. - if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id; - let n_refs = max(n_refs, usize::from(!is_copy(cx, receiver_ty))); + if let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) { + Some((n_refs, receiver_ty)) + } else if trait_predicate.def_id() != deref_trait_id { + Some((1, cx.tcx.mk_ref( + cx.tcx.lifetimes.re_erased, + ty::TypeAndMut { + ty: receiver_ty, + mutbl: Mutability::Not, + }, + ))) + } else { + None + }; + if can_change_type(cx, maybe_arg, receiver_ty); if let Some(receiver_snippet) = snippet_opt(cx, receiver.span); then { span_lint_and_sugg( diff --git a/tests/ui/unnecessary_to_owned.fixed b/tests/ui/unnecessary_to_owned.fixed index fe09aad06bc..fadcf7f9c9e 100644 --- a/tests/ui/unnecessary_to_owned.fixed +++ b/tests/ui/unnecessary_to_owned.fixed @@ -426,3 +426,32 @@ mod issue_9504 { foo(std::path::PathBuf::new().to_string_lossy().to_string()).await; } } + +mod issue_9771a { + #![allow(dead_code)] + + use std::marker::PhantomData; + + pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>); + + impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> { + pub fn new(key: K) -> Key<K, V> { + Key(key, PhantomData) + } + } + + pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> { + Key::new([b"pkh-", pkh].concat().to_vec()) + } +} + +mod issue_9771b { + #![allow(dead_code)] + + pub struct Key<K: AsRef<[u8]>>(K); + + pub fn from(c: &[u8]) -> Key<Vec<u8>> { + let v = [c].concat(); + Key(v.to_vec()) + } +} diff --git a/tests/ui/unnecessary_to_owned.rs b/tests/ui/unnecessary_to_owned.rs index 3de6d0903c0..fe6864b9e07 100644 --- a/tests/ui/unnecessary_to_owned.rs +++ b/tests/ui/unnecessary_to_owned.rs @@ -426,3 +426,32 @@ mod issue_9504 { foo(std::path::PathBuf::new().to_string_lossy().to_string()).await; } } + +mod issue_9771a { + #![allow(dead_code)] + + use std::marker::PhantomData; + + pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>); + + impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> { + pub fn new(key: K) -> Key<K, V> { + Key(key, PhantomData) + } + } + + pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> { + Key::new([b"pkh-", pkh].concat().to_vec()) + } +} + +mod issue_9771b { + #![allow(dead_code)] + + pub struct Key<K: AsRef<[u8]>>(K); + + pub fn from(c: &[u8]) -> Key<Vec<u8>> { + let v = [c].concat(); + Key(v.to_vec()) + } +} |
