Skip to content

Commit 40ec760

Browse files
committed
fix doc test failure;
apply review suggestions by @Centri3: use multi suggestion; change output message format; add macro expansion check & tests;
1 parent 28d5115 commit 40ec760

File tree

4 files changed

+142
-85
lines changed

4 files changed

+142
-85
lines changed

clippy_lints/src/functions/mod.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,8 @@ declare_clippy_lint! {
371371
///
372372
/// ### Example
373373
/// ```rust
374+
/// struct A(u32);
375+
///
374376
/// impl From<A> for String {
375377
/// fn from(a: A) -> Self {
376378
/// a.0.to_string()
@@ -379,6 +381,8 @@ declare_clippy_lint! {
379381
/// ```
380382
/// Use instead:
381383
/// ```rust
384+
/// struct A(u32);
385+
///
382386
/// impl From<A> for String {
383387
/// fn from(value: A) -> Self {
384388
/// value.0.to_string()

clippy_lints/src/functions/renamed_function_params.rs

Lines changed: 63 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,93 @@
1-
use clippy_utils::diagnostics::span_lint_and_help;
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use rustc_errors::{Applicability, MultiSpan};
23
use rustc_hir::def_id::DefId;
34
use rustc_hir::hir_id::OwnerId;
45
use rustc_hir::{ImplItem, ImplItemKind, ItemKind, Node};
56
use rustc_lint::LateContext;
6-
use rustc_span::symbol::{Ident, Symbol};
7+
use rustc_span::symbol::{kw, Ident, Symbol};
78
use rustc_span::Span;
89

910
use super::RENAMED_FUNCTION_PARAMS;
1011

1112
pub(super) fn check_impl_item(cx: &LateContext<'_>, item: &ImplItem<'_>) {
12-
if let ImplItemKind::Fn(_, body_id) = item.kind &&
13-
let Some(did) = impled_item_def_id(cx, item.owner_id)
13+
if !item.span.from_expansion()
14+
&& let ImplItemKind::Fn(_, body_id) = item.kind
15+
&& let Some(did) = trait_item_def_id_of_impl(cx, item.owner_id)
1416
{
1517
let mut param_idents_iter = cx.tcx.hir().body_param_names(body_id);
1618
let mut default_param_idents_iter = cx.tcx.fn_arg_names(did).iter().copied();
1719

18-
let renames = renamed_params(&mut default_param_idents_iter, &mut param_idents_iter);
19-
// FIXME: Should we use `MultiSpan` to combine output together?
20-
// But how should we display help message if so.
21-
for rename in renames {
22-
span_lint_and_help(
20+
let renames = RenamedFnArgs::new(&mut default_param_idents_iter, &mut param_idents_iter);
21+
if !renames.0.is_empty() {
22+
let multi_span = renames.multi_span();
23+
let plural = if renames.0.len() == 1 { "" } else { "s" };
24+
span_lint_and_then(
2325
cx,
2426
RENAMED_FUNCTION_PARAMS,
25-
rename.renamed_span,
26-
"function parameter name was renamed from its trait default",
27-
None,
28-
&format!("consider changing the name to: '{}'", rename.default_name.as_str())
27+
multi_span,
28+
&format!("renamed function parameter{plural} of trait impl"),
29+
|diag| {
30+
diag.multipart_suggestion(
31+
format!("consider using the default name{plural}"),
32+
renames.0,
33+
Applicability::Unspecified,
34+
);
35+
},
2936
);
3037
}
3138
}
3239
}
3340

34-
struct RenamedParam {
35-
renamed_span: Span,
36-
default_name: Symbol,
37-
}
41+
struct RenamedFnArgs(Vec<(Span, String)>);
3842

39-
fn renamed_params<I, T>(default_names: &mut I, current_names: &mut T) -> Vec<RenamedParam>
40-
where
41-
I: Iterator<Item = Ident>,
42-
T: Iterator<Item = Ident>,
43-
{
44-
let mut renamed = vec![];
45-
// FIXME: Should we stop if they have different length?
46-
while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) {
47-
let current_name = cur_name.name;
48-
let default_name = def_name.name;
49-
if is_ignored_or_empty_symbol(current_name) || is_ignored_or_empty_symbol(default_name) {
50-
continue;
51-
}
52-
if current_name != default_name {
53-
renamed.push(RenamedParam {
54-
renamed_span: cur_name.span,
55-
default_name,
56-
});
43+
impl RenamedFnArgs {
44+
/// Comparing between an iterator of default names and one with current names,
45+
/// then collect the ones that got renamed.
46+
fn new<I, T>(default_names: &mut I, current_names: &mut T) -> Self
47+
where
48+
I: Iterator<Item = Ident>,
49+
T: Iterator<Item = Ident>,
50+
{
51+
let mut renamed: Vec<(Span, String)> = vec![];
52+
53+
debug_assert!(default_names.size_hint() == current_names.size_hint());
54+
while let (Some(def_name), Some(cur_name)) = (default_names.next(), current_names.next()) {
55+
let current_name = cur_name.name;
56+
let default_name = def_name.name;
57+
if is_unused_or_empty_symbol(current_name) || is_unused_or_empty_symbol(default_name) {
58+
continue;
59+
}
60+
if current_name != default_name {
61+
renamed.push((cur_name.span, default_name.to_string()));
62+
}
5763
}
64+
65+
Self(renamed)
66+
}
67+
68+
fn multi_span(&self) -> MultiSpan {
69+
self.0
70+
.iter()
71+
.map(|(span, _)| span)
72+
.copied()
73+
.collect::<Vec<Span>>()
74+
.into()
5875
}
59-
renamed
6076
}
6177

62-
fn is_ignored_or_empty_symbol(symbol: Symbol) -> bool {
63-
let s = symbol.as_str();
64-
s.is_empty() || s.starts_with('_')
78+
fn is_unused_or_empty_symbol(symbol: Symbol) -> bool {
79+
// FIXME: `body_param_names` currently returning empty symbols for `wild` as well,
80+
// so we need to check if the symbol is empty first.
81+
// Therefore the check of whether it's equal to [`kw::Underscore`] has no use for now,
82+
// but it would be nice to keep it here just to be future-proof.
83+
symbol.is_empty() || symbol == kw::Underscore || symbol.as_str().starts_with('_')
6584
}
6685

67-
fn impled_item_def_id(cx: &LateContext<'_>, impl_item_id: OwnerId) -> Option<DefId> {
68-
let trait_node = cx.tcx.hir().find_parent(impl_item_id.into())?;
69-
if let Node::Item(item) = trait_node &&
70-
let ItemKind::Impl(impl_) = &item.kind
86+
/// Get the [`trait_item_def_id`](rustc_hir::hir::ImplItemRef::trait_item_def_id) of an impl item.
87+
fn trait_item_def_id_of_impl(cx: &LateContext<'_>, impl_item_id: OwnerId) -> Option<DefId> {
88+
let trait_node = cx.tcx.parent_hir_node(impl_item_id.into());
89+
if let Node::Item(item) = trait_node
90+
&& let ItemKind::Impl(impl_) = &item.kind
7191
{
7292
impl_.items.iter().find_map(|item| {
7393
if item.id.owner_id == impl_item_id {

tests/ui/renamed_function_params.rs

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
//@no-rustfix
12
#![warn(clippy::renamed_function_params)]
2-
#![allow(clippy::partialeq_ne_impl)]
3+
#![allow(clippy::partialeq_ne_impl, clippy::to_string_trait_impl)]
34
#![allow(unused)]
45

56
use std::hash::{Hash, Hasher};
@@ -19,17 +20,17 @@ impl ToString for A {
1920
struct B(u32);
2021
impl From<B> for String {
2122
fn from(b: B) -> Self {
22-
//~^ ERROR: function parameter name was renamed from its trait default
23+
//~^ ERROR: renamed function parameter of trait impl
2324
b.0.to_string()
2425
}
2526
}
2627
impl PartialEq for B {
2728
fn eq(&self, rhs: &Self) -> bool {
28-
//~^ ERROR: function parameter name was renamed from its trait default
29+
//~^ ERROR: renamed function parameter of trait impl
2930
self.0 == rhs.0
3031
}
3132
fn ne(&self, rhs: &Self) -> bool {
32-
//~^ ERROR: function parameter name was renamed from its trait default
33+
//~^ ERROR: renamed function parameter of trait impl
3334
self.0 != rhs.0
3435
}
3536
}
@@ -38,22 +39,24 @@ trait MyTrait {
3839
fn foo(&self, val: u8);
3940
fn bar(a: u8, b: u8);
4041
fn baz(self, _val: u8);
42+
fn quz(&self, _: u8);
4143
}
4244

4345
impl MyTrait for B {
4446
fn foo(&self, i_dont_wanna_use_your_name: u8) {}
45-
//~^ ERROR: function parameter name was renamed from its trait default
46-
fn bar(_a: u8, _b: u8) {}
47+
//~^ ERROR: renamed function parameter of trait impl
48+
fn bar(_a: u8, _: u8) {}
4749
fn baz(self, val: u8) {}
50+
fn quz(&self, val: u8) {}
4851
}
4952

5053
impl Hash for B {
5154
fn hash<H: Hasher>(&self, states: &mut H) {
52-
//~^ ERROR: function parameter name was renamed from its trait default
55+
//~^ ERROR: renamed function parameter of trait impl
5356
self.0.hash(states);
5457
}
5558
fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
56-
//~^ ERROR: function parameter name was renamed from its trait default
59+
//~^ ERROR: renamed function parameters of trait impl
5760
for d in date {
5861
d.hash(states);
5962
}
@@ -65,4 +68,42 @@ impl B {
6568
fn some_fn(&self, other: impl MyTrait) {}
6669
}
6770

71+
#[derive(Copy, Clone)]
72+
enum C {
73+
A,
74+
B(u32),
75+
}
76+
77+
impl std::ops::Add<B> for C {
78+
type Output = C;
79+
fn add(self, b: B) -> C {
80+
//~^ ERROR: renamed function parameter of trait impl
81+
C::B(b.0)
82+
}
83+
}
84+
85+
impl From<A> for C {
86+
fn from(_: A) -> C {
87+
C::A
88+
}
89+
}
90+
91+
trait CustomTraitA {
92+
fn foo(&self, other: u32);
93+
}
94+
trait CustomTraitB {
95+
fn bar(&self, value: u8);
96+
}
97+
98+
macro_rules! impl_trait {
99+
($impl_for:ident, $tr:ty, $fn_name:ident, $t:ty) => {
100+
impl $tr for $impl_for {
101+
fn $fn_name(&self, v: $t) {}
102+
}
103+
};
104+
}
105+
106+
impl_trait!(C, CustomTraitA, foo, u32);
107+
impl_trait!(C, CustomTraitB, bar, u8);
108+
68109
fn main() {}
Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,52 @@
1-
error: function parameter name was renamed from its trait default
2-
--> $DIR/renamed_function_params.rs:21:13
1+
error: renamed function parameter of trait impl
2+
--> tests/ui/renamed_function_params.rs:22:13
33
|
44
LL | fn from(b: B) -> Self {
5-
| ^
5+
| ^ help: consider using the default name: `value`
66
|
7-
= help: consider changing the name to: 'value'
87
= note: `-D clippy::renamed-function-params` implied by `-D warnings`
98
= help: to override `-D warnings` add `#[allow(clippy::renamed_function_params)]`
109

11-
error: function parameter name was renamed from its trait default
12-
--> $DIR/renamed_function_params.rs:27:18
10+
error: renamed function parameter of trait impl
11+
--> tests/ui/renamed_function_params.rs:28:18
1312
|
1413
LL | fn eq(&self, rhs: &Self) -> bool {
15-
| ^^^
16-
|
17-
= help: consider changing the name to: 'other'
14+
| ^^^ help: consider using the default name: `other`
1815

19-
error: function parameter name was renamed from its trait default
20-
--> $DIR/renamed_function_params.rs:31:18
16+
error: renamed function parameter of trait impl
17+
--> tests/ui/renamed_function_params.rs:32:18
2118
|
2219
LL | fn ne(&self, rhs: &Self) -> bool {
23-
| ^^^
24-
|
25-
= help: consider changing the name to: 'other'
20+
| ^^^ help: consider using the default name: `other`
2621

27-
error: function parameter name was renamed from its trait default
28-
--> $DIR/renamed_function_params.rs:44:19
22+
error: renamed function parameter of trait impl
23+
--> tests/ui/renamed_function_params.rs:46:19
2924
|
3025
LL | fn foo(&self, i_dont_wanna_use_your_name: u8) {}
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
32-
|
33-
= help: consider changing the name to: 'val'
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the default name: `val`
3427

35-
error: function parameter name was renamed from its trait default
36-
--> $DIR/renamed_function_params.rs:51:31
28+
error: renamed function parameter of trait impl
29+
--> tests/ui/renamed_function_params.rs:54:31
3730
|
3831
LL | fn hash<H: Hasher>(&self, states: &mut H) {
39-
| ^^^^^^
40-
|
41-
= help: consider changing the name to: 'state'
32+
| ^^^^^^ help: consider using the default name: `state`
4233

43-
error: function parameter name was renamed from its trait default
44-
--> $DIR/renamed_function_params.rs:55:30
34+
error: renamed function parameters of trait impl
35+
--> tests/ui/renamed_function_params.rs:58:30
4536
|
4637
LL | fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
47-
| ^^^^
38+
| ^^^^ ^^^^^^
4839
|
49-
= help: consider changing the name to: 'data'
50-
51-
error: function parameter name was renamed from its trait default
52-
--> $DIR/renamed_function_params.rs:55:45
40+
help: consider using the default names
5341
|
54-
LL | fn hash_slice<H: Hasher>(date: &[Self], states: &mut H) {
55-
| ^^^^^^
42+
LL | fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) {
43+
| ~~~~ ~~~~~
44+
45+
error: renamed function parameter of trait impl
46+
--> tests/ui/renamed_function_params.rs:79:18
5647
|
57-
= help: consider changing the name to: 'state'
48+
LL | fn add(self, b: B) -> C {
49+
| ^ help: consider using the default name: `rhs`
5850

5951
error: aborting due to 7 previous errors
6052

0 commit comments

Comments
 (0)