Skip to content

Commit 9f9e9f7

Browse files
committed
Auto merge of #6316 - ThibsG:WrongSelfConventionTraitDef, r=ebroto
Lint also in trait def for `wrong_self_convention` Extends `wrong_self_convention` to lint also in trait definition. By the way, I think the `wrong_pub_self_convention` [example](https://github.com/rust-lang/rust-clippy/blob/dd826b4626c00da53f76f00f02f03556803e9cdb/clippy_lints/src/methods/mod.rs#L197) is misleading. On [playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=32615ab3f6009e7e42cc3754be0ca17f), it fires `wrong_self_convention`, so the example (or the lint maybe?) needs to be reworked. The difference with `wrong_self_convention` [example](https://github.com/rust-lang/rust-clippy/blob/dd826b4626c00da53f76f00f02f03556803e9cdb/clippy_lints/src/methods/mod.rs#L172) is mainly the `pub` keyword on the method `as_str`, but the lint doesn't use the function visibility as condition to choose which lint to fire (in fact it uses the visibility of the impl item). fixes: #6307 changelog: Lint `wrong_self_convention` lint in trait def also
2 parents 0904f54 + 90a16e4 commit 9f9e9f7

File tree

6 files changed

+195
-53
lines changed

6 files changed

+195
-53
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 64 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_semver::RustcVersion;
2222
use rustc_session::{declare_tool_lint, impl_lint_pass};
2323
use rustc_span::source_map::Span;
2424
use rustc_span::symbol::{sym, SymbolStr};
25+
use rustc_typeck::hir_ty_to_ty;
2526

2627
use crate::consts::{constant, Constant};
2728
use crate::utils::eager_or_lazy::is_lazyness_candidate;
@@ -1623,10 +1624,15 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16231624
let item = cx.tcx.hir().expect_item(parent);
16241625
let def_id = cx.tcx.hir().local_def_id(item.hir_id);
16251626
let self_ty = cx.tcx.type_of(def_id);
1627+
1628+
// if this impl block implements a trait, lint in trait definition instead
1629+
if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
1630+
return;
1631+
}
1632+
16261633
if_chain! {
16271634
if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind;
16281635
if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next();
1629-
if let hir::ItemKind::Impl{ of_trait: None, .. } = item.kind;
16301636

16311637
let method_def_id = cx.tcx.hir().local_def_id(impl_item.hir_id);
16321638
let method_sig = cx.tcx.fn_sig(method_def_id);
@@ -1668,40 +1674,17 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16681674
}
16691675
}
16701676

1671-
if let Some((ref conv, self_kinds)) = &CONVENTIONS
1672-
.iter()
1673-
.find(|(ref conv, _)| conv.check(&name))
1674-
{
1675-
if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) {
1676-
let lint = if item.vis.node.is_pub() {
1677-
WRONG_PUB_SELF_CONVENTION
1678-
} else {
1679-
WRONG_SELF_CONVENTION
1680-
};
1681-
1682-
span_lint(
1683-
cx,
1684-
lint,
1685-
first_arg.pat.span,
1686-
&format!("methods called `{}` usually take {}; consider choosing a less ambiguous name",
1687-
conv,
1688-
&self_kinds
1689-
.iter()
1690-
.map(|k| k.description())
1691-
.collect::<Vec<_>>()
1692-
.join(" or ")
1693-
),
1694-
);
1695-
}
1696-
}
1677+
lint_wrong_self_convention(
1678+
cx,
1679+
&name,
1680+
item.vis.node.is_pub(),
1681+
self_ty,
1682+
first_arg_ty,
1683+
first_arg.pat.span
1684+
);
16971685
}
16981686
}
16991687

1700-
// if this impl block implements a trait, lint in trait definition instead
1701-
if let hir::ItemKind::Impl { of_trait: Some(_), .. } = item.kind {
1702-
return;
1703-
}
1704-
17051688
if let hir::ImplItemKind::Fn(_, _) = impl_item.kind {
17061689
let ret_ty = return_ty(cx, impl_item.hir_id);
17071690

@@ -1735,8 +1718,23 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
17351718
}
17361719

17371720
fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>) {
1721+
if in_external_macro(cx.tcx.sess, item.span) {
1722+
return;
1723+
}
1724+
1725+
if_chain! {
1726+
if let TraitItemKind::Fn(ref sig, _) = item.kind;
1727+
if let Some(first_arg_ty) = sig.decl.inputs.iter().next();
1728+
let first_arg_span = first_arg_ty.span;
1729+
let first_arg_ty = hir_ty_to_ty(cx.tcx, first_arg_ty);
1730+
let self_ty = TraitRef::identity(cx.tcx, item.hir_id.owner.to_def_id()).self_ty();
1731+
1732+
then {
1733+
lint_wrong_self_convention(cx, &item.ident.name.as_str(), false, self_ty, first_arg_ty, first_arg_span);
1734+
}
1735+
}
1736+
17381737
if_chain! {
1739-
if !in_external_macro(cx.tcx.sess, item.span);
17401738
if item.ident.name == sym::new;
17411739
if let TraitItemKind::Fn(_, _) = item.kind;
17421740
let ret_ty = return_ty(cx, item.hir_id);
@@ -1757,6 +1755,39 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
17571755
extract_msrv_attr!(LateContext);
17581756
}
17591757

1758+
fn lint_wrong_self_convention<'tcx>(
1759+
cx: &LateContext<'tcx>,
1760+
item_name: &str,
1761+
is_pub: bool,
1762+
self_ty: &'tcx TyS<'tcx>,
1763+
first_arg_ty: &'tcx TyS<'tcx>,
1764+
first_arg_span: Span,
1765+
) {
1766+
let lint = if is_pub {
1767+
WRONG_PUB_SELF_CONVENTION
1768+
} else {
1769+
WRONG_SELF_CONVENTION
1770+
};
1771+
if let Some((ref conv, self_kinds)) = &CONVENTIONS.iter().find(|(ref conv, _)| conv.check(item_name)) {
1772+
if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) {
1773+
span_lint(
1774+
cx,
1775+
lint,
1776+
first_arg_span,
1777+
&format!(
1778+
"methods called `{}` usually take {}; consider choosing a less ambiguous name",
1779+
conv,
1780+
&self_kinds
1781+
.iter()
1782+
.map(|k| k.description())
1783+
.collect::<Vec<_>>()
1784+
.join(" or ")
1785+
),
1786+
);
1787+
}
1788+
}
1789+
}
1790+
17601791
/// Checks for the `OR_FUN_CALL` lint.
17611792
#[allow(clippy::too_many_lines)]
17621793
fn lint_or_fun_call<'tcx>(

tests/ui/use_self.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ mod lifetimes {
7171

7272
mod issue2894 {
7373
trait IntoBytes {
74+
#[allow(clippy::wrong_self_convention)]
7475
fn into_bytes(&self) -> Vec<u8>;
7576
}
7677

tests/ui/use_self.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ mod lifetimes {
7171

7272
mod issue2894 {
7373
trait IntoBytes {
74+
#[allow(clippy::wrong_self_convention)]
7475
fn into_bytes(&self) -> Vec<u8>;
7576
}
7677

tests/ui/use_self.stderr

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ LL | Foo::new()
3737
| ^^^ help: use the applicable keyword: `Self`
3838

3939
error: unnecessary structure name repetition
40-
--> $DIR/use_self.rs:89:56
40+
--> $DIR/use_self.rs:90:56
4141
|
4242
LL | fn bad(foos: &[Self]) -> impl Iterator<Item = &Foo> {
4343
| ^^^ help: use the applicable keyword: `Self`
4444

4545
error: unnecessary structure name repetition
46-
--> $DIR/use_self.rs:104:13
46+
--> $DIR/use_self.rs:105:13
4747
|
4848
LL | TS(0)
4949
| ^^ help: use the applicable keyword: `Self`
5050

5151
error: unnecessary structure name repetition
52-
--> $DIR/use_self.rs:112:25
52+
--> $DIR/use_self.rs:113:25
5353
|
5454
LL | fn new() -> Foo {
5555
| ^^^ help: use the applicable keyword: `Self`
@@ -60,7 +60,7 @@ LL | use_self_expand!(); // Should lint in local macros
6060
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
6161

6262
error: unnecessary structure name repetition
63-
--> $DIR/use_self.rs:113:17
63+
--> $DIR/use_self.rs:114:17
6464
|
6565
LL | Foo {}
6666
| ^^^ help: use the applicable keyword: `Self`
@@ -71,91 +71,91 @@ LL | use_self_expand!(); // Should lint in local macros
7171
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
7272

7373
error: unnecessary structure name repetition
74-
--> $DIR/use_self.rs:148:21
74+
--> $DIR/use_self.rs:149:21
7575
|
7676
LL | fn baz() -> Foo {
7777
| ^^^ help: use the applicable keyword: `Self`
7878

7979
error: unnecessary structure name repetition
80-
--> $DIR/use_self.rs:149:13
80+
--> $DIR/use_self.rs:150:13
8181
|
8282
LL | Foo {}
8383
| ^^^ help: use the applicable keyword: `Self`
8484

8585
error: unnecessary structure name repetition
86-
--> $DIR/use_self.rs:136:29
86+
--> $DIR/use_self.rs:137:29
8787
|
8888
LL | fn bar() -> Bar {
8989
| ^^^ help: use the applicable keyword: `Self`
9090

9191
error: unnecessary structure name repetition
92-
--> $DIR/use_self.rs:137:21
92+
--> $DIR/use_self.rs:138:21
9393
|
9494
LL | Bar { foo: Foo {} }
9595
| ^^^ help: use the applicable keyword: `Self`
9696

9797
error: unnecessary structure name repetition
98-
--> $DIR/use_self.rs:166:21
98+
--> $DIR/use_self.rs:167:21
9999
|
100100
LL | let _ = Enum::B(42);
101101
| ^^^^ help: use the applicable keyword: `Self`
102102

103103
error: unnecessary structure name repetition
104-
--> $DIR/use_self.rs:167:21
104+
--> $DIR/use_self.rs:168:21
105105
|
106106
LL | let _ = Enum::C { field: true };
107107
| ^^^^ help: use the applicable keyword: `Self`
108108

109109
error: unnecessary structure name repetition
110-
--> $DIR/use_self.rs:168:21
110+
--> $DIR/use_self.rs:169:21
111111
|
112112
LL | let _ = Enum::A;
113113
| ^^^^ help: use the applicable keyword: `Self`
114114

115115
error: unnecessary structure name repetition
116-
--> $DIR/use_self.rs:199:13
116+
--> $DIR/use_self.rs:200:13
117117
|
118118
LL | nested::A::fun_1();
119119
| ^^^^^^^^^ help: use the applicable keyword: `Self`
120120

121121
error: unnecessary structure name repetition
122-
--> $DIR/use_self.rs:200:13
122+
--> $DIR/use_self.rs:201:13
123123
|
124124
LL | nested::A::A;
125125
| ^^^^^^^^^ help: use the applicable keyword: `Self`
126126

127127
error: unnecessary structure name repetition
128-
--> $DIR/use_self.rs:202:13
128+
--> $DIR/use_self.rs:203:13
129129
|
130130
LL | nested::A {};
131131
| ^^^^^^^^^ help: use the applicable keyword: `Self`
132132

133133
error: unnecessary structure name repetition
134-
--> $DIR/use_self.rs:221:13
134+
--> $DIR/use_self.rs:222:13
135135
|
136136
LL | TestStruct::from_something()
137137
| ^^^^^^^^^^ help: use the applicable keyword: `Self`
138138

139139
error: unnecessary structure name repetition
140-
--> $DIR/use_self.rs:235:25
140+
--> $DIR/use_self.rs:236:25
141141
|
142142
LL | async fn g() -> S {
143143
| ^ help: use the applicable keyword: `Self`
144144

145145
error: unnecessary structure name repetition
146-
--> $DIR/use_self.rs:236:13
146+
--> $DIR/use_self.rs:237:13
147147
|
148148
LL | S {}
149149
| ^ help: use the applicable keyword: `Self`
150150

151151
error: unnecessary structure name repetition
152-
--> $DIR/use_self.rs:240:16
152+
--> $DIR/use_self.rs:241:16
153153
|
154154
LL | &p[S::A..S::B]
155155
| ^ help: use the applicable keyword: `Self`
156156

157157
error: unnecessary structure name repetition
158-
--> $DIR/use_self.rs:240:22
158+
--> $DIR/use_self.rs:241:22
159159
|
160160
LL | &p[S::A..S::B]
161161
| ^ help: use the applicable keyword: `Self`

tests/ui/wrong_self_convention.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,52 @@ mod issue4037 {
8888
}
8989
}
9090
}
91+
92+
// Lint also in trait definition (see #6307)
93+
mod issue6307 {
94+
trait T: Sized {
95+
fn as_i32(self) {}
96+
fn as_u32(&self) {}
97+
fn into_i32(&self) {}
98+
fn into_u32(self) {}
99+
fn is_i32(self) {}
100+
fn is_u32(&self) {}
101+
fn to_i32(self) {}
102+
fn to_u32(&self) {}
103+
fn from_i32(self) {}
104+
// check whether the lint can be allowed at the function level
105+
#[allow(clippy::wrong_self_convention)]
106+
fn from_cake(self) {}
107+
108+
// test for false positives
109+
fn as_(self) {}
110+
fn into_(&self) {}
111+
fn is_(self) {}
112+
fn to_(self) {}
113+
fn from_(self) {}
114+
fn to_mut(&mut self) {}
115+
}
116+
117+
trait U {
118+
fn as_i32(self);
119+
fn as_u32(&self);
120+
fn into_i32(&self);
121+
fn into_u32(self);
122+
fn is_i32(self);
123+
fn is_u32(&self);
124+
fn to_i32(self);
125+
fn to_u32(&self);
126+
fn from_i32(self);
127+
// check whether the lint can be allowed at the function level
128+
#[allow(clippy::wrong_self_convention)]
129+
fn from_cake(self);
130+
131+
// test for false positives
132+
fn as_(self);
133+
fn into_(&self);
134+
fn is_(self);
135+
fn to_(self);
136+
fn from_(self);
137+
fn to_mut(&mut self);
138+
}
139+
}

0 commit comments

Comments
 (0)