This commit is contained in:
Samuel E. Moelius III 2022-03-05 21:18:44 -05:00
parent ce841fe73b
commit 1a95590faf
4 changed files with 112 additions and 2 deletions

View file

@ -2,7 +2,9 @@ use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
use clippy_utils::ty::{
contains_ty, get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs,
};
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item};
use rustc_errors::Applicability;
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind};
@ -260,6 +262,12 @@ fn check_other_call_arg<'tcx>(
// `Target = T`.
if n_refs > 0 || is_copy(cx, receiver_ty) || trait_predicate.def_id() != deref_trait_id;
let n_refs = max(n_refs, if is_copy(cx, receiver_ty) { 0 } else { 1 });
// If the trait is `AsRef` and the input type variable `T` occurs in the output type, then
// `T` must not be instantiated with a reference
// (https://github.com/rust-lang/rust-clippy/issues/8507).
if (n_refs == 0 && !receiver_ty.is_ref())
|| trait_predicate.def_id() != as_ref_trait_id
|| !contains_ty(fn_sig.output(), input);
if let Some(receiver_snippet) = snippet_opt(cx, receiver.span);
then {
span_lint_and_sugg(

View file

@ -212,3 +212,51 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E
}
fn require_string(_: &String) {}
// https://github.com/rust-lang/rust-clippy/issues/8507
mod issue_8507 {
#![allow(dead_code)]
struct Opaque<P>(P);
pub trait Abstracted {}
impl<P> Abstracted for Opaque<P> {}
fn build<P>(p: P) -> Opaque<P>
where
P: AsRef<str>,
{
Opaque(p)
}
// Should not lint.
fn test_str(s: &str) -> Box<dyn Abstracted> {
Box::new(build(s.to_string()))
}
// Should not lint.
fn test_x(x: super::X) -> Box<dyn Abstracted> {
Box::new(build(x))
}
#[derive(Clone, Copy)]
struct Y(&'static str);
impl AsRef<str> for Y {
fn as_ref(&self) -> &str {
self.0
}
}
impl ToString for Y {
fn to_string(&self) -> String {
self.0.to_string()
}
}
// Should lint because Y is copy.
fn test_y(y: Y) -> Box<dyn Abstracted> {
Box::new(build(y))
}
}

View file

@ -212,3 +212,51 @@ fn get_file_path(_file_type: &FileType) -> Result<std::path::PathBuf, std::io::E
}
fn require_string(_: &String) {}
// https://github.com/rust-lang/rust-clippy/issues/8507
mod issue_8507 {
#![allow(dead_code)]
struct Opaque<P>(P);
pub trait Abstracted {}
impl<P> Abstracted for Opaque<P> {}
fn build<P>(p: P) -> Opaque<P>
where
P: AsRef<str>,
{
Opaque(p)
}
// Should not lint.
fn test_str(s: &str) -> Box<dyn Abstracted> {
Box::new(build(s.to_string()))
}
// Should not lint.
fn test_x(x: super::X) -> Box<dyn Abstracted> {
Box::new(build(x))
}
#[derive(Clone, Copy)]
struct Y(&'static str);
impl AsRef<str> for Y {
fn as_ref(&self) -> &str {
self.0
}
}
impl ToString for Y {
fn to_string(&self) -> String {
self.0.to_string()
}
}
// Should lint because Y is copy.
fn test_y(y: Y) -> Box<dyn Abstracted> {
Box::new(build(y.to_string()))
}
}

View file

@ -491,5 +491,11 @@ LL - let path = match get_file_path(&t) {
LL + let path = match get_file_path(t) {
|
error: aborting due to 76 previous errors
error: unnecessary use of `to_string`
--> $DIR/unnecessary_to_owned.rs:260:24
|
LL | Box::new(build(y.to_string()))
| ^^^^^^^^^^^^^ help: use: `y`
error: aborting due to 77 previous errors