about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-11-10 13:16:35 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-11-10 13:16:35 +0000
commit82044946cd7afaba1189a4134bb8f874b24b4aec (patch)
tree354d7b7e80f4f2169bf07f12dc9240ab53c26105
parent3bb88775de5a6f8f5c5743dd11af6c820122ccc7 (diff)
parent460c2b317b9768593f084545f4ae812d612ccacc (diff)
downloadrust-82044946cd7afaba1189a4134bb8f874b24b4aec.tar.gz
rust-82044946cd7afaba1189a4134bb8f874b24b4aec.zip
Merge #3423
3423: Fix `use_self` false positive r=flip1995 a=mikerite

This fixes the first error reported in issue #3410.

Co-authored-by: Michael Wright <mikerite@lavabit.com>
-rw-r--r--clippy_lints/src/use_self.rs39
-rw-r--r--tests/ui/use_self.rs14
2 files changed, 38 insertions, 15 deletions
diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs
index b997d76d0e7..db393616ff2 100644
--- a/clippy_lints/src/use_self.rs
+++ b/clippy_lints/src/use_self.rs
@@ -73,7 +73,7 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) {
 }
 
 struct TraitImplTyVisitor<'a, 'tcx: 'a> {
-    item_path: &'a Path,
+    item_type: ty::Ty<'tcx>,
     cx: &'a LateContext<'a, 'tcx>,
     trait_type_walker: ty::walk::TypeWalker<'tcx>,
     impl_type_walker: ty::walk::TypeWalker<'tcx>,
@@ -85,21 +85,28 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
         let impl_ty = self.impl_type_walker.next();
 
         if let TyKind::Path(QPath::Resolved(_, path)) = &t.node {
-            if self.item_path.def == path.def {
-                let is_self_ty = if let def::Def::SelfTy(..) = path.def {
-                    true
-                } else {
-                    false
-                };
 
-                if !is_self_ty && impl_ty != trait_ty {
-                    // The implementation and trait types don't match which means that
-                    // the concrete type was specified by the implementation but
-                    // it didn't use `Self`
-                    span_use_self_lint(self.cx, path);
+            // The implementation and trait types don't match which means that
+            // the concrete type was specified by the implementation
+            if impl_ty != trait_ty {
+
+                if let Some(impl_ty) = impl_ty {
+                    if self.item_type == impl_ty {
+                        let is_self_ty = if let def::Def::SelfTy(..) = path.def {
+                            true
+                        } else {
+                            false
+                        };
+
+                        if !is_self_ty {
+                            span_use_self_lint(self.cx, path);
+                        }
+                    }
                 }
+
             }
         }
+
         walk_ty(self, t)
     }
 
@@ -110,7 +117,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> {
 
 fn check_trait_method_impl_decl<'a, 'tcx: 'a>(
     cx: &'a LateContext<'a, 'tcx>,
-    item_path: &'a Path,
+    item_type: ty::Ty<'tcx>,
     impl_item: &ImplItem,
     impl_decl: &'tcx FnDecl,
     impl_trait_ref: &ty::TraitRef<'_>,
@@ -151,7 +158,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>(
     ) {
         let mut visitor = TraitImplTyVisitor {
             cx,
-            item_path,
+            item_type,
             trait_type_walker: trait_ty.walk(),
             impl_type_walker: impl_ty.walk(),
         };
@@ -192,7 +199,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf {
                             let impl_item = cx.tcx.hir.impl_item(impl_item_ref.id);
                             if let ImplItemKind::Method(MethodSig{ decl: impl_decl, .. }, impl_body_id)
                                     = &impl_item.node {
-                                check_trait_method_impl_decl(cx, item_path, impl_item, impl_decl, &impl_trait_ref);
+                                let item_type = cx.tcx.type_of(impl_def_id);
+                                check_trait_method_impl_decl(cx, item_type, impl_item, impl_decl, &impl_trait_ref);
+
                                 let body = cx.tcx.hir.body(*impl_body_id);
                                 visitor.visit_body(body);
                             } else {
diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs
index 073d64d5a4b..4c1ec2ad2b9 100644
--- a/tests/ui/use_self.rs
+++ b/tests/ui/use_self.rs
@@ -219,3 +219,17 @@ mod existential {
         }
     }
 }
+
+mod issue3410 {
+
+    struct A;
+    struct B;
+
+    trait Trait<T>: Sized {
+        fn a(v: T);
+    }
+
+    impl Trait<Vec<A>> for Vec<B> {
+        fn a(_: Vec<A>) {}
+    }
+}