Rust upgrade to rustc 1.5.0-nightly (9d3e79ad3
2015-10-10)
This commit is contained in:
parent
6f84e3551b
commit
4e2b09831b
@ -75,7 +75,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_late_lint_pass(box misc::ModuloOne);
|
||||
reg.register_late_lint_pass(box unicode::Unicode);
|
||||
reg.register_late_lint_pass(box strings::StringAdd);
|
||||
reg.register_late_lint_pass(box returns::ReturnPass);
|
||||
reg.register_early_lint_pass(box returns::ReturnPass);
|
||||
reg.register_late_lint_pass(box methods::MethodsPass);
|
||||
reg.register_late_lint_pass(box shadow::ShadowPass);
|
||||
reg.register_late_lint_pass(box types::LetPass);
|
||||
|
@ -1,10 +1,10 @@
|
||||
use rustc::lint::*;
|
||||
use rustc_front::hir::*;
|
||||
use reexport::*;
|
||||
use syntax::ast::*;
|
||||
//use reexport::*;
|
||||
use syntax::codemap::{Span, Spanned};
|
||||
use rustc_front::visit::FnKind;
|
||||
use syntax::visit::FnKind;
|
||||
|
||||
use utils::{span_lint, snippet, match_path, in_external_macro};
|
||||
use utils::{span_lint, snippet, match_path_ast, in_external_macro};
|
||||
|
||||
declare_lint!(pub NEEDLESS_RETURN, Warn,
|
||||
"using a return statement like `return expr;` where an expression would suffice");
|
||||
@ -17,7 +17,7 @@ pub struct ReturnPass;
|
||||
|
||||
impl ReturnPass {
|
||||
// Check the final stmt or expr in a block for unnecessary return.
|
||||
fn check_block_return(&mut self, cx: &LateContext, block: &Block) {
|
||||
fn check_block_return(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
if let Some(ref expr) = block.expr {
|
||||
self.check_final_expr(cx, expr);
|
||||
} else if let Some(stmt) = block.stmts.last() {
|
||||
@ -30,7 +30,7 @@ impl ReturnPass {
|
||||
}
|
||||
|
||||
// Check a the final expression in a block if it's a return.
|
||||
fn check_final_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
||||
fn check_final_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
|
||||
match expr.node {
|
||||
// simple return is always "bad"
|
||||
ExprRet(Some(ref inner)) => {
|
||||
@ -48,7 +48,7 @@ impl ReturnPass {
|
||||
self.check_final_expr(cx, elsexpr);
|
||||
}
|
||||
// a match expr, check all arms
|
||||
ExprMatch(_, ref arms, _) => {
|
||||
ExprMatch(_, ref arms) => {
|
||||
for arm in arms {
|
||||
self.check_final_expr(cx, &arm.body);
|
||||
}
|
||||
@ -57,7 +57,7 @@ impl ReturnPass {
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_return_lint(&mut self, cx: &LateContext, spans: (Span, Span)) {
|
||||
fn emit_return_lint(&mut self, cx: &EarlyContext, spans: (Span, Span)) {
|
||||
if in_external_macro(cx, spans.1) {return;}
|
||||
span_lint(cx, NEEDLESS_RETURN, spans.0, &format!(
|
||||
"unneeded return statement. Consider using `{}` \
|
||||
@ -66,7 +66,7 @@ impl ReturnPass {
|
||||
}
|
||||
|
||||
// Check for "let x = EXPR; x"
|
||||
fn check_let_return(&mut self, cx: &LateContext, block: &Block) {
|
||||
fn check_let_return(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
// we need both a let-binding stmt and an expr
|
||||
if_let_chain! {
|
||||
[
|
||||
@ -77,14 +77,14 @@ impl ReturnPass {
|
||||
let Some(ref initexpr) = local.init,
|
||||
let PatIdent(_, Spanned { node: id, .. }, _) = local.pat.node,
|
||||
let ExprPath(_, ref path) = retexpr.node,
|
||||
match_path(path, &[&id.name.as_str()])
|
||||
match_path_ast(path, &[&id.name.as_str()])
|
||||
], {
|
||||
self.emit_let_lint(cx, retexpr.span, initexpr.span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn emit_let_lint(&mut self, cx: &LateContext, lint_span: Span, note_span: Span) {
|
||||
fn emit_let_lint(&mut self, cx: &EarlyContext, lint_span: Span, note_span: Span) {
|
||||
if in_external_macro(cx, note_span) {return;}
|
||||
span_lint(cx, LET_AND_RETURN, lint_span,
|
||||
"returning the result of a let binding from a block. \
|
||||
@ -102,13 +102,13 @@ impl LintPass for ReturnPass {
|
||||
}
|
||||
}
|
||||
|
||||
impl LateLintPass for ReturnPass {
|
||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, _: &FnDecl,
|
||||
impl EarlyLintPass for ReturnPass {
|
||||
fn check_fn(&mut self, cx: &EarlyContext, _: FnKind, _: &FnDecl,
|
||||
block: &Block, _: Span, _: NodeId) {
|
||||
self.check_block_return(cx, block);
|
||||
}
|
||||
|
||||
fn check_block(&mut self, cx: &LateContext, block: &Block) {
|
||||
fn check_block(&mut self, cx: &EarlyContext, block: &Block) {
|
||||
self.check_let_return(cx, block);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use rustc_front::visit::FnKind;
|
||||
use rustc::lint::*;
|
||||
use rustc::middle::def::Def::{DefVariant, DefStruct};
|
||||
|
||||
use utils::{in_external_macro, snippet, span_lint, span_note_and_lint};
|
||||
use utils::{is_from_for_desugar, in_external_macro, snippet, span_lint, span_note_and_lint};
|
||||
|
||||
declare_lint!(pub SHADOW_SAME, Allow,
|
||||
"rebinding a name to itself, e.g. `let mut x = &mut x`");
|
||||
@ -60,6 +60,7 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>
|
||||
|
||||
fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
|
||||
if in_external_macro(cx, decl.span) { return; }
|
||||
if is_from_for_desugar(decl) { return; }
|
||||
if let DeclLocal(ref local) = decl.node {
|
||||
let Local{ ref pat, ref ty, ref init, id: _, span } = **local;
|
||||
if let &Some(ref t) = ty { check_ty(cx, t, bindings) }
|
||||
|
10
src/types.rs
10
src/types.rs
@ -9,7 +9,8 @@ use syntax::ast::IntTy::*;
|
||||
use syntax::ast::UintTy::*;
|
||||
use syntax::ast::FloatTy::*;
|
||||
|
||||
use utils::{match_type, snippet, span_lint, span_help_and_lint, in_macro, in_external_macro};
|
||||
use utils::{match_type, snippet, span_lint, span_help_and_lint};
|
||||
use utils::{is_from_for_desugar, in_macro, in_external_macro};
|
||||
use utils::{LL_PATH, VEC_PATH};
|
||||
|
||||
/// Handles all the linting of funky types
|
||||
@ -61,9 +62,10 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) {
|
||||
if *bindtype == ty::TyTuple(vec![]) {
|
||||
if in_external_macro(cx, decl.span) ||
|
||||
in_macro(cx, local.pat.span) { return; }
|
||||
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
|
||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||
snippet(cx, local.pat.span, "..")));
|
||||
if is_from_for_desugar(decl) { return; }
|
||||
span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
|
||||
"this let-binding has unit value. Consider omitting `let {} =`",
|
||||
snippet(cx, local.pat.span, "..")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
139
src/utils.rs
139
src/utils.rs
@ -7,6 +7,7 @@ use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::ty;
|
||||
use std::borrow::Cow;
|
||||
use syntax::ast::Lit_::*;
|
||||
use syntax::ast;
|
||||
|
||||
// module DefPaths for certain structs/enums we check for
|
||||
pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"];
|
||||
@ -15,15 +16,56 @@ pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"];
|
||||
pub const VEC_PATH: [&'static str; 3] = ["collections", "vec", "Vec"];
|
||||
pub const LL_PATH: [&'static str; 3] = ["collections", "linked_list", "LinkedList"];
|
||||
|
||||
/// Produce a nested chain of if-lets and ifs from the patterns:
|
||||
///
|
||||
/// if_let_chain! {
|
||||
/// [
|
||||
/// Some(y) = x,
|
||||
/// y.len() == 2,
|
||||
/// Some(z) = y,
|
||||
/// ],
|
||||
/// {
|
||||
/// block
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// becomes
|
||||
///
|
||||
/// if let Some(y) = x {
|
||||
/// if y.len() == 2 {
|
||||
/// if let Some(z) = y {
|
||||
/// block
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
#[macro_export]
|
||||
macro_rules! if_let_chain {
|
||||
([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => {
|
||||
if let $pat = $expr {
|
||||
if_let_chain!{ [$($tt)+], $block }
|
||||
}
|
||||
};
|
||||
([let $pat:pat = $expr:expr], $block:block) => {
|
||||
if let $pat = $expr {
|
||||
$block
|
||||
}
|
||||
};
|
||||
([$expr:expr, $($tt:tt)+], $block:block) => {
|
||||
if $expr {
|
||||
if_let_chain!{ [$($tt)+], $block }
|
||||
}
|
||||
};
|
||||
([$expr:expr], $block:block) => {
|
||||
if $expr {
|
||||
$block
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// returns true this expn_info was expanded by any macro
|
||||
pub fn in_macro(cx: &LateContext, span: Span) -> bool {
|
||||
cx.sess().codemap().with_expn_info(span.expn_id,
|
||||
|info| info.map_or(false, |i| {
|
||||
match i.callee.format {
|
||||
ExpnFormat::CompilerExpansion(..) => false,
|
||||
_ => true,
|
||||
}
|
||||
}))
|
||||
|info| info.is_some())
|
||||
}
|
||||
|
||||
/// returns true if the macro that expanded the crate was outside of
|
||||
@ -34,17 +76,9 @@ pub fn in_external_macro<T: LintContext>(cx: &T, span: Span) -> bool {
|
||||
fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool {
|
||||
// no ExpnInfo = no macro
|
||||
opt_info.map_or(false, |info| {
|
||||
match info.callee.format {
|
||||
ExpnFormat::CompilerExpansion(..) => {
|
||||
if info.callee.name().as_str() == "closure expansion" {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
ExpnFormat::MacroAttribute(..) => {
|
||||
// these are all plugins
|
||||
return true;
|
||||
},
|
||||
_ => (),
|
||||
if let ExpnFormat::MacroAttribute(..) = info.callee.format {
|
||||
// these are all plugins
|
||||
return true;
|
||||
}
|
||||
// no span for the callee = external macro
|
||||
info.callee.span.map_or(true, |span| {
|
||||
@ -102,6 +136,13 @@ pub fn match_path(path: &Path, segments: &[&str]) -> bool {
|
||||
|(a, b)| a.identifier.name.as_str() == *b)
|
||||
}
|
||||
|
||||
/// match a Path against a slice of segment string literals, e.g.
|
||||
/// `match_path(path, &["std", "rt", "begin_unwind"])`
|
||||
pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
|
||||
path.segments.iter().rev().zip(segments.iter().rev()).all(
|
||||
|(a, b)| a.identifier.name.as_str() == *b)
|
||||
}
|
||||
|
||||
/// get the name of the item the expression is in, if available
|
||||
pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> {
|
||||
let parent_id = cx.tcx.map.get_parent(expr.id);
|
||||
@ -115,6 +156,24 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> {
|
||||
}
|
||||
}
|
||||
|
||||
/// checks if a `let` decl is from a for loop desugaring
|
||||
pub fn is_from_for_desugar(decl: &Decl) -> bool {
|
||||
if_let_chain! {
|
||||
[
|
||||
let DeclLocal(ref loc) = decl.node,
|
||||
let Some(ref expr) = loc.init,
|
||||
// FIXME: This should check for MatchSource::ForLoop
|
||||
// but right now there's a bug where the match source isn't
|
||||
// set during lowering
|
||||
// https://github.com/rust-lang/rust/pull/28973
|
||||
let ExprMatch(_, _, _) = expr.node
|
||||
],
|
||||
{ return true; }
|
||||
};
|
||||
false
|
||||
}
|
||||
|
||||
|
||||
/// convert a span to a code snippet if available, otherwise use default, e.g.
|
||||
/// `snippet(cx, expr.span, "..")`
|
||||
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||
@ -262,49 +321,3 @@ pub fn is_integer_literal(expr: &Expr, value: u64) -> bool
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Produce a nested chain of if-lets and ifs from the patterns:
|
||||
///
|
||||
/// if_let_chain! {
|
||||
/// [
|
||||
/// Some(y) = x,
|
||||
/// y.len() == 2,
|
||||
/// Some(z) = y,
|
||||
/// ],
|
||||
/// {
|
||||
/// block
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// becomes
|
||||
///
|
||||
/// if let Some(y) = x {
|
||||
/// if y.len() == 2 {
|
||||
/// if let Some(z) = y {
|
||||
/// block
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
#[macro_export]
|
||||
macro_rules! if_let_chain {
|
||||
([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => {
|
||||
if let $pat = $expr {
|
||||
if_let_chain!{ [$($tt)+], $block }
|
||||
}
|
||||
};
|
||||
([let $pat:pat = $expr:expr], $block:block) => {
|
||||
if let $pat = $expr {
|
||||
$block
|
||||
}
|
||||
};
|
||||
([$expr:expr, $($tt:tt)+], $block:block) => {
|
||||
if $expr {
|
||||
if_let_chain!{ [$($tt)+], $block }
|
||||
}
|
||||
};
|
||||
([$expr:expr], $block:block) => {
|
||||
if $expr {
|
||||
$block
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
fn add_only() { // ignores assignment distinction
|
||||
let mut x = "".to_owned();
|
||||
|
||||
for _ in (1..3) {
|
||||
for _ in 1..3 {
|
||||
x = x + "."; //~ERROR you added something to a string.
|
||||
}
|
||||
|
||||
@ -20,7 +20,7 @@ fn add_only() { // ignores assignment distinction
|
||||
fn add_assign_only() {
|
||||
let mut x = "".to_owned();
|
||||
|
||||
for _ in (1..3) {
|
||||
for _ in 1..3 {
|
||||
x = x + "."; //~ERROR you assigned the result of adding something to this string.
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ fn add_assign_only() {
|
||||
fn both() {
|
||||
let mut x = "".to_owned();
|
||||
|
||||
for _ in (1..3) {
|
||||
for _ in 1..3 {
|
||||
x = x + "."; //~ERROR you assigned the result of adding something to this string.
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user