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