Skip to content

Commit a40d8e4

Browse files
committed
Auto merge of #3679 - daxpedda:use_self, r=phansch
Fix automatic suggestion on `use_self`. In an example like this: ```rust impl Example { fn fun_1() { } fn fun_2() { Example::fun_1(); } } ``` Clippy tries to replace `Example::fun_1` with `Self`, loosing `::fun_1` in the process, it should rather try to replace `Example` with `Self`. **Question** - There may be other paths that need the same treatment, but I'm not sure I understand them fully: - https://github.com/rust-lang/rust-clippy/blob/e648adf0866a1cea7db6ce2d33ea86e442f25377/clippy_lints/src/use_self.rs#L94-L96 - https://github.com/rust-lang/rust-clippy/blob/e648adf0866a1cea7db6ce2d33ea86e442f25377/clippy_lints/src/use_self.rs#L225-L229
2 parents 280069d + 42d5a07 commit a40d8e4

File tree

4 files changed

+376
-31
lines changed

4 files changed

+376
-31
lines changed

clippy_lints/src/use_self.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@ impl LintPass for UseSelf {
5656
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
5757

5858
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
59+
// path segments only include actual path, no methods or fields
60+
let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span;
61+
// only take path up to the end of last_path_span
62+
let span = path.span.with_hi(last_path_span.hi());
63+
5964
span_lint_and_sugg(
6065
cx,
6166
USE_SELF,
62-
path.span,
67+
span,
6368
"unnecessary structure name repetition",
6469
"use the applicable keyword",
6570
"Self".to_owned(),

tests/ui/use_self.fixed

+299
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::use_self)]
4+
#![allow(dead_code)]
5+
#![allow(clippy::should_implement_trait)]
6+
7+
fn main() {}
8+
9+
mod use_self {
10+
struct Foo {}
11+
12+
impl Foo {
13+
fn new() -> Self {
14+
Self {}
15+
}
16+
fn test() -> Self {
17+
Self::new()
18+
}
19+
}
20+
21+
impl Default for Foo {
22+
fn default() -> Self {
23+
Self::new()
24+
}
25+
}
26+
}
27+
28+
mod better {
29+
struct Foo {}
30+
31+
impl Foo {
32+
fn new() -> Self {
33+
Self {}
34+
}
35+
fn test() -> Self {
36+
Self::new()
37+
}
38+
}
39+
40+
impl Default for Foo {
41+
fn default() -> Self {
42+
Self::new()
43+
}
44+
}
45+
}
46+
47+
mod lifetimes {
48+
struct Foo<'a> {
49+
foo_str: &'a str,
50+
}
51+
52+
impl<'a> Foo<'a> {
53+
// Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) ->
54+
// Foo<'b>`
55+
fn foo(s: &str) -> Foo {
56+
Foo { foo_str: s }
57+
}
58+
// cannot replace with `Self`, because that's `Foo<'a>`
59+
fn bar() -> Foo<'static> {
60+
Foo { foo_str: "foo" }
61+
}
62+
63+
// FIXME: the lint does not handle lifetimed struct
64+
// `Self` should be applicable here
65+
fn clone(&self) -> Foo<'a> {
66+
Foo { foo_str: self.foo_str }
67+
}
68+
}
69+
}
70+
71+
#[allow(clippy::boxed_local)]
72+
mod traits {
73+
74+
use std::ops::Mul;
75+
76+
trait SelfTrait {
77+
fn refs(p1: &Self) -> &Self;
78+
fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self;
79+
fn mut_refs(p1: &mut Self) -> &mut Self;
80+
fn nested(p1: Box<Self>, p2: (&u8, &Self));
81+
fn vals(r: Self) -> Self;
82+
}
83+
84+
#[derive(Default)]
85+
struct Bad;
86+
87+
impl SelfTrait for Bad {
88+
fn refs(p1: &Self) -> &Self {
89+
p1
90+
}
91+
92+
fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self {
93+
p1
94+
}
95+
96+
fn mut_refs(p1: &mut Self) -> &mut Self {
97+
p1
98+
}
99+
100+
fn nested(_p1: Box<Self>, _p2: (&u8, &Self)) {}
101+
102+
fn vals(_: Self) -> Self {
103+
Self::default()
104+
}
105+
}
106+
107+
impl Mul for Bad {
108+
type Output = Self;
109+
110+
fn mul(self, rhs: Self) -> Self {
111+
rhs
112+
}
113+
}
114+
115+
#[derive(Default)]
116+
struct Good;
117+
118+
impl SelfTrait for Good {
119+
fn refs(p1: &Self) -> &Self {
120+
p1
121+
}
122+
123+
fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self {
124+
p1
125+
}
126+
127+
fn mut_refs(p1: &mut Self) -> &mut Self {
128+
p1
129+
}
130+
131+
fn nested(_p1: Box<Self>, _p2: (&u8, &Self)) {}
132+
133+
fn vals(_: Self) -> Self {
134+
Self::default()
135+
}
136+
}
137+
138+
impl Mul for Good {
139+
type Output = Self;
140+
141+
fn mul(self, rhs: Self) -> Self {
142+
rhs
143+
}
144+
}
145+
146+
trait NameTrait {
147+
fn refs(p1: &u8) -> &u8;
148+
fn ref_refs<'a>(p1: &'a &'a u8) -> &'a &'a u8;
149+
fn mut_refs(p1: &mut u8) -> &mut u8;
150+
fn nested(p1: Box<u8>, p2: (&u8, &u8));
151+
fn vals(p1: u8) -> u8;
152+
}
153+
154+
// Using `Self` instead of the type name is OK
155+
impl NameTrait for u8 {
156+
fn refs(p1: &Self) -> &Self {
157+
p1
158+
}
159+
160+
fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self {
161+
p1
162+
}
163+
164+
fn mut_refs(p1: &mut Self) -> &mut Self {
165+
p1
166+
}
167+
168+
fn nested(_p1: Box<Self>, _p2: (&Self, &Self)) {}
169+
170+
fn vals(_: Self) -> Self {
171+
Self::default()
172+
}
173+
}
174+
175+
// Check that self arg isn't linted
176+
impl Clone for Good {
177+
fn clone(&self) -> Self {
178+
// Note: Not linted and it wouldn't be valid
179+
// because "can't use `Self` as a constructor`"
180+
Good
181+
}
182+
}
183+
}
184+
185+
mod issue2894 {
186+
trait IntoBytes {
187+
fn into_bytes(&self) -> Vec<u8>;
188+
}
189+
190+
// This should not be linted
191+
impl IntoBytes for u8 {
192+
fn into_bytes(&self) -> Vec<u8> {
193+
vec![*self]
194+
}
195+
}
196+
}
197+
198+
mod existential {
199+
struct Foo;
200+
201+
impl Foo {
202+
fn bad(foos: &[Self]) -> impl Iterator<Item = &Self> {
203+
foos.iter()
204+
}
205+
206+
fn good(foos: &[Self]) -> impl Iterator<Item = &Self> {
207+
foos.iter()
208+
}
209+
}
210+
}
211+
212+
mod tuple_structs {
213+
pub struct TS(i32);
214+
215+
impl TS {
216+
pub fn ts() -> Self {
217+
Self(0)
218+
}
219+
}
220+
}
221+
222+
mod macros {
223+
macro_rules! use_self_expand {
224+
() => {
225+
fn new() -> Self {
226+
Self {}
227+
}
228+
};
229+
}
230+
231+
struct Foo {}
232+
233+
impl Foo {
234+
use_self_expand!(); // Should lint in local macros
235+
}
236+
}
237+
238+
mod nesting {
239+
struct Foo {}
240+
impl Foo {
241+
fn foo() {
242+
use self::Foo; // Can't use Self here
243+
struct Bar {
244+
foo: Foo, // Foo != Self
245+
}
246+
247+
impl Bar {
248+
fn bar() -> Self {
249+
Self { foo: Foo {} }
250+
}
251+
}
252+
}
253+
}
254+
255+
enum Enum {
256+
A,
257+
}
258+
impl Enum {
259+
fn method() {
260+
#[allow(unused_imports)]
261+
use self::Enum::*; // Issue 3425
262+
static STATIC: Enum = Enum::A; // Can't use Self as type
263+
}
264+
}
265+
}
266+
267+
mod issue3410 {
268+
269+
struct A;
270+
struct B;
271+
272+
trait Trait<T> {
273+
fn a(v: T);
274+
}
275+
276+
impl Trait<Vec<A>> for Vec<B> {
277+
fn a(_: Vec<A>) {}
278+
}
279+
}
280+
281+
#[allow(clippy::no_effect, path_statements)]
282+
mod rustfix {
283+
mod nested {
284+
pub struct A {}
285+
}
286+
287+
impl nested::A {
288+
const A: bool = true;
289+
290+
fn fun_1() {}
291+
292+
fn fun_2() {
293+
Self::fun_1();
294+
Self::A;
295+
296+
Self {};
297+
}
298+
}
299+
}

tests/ui/use_self.rs

+23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// run-rustfix
2+
13
#![warn(clippy::use_self)]
24
#![allow(dead_code)]
35
#![allow(clippy::should_implement_trait)]
@@ -255,6 +257,7 @@ mod nesting {
255257
}
256258
impl Enum {
257259
fn method() {
260+
#[allow(unused_imports)]
258261
use self::Enum::*; // Issue 3425
259262
static STATIC: Enum = Enum::A; // Can't use Self as type
260263
}
@@ -274,3 +277,23 @@ mod issue3410 {
274277
fn a(_: Vec<A>) {}
275278
}
276279
}
280+
281+
#[allow(clippy::no_effect, path_statements)]
282+
mod rustfix {
283+
mod nested {
284+
pub struct A {}
285+
}
286+
287+
impl nested::A {
288+
const A: bool = true;
289+
290+
fn fun_1() {}
291+
292+
fn fun_2() {
293+
nested::A::fun_1();
294+
nested::A::A;
295+
296+
nested::A {};
297+
}
298+
}
299+
}

0 commit comments

Comments
 (0)