diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 653b6630b3c..b031e8b1c44 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -9,6 +9,7 @@ use crate::utils::{in_macro, span_lint_and_sugg}; use if_chain::if_chain; +use rustc::hir::def::{CtorKind, Def}; use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; @@ -25,7 +26,10 @@ use syntax_pos::symbol::keywords::SelfUpper; /// name /// feels inconsistent. /// -/// **Known problems:** None. +/// **Known problems:** +/// - False positive when using associated types (#2843) +/// - False positives in some situations when using generics (#3410) +/// - False positive when type from outer function can't be used (#3463) /// /// **Example:** /// ```rust @@ -226,10 +230,15 @@ struct UseSelfVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { - if self.item_path.def == path.def && path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { - span_use_self_lint(self.cx, path); + if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { + if self.item_path.def == path.def { + span_use_self_lint(self.cx, path); + } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def { + if self.item_path.def.opt_def_id() == self.cx.tcx.parent_def_id(ctor_did) { + span_use_self_lint(self.cx, path); + } + } } - walk_path(self, path); } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index c21df403035..b201e160ebd 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -51,8 +51,6 @@ mod better { } } -//todo the lint does not handle lifetimed struct -//the following module should trigger the lint on the third method only mod lifetimes { struct Foo<'a> { foo_str: &'a str, @@ -69,7 +67,8 @@ mod lifetimes { Foo { foo_str: "foo" } } - // `Self` is applicable here + // FIXME: the lint does not handle lifetimed struct + // `Self` should be applicable here fn clone(&self) -> Foo<'a> { Foo { foo_str: self.foo_str } } @@ -217,6 +216,16 @@ mod existential { } } +mod tuple_structs { + pub struct TS(i32); + + impl TS { + pub fn ts() -> Self { + TS(0) + } + } +} + mod issue3410 { struct A; diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 82b44d424df..d52fce76de5 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -37,94 +37,100 @@ LL | Foo::new() | ^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:22 + --> $DIR/use_self.rs:95:22 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:96:31 + --> $DIR/use_self.rs:95:31 | LL | fn refs(p1: &Bad) -> &Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:37 + --> $DIR/use_self.rs:99:37 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:100:53 + --> $DIR/use_self.rs:99:53 | LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:30 + --> $DIR/use_self.rs:103:30 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:104:43 + --> $DIR/use_self.rs:103:43 | LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:28 + --> $DIR/use_self.rs:107:28 | LL | fn nested(_p1: Box<Bad>, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:108:46 + --> $DIR/use_self.rs:107:46 | LL | fn nested(_p1: Box<Bad>, _p2: (&u8, &Bad)) {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:20 + --> $DIR/use_self.rs:109:20 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:110:28 + --> $DIR/use_self.rs:109:28 | LL | fn vals(_: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:111:13 + --> $DIR/use_self.rs:110:13 | LL | Bad::default() | ^^^^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:116:23 + --> $DIR/use_self.rs:115:23 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:27 + --> $DIR/use_self.rs:117:27 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:118:35 + --> $DIR/use_self.rs:117:35 | LL | fn mul(self, rhs: Bad) -> Bad { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:210:56 + --> $DIR/use_self.rs:209:56 | LL | fn bad(foos: &[Self]) -> impl Iterator<Item = &Foo> { | ^^^ help: use the applicable keyword: `Self` -error: aborting due to 21 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:224:13 + | +LL | TS(0) + | ^^ help: use the applicable keyword: `Self` + +error: aborting due to 22 previous errors