Merge pull request #1054 from Manishearth/rustup

Rustup to ea0dc92972
This commit is contained in:
Martin Carton
2016-07-02 16:15:57 +02:00
committed by GitHub
17 changed files with 107 additions and 98 deletions

View File

@@ -1,7 +1,8 @@
# Change Log # Change Log
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
## 0.0.78 - TBA ## 0.0.78 - 2016-07-02
* Rustup to *rustc 1.11.0-nightly (01411937f 2016-07-01)*
* New lints: [`wrong_transmute`, `double_neg`] * New lints: [`wrong_transmute`, `double_neg`]
* For compatibility, `cargo clippy` does not defines the `clippy` feature * For compatibility, `cargo clippy` does not defines the `clippy` feature
introduced in 0.0.76 anymore introduced in 0.0.76 anymore

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "clippy" name = "clippy"
version = "0.0.77" version = "0.0.78"
authors = [ authors = [
"Manish Goregaokar <manishsmail@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>", "Andre Bogus <bogusandre@gmail.com>",
@@ -25,7 +25,7 @@ test = false
[dependencies] [dependencies]
# begin automatic update # begin automatic update
clippy_lints = { version = "0.0.77", path = "clippy_lints" } clippy_lints = { version = "0.0.78", path = "clippy_lints" }
# end automatic update # end automatic update
[dev-dependencies] [dev-dependencies]

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "clippy_lints" name = "clippy_lints"
# begin automatic update # begin automatic update
version = "0.0.77" version = "0.0.78"
# end automatic update # end automatic update
authors = [ authors = [
"Manish Goregaokar <manishsmail@gmail.com>", "Manish Goregaokar <manishsmail@gmail.com>",

View File

@@ -3,6 +3,7 @@ use rustc::hir::*;
use rustc::hir::intravisit::*; use rustc::hir::intravisit::*;
use syntax::ast::{LitKind, DUMMY_NODE_ID}; use syntax::ast::{LitKind, DUMMY_NODE_ID};
use syntax::codemap::{DUMMY_SP, dummy_spanned}; use syntax::codemap::{DUMMY_SP, dummy_spanned};
use syntax::util::ThinVec;
use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq}; use utils::{span_lint_and_then, in_macro, snippet_opt, SpanlessEq};
/// **What it does:** This lint checks for boolean expressions that can be written more concisely /// **What it does:** This lint checks for boolean expressions that can be written more concisely
@@ -99,7 +100,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
Expr { Expr {
id: DUMMY_NODE_ID, id: DUMMY_NODE_ID,
span: DUMMY_SP, span: DUMMY_SP,
attrs: None, attrs: ThinVec::new(),
node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()), node: ExprBinary(dummy_spanned(op), lhs.clone(), rhs.clone()),
} }
}; };

View File

@@ -72,8 +72,8 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) {
fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) { fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) {
if_let_chain! {[ if_let_chain! {[
let ast::ExprKind::Block(ref block) = else_.node, let ast::ExprKind::Block(ref block) = else_.node,
block.stmts.is_empty(), let Some(ref else_) = expr_block(block),
let Some(ref else_) = block.expr, !in_macro(cx, else_.span),
], { ], {
match else_.node { match else_.node {
ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => { ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => {
@@ -96,7 +96,7 @@ fn check_collapsible_no_if_let(
then: &ast::Block, then: &ast::Block,
) { ) {
if_let_chain! {[ if_let_chain! {[
let Some(inner) = single_stmt_of_block(then), let Some(inner) = expr_block(then),
let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node, let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node,
], { ], {
if expr.span.expn_id != inner.span.expn_id { if expr.span.expn_id != inner.span.expn_id {
@@ -128,28 +128,16 @@ fn check_to_string(cx: &EarlyContext, e: &ast::Expr) -> Cow<'static, str> {
} }
} }
fn single_stmt_of_block(block: &ast::Block) -> Option<&ast::Expr> { /// If the block contains only one expression, returns it.
if block.stmts.len() == 1 && block.expr.is_none() { fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
if let ast::StmtKind::Expr(ref expr, _) = block.stmts[0].node { let mut it = block.stmts.iter();
single_stmt_of_expr(expr)
} else {
None
}
} else if block.stmts.is_empty() {
if let Some(ref p) = block.expr {
Some(p)
} else {
None
}
} else {
None
}
}
fn single_stmt_of_expr(expr: &ast::Expr) -> Option<&ast::Expr> { if let (Some(stmt), None) = (it.next(), it.next()) {
if let ast::ExprKind::Block(ref block) = expr.node { match stmt.node {
single_stmt_of_block(block) ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr),
_ => None,
}
} else { } else {
Some(expr) None
} }
} }

View File

@@ -59,21 +59,13 @@ impl EarlyLintPass for Formatting {
fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) { fn check_block(&mut self, cx: &EarlyContext, block: &ast::Block) {
for w in block.stmts.windows(2) { for w in block.stmts.windows(2) {
match (&w[0].node, &w[1].node) { match (&w[0].node, &w[1].node) {
(&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Expr(ref second, _)) | (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Expr(ref second)) |
(&ast::StmtKind::Expr(ref first, _), &ast::StmtKind::Semi(ref second, _)) => { (&ast::StmtKind::Expr(ref first), &ast::StmtKind::Semi(ref second)) => {
check_consecutive_ifs(cx, first, second); check_consecutive_ifs(cx, first, second);
} }
_ => (), _ => (),
} }
} }
if let Some(ref expr) = block.expr {
if let Some(ref stmt) = block.stmts.iter().last() {
if let ast::StmtKind::Expr(ref first, _) = stmt.node {
check_consecutive_ifs(cx, first, expr);
}
}
}
} }
fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) { fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {

View File

@@ -2,7 +2,7 @@
use rustc::lint::*; use rustc::lint::*;
use syntax::ast::*; use syntax::ast::*;
use utils::in_macro; use utils::{in_macro, span_lint};
/// **What it does:** This lints checks for items declared after some statement in a block /// **What it does:** This lints checks for items declared after some statement in a block
/// ///
@@ -44,26 +44,23 @@ impl EarlyLintPass for ItemsAfterStatements {
if in_macro(cx, item.span) { if in_macro(cx, item.span) {
return; return;
} }
let mut stmts = item.stmts.iter().map(|stmt| &stmt.node);
// skip initial items // skip initial items
while let Some(&StmtKind::Decl(ref decl, _)) = stmts.next() { let stmts = item.stmts.iter()
if let DeclKind::Local(_) = decl.node { .map(|stmt| &stmt.node)
break; .skip_while(|s| matches!(**s, StmtKind::Item(..)));
}
}
// lint on all further items // lint on all further items
for stmt in stmts { for stmt in stmts {
if let StmtKind::Decl(ref decl, _) = *stmt { if let StmtKind::Item(ref it) = *stmt {
if let DeclKind::Item(ref it) = decl.node {
if in_macro(cx, it.span) { if in_macro(cx, it.span) {
return; return;
} }
cx.struct_span_lint(ITEMS_AFTER_STATEMENTS, span_lint(cx,
ITEMS_AFTER_STATEMENTS,
it.span, it.span,
"adding items after statements is confusing, since items exist from the \ "adding items after statements is confusing, since items exist from the \
start of the scope") start of the scope");
.emit();
}
} }
} }
} }

View File

@@ -171,12 +171,11 @@ impl EarlyLintPass for MiscEarly {
fn check_block(&mut self, cx: &EarlyContext, block: &Block) { fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
for w in block.stmts.windows(2) { for w in block.stmts.windows(2) {
if_let_chain! {[ if_let_chain! {[
let StmtKind::Decl(ref first, _) = w[0].node, let StmtKind::Local(ref local) = w[0].node,
let DeclKind::Local(ref local) = first.node,
let Option::Some(ref t) = local.init, let Option::Some(ref t) = local.init,
let ExprKind::Closure(_, _, _, _) = t.node, let ExprKind::Closure(_, _, _, _) = t.node,
let PatKind::Ident(_, sp_ident, _) = local.pat.node, let PatKind::Ident(_, sp_ident, _) = local.pat.node,
let StmtKind::Semi(ref second,_) = w[1].node, let StmtKind::Semi(ref second) = w[1].node,
let ExprKind::Assign(_, ref call) = second.node, let ExprKind::Assign(_, ref call) = second.node,
let ExprKind::Call(ref closure, _) = call.node, let ExprKind::Call(ref closure, _) = call.node,
let ExprKind::Path(_, ref path) = closure.node let ExprKind::Path(_, ref path) = closure.node

View File

@@ -68,8 +68,8 @@ const WHITELIST: &'static [&'static [&'static str]] = &[
struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>); struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>);
impl<'v, 'a, 'b, 'c> Visitor<'v> for SimilarNamesNameVisitor<'a, 'b, 'c> { impl<'a, 'b, 'c> Visitor for SimilarNamesNameVisitor<'a, 'b, 'c> {
fn visit_pat(&mut self, pat: &'v Pat) { fn visit_pat(&mut self, pat: &Pat) {
match pat.node { match pat.node {
PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name), PatKind::Ident(_, id, _) => self.check_name(id.span, id.node.name),
PatKind::Struct(_, ref fields, _) => { PatKind::Struct(_, ref fields, _) => {
@@ -226,25 +226,25 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> {
} }
} }
impl<'v, 'a, 'b> Visitor<'v> for SimilarNamesLocalVisitor<'a, 'b> { impl<'a, 'b> Visitor for SimilarNamesLocalVisitor<'a, 'b> {
fn visit_local(&mut self, local: &'v Local) { fn visit_local(&mut self, local: &Local) {
if let Some(ref init) = local.init { if let Some(ref init) = local.init {
self.apply(|this| walk_expr(this, &**init)); self.apply(|this| walk_expr(this, &**init));
} }
// add the pattern after the expression because the bindings aren't available yet in the init expression // add the pattern after the expression because the bindings aren't available yet in the init expression
SimilarNamesNameVisitor(self).visit_pat(&*local.pat); SimilarNamesNameVisitor(self).visit_pat(&*local.pat);
} }
fn visit_block(&mut self, blk: &'v Block) { fn visit_block(&mut self, blk: &Block) {
self.apply(|this| walk_block(this, blk)); self.apply(|this| walk_block(this, blk));
} }
fn visit_arm(&mut self, arm: &'v Arm) { fn visit_arm(&mut self, arm: &Arm) {
self.apply(|this| { self.apply(|this| {
// just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier // just go through the first pattern, as either all patterns bind the same bindings or rustc would have errored much earlier
SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]);
this.apply(|this| walk_expr(this, &arm.body)); this.apply(|this| walk_expr(this, &arm.body));
}); });
} }
fn visit_item(&mut self, _: &'v Item) { fn visit_item(&mut self, _: &Item) {
// do not recurse into inner items // do not recurse into inner items
} }
} }

View File

@@ -36,13 +36,12 @@ pub struct ReturnPass;
impl ReturnPass { impl ReturnPass {
// Check the final stmt or expr in a block for unnecessary return. // Check the final stmt or expr in a block for unnecessary return.
fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) { fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
if let Some(ref expr) = block.expr { if let Some(stmt) = block.stmts.last() {
match stmt.node {
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
self.check_final_expr(cx, expr); self.check_final_expr(cx, expr);
} else if let Some(stmt) = block.stmts.last() {
if let StmtKind::Semi(ref expr, _) = stmt.node {
if let ExprKind::Ret(Some(ref inner)) = expr.node {
self.emit_return_lint(cx, (stmt.span, inner.span));
} }
_ => (),
} }
} }
} }
@@ -88,12 +87,14 @@ impl ReturnPass {
// Check for "let x = EXPR; x" // Check for "let x = EXPR; x"
fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) { fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
let mut it = block.stmts.iter();
// we need both a let-binding stmt and an expr // we need both a let-binding stmt and an expr
if_let_chain! {[ if_let_chain! {[
let Some(stmt) = block.stmts.last(), let Some(ref retexpr) = it.next_back(),
let Some(ref retexpr) = block.expr, let StmtKind::Expr(ref retexpr) = retexpr.node,
let StmtKind::Decl(ref decl, _) = stmt.node, let Some(stmt) = it.next_back(),
let DeclKind::Local(ref local) = decl.node, let StmtKind::Local(ref local) = stmt.node,
let Some(ref initexpr) = local.init, let Some(ref initexpr) = local.init,
let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node, let PatKind::Ident(_, Spanned { node: id, .. }, _) = local.pat.node,
let ExprKind::Path(_, ref path) = retexpr.node, let ExprKind::Path(_, ref path) = retexpr.node,

View File

@@ -5,7 +5,7 @@ extern crate rustc;
extern crate rustc_plugin; extern crate rustc_plugin;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ast::TokenTree; use syntax::tokenstream::TokenTree;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; use syntax::ext::base::{ExtCtxt, MacResult, MacEager};
use syntax::ext::build::AstBuilder; // trait for expr_usize use syntax::ext::build::AstBuilder; // trait for expr_usize
use rustc_plugin::Registry; use rustc_plugin::Registry;

View File

@@ -2,17 +2,17 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(rustc_private)] #![feature(rustc_private)]
extern crate rustc_driver; extern crate clippy_lints;
extern crate getopts; extern crate getopts;
extern crate rustc; extern crate rustc;
extern crate syntax; extern crate rustc_driver;
extern crate rustc_errors;
extern crate rustc_plugin; extern crate rustc_plugin;
extern crate clippy_lints; extern crate syntax;
use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation}; use rustc_driver::{driver, CompilerCalls, RustcDefaultCalls, Compilation};
use rustc::session::{config, Session}; use rustc::session::{config, Session};
use rustc::session::config::{Input, ErrorOutputType}; use rustc::session::config::{Input, ErrorOutputType};
use syntax::diagnostics;
use std::path::PathBuf; use std::path::PathBuf;
use std::process::Command; use std::process::Command;
@@ -36,7 +36,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
fn early_callback(&mut self, fn early_callback(&mut self,
matches: &getopts::Matches, matches: &getopts::Matches,
sopts: &config::Options, sopts: &config::Options,
descriptions: &diagnostics::registry::Registry, descriptions: &rustc_errors::registry::Registry,
output: ErrorOutputType) output: ErrorOutputType)
-> Compilation { -> Compilation {
self.0.early_callback(matches, sopts, descriptions, output) self.0.early_callback(matches, sopts, descriptions, output)
@@ -46,7 +46,7 @@ impl<'a> CompilerCalls<'a> for ClippyCompilerCalls {
sopts: &config::Options, sopts: &config::Options,
odir: &Option<PathBuf>, odir: &Option<PathBuf>,
ofile: &Option<PathBuf>, ofile: &Option<PathBuf>,
descriptions: &diagnostics::registry::Registry) descriptions: &rustc_errors::registry::Registry)
-> Option<(Input, Option<PathBuf>)> { -> Option<(Input, Option<PathBuf>)> {
self.0.no_input(matches, sopts, odir, ofile, descriptions) self.0.no_input(matches, sopts, odir, ofile, descriptions)
} }

View File

@@ -139,4 +139,9 @@ fn main() {
println!("world!") println!("world!")
} }
} }
if true {
} else {
assert!(true); // assert! is just an `if`
}
} }

View File

@@ -16,7 +16,9 @@ fn main() {
//~| NOTE add the missing `else` or //~| NOTE add the missing `else` or
} }
let _ = { let _ = { // if as the last expression
let _ = 0;
if foo() { if foo() {
} if foo() { } if foo() {
//~^ ERROR this looks like an `else if` but the `else` is missing //~^ ERROR this looks like an `else if` but the `else` is missing
@@ -26,6 +28,18 @@ fn main() {
} }
}; };
let _ = { // if in the middle of a block
if foo() {
} if foo() {
//~^ ERROR this looks like an `else if` but the `else` is missing
//~| NOTE add the missing `else` or
}
else {
}
let _ = 0;
};
if foo() { if foo() {
} else } else
//~^ ERROR this is an `else if` but the formatting might hide it //~^ ERROR this is an `else if` but the formatting might hide it

View File

@@ -2,6 +2,16 @@
#![plugin(clippy)] #![plugin(clippy)]
#![deny(items_after_statements)] #![deny(items_after_statements)]
fn ok() {
fn foo() { println!("foo"); }
foo();
}
fn last() {
foo();
fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing
}
fn main() { fn main() {
foo(); foo();
fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing fn foo() { println!("foo"); } //~ ERROR adding items after statements is confusing

View File

@@ -1,8 +1,8 @@
#![feature(plugin)] #![feature(plugin)]
#![plugin(clippy)] #![plugin(clippy)]
#![deny(needless_bool)]
#[allow(if_same_then_else)] #[allow(if_same_then_else)]
#[deny(needless_bool)]
fn main() { fn main() {
let x = true; let x = true;
if x { true } else { true }; //~ERROR this if-then-else expression will always return true if x { true } else { true }; //~ERROR this if-then-else expression will always return true
@@ -22,19 +22,19 @@ fn main() {
bool_ret4(x); bool_ret4(x);
} }
#[deny(needless_bool)] #[allow(if_same_then_else, needless_return)]
#[allow(if_same_then_else)]
fn bool_ret(x: bool) -> bool { fn bool_ret(x: bool) -> bool {
if x { return true } else { return true }; //~ERROR this if-then-else expression will always return true if x { return true } else { return true };
//~^ ERROR this if-then-else expression will always return true
} }
#[deny(needless_bool)] #[allow(if_same_then_else, needless_return)]
#[allow(if_same_then_else)]
fn bool_ret2(x: bool) -> bool { fn bool_ret2(x: bool) -> bool {
if x { return false } else { return false }; //~ERROR this if-then-else expression will always return false if x { return false } else { return false };
//~^ ERROR this if-then-else expression will always return false
} }
#[deny(needless_bool)] #[allow(needless_return)]
fn bool_ret3(x: bool) -> bool { fn bool_ret3(x: bool) -> bool {
if x { return true } else { return false }; if x { return true } else { return false };
//~^ ERROR this if-then-else expression returns a bool literal //~^ ERROR this if-then-else expression returns a bool literal
@@ -42,7 +42,7 @@ fn bool_ret3(x: bool) -> bool {
//~| SUGGESTION `return x` //~| SUGGESTION `return x`
} }
#[deny(needless_bool)] #[allow(needless_return)]
fn bool_ret4(x: bool) -> bool { fn bool_ret4(x: bool) -> bool {
if x { return false } else { return true }; if x { return false } else { return true };
//~^ ERROR this if-then-else expression returns a bool literal //~^ ERROR this if-then-else expression returns a bool literal

View File

@@ -14,6 +14,7 @@ use syntax::ast::{LitIntType, LitKind, StrStyle};
use syntax::codemap::{Spanned, COMMAND_LINE_SP}; use syntax::codemap::{Spanned, COMMAND_LINE_SP};
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
use syntax::ptr::P; use syntax::ptr::P;
use syntax::util::ThinVec;
fn spanned<T>(t: T) -> Spanned<T> { fn spanned<T>(t: T) -> Spanned<T> {
Spanned { Spanned {
@@ -27,7 +28,7 @@ fn expr(n: Expr_) -> Expr {
id: 1, id: 1,
node: n, node: n,
span: COMMAND_LINE_SP, span: COMMAND_LINE_SP,
attrs: None, attrs: ThinVec::new(),
} }
} }