Skip to content

Commit 93a4992

Browse files
authored
Fix useless_asref suggests wrongly when used in ctor (#16115)
Closes #16098 changelog: [`useless_asref`] fix wrong suggestions when used in ctor
2 parents 4d2729b + 1a86849 commit 93a4992

File tree

4 files changed

+127
-3
lines changed

4 files changed

+127
-3
lines changed

clippy_lints/src/methods/useless_asref.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::ty::{implements_trait, peel_and_count_ty_refs, should_call_clone_as_function};
55
use clippy_utils::{get_parent_expr, peel_blocks, strip_pat_refs};
66
use rustc_errors::Applicability;
7-
use rustc_hir::{self as hir, LangItem};
7+
use rustc_hir::def::{DefKind, Res};
8+
use rustc_hir::{self as hir, LangItem, Node};
89
use rustc_lint::LateContext;
910
use rustc_middle::ty::adjustment::Adjust;
1011
use rustc_middle::ty::{Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
@@ -69,14 +70,37 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, call_name: Symbo
6970
}
7071
}
7172

73+
// Add `*` derefs if the expr is used in a ctor, because automatic derefs don't apply in that case.
74+
let deref = if rcv_depth > res_depth {
75+
let parent = cx.tcx.parent_hir_node(expr.hir_id);
76+
match parent {
77+
Node::ExprField(_) => "*".repeat(rcv_depth - res_depth),
78+
Node::Expr(parent)
79+
if let hir::ExprKind::Call(func, _) = parent.kind
80+
&& let (_, Some(path)) = func.opt_res_path()
81+
&& matches!(path.res, Res::Def(DefKind::Ctor(_, _), _) | Res::SelfCtor(_)) =>
82+
{
83+
"*".repeat(rcv_depth - res_depth)
84+
},
85+
_ => String::new(),
86+
}
87+
} else {
88+
String::new()
89+
};
90+
7291
let mut applicability = Applicability::MachineApplicable;
92+
let suggestion = format!(
93+
"{deref}{}",
94+
snippet_with_applicability(cx, recvr.span, "..", &mut applicability)
95+
);
96+
7397
span_lint_and_sugg(
7498
cx,
7599
USELESS_ASREF,
76100
expr.span,
77101
format!("this call to `{call_name}` does nothing"),
78102
"try",
79-
snippet_with_applicability(cx, recvr.span, "..", &mut applicability).to_string(),
103+
suggestion,
80104
applicability,
81105
);
82106
}

tests/ui/useless_asref.fixed

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,41 @@ fn issue_14828() {
258258
().as_ref();
259259
}
260260

261+
fn issue16098(exts: Vec<&str>) {
262+
use std::borrow::Cow;
263+
264+
let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(*s)).collect();
265+
//~^ useless_asref
266+
267+
trait Identity {
268+
fn id(self) -> Self
269+
where
270+
Self: Sized,
271+
{
272+
self
273+
}
274+
}
275+
impl Identity for &str {}
276+
277+
let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(s.id())).collect();
278+
//~^ useless_asref
279+
280+
let v: Vec<Cow<'_, str>> = exts
281+
.iter()
282+
.map(|s| Cow::Borrowed(*std::convert::identity(s)))
283+
//~^ useless_asref
284+
.collect();
285+
286+
struct Wrapper<'a>(&'a str);
287+
let exts_field: Vec<Wrapper> = exts.iter().map(|s| Wrapper(s)).collect();
288+
let v: Vec<Cow<'_, str>> = exts_field.iter().map(|w| Cow::Borrowed(w.0)).collect();
289+
//~^ useless_asref
290+
291+
let exts_index: Vec<&[&str]> = exts.iter().map(|s| std::slice::from_ref(s)).collect();
292+
let v: Vec<Cow<'_, str>> = exts_index.iter().map(|arr| Cow::Borrowed(arr[0])).collect();
293+
//~^ useless_asref
294+
}
295+
261296
fn main() {
262297
not_ok();
263298
ok();

tests/ui/useless_asref.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,41 @@ fn issue_14828() {
258258
().as_ref();
259259
}
260260

261+
fn issue16098(exts: Vec<&str>) {
262+
use std::borrow::Cow;
263+
264+
let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(s.as_ref())).collect();
265+
//~^ useless_asref
266+
267+
trait Identity {
268+
fn id(self) -> Self
269+
where
270+
Self: Sized,
271+
{
272+
self
273+
}
274+
}
275+
impl Identity for &str {}
276+
277+
let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(s.id().as_ref())).collect();
278+
//~^ useless_asref
279+
280+
let v: Vec<Cow<'_, str>> = exts
281+
.iter()
282+
.map(|s| Cow::Borrowed(std::convert::identity(s).as_ref()))
283+
//~^ useless_asref
284+
.collect();
285+
286+
struct Wrapper<'a>(&'a str);
287+
let exts_field: Vec<Wrapper> = exts.iter().map(|s| Wrapper(s)).collect();
288+
let v: Vec<Cow<'_, str>> = exts_field.iter().map(|w| Cow::Borrowed(w.0.as_ref())).collect();
289+
//~^ useless_asref
290+
291+
let exts_index: Vec<&[&str]> = exts.iter().map(|s| std::slice::from_ref(s)).collect();
292+
let v: Vec<Cow<'_, str>> = exts_index.iter().map(|arr| Cow::Borrowed(arr[0].as_ref())).collect();
293+
//~^ useless_asref
294+
}
295+
261296
fn main() {
262297
not_ok();
263298
ok();

tests/ui/useless_asref.stderr

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,5 +112,35 @@ error: this call to `as_ref.map(...)` does nothing
112112
LL | Some(1).as_ref().map(|&x| x.clone());
113113
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Some(1).clone()`
114114

115-
error: aborting due to 18 previous errors
115+
error: this call to `as_ref` does nothing
116+
--> tests/ui/useless_asref.rs:264:66
117+
|
118+
LL | let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(s.as_ref())).collect();
119+
| ^^^^^^^^^^ help: try: `*s`
120+
121+
error: this call to `as_ref` does nothing
122+
--> tests/ui/useless_asref.rs:277:66
123+
|
124+
LL | let v: Vec<Cow<'_, str>> = exts.iter().map(|s| Cow::Borrowed(s.id().as_ref())).collect();
125+
| ^^^^^^^^^^^^^^^ help: try: `s.id()`
126+
127+
error: this call to `as_ref` does nothing
128+
--> tests/ui/useless_asref.rs:282:32
129+
|
130+
LL | .map(|s| Cow::Borrowed(std::convert::identity(s).as_ref()))
131+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `*std::convert::identity(s)`
132+
133+
error: this call to `as_ref` does nothing
134+
--> tests/ui/useless_asref.rs:288:72
135+
|
136+
LL | let v: Vec<Cow<'_, str>> = exts_field.iter().map(|w| Cow::Borrowed(w.0.as_ref())).collect();
137+
| ^^^^^^^^^^^^ help: try: `w.0`
138+
139+
error: this call to `as_ref` does nothing
140+
--> tests/ui/useless_asref.rs:292:74
141+
|
142+
LL | let v: Vec<Cow<'_, str>> = exts_index.iter().map(|arr| Cow::Borrowed(arr[0].as_ref())).collect();
143+
| ^^^^^^^^^^^^^^^ help: try: `arr[0]`
144+
145+
error: aborting due to 23 previous errors
116146

0 commit comments

Comments
 (0)