Skip to content

Commit 1a95590

Browse files
committed
1 parent ce841fe commit 1a95590

File tree

4 files changed

+112
-2
lines changed

4 files changed

+112
-2
lines changed

clippy_lints/src/methods/unnecessary_to_owned.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use super::implicit_clone::is_clone_like;
22
use super::unnecessary_iter_cloned::{self, is_into_iter};
33
use clippy_utils::diagnostics::span_lint_and_sugg;
44
use clippy_utils::source::snippet_opt;
5-
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
5+
use clippy_utils::ty::{
6+
contains_ty, get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs,
7+
};
68
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item};
79
use rustc_errors::Applicability;
810
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind};
@@ -260,6 +262,12 @@ fn check_other_call_arg<'tcx>(
260262
// `Target = T`.
261263
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
262264
let n_refs = max(n_refs, if is_copy(cx, receiver_ty) { 0 } else { 1 });
265+
// If the trait is `AsRef` and the input type variable `T` occurs in the output type, then
266+
// `T` must not be instantiated with a reference
267+
// (https://github.com/rust-lang/rust-clippy/issues/8507).
268+
if (n_refs == 0 && !receiver_ty.is_ref())
269+
|| trait_predicate.def_id() != as_ref_trait_id
270+
|| !contains_ty(fn_sig.output(), input);
263271
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
264272
then {
265273
span_lint_and_sugg(

tests/ui/unnecessary_to_owned.fixed

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,51 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E
212212
}
213213

214214
fn require_string(_: &String) {}
215+
216+
// https://github.com/rust-lang/rust-clippy/issues/8507
217+
mod issue_8507 {
218+
#![allow(dead_code)]
219+
220+
struct Opaque<P>(P);
221+
222+
pub trait Abstracted {}
223+
224+
impl<P> Abstracted for Opaque<P> {}
225+
226+
fn build<P>(p: P) -> Opaque<P>
227+
where
228+
P: AsRef<str>,
229+
{
230+
Opaque(p)
231+
}
232+
233+
// Should not lint.
234+
fn test_str(s: &str) -> Box<dyn Abstracted> {
235+
Box::new(build(s.to_string()))
236+
}
237+
238+
// Should not lint.
239+
fn test_x(x: super::X) -> Box<dyn Abstracted> {
240+
Box::new(build(x))
241+
}
242+
243+
#[derive(Clone, Copy)]
244+
struct Y(&'static str);
245+
246+
impl AsRef<str> for Y {
247+
fn as_ref(&self) -> &str {
248+
self.0
249+
}
250+
}
251+
252+
impl ToString for Y {
253+
fn to_string(&self) -> String {
254+
self.0.to_string()
255+
}
256+
}
257+
258+
// Should lint because Y is copy.
259+
fn test_y(y: Y) -> Box<dyn Abstracted> {
260+
Box::new(build(y))
261+
}
262+
}

tests/ui/unnecessary_to_owned.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,3 +212,51 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E
212212
}
213213

214214
fn require_string(_: &String) {}
215+
216+
// https://github.com/rust-lang/rust-clippy/issues/8507
217+
mod issue_8507 {
218+
#![allow(dead_code)]
219+
220+
struct Opaque<P>(P);
221+
222+
pub trait Abstracted {}
223+
224+
impl<P> Abstracted for Opaque<P> {}
225+
226+
fn build<P>(p: P) -> Opaque<P>
227+
where
228+
P: AsRef<str>,
229+
{
230+
Opaque(p)
231+
}
232+
233+
// Should not lint.
234+
fn test_str(s: &str) -> Box<dyn Abstracted> {
235+
Box::new(build(s.to_string()))
236+
}
237+
238+
// Should not lint.
239+
fn test_x(x: super::X) -> Box<dyn Abstracted> {
240+
Box::new(build(x))
241+
}
242+
243+
#[derive(Clone, Copy)]
244+
struct Y(&'static str);
245+
246+
impl AsRef<str> for Y {
247+
fn as_ref(&self) -> &str {
248+
self.0
249+
}
250+
}
251+
252+
impl ToString for Y {
253+
fn to_string(&self) -> String {
254+
self.0.to_string()
255+
}
256+
}
257+
258+
// Should lint because Y is copy.
259+
fn test_y(y: Y) -> Box<dyn Abstracted> {
260+
Box::new(build(y.to_string()))
261+
}
262+
}

tests/ui/unnecessary_to_owned.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -491,5 +491,11 @@ LL - let path = match get_file_path(&t) {
491491
LL + let path = match get_file_path(t) {
492492
|
493493

494-
error: aborting due to 76 previous errors
494+
error: unnecessary use of `to_string`
495+
--> $DIR/unnecessary_to_owned.rs:260:24
496+
|
497+
LL | Box::new(build(y.to_string()))
498+
| ^^^^^^^^^^^^^ help: use: `y`
499+
500+
error: aborting due to 77 previous errors
495501

0 commit comments

Comments
 (0)