Merge pull request #1349 from philipturnbull/extend-chars

Lint `.extend(s.chars())` (closes #792)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c9bc5d0..14bf8ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,9 @@
 # Change Log
 All notable changes to this project will be documented in this file.
 
+## 0.0.100 — 2016-11-20
+* Update to *rustc 1.15.0-nightly (ac635aa95 2016-11-18)*
+
 ## 0.0.99 — 2016-11-18
 * Update to rustc 1.15.0-nightly (0ed951993 2016-11-14)
 
diff --git a/Cargo.toml b/Cargo.toml
index a29b962..039ef9e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "clippy"
-version = "0.0.99"
+version = "0.0.100"
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
 	"Andre Bogus <bogusandre@gmail.com>",
@@ -25,7 +25,7 @@
 
 [dependencies]
 # begin automatic update
-clippy_lints = { version = "0.0.99", path = "clippy_lints" }
+clippy_lints = { version = "0.0.100", path = "clippy_lints" }
 # end automatic update
 
 [dev-dependencies]
diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml
index f8f40d1..c7b0b35 100644
--- a/clippy_lints/Cargo.toml
+++ b/clippy_lints/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "clippy_lints"
 # begin automatic update
-version = "0.0.99"
+version = "0.0.100"
 # end automatic update
 authors = [
 	"Manish Goregaokar <manishsmail@gmail.com>",
diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs
index 2699367..a6f4882 100644
--- a/clippy_lints/src/len_zero.rs
+++ b/clippy_lints/src/len_zero.rs
@@ -92,7 +92,11 @@
     fn is_named_self(item: &TraitItem, name: &str) -> bool {
         item.name.as_str() == name &&
         if let MethodTraitItem(ref sig, _) = item.node {
-            is_self_sig(sig)
+            if sig.decl.has_self() {
+                sig.decl.inputs.len() == 1
+            } else {
+                false
+            }
         } else {
             false
         }
@@ -111,18 +115,22 @@
     }
 }
 
-fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItem]) {
-    fn is_named_self(item: &ImplItem, name: &str) -> bool {
+fn check_impl_items(cx: &LateContext, item: &Item, impl_items: &[ImplItemRef]) {
+    fn is_named_self(cx: &LateContext, item: &ImplItemRef, name: &str) -> bool {
         item.name.as_str() == name &&
-        if let ImplItemKind::Method(ref sig, _) = item.node {
-            is_self_sig(sig)
+        if let AssociatedItemKind::Method { has_self } = item.kind {
+            has_self && {
+                let did = cx.tcx.map.local_def_id(item.id.node_id);
+                let impl_ty = cx.tcx.item_type(did);
+                impl_ty.fn_args().skip_binder().len() == 1
+            }
         } else {
             false
         }
     }
 
-    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(i, "is_empty")) {
-        if cx.access_levels.is_exported(is_empty.id) {
+    let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) {
+        if cx.access_levels.is_exported(is_empty.id.node_id) {
             return;
         } else {
             "a private"
@@ -131,8 +139,8 @@
         "no corresponding"
     };
 
-    if let Some(i) = impl_items.iter().find(|i| is_named_self(i, "len")) {
-        if cx.access_levels.is_exported(i.id) {
+    if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) {
+        if cx.access_levels.is_exported(i.id.node_id) {
             let def_id = cx.tcx.map.local_def_id(item.id);
             let ty = cx.tcx.item_type(def_id);
 
@@ -146,14 +154,6 @@
     }
 }
 
-fn is_self_sig(sig: &MethodSig) -> bool {
-    if sig.decl.has_self() {
-        sig.decl.inputs.len() == 1
-    } else {
-        false
-    }
-}
-
 fn check_cmp(cx: &LateContext, span: Span, left: &Expr, right: &Expr, op: &str) {
     // check if we are in an is_empty() method
     if let Some(name) = get_item_name(cx, left) {
diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs
index 0e6de0d..b19d7b9 100644
--- a/clippy_lints/src/returns.rs
+++ b/clippy_lints/src/returns.rs
@@ -61,7 +61,10 @@
         match expr.node {
             // simple return is always "bad"
             ast::ExprKind::Ret(Some(ref inner)) => {
-                self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
+                // allow `#[cfg(a)] return a; #[cfg(b)] return b;`
+                if !expr.attrs.iter().any(attr_is_cfg) {
+                    self.emit_return_lint(cx, span.expect("`else return` is not possible"), inner.span);
+                }
             }
             // a whole block? check it!
             ast::ExprKind::Block(ref block) => {
@@ -105,6 +108,7 @@
             let ast::StmtKind::Expr(ref retexpr) = retexpr.node,
             let Some(stmt) = it.next_back(),
             let ast::StmtKind::Local(ref local) = stmt.node,
+            !local.attrs.iter().any(attr_is_cfg),
             let Some(ref initexpr) = local.init,
             let ast::PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
             let ast::ExprKind::Path(_, ref path) = retexpr.node,
@@ -140,3 +144,12 @@
         self.check_let_return(cx, block);
     }
 }
+
+fn attr_is_cfg(attr: &ast::Attribute) -> bool {
+    if let ast::MetaItemKind::List(ref key, _) = attr.node.value.node {
+        *key == "cfg"
+    } else {
+        false
+    }
+}
+
diff --git a/tests/run-pass/returns.rs b/tests/run-pass/returns.rs
new file mode 100644
index 0000000..882d3aa
--- /dev/null
+++ b/tests/run-pass/returns.rs
@@ -0,0 +1,19 @@
+#[deny(warnings)]
+fn cfg_return() -> i32 {
+    #[cfg(unix)] return 1;
+    #[cfg(not(unix))] return 2;
+}
+
+#[deny(warnings)]
+fn cfg_let_and_return() -> i32 {
+    #[cfg(unix)]
+    let x = 1;
+    #[cfg(not(unix))]
+    let x = 2;
+    x
+}
+
+fn main() {
+    cfg_return();
+    cfg_let_and_return();
+}