Skip to content

Commit f27ca5c

Browse files
committed
Fix rust-lang#9771 (unnecessary_to_owned false positive)
1 parent 704e00c commit f27ca5c

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

clippy_lints/src/methods/unnecessary_to_owned.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitP
1919
use rustc_semver::RustcVersion;
2020
use rustc_span::{sym, Symbol};
2121
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
22-
use std::cmp::max;
2322

2423
use super::UNNECESSARY_TO_OWNED;
2524

@@ -263,11 +262,22 @@ fn check_other_call_arg<'tcx>(
263262
if let Some(as_ref_trait_id) = cx.tcx.get_diagnostic_item(sym::AsRef);
264263
if trait_predicate.def_id() == deref_trait_id || trait_predicate.def_id() == as_ref_trait_id;
265264
let receiver_ty = cx.typeck_results().expr_ty(receiver);
266-
if can_change_type(cx, maybe_arg, receiver_ty);
267265
// We can't add an `&` when the trait is `Deref` because `Target = &T` won't match
268266
// `Target = T`.
269-
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
270-
let n_refs = max(n_refs, usize::from(!is_copy(cx, receiver_ty)));
267+
if let Some((n_refs, receiver_ty)) = if n_refs > 0 || is_copy(cx, receiver_ty) {
268+
Some((n_refs, receiver_ty))
269+
} else if trait_predicate.def_id() != deref_trait_id {
270+
Some((1, cx.tcx.mk_ref(
271+
cx.tcx.lifetimes.re_erased,
272+
ty::TypeAndMut {
273+
ty: receiver_ty,
274+
mutbl: Mutability::Not,
275+
},
276+
)))
277+
} else {
278+
None
279+
};
280+
if can_change_type(cx, maybe_arg, receiver_ty);
271281
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
272282
then {
273283
span_lint_and_sugg(

tests/ui/unnecessary_to_owned.fixed

+29
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,32 @@ mod issue_9504 {
426426
foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
427427
}
428428
}
429+
430+
mod issue_9771a {
431+
#![allow(dead_code)]
432+
433+
use std::marker::PhantomData;
434+
435+
pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>);
436+
437+
impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> {
438+
pub fn new(key: K) -> Key<K, V> {
439+
Key(key, PhantomData)
440+
}
441+
}
442+
443+
pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> {
444+
Key::new([b"pkh-", pkh].concat().to_vec())
445+
}
446+
}
447+
448+
mod issue_9771b {
449+
#![allow(dead_code)]
450+
451+
pub struct Key<K: AsRef<[u8]>>(K);
452+
453+
pub fn from(c: &[u8]) -> Key<Vec<u8>> {
454+
let v = [c].concat();
455+
Key(v.to_vec())
456+
}
457+
}

tests/ui/unnecessary_to_owned.rs

+29
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,32 @@ mod issue_9504 {
426426
foo(std::path::PathBuf::new().to_string_lossy().to_string()).await;
427427
}
428428
}
429+
430+
mod issue_9771a {
431+
#![allow(dead_code)]
432+
433+
use std::marker::PhantomData;
434+
435+
pub struct Key<K: AsRef<[u8]>, V: ?Sized>(K, PhantomData<V>);
436+
437+
impl<K: AsRef<[u8]>, V: ?Sized> Key<K, V> {
438+
pub fn new(key: K) -> Key<K, V> {
439+
Key(key, PhantomData)
440+
}
441+
}
442+
443+
pub fn pkh(pkh: &[u8]) -> Key<Vec<u8>, String> {
444+
Key::new([b"pkh-", pkh].concat().to_vec())
445+
}
446+
}
447+
448+
mod issue_9771b {
449+
#![allow(dead_code)]
450+
451+
pub struct Key<K: AsRef<[u8]>>(K);
452+
453+
pub fn from(c: &[u8]) -> Key<Vec<u8>> {
454+
let v = [c].concat();
455+
Key(v.to_vec())
456+
}
457+
}

0 commit comments

Comments
 (0)