]> git.lizzy.rs Git - rust.git/commitdiff
Fix `len_zero` ICE
authorOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Mon, 4 Sep 2017 15:05:47 +0000 (17:05 +0200)
committerOliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>
Mon, 4 Sep 2017 15:05:47 +0000 (17:05 +0200)
clippy_lints/src/len_zero.rs
tests/ui/len_zero.rs
tests/ui/len_zero.stderr

index 798d48f177d356a2eb0aa45bf35254641098e42a..e862240da59a413b21da3e2f10e1f54f540638f4 100644 (file)
@@ -104,34 +104,28 @@ fn is_named_self(cx: &LateContext, item: &TraitItemRef, name: &str) -> bool {
     }
 
     // fill the set with current and super traits
-    fn fill_trait_set<'a, 'b: 'a>(traitt: &'b Item, set: &'a mut HashSet<&'b Item>, cx: &'b LateContext) {
+    fn fill_trait_set(traitt: DefId, set: &mut HashSet<DefId>, cx: &LateContext) {
         if set.insert(traitt) {
-            if let ItemTrait(.., ref ty_param_bounds, _) = traitt.node {
-                for ty_param_bound in ty_param_bounds {
-                    if let TraitTyParamBound(ref poly_trait_ref, _) = *ty_param_bound {
-                        let super_trait_node_id = cx.tcx
-                            .hir
-                            .as_local_node_id(poly_trait_ref.trait_ref.path.def.def_id())
-                            .expect("the DefId is local, the NodeId should be available");
-                        let super_trait = cx.tcx.hir.expect_item(super_trait_node_id);
-                        fill_trait_set(super_trait, set, cx);
-                    }
-                }
+            for supertrait in ::rustc::traits::supertrait_def_ids(cx.tcx, traitt) {
+                fill_trait_set(supertrait, set, cx);
             }
         }
     }
 
     if cx.access_levels.is_exported(visited_trait.id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) {
         let mut current_and_super_traits = HashSet::new();
-        fill_trait_set(visited_trait, &mut current_and_super_traits, cx);
+        let visited_trait_def_id = cx.tcx.hir.local_def_id(visited_trait.id);
+        fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx);
 
         let is_empty_method_found = current_and_super_traits
             .iter()
-            .flat_map(|i| match i.node {
-                ItemTrait(.., ref trait_items) => trait_items.iter(),
-                _ => bug!("should only handle traits"),
-            })
-            .any(|i| is_named_self(cx, i, "is_empty"));
+            .flat_map(|&i| cx.tcx.associated_items(i))
+            .any(|i| {
+                i.kind == ty::AssociatedKind::Method &&
+                i.method_has_self_argument &&
+                i.name == "is_empty" &&
+                cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1
+            });
 
         if !is_empty_method_found {
             span_lint(
index e0e735a934b2b4a3f06bc13bfbede3efa3cc41ef..9c66d5a8148a0f22cbdf9661711dd3ded8254cf6 100644 (file)
@@ -182,3 +182,10 @@ fn test_slice(b: &[u8]) {
     if b.len() != 0 {
     }
 }
+
+// this used to ICE
+pub trait Foo: Sized {}
+
+pub trait DependsOnFoo: Foo {
+    fn len(&mut self) -> usize;
+}
index 5e3961808b87ed1865dce7b15f61f27fafcccbda..6e3cf1b3ca1d96484d671681a7af1f7ce3802ae8 100644 (file)
@@ -86,5 +86,13 @@ error: length comparison to zero
 182 |     if b.len() != 0 {
     |        ^^^^^^^^^^^^ help: using `is_empty` is more concise: `!b.is_empty()`
 
-error: aborting due to 11 previous errors
+error: trait `DependsOnFoo` has a `len` method but no (possibly inherited) `is_empty` method
+   --> $DIR/len_zero.rs:189:1
+    |
+189 | / pub trait DependsOnFoo: Foo {
+190 | |     fn len(&mut self) -> usize;
+191 | | }
+    | |_^
+
+error: aborting due to 12 previous errors