Skip to content

Commit 41110b0

Browse files
committed
Extend the use_self lint to suggest uses of Self::Variant.
1 parent c3e9136 commit 41110b0

File tree

4 files changed

+76
-24
lines changed

4 files changed

+76
-24
lines changed

clippy_lints/src/use_self.rs

+38-20
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ declare_lint_pass!(UseSelf => [USE_SELF]);
5151

5252
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
5353

54-
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
54+
fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path, last_segment: Option<&PathSegment>) {
55+
let last_segment = last_segment.unwrap_or_else(|| path.segments.last().expect(SEGMENTS_MSG));
56+
5557
// Path segments only include actual path, no methods or fields.
56-
let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span;
58+
let last_path_span = last_segment.ident.span;
5759
// Only take path up to the end of last_path_span.
5860
let span = path.span.with_hi(last_path_span.hi());
5961

@@ -80,22 +82,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
8082
let trait_ty = self.trait_type_walker.next();
8183
let impl_ty = self.impl_type_walker.next();
8284

83-
if let TyKind::Path(QPath::Resolved(_, path)) = &t.node {
85+
if_chain! {
86+
if let TyKind::Path(QPath::Resolved(_, path)) = &t.node;
87+
8488
// The implementation and trait types don't match which means that
8589
// the concrete type was specified by the implementation
86-
if impl_ty != trait_ty {
87-
if let Some(impl_ty) = impl_ty {
88-
if self.item_type == impl_ty {
89-
let is_self_ty = if let def::Res::SelfTy(..) = path.res {
90-
true
91-
} else {
92-
false
93-
};
94-
95-
if !is_self_ty {
96-
span_use_self_lint(self.cx, path);
97-
}
98-
}
90+
if impl_ty != trait_ty;
91+
if let Some(impl_ty) = impl_ty;
92+
if self.item_type == impl_ty;
93+
then {
94+
match path.res {
95+
def::Res::SelfTy(..) => {},
96+
_ => span_use_self_lint(self.cx, path, None)
9997
}
10098
}
10199
}
@@ -220,15 +218,35 @@ struct UseSelfVisitor<'a, 'tcx> {
220218

221219
impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> {
222220
fn visit_path(&mut self, path: &'tcx Path, _id: HirId) {
221+
if path.segments.len() >= 2 {
222+
let last_but_one = &path.segments[path.segments.len() - 2];
223+
if last_but_one.ident.name != kw::SelfUpper {
224+
let enum_def_id = match path.res {
225+
Res::Def(DefKind::Variant, variant_def_id) =>
226+
self.cx.tcx.parent(variant_def_id),
227+
Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), ctor_def_id) => {
228+
let variant_def_id = self.cx.tcx.parent(ctor_def_id);
229+
variant_def_id.and_then(|def_id| self.cx.tcx.parent(def_id))
230+
}
231+
_ => None
232+
};
233+
234+
if self.item_path.res.opt_def_id() == enum_def_id {
235+
span_use_self_lint(self.cx, path, Some(last_but_one));
236+
}
237+
}
238+
}
239+
223240
if path.segments.last().expect(SEGMENTS_MSG).ident.name != kw::SelfUpper {
224241
if self.item_path.res == path.res {
225-
span_use_self_lint(self.cx, path);
226-
} else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_did) = path.res {
227-
if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_did) {
228-
span_use_self_lint(self.cx, path);
242+
span_use_self_lint(self.cx, path, None);
243+
} else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_def_id) = path.res {
244+
if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_def_id) {
245+
span_use_self_lint(self.cx, path, None);
229246
}
230247
}
231248
}
249+
232250
walk_path(self, path);
233251
}
234252

tests/ui/use_self.fixed

+8
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,21 @@ mod nesting {
265265

266266
enum Enum {
267267
A,
268+
B(u64),
269+
C { field: bool }
268270
}
269271
impl Enum {
270272
fn method() {
271273
#[allow(unused_imports)]
272274
use self::Enum::*; // Issue 3425
273275
static STATIC: Enum = Enum::A; // Can't use Self as type
274276
}
277+
278+
fn method2() {
279+
let _ = Self::B(42);
280+
let _ = Self::C { field: true };
281+
let _ = Self::A;
282+
}
275283
}
276284
}
277285

tests/ui/use_self.rs

+8
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,21 @@ mod nesting {
265265

266266
enum Enum {
267267
A,
268+
B(u64),
269+
C { field: bool }
268270
}
269271
impl Enum {
270272
fn method() {
271273
#[allow(unused_imports)]
272274
use self::Enum::*; // Issue 3425
273275
static STATIC: Enum = Enum::A; // Can't use Self as type
274276
}
277+
278+
fn method2() {
279+
let _ = Enum::B(42);
280+
let _ = Enum::C { field: true };
281+
let _ = Enum::A;
282+
}
275283
}
276284
}
277285

tests/ui/use_self.stderr

+22-4
Original file line numberDiff line numberDiff line change
@@ -175,22 +175,40 @@ LL | Bar { foo: Foo {} }
175175
| ^^^ help: use the applicable keyword: `Self`
176176

177177
error: unnecessary structure name repetition
178-
--> $DIR/use_self.rs:304:13
178+
--> $DIR/use_self.rs:279:21
179+
|
180+
LL | let _ = Enum::B(42);
181+
| ^^^^ help: use the applicable keyword: `Self`
182+
183+
error: unnecessary structure name repetition
184+
--> $DIR/use_self.rs:280:21
185+
|
186+
LL | let _ = Enum::C { field: true };
187+
| ^^^^ help: use the applicable keyword: `Self`
188+
189+
error: unnecessary structure name repetition
190+
--> $DIR/use_self.rs:281:21
191+
|
192+
LL | let _ = Enum::A;
193+
| ^^^^ help: use the applicable keyword: `Self`
194+
195+
error: unnecessary structure name repetition
196+
--> $DIR/use_self.rs:312:13
179197
|
180198
LL | nested::A::fun_1();
181199
| ^^^^^^^^^ help: use the applicable keyword: `Self`
182200

183201
error: unnecessary structure name repetition
184-
--> $DIR/use_self.rs:305:13
202+
--> $DIR/use_self.rs:313:13
185203
|
186204
LL | nested::A::A;
187205
| ^^^^^^^^^ help: use the applicable keyword: `Self`
188206

189207
error: unnecessary structure name repetition
190-
--> $DIR/use_self.rs:307:13
208+
--> $DIR/use_self.rs:315:13
191209
|
192210
LL | nested::A {};
193211
| ^^^^^^^^^ help: use the applicable keyword: `Self`
194212

195-
error: aborting due to 31 previous errors
213+
error: aborting due to 34 previous errors
196214

0 commit comments

Comments
 (0)