Merge pull request #1649 from ensch/master
Fix for rustc 1.18.0-nightly (5c94997b6
2017-03-30)
This commit is contained in:
commit
3052000c73
@ -215,7 +215,7 @@ fn is_relevant_expr(tcx: ty::TyCtxt, tables: &ty::TypeckTables, expr: &Expr) ->
|
||||
}
|
||||
|
||||
fn check_attrs(cx: &LateContext, span: Span, name: &Name, attrs: &[Attribute]) {
|
||||
if in_macro(cx, span) {
|
||||
if in_macro(span) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
|
||||
if let Some(ref ex) = block.expr {
|
||||
// don't dig into the expression here, just suggest that they remove
|
||||
// the block
|
||||
if in_macro(cx, expr.span) || differing_macro_contexts(expr.span, ex.span) {
|
||||
if in_macro(expr.span) || differing_macro_contexts(expr.span, ex.span) {
|
||||
return;
|
||||
}
|
||||
span_help_and_lint(cx,
|
||||
@ -97,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlockInIfCondition {
|
||||
}
|
||||
} else {
|
||||
let span = block.expr.as_ref().map_or_else(|| block.stmts[0].span, |e| e.span);
|
||||
if in_macro(cx, span) || differing_macro_contexts(expr.span, span) {
|
||||
if in_macro(span) || differing_macro_contexts(expr.span, span) {
|
||||
return;
|
||||
}
|
||||
// move block higher
|
||||
|
@ -93,7 +93,7 @@ impl<'a, 'tcx, 'v> Hir2Qmm<'a, 'tcx, 'v> {
|
||||
|
||||
fn run(&mut self, e: &'v Expr) -> Result<Bool, String> {
|
||||
// prevent folding of `cfg!` macros and the like
|
||||
if !in_macro(self.cx, e.span) {
|
||||
if !in_macro(e.span) {
|
||||
match e.node {
|
||||
ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
|
||||
ExprBinary(binop, ref lhs, ref rhs) => {
|
||||
@ -394,7 +394,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
|
||||
fn visit_expr(&mut self, e: &'tcx Expr) {
|
||||
if in_macro(self.cx, e.span) {
|
||||
if in_macro(e.span) {
|
||||
return;
|
||||
}
|
||||
match e.node {
|
||||
|
@ -78,7 +78,7 @@ impl LintPass for CollapsibleIf {
|
||||
|
||||
impl EarlyLintPass for CollapsibleIf {
|
||||
fn check_expr(&mut self, cx: &EarlyContext, expr: &ast::Expr) {
|
||||
if !in_macro(cx, expr.span) {
|
||||
if !in_macro(expr.span) {
|
||||
check_if(cx, expr)
|
||||
}
|
||||
}
|
||||
@ -103,8 +103,8 @@ fn check_if(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
fn check_collapsible_maybe_if_let(cx: &EarlyContext, else_: &ast::Expr) {
|
||||
if_let_chain! {[
|
||||
let ast::ExprKind::Block(ref block) = else_.node,
|
||||
let Some(ref else_) = expr_block(block),
|
||||
!in_macro(cx, else_.span),
|
||||
let Some(else_) = expr_block(block),
|
||||
!in_macro(else_.span),
|
||||
], {
|
||||
match else_.node {
|
||||
ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => {
|
||||
@ -125,7 +125,7 @@ fn check_collapsible_no_if_let(cx: &EarlyContext, expr: &ast::Expr, check: &ast:
|
||||
let Some(inner) = expr_block(then),
|
||||
let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node,
|
||||
], {
|
||||
if expr.span.expn_id != inner.span.expn_id {
|
||||
if expr.span.ctxt != inner.span.ctxt {
|
||||
return;
|
||||
}
|
||||
span_lint_and_then(cx, COLLAPSIBLE_IF, expr.span, "this if statement can be collapsed", |db| {
|
||||
|
@ -313,10 +313,10 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> {
|
||||
}
|
||||
}
|
||||
|
||||
fn ifthenelse(&mut self, cond: &Expr, then: &Block, otherwise: &Option<P<Expr>>) -> Option<Constant> {
|
||||
fn ifthenelse(&mut self, cond: &Expr, then: &P<Expr>, otherwise: &Option<P<Expr>>) -> Option<Constant> {
|
||||
if let Some(Constant::Bool(b)) = self.expr(cond) {
|
||||
if b {
|
||||
self.block(then)
|
||||
self.expr(&**then)
|
||||
} else {
|
||||
otherwise.as_ref().and_then(|expr| self.expr(expr))
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ impl LintPass for CopyAndPaste {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CopyAndPaste {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if !in_macro(cx, expr.span) {
|
||||
if !in_macro(expr.span) {
|
||||
// skip ifs directly in else, it will be checked in the parent if
|
||||
if let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) {
|
||||
if else_expr.id == expr.id {
|
||||
@ -223,11 +223,15 @@ fn lint_match_arms(cx: &LateContext, expr: &Expr) {
|
||||
/// `if a { c } else if b { d } else { e }`.
|
||||
fn if_sequence(mut expr: &Expr) -> (SmallVector<&Expr>, SmallVector<&Block>) {
|
||||
let mut conds = SmallVector::new();
|
||||
let mut blocks = SmallVector::new();
|
||||
let mut blocks : SmallVector<&Block> = SmallVector::new();
|
||||
|
||||
while let ExprIf(ref cond, ref then_block, ref else_expr) = expr.node {
|
||||
while let ExprIf(ref cond, ref then_expr, ref else_expr) = expr.node {
|
||||
conds.push(&**cond);
|
||||
blocks.push(&**then_block);
|
||||
if let ExprBlock(ref block) = then_expr.node {
|
||||
blocks.push(block);
|
||||
} else {
|
||||
panic!("ExprIf node is not an ExprBlock");
|
||||
}
|
||||
|
||||
if let Some(ref else_expr) = *else_expr {
|
||||
expr = else_expr;
|
||||
@ -311,10 +315,10 @@ fn search_same<T, Hash, Eq>(exprs: &[T], hash: Hash, eq: Eq) -> Option<(&T, &T)>
|
||||
return None;
|
||||
} else if exprs.len() == 2 {
|
||||
return if eq(&exprs[0], &exprs[1]) {
|
||||
Some((&exprs[0], &exprs[1]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some((&exprs[0], &exprs[1]))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
}
|
||||
|
||||
let mut map: HashMap<_, Vec<&_>> = HashMap::with_capacity(exprs.len());
|
||||
|
@ -42,7 +42,7 @@ impl LintPass for CyclomaticComplexity {
|
||||
|
||||
impl CyclomaticComplexity {
|
||||
fn check<'a, 'tcx: 'a>(&mut self, cx: &'a LateContext<'a, 'tcx>, body: &'tcx Body, span: Span) {
|
||||
if in_macro(cx, span) {
|
||||
if in_macro(span) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use rustc::hir::*;
|
||||
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, NestedVisitorMap};
|
||||
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::Span;
|
||||
use utils::SpanlessEq;
|
||||
@ -46,8 +46,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint {
|
||||
if let Some((ty, map, key)) = check_cond(cx, check) {
|
||||
// in case of `if !m.contains_key(&k) { m.insert(k, v); }`
|
||||
// we can give a better error message
|
||||
let sole_expr = else_block.is_none() &&
|
||||
((then_block.expr.is_some() as usize) + then_block.stmts.len() == 1);
|
||||
let sole_expr = {
|
||||
else_block.is_none() &&
|
||||
if let ExprBlock(ref then_block) = then_block.node {
|
||||
(then_block.expr.is_some() as usize) + then_block.stmts.len() == 1
|
||||
} else {
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
let mut visitor = InsertVisitor {
|
||||
cx: cx,
|
||||
@ -58,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for HashMapLint {
|
||||
sole_expr: sole_expr,
|
||||
};
|
||||
|
||||
walk_block(&mut visitor, then_block);
|
||||
walk_expr(&mut visitor, &**then_block);
|
||||
}
|
||||
} else if let Some(ref else_block) = *else_block {
|
||||
if let Some((ty, map, key)) = check_cond(cx, check) {
|
||||
|
@ -228,7 +228,7 @@ impl EarlyLintPass for EnumVariantNames {
|
||||
let item_name = item.ident.name.as_str();
|
||||
let item_name_chars = item_name.chars().count();
|
||||
let item_camel = to_camel_case(&item_name);
|
||||
if !in_macro(cx, item.span) {
|
||||
if !in_macro(item.span) {
|
||||
if let Some(&(ref mod_name, ref mod_camel)) = self.modules.last() {
|
||||
// constants don't have surrounding modules
|
||||
if !mod_camel.is_empty() {
|
||||
|
@ -40,7 +40,7 @@ impl LintPass for Pass {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if let Some(span) = is_expn_of(cx, expr.span, "format") {
|
||||
if let Some(span) = is_expn_of(expr.span, "format") {
|
||||
match expr.node {
|
||||
// `format!("{}", foo)` expansion
|
||||
ExprCall(ref fun, ref args) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use syntax::codemap::mk_sp;
|
||||
use syntax::ast;
|
||||
use syntax_pos::{Span, NO_EXPANSION};
|
||||
use utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint};
|
||||
use syntax::ptr::P;
|
||||
|
||||
@ -99,13 +99,12 @@ impl EarlyLintPass for Formatting {
|
||||
/// Implementation of the `SUSPICIOUS_ASSIGNMENT_FORMATTING` lint.
|
||||
fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
if let ast::ExprKind::Assign(ref lhs, ref rhs) = expr.node {
|
||||
if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(cx, lhs.span) {
|
||||
let eq_span = mk_sp(lhs.span.hi, rhs.span.lo);
|
||||
|
||||
if !differing_macro_contexts(lhs.span, rhs.span) && !in_macro(lhs.span) {
|
||||
let eq_span = Span { lo: lhs.span.hi, hi: rhs.span.lo, ctxt: NO_EXPANSION };
|
||||
if let ast::ExprKind::Unary(op, ref sub_rhs) = rhs.node {
|
||||
if let Some(eq_snippet) = snippet_opt(cx, eq_span) {
|
||||
let op = ast::UnOp::to_string(op);
|
||||
let eqop_span = mk_sp(lhs.span.hi, sub_rhs.span.lo);
|
||||
let eqop_span= Span { lo: lhs.span.hi, hi: sub_rhs.span.lo, ctxt: NO_EXPANSION };
|
||||
if eq_snippet.ends_with('=') {
|
||||
span_note_and_lint(cx,
|
||||
SUSPICIOUS_ASSIGNMENT_FORMATTING,
|
||||
@ -125,10 +124,10 @@ fn check_assign(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for weird `else if`.
|
||||
fn check_else_if(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
if let Some((then, &Some(ref else_))) = unsugar_if(expr) {
|
||||
if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(cx, then.span) {
|
||||
if unsugar_if(else_).is_some() && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) {
|
||||
// this will be a span from the closing ‘}’ of the “then” block (excluding) to the
|
||||
// “if” of the “else if” block (excluding)
|
||||
let else_span = mk_sp(then.span.hi, else_.span.lo);
|
||||
let else_span = Span { lo: then.span.hi, hi: else_.span.lo, ctxt: NO_EXPANSION };
|
||||
|
||||
// the snippet should look like " else \n " with maybe comments anywhere
|
||||
// it’s bad when there is a ‘\n’ after the “else”
|
||||
@ -155,9 +154,9 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
for element in array {
|
||||
if let ast::ExprKind::Binary(ref op, ref lhs, _) = element.node {
|
||||
if !differing_macro_contexts(lhs.span, op.span) {
|
||||
let space_span = mk_sp(lhs.span.hi, op.span.lo);
|
||||
let space_span = Span { lo: lhs.span.hi, hi: op.span.lo, ctxt: NO_EXPANSION };
|
||||
if let Some(space_snippet) = snippet_opt(cx, space_span) {
|
||||
let lint_span = mk_sp(lhs.span.hi, lhs.span.hi);
|
||||
let lint_span = Span { lo: lhs.span.hi, hi: lhs.span.hi, ctxt: NO_EXPANSION };
|
||||
if space_snippet.contains('\n') {
|
||||
span_note_and_lint(cx,
|
||||
POSSIBLE_MISSING_COMMA,
|
||||
@ -175,10 +174,10 @@ fn check_array(cx: &EarlyContext, expr: &ast::Expr) {
|
||||
|
||||
/// Implementation of the `SUSPICIOUS_ELSE_FORMATTING` lint for consecutive ifs.
|
||||
fn check_consecutive_ifs(cx: &EarlyContext, first: &ast::Expr, second: &ast::Expr) {
|
||||
if !differing_macro_contexts(first.span, second.span) && !in_macro(cx, first.span) &&
|
||||
if !differing_macro_contexts(first.span, second.span) && !in_macro(first.span) &&
|
||||
unsugar_if(first).is_some() && unsugar_if(second).is_some() {
|
||||
// where the else would be
|
||||
let else_span = mk_sp(first.span.hi, second.span.lo);
|
||||
let else_span = Span { lo: first.span.hi, hi: second.span.lo, ctxt: NO_EXPANSION };
|
||||
|
||||
if let Some(else_snippet) = snippet_opt(cx, else_span) {
|
||||
if !else_snippet.contains('\n') {
|
||||
|
@ -33,7 +33,7 @@ impl LintPass for IdentityOp {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityOp {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||
if in_macro(cx, e.span) {
|
||||
if in_macro(e.span) {
|
||||
return;
|
||||
}
|
||||
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
|
||||
|
@ -75,7 +75,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
let span = Span {
|
||||
lo: expr.span.lo,
|
||||
hi: op.span.hi,
|
||||
expn_id: expr.span.expn_id,
|
||||
ctxt: expr.span.ctxt,
|
||||
};
|
||||
db.span_suggestion(span, "try this", format!("if {}.{}", snippet(cx, op.span, "_"), good_method));
|
||||
});
|
||||
|
@ -42,7 +42,7 @@ impl LintPass for ItemsAfterStatements {
|
||||
|
||||
impl EarlyLintPass for ItemsAfterStatements {
|
||||
fn check_block(&mut self, cx: &EarlyContext, item: &Block) {
|
||||
if in_macro(cx, item.span) {
|
||||
if in_macro(item.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ impl EarlyLintPass for ItemsAfterStatements {
|
||||
// lint on all further items
|
||||
for stmt in stmts {
|
||||
if let StmtKind::Item(ref it) = *stmt {
|
||||
if in_macro(cx, it.span) {
|
||||
if in_macro(it.span) {
|
||||
return;
|
||||
}
|
||||
if let ItemKind::MacroDef(..) = it.node {
|
||||
|
@ -61,7 +61,7 @@ impl LintPass for LenZero {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
|
||||
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||
if in_macro(cx, item.span) {
|
||||
if in_macro(item.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero {
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if in_macro(cx, expr.span) {
|
||||
if in_macro(expr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
use rustc::lint::*;
|
||||
use rustc::hir;
|
||||
use syntax::codemap;
|
||||
use syntax_pos::{Span, NO_EXPANSION};
|
||||
use utils::{snippet, span_lint_and_then};
|
||||
|
||||
/// **What it does:** Checks for variable declarations immediately followed by a
|
||||
@ -69,10 +69,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
|
||||
let hir::StmtExpr(ref if_, _) = expr.node,
|
||||
let hir::ExprIf(ref cond, ref then, ref else_) = if_.node,
|
||||
!used_in_expr(cx, def_id, cond),
|
||||
let Some(value) = check_assign(cx, def_id, then),
|
||||
let hir::ExprBlock(ref then) = then.node,
|
||||
let Some(value) = check_assign(cx, def_id, &*then),
|
||||
!used_in_expr(cx, def_id, value),
|
||||
], {
|
||||
let span = codemap::mk_sp(stmt.span.lo, if_.span.hi);
|
||||
let span = Span { lo: stmt.span.lo, hi: if_.span.hi, ctxt: NO_EXPANSION };
|
||||
|
||||
let (default_multi_stmts, default) = if let Some(ref else_) = *else_ {
|
||||
if let hir::ExprBlock(ref else_) = else_.node {
|
||||
|
@ -894,7 +894,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
|
||||
match def {
|
||||
Def::Local(..) | Def::Upvar(..) => {
|
||||
let def_id = def.def_id();
|
||||
let node_id = self.cx.tcx.hir.as_local_node_id(def_id).unwrap();
|
||||
let node_id = self.cx.tcx.hir.as_local_node_id(def_id).expect("local/upvar are local nodes");
|
||||
|
||||
let extent = self.cx.tcx.region_maps.var_scope(node_id);
|
||||
self.indexed.insert(seqvar.segments[0].name, Some(extent));
|
||||
|
@ -342,7 +342,7 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
|
||||
path_str == "Err",
|
||||
inner.iter().any(|pat| pat.node == PatKind::Wild),
|
||||
let ExprBlock(ref block) = arm.body.node,
|
||||
is_panic_block(cx, block)
|
||||
is_panic_block(block)
|
||||
], {
|
||||
// `Err(_)` arm with `panic!` found
|
||||
span_note_and_lint(cx,
|
||||
@ -359,13 +359,13 @@ fn check_wild_err_arm(cx: &LateContext, ex: &Expr, arms: &[Arm]) {
|
||||
}
|
||||
|
||||
// If the block contains only a `panic!` macro (as expression or statement)
|
||||
fn is_panic_block(cx: &LateContext, block: &Block) -> bool {
|
||||
fn is_panic_block(block: &Block) -> bool {
|
||||
match (&block.expr, block.stmts.len(), block.stmts.first()) {
|
||||
(&Some(ref exp), 0, _) => {
|
||||
is_expn_of(cx, exp.span, "panic").is_some() && is_expn_of(cx, exp.span, "unreachable").is_none()
|
||||
is_expn_of(exp.span, "panic").is_some() && is_expn_of(exp.span, "unreachable").is_none()
|
||||
},
|
||||
(&None, 1, Some(stmt)) => {
|
||||
is_expn_of(cx, stmt.span, "panic").is_some() && is_expn_of(cx, stmt.span, "unreachable").is_none()
|
||||
is_expn_of(stmt.span, "panic").is_some() && is_expn_of(stmt.span, "unreachable").is_none()
|
||||
},
|
||||
_ => false,
|
||||
}
|
||||
|
@ -554,7 +554,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
// ^ required because `cyclomatic_complexity` attribute shows up as unused
|
||||
#[cyclomatic_complexity = "30"]
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||
if in_macro(cx, expr.span) {
|
||||
if in_macro(expr.span) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -649,7 +649,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
if name == method_name &&
|
||||
sig.decl.inputs.len() == n_args &&
|
||||
out_type.matches(&sig.decl.output) &&
|
||||
self_kind.matches(&first_arg_ty, &first_arg, &self_ty, false) {
|
||||
self_kind.matches(first_arg_ty, first_arg, self_ty, false) {
|
||||
span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
|
||||
"defining a method called `{}` on this type; consider implementing \
|
||||
the `{}` trait or choosing a less ambiguous name", name, trait_name));
|
||||
@ -662,7 +662,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
for &(ref conv, self_kinds) in &CONVENTIONS {
|
||||
if_let_chain! {[
|
||||
conv.check(&name.as_str()),
|
||||
!self_kinds.iter().any(|k| k.matches(&first_arg_ty, &first_arg, &self_ty, is_copy)),
|
||||
!self_kinds.iter().any(|k| k.matches(first_arg_ty, first_arg, self_ty, is_copy)),
|
||||
], {
|
||||
let lint = if item.vis == hir::Visibility::Public {
|
||||
WRONG_PUB_SELF_CONVENTION
|
||||
@ -1065,7 +1065,7 @@ fn lint_map_unwrap_or(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::Expr]
|
||||
// lint, with note if neither arg is > 1 line and both map() and
|
||||
// unwrap_or() have the same span
|
||||
let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
|
||||
let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id;
|
||||
let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt;
|
||||
if same_span && !multiline {
|
||||
span_note_and_lint(cx,
|
||||
OPTION_MAP_UNWRAP_OR,
|
||||
@ -1094,7 +1094,7 @@ fn lint_map_unwrap_or_else(cx: &LateContext, expr: &hir::Expr, map_args: &[hir::
|
||||
// lint, with note if neither arg is > 1 line and both map() and
|
||||
// unwrap_or_else() have the same span
|
||||
let multiline = map_snippet.lines().count() > 1 || unwrap_snippet.lines().count() > 1;
|
||||
let same_span = map_args[1].span.expn_id == unwrap_args[1].span.expn_id;
|
||||
let same_span = map_args[1].span.ctxt == unwrap_args[1].span.ctxt;
|
||||
if same_span && !multiline {
|
||||
span_note_and_lint(cx,
|
||||
OPTION_MAP_UNWRAP_OR_ELSE,
|
||||
|
@ -326,7 +326,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
if in_attributes_expansion(cx, expr) {
|
||||
if in_attributes_expansion(expr) {
|
||||
// Don't lint things expanded by #[derive(...)], etc
|
||||
return;
|
||||
}
|
||||
@ -498,9 +498,9 @@ fn is_used(cx: &LateContext, expr: &Expr) -> bool {
|
||||
|
||||
/// Test whether an expression is in a macro expansion (e.g. something generated by
|
||||
/// `#[derive(...)`] or the like).
|
||||
fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
|
||||
cx.sess().codemap().with_expn_info(expr.span.expn_id, |info_opt| {
|
||||
info_opt.map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)))
|
||||
fn in_attributes_expansion(expr: &Expr) -> bool {
|
||||
expr.span.ctxt.outer().expn_info().map_or(false, |info| {
|
||||
matches!(info.callee.format, ExpnFormat::MacroAttribute(_))
|
||||
})
|
||||
}
|
||||
|
||||
@ -510,7 +510,7 @@ fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
||||
def::Def::Local(id) |
|
||||
def::Def::Upvar(id, _, _) => {
|
||||
if let Some(span) = cx.tcx.hir.span_if_local(id) {
|
||||
!in_macro(cx, span)
|
||||
!in_macro(span)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ impl MissingDoc {
|
||||
return;
|
||||
}
|
||||
|
||||
if in_macro(cx, sp) {
|
||||
if in_macro(sp) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
|
||||
"this if-then-else expression returns a bool literal",
|
||||
|db| { db.span_suggestion(e.span, "you can reduce it to", hint); });
|
||||
};
|
||||
if let ExprBlock(ref then_block) = then_block.node {
|
||||
match (fetch_bool_block(then_block), fetch_bool_expr(else_expr)) {
|
||||
(RetBool(true), RetBool(true)) |
|
||||
(Bool(true), Bool(true)) => {
|
||||
@ -97,6 +98,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBool {
|
||||
(Bool(false), Bool(true)) => reduce(false, true),
|
||||
_ => (),
|
||||
}
|
||||
} else {
|
||||
panic!("IfExpr 'then' node is not an ExprBlock");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ impl LintPass for NeedlessBorrow {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||
if in_macro(cx, e.span) {
|
||||
if in_macro(e.span) {
|
||||
return;
|
||||
}
|
||||
if let ExprAddrOf(MutImmutable, ref inner) = e.node {
|
||||
@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessBorrow {
|
||||
}
|
||||
}
|
||||
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
|
||||
if in_macro(cx, pat.span) {
|
||||
if in_macro(pat.span) {
|
||||
return;
|
||||
}
|
||||
if_let_chain! {[
|
||||
|
@ -55,7 +55,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
|
||||
span: Span,
|
||||
node_id: NodeId
|
||||
) {
|
||||
if in_macro(cx, span) {
|
||||
if in_macro(span) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ declare_lint! {
|
||||
}
|
||||
|
||||
fn has_no_effect(cx: &LateContext, expr: &Expr) -> bool {
|
||||
if in_macro(cx, expr.span) {
|
||||
if in_macro(expr.span) {
|
||||
return false;
|
||||
}
|
||||
match expr.node {
|
||||
@ -110,7 +110,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
} else if let Some(reduced) = reduce_expression(cx, expr) {
|
||||
let mut snippet = String::new();
|
||||
for e in reduced {
|
||||
if in_macro(cx, e.span) {
|
||||
if in_macro(e.span) {
|
||||
return;
|
||||
}
|
||||
if let Some(snip) = snippet_opt(cx, e.span) {
|
||||
@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
|
||||
|
||||
fn reduce_expression<'a>(cx: &LateContext, expr: &'a Expr) -> Option<Vec<&'a Expr>> {
|
||||
if in_macro(cx, expr.span) {
|
||||
if in_macro(expr.span) {
|
||||
return None;
|
||||
}
|
||||
match expr.node {
|
||||
|
@ -135,7 +135,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
|
||||
}
|
||||
}
|
||||
fn check_name(&mut self, span: Span, name: Name) {
|
||||
if in_macro(self.0.cx, span) {
|
||||
if in_macro(span) {
|
||||
return;
|
||||
}
|
||||
let interned_name = name.as_str();
|
||||
|
@ -42,7 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
let ExprPath(ref qpath) = fun.node,
|
||||
match_def_path(cx.tcx, resolve_node(cx, qpath, fun.id).def_id(), &paths::BEGIN_PANIC),
|
||||
let ExprLit(ref lit) = params[0].node,
|
||||
is_direct_expn_of(cx, params[0].span, "panic").is_some(),
|
||||
is_direct_expn_of(params[0].span, "panic").is_some(),
|
||||
let LitKind::Str(ref string, _) = lit.node,
|
||||
let Some(par) = string.as_str().find('{'),
|
||||
string.as_str()[par..].contains('}')
|
||||
|
@ -40,7 +40,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
if_let_chain! {[
|
||||
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
|
||||
!is_automatically_derived(&*item.attrs),
|
||||
trait_ref.path.def.def_id() == cx.tcx.lang_items.eq_trait().unwrap(),
|
||||
let Some(eq_trait) = cx.tcx.lang_items.eq_trait(),
|
||||
trait_ref.path.def.def_id() == eq_trait
|
||||
], {
|
||||
for impl_item in impl_items {
|
||||
if impl_item.name == "ne" {
|
||||
|
@ -77,9 +77,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
// Search for `std::io::_print(..)` which is unique in a
|
||||
// `print!` expansion.
|
||||
if match_def_path(cx.tcx, fun_id, &paths::IO_PRINT) {
|
||||
if let Some(span) = is_expn_of(cx, expr.span, "print") {
|
||||
if let Some(span) = is_expn_of(expr.span, "print") {
|
||||
// `println!` uses `print!`.
|
||||
let (span, name) = match is_expn_of(cx, span, "println") {
|
||||
let (span, name) = match is_expn_of(span, "println") {
|
||||
Some(span) => (span, "println"),
|
||||
None => (span, "print"),
|
||||
};
|
||||
@ -125,7 +125,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
if let ExprPath(ref qpath) = args[1].node {
|
||||
let def_id = cx.tables.qpath_def(qpath, args[1].id).def_id();
|
||||
if match_def_path(cx.tcx, def_id, &paths::DEBUG_FMT_METHOD) && !is_in_debug_impl(cx, expr) &&
|
||||
is_expn_of(cx, expr.span, "panic").is_none() {
|
||||
is_expn_of(expr.span, "panic").is_none() {
|
||||
span_lint(cx, USE_DEBUG, args[0].span, "use of `Debug`-based formatting");
|
||||
}
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StepByZero {
|
||||
let ExprMethodCall( Spanned { node: iter_name, .. }, _, ref iter_args ) = *iter,
|
||||
iter_name == "iter",
|
||||
// range expression in .zip() call: 0..x.len()
|
||||
let Some(higher::Range { start: Some(ref start), end: Some(ref end), .. }) = higher::range(zip_arg),
|
||||
let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg),
|
||||
is_integer_literal(start, 0),
|
||||
// .len() call
|
||||
let ExprMethodCall(Spanned { node: len_name, .. }, _, ref len_args) = end.node,
|
||||
|
@ -91,7 +91,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
self.last.is_none(),
|
||||
let Some(ref expr) = block.expr,
|
||||
match_type(cx, cx.tables.expr_ty(expr), &paths::REGEX),
|
||||
let Some(span) = is_expn_of(cx, expr.span, "regex"),
|
||||
let Some(span) = is_expn_of(expr.span, "regex"),
|
||||
], {
|
||||
if !self.spans.contains(&span) {
|
||||
span_lint(cx,
|
||||
|
@ -107,7 +107,7 @@ impl ReturnPass {
|
||||
|
||||
// we need both a let-binding stmt and an expr
|
||||
if_let_chain! {[
|
||||
let Some(ref retexpr) = it.next_back(),
|
||||
let Some(retexpr) = it.next_back(),
|
||||
let ast::StmtKind::Expr(ref retexpr) = retexpr.node,
|
||||
let Some(stmt) = it.next_back(),
|
||||
let ast::StmtKind::Local(ref local) = stmt.node,
|
||||
|
@ -305,7 +305,7 @@ fn check_expr<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings:
|
||||
},
|
||||
ExprIf(ref cond, ref then, ref otherwise) => {
|
||||
check_expr(cx, cond, bindings);
|
||||
check_block(cx, then, bindings);
|
||||
check_expr(cx, &**then, bindings);
|
||||
if let Some(ref o) = *otherwise {
|
||||
check_expr(cx, o, bindings);
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ShouldAssertEq {
|
||||
let ExprIf(ref cond, ..) = e.node,
|
||||
let ExprUnary(UnOp::UnNot, ref cond) = cond.node,
|
||||
let ExprBinary(ref binop, ref expr1, ref expr2) = cond.node,
|
||||
is_direct_expn_of(cx, e.span, "assert").is_some(),
|
||||
is_direct_expn_of(e.span, "assert").is_some(),
|
||||
let Some(debug_trait) = cx.tcx.lang_items.debug_trait(),
|
||||
], {
|
||||
let sugg = match binop.node {
|
||||
|
@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
|
||||
if name.node == "as_bytes" {
|
||||
if let ExprLit(ref lit) = args[0].node {
|
||||
if let LitKind::Str(ref lit_content, _) = lit.node {
|
||||
if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(cx, args[0].span) {
|
||||
if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) {
|
||||
span_lint_and_then(cx,
|
||||
STRING_LIT_AS_BYTES,
|
||||
e.span,
|
||||
|
@ -1,9 +1,9 @@
|
||||
use rustc::hir::*;
|
||||
use rustc::lint::*;
|
||||
use rustc::ty;
|
||||
use syntax::codemap::mk_sp;
|
||||
use utils::{differing_macro_contexts, match_type, paths, snippet, span_lint_and_then, walk_ptrs_ty, SpanlessEq};
|
||||
use utils::sugg::Sugg;
|
||||
use syntax_pos::{Span, NO_EXPANSION};
|
||||
|
||||
/// **What it does:** Checks for manual swapping.
|
||||
///
|
||||
@ -115,16 +115,14 @@ fn check_manual_swap(cx: &LateContext, block: &Block) {
|
||||
} else {
|
||||
(false, "".to_owned(), "".to_owned())
|
||||
}
|
||||
} else if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
|
||||
(true, format!(" `{}` and `{}`", first, second),
|
||||
format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()))
|
||||
} else {
|
||||
if let (Some(first), Some(second)) = (Sugg::hir_opt(cx, lhs1), Sugg::hir_opt(cx, rhs1)) {
|
||||
(true, format!(" `{}` and `{}`", first, second),
|
||||
format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()))
|
||||
} else {
|
||||
(true, "".to_owned(), "".to_owned())
|
||||
}
|
||||
(true, "".to_owned(), "".to_owned())
|
||||
};
|
||||
|
||||
let span = mk_sp(w[0].span.lo, second.span.hi);
|
||||
let span = Span { lo: w[0].span.lo, hi: second.span.hi, ctxt: NO_EXPANSION};
|
||||
|
||||
span_lint_and_then(cx,
|
||||
MANUAL_SWAP,
|
||||
@ -163,7 +161,7 @@ fn check_suspicious_swap(cx: &LateContext, block: &Block) {
|
||||
("".to_owned(), "".to_owned(), "".to_owned())
|
||||
};
|
||||
|
||||
let span = mk_sp(first.span.lo, second.span.hi);
|
||||
let span = Span{ lo: first.span.lo, hi: second.span.hi, ctxt: NO_EXPANSION};
|
||||
|
||||
span_lint_and_then(cx,
|
||||
ALMOST_SWAPPED,
|
||||
|
@ -107,7 +107,7 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
|
||||
}
|
||||
|
||||
fn check_ty(cx: &LateContext, ast_ty: &Ty) {
|
||||
if in_macro(cx, ast_ty.span) {
|
||||
if in_macro(ast_ty.span) {
|
||||
return;
|
||||
}
|
||||
match ast_ty.node {
|
||||
@ -118,7 +118,7 @@ fn check_ty(cx: &LateContext, ast_ty: &Ty) {
|
||||
let last = last_path_segment(qpath);
|
||||
if_let_chain! {[
|
||||
let PathParameters::AngleBracketedParameters(ref ag) = last.parameters,
|
||||
let Some(ref vec) = ag.types.get(0),
|
||||
let Some(vec) = ag.types.get(0),
|
||||
let TyPath(ref qpath) = vec.node,
|
||||
let def::Def::Struct(..) = cx.tables.qpath_def(qpath, vec.id),
|
||||
let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, vec.id)),
|
||||
@ -199,7 +199,7 @@ fn check_let_unit(cx: &LateContext, decl: &Decl) {
|
||||
let bindtype = &cx.tables.pat_ty(&local.pat).sty;
|
||||
match *bindtype {
|
||||
ty::TyTuple(slice, _) if slice.is_empty() => {
|
||||
if in_external_macro(cx, decl.span) || in_macro(cx, local.pat.span) {
|
||||
if in_external_macro(cx, decl.span) || in_macro(local.pat.span) {
|
||||
return;
|
||||
}
|
||||
if higher::is_from_for_desugar(decl) {
|
||||
@ -261,7 +261,7 @@ impl LintPass for UnitCmp {
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitCmp {
|
||||
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||
if in_macro(cx, expr.span) {
|
||||
if in_macro(expr.span) {
|
||||
return;
|
||||
}
|
||||
if let ExprBinary(ref cmp, ref left, _) = expr.node {
|
||||
@ -694,7 +694,7 @@ impl<'a, 'tcx> TypeComplexityPass {
|
||||
}
|
||||
|
||||
fn check_type(&self, cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty) {
|
||||
if in_macro(cx, ty.span) {
|
||||
if in_macro(ty.span) {
|
||||
return;
|
||||
}
|
||||
let score = {
|
||||
@ -797,7 +797,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 {
|
||||
if let ExprCast(ref e, _) = expr.node {
|
||||
if let ExprLit(ref l) = e.node {
|
||||
if let LitKind::Char(_) = l.node {
|
||||
if ty::TyUint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(cx, expr.span) {
|
||||
if ty::TyUint(UintTy::U8) == cx.tables.expr_ty(expr).sty && !in_macro(expr.span) {
|
||||
let msg = "casting character literal to u8. `char`s \
|
||||
are 4 bytes wide in rust, so casting to u8 \
|
||||
truncates them";
|
||||
@ -971,7 +971,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AbsurdExtremeComparisons {
|
||||
|
||||
if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node {
|
||||
if let Some((culprit, result)) = detect_absurd_comparison(cx, cmp.node, lhs, rhs) {
|
||||
if !in_macro(cx, expr.span) {
|
||||
if !in_macro(expr.span) {
|
||||
let msg = "this comparison involving the minimum or maximum element for this \
|
||||
type contains a case that is always true or always false";
|
||||
|
||||
|
@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
|
||||
span: Span,
|
||||
fn_id: ast::NodeId
|
||||
) {
|
||||
if in_macro(cx, span) {
|
||||
if in_macro(span) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ pub fn vec_macro<'e>(cx: &LateContext, expr: &'e hir::Expr) -> Option<VecArgs<'e
|
||||
if_let_chain!{[
|
||||
let hir::ExprCall(ref fun, ref args) = expr.node,
|
||||
let hir::ExprPath(ref path) = fun.node,
|
||||
is_expn_of(cx, fun.span, "vec").is_some(),
|
||||
is_expn_of(fun.span, "vec").is_some(),
|
||||
], {
|
||||
let fun_def = resolve_node(cx, path, fun.id);
|
||||
return if match_def_path(cx.tcx, fun_def.def_id(), &paths::VEC_FROM_ELEM) && args.len() == 2 {
|
||||
|
@ -97,7 +97,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
|
||||
},
|
||||
(&ExprIndex(ref la, ref li), &ExprIndex(ref ra, ref ri)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
|
||||
(&ExprIf(ref lc, ref lt, ref le), &ExprIf(ref rc, ref rt, ref re)) => {
|
||||
self.eq_expr(lc, rc) && self.eq_block(lt, rt) && both(le, re, |l, r| self.eq_expr(l, r))
|
||||
self.eq_expr(lc, rc) && self.eq_expr(&**lt, &**rt) && both(le, re, |l, r| self.eq_expr(l, r))
|
||||
},
|
||||
(&ExprLit(ref l), &ExprLit(ref r)) => l.node == r.node,
|
||||
(&ExprLoop(ref lb, ref ll, ref lls), &ExprLoop(ref rb, ref rl, ref rls)) => {
|
||||
@ -395,7 +395,7 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||
let c: fn(_, _, _) -> _ = ExprIf;
|
||||
c.hash(&mut self.s);
|
||||
self.hash_expr(cond);
|
||||
self.hash_block(t);
|
||||
self.hash_expr(&**t);
|
||||
if let Some(ref e) = *e {
|
||||
self.hash_expr(e);
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
|
||||
// not able to capture the error.
|
||||
// Therefore, we need to climb the macro expansion tree and find the
|
||||
// actual span that invoked `declare_lint!`:
|
||||
let lint_span = cx.sess().codemap().source_callsite(lint_span);
|
||||
let lint_span = lint_span.ctxt.outer().expn_info().map(|ei| ei.call_site).expect("unable to get call_site");
|
||||
|
||||
if !self.registered_lints.contains(lint_name) {
|
||||
span_lint(cx,
|
||||
|
@ -97,7 +97,7 @@ pub mod higher;
|
||||
/// Returns true if the two spans come from differing expansions (i.e. one is from a macro and one
|
||||
/// isn't).
|
||||
pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
|
||||
rhs.expn_id != lhs.expn_id
|
||||
rhs.ctxt != lhs.ctxt
|
||||
}
|
||||
|
||||
pub fn in_constant(cx: &LateContext, id: NodeId) -> bool {
|
||||
@ -111,17 +111,11 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool {
|
||||
}
|
||||
|
||||
/// Returns true if this `expn_info` was expanded by any macro.
|
||||
pub fn in_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
|
||||
cx.sess().codemap().with_expn_info(span.expn_id, |info| {
|
||||
match info {
|
||||
Some(info) => {
|
||||
match info.callee.format {
|
||||
// don't treat range expressions desugared to structs as "in_macro"
|
||||
ExpnFormat::CompilerDesugaring(name) => name != "...",
|
||||
_ => true,
|
||||
}
|
||||
},
|
||||
None => false,
|
||||
pub fn in_macro(span: Span) -> bool {
|
||||
span.ctxt.outer().expn_info().map_or(false, |info| {
|
||||
match info.callee.format {// don't treat range expressions desugared to structs as "in_macro"
|
||||
ExpnFormat::CompilerDesugaring(name) => name != "...",
|
||||
_ => true,
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -131,22 +125,20 @@ pub fn in_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
|
||||
pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
|
||||
/// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use
|
||||
/// this after other checks have already happened.
|
||||
fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool {
|
||||
fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool {
|
||||
// no ExpnInfo = no macro
|
||||
opt_info.map_or(false, |info| {
|
||||
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| {
|
||||
// no snippet = external macro or compiler-builtin expansion
|
||||
cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules"))
|
||||
})
|
||||
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| {
|
||||
// no snippet = external macro or compiler-builtin expansion
|
||||
cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code| !code.starts_with("macro_rules"))
|
||||
})
|
||||
}
|
||||
|
||||
cx.sess().codemap().with_expn_info(span.expn_id, |info| in_macro_ext(cx, info))
|
||||
span.ctxt.outer().expn_info().map_or(false, |info| in_macro_ext(cx, &info))
|
||||
}
|
||||
|
||||
/// Check if a `DefId`'s path matches the given absolute type path usage.
|
||||
@ -365,6 +357,9 @@ pub fn method_chain_args<'a>(expr: &'a Expr, methods: &[&str]) -> Option<Vec<&'a
|
||||
// method chains are stored last -> first
|
||||
if let ExprMethodCall(ref name, _, ref args) = current.node {
|
||||
if name.node == *method_name {
|
||||
if args.iter().any(|e| in_macro(e.span)) {
|
||||
return None;
|
||||
}
|
||||
matched.push(&**args); // build up `matched` backwards
|
||||
current = &args[0] // go to parent expression
|
||||
} else {
|
||||
@ -693,12 +688,10 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
|
||||
|
||||
/// Return the pre-expansion span if is this comes from an expansion of the macro `name`.
|
||||
/// See also `is_direct_expn_of`.
|
||||
pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span> {
|
||||
pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
|
||||
loop {
|
||||
let span_name_span = cx.tcx
|
||||
.sess
|
||||
.codemap()
|
||||
.with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site)));
|
||||
let span_name_span = span.ctxt.outer()
|
||||
.expn_info().map(|ei| (ei.callee.name(), ei.call_site));
|
||||
|
||||
match span_name_span {
|
||||
Some((mac_name, new_span)) if mac_name == name => return Some(new_span),
|
||||
@ -715,11 +708,9 @@ pub fn is_expn_of(cx: &LateContext, mut span: Span, name: &str) -> Option<Span>
|
||||
/// ```
|
||||
/// `42` is considered expanded from `foo!` and `bar!` by `is_expn_of` but only `bar!` by
|
||||
/// `is_direct_expn_of`.
|
||||
pub fn is_direct_expn_of(cx: &LateContext, span: Span, name: &str) -> Option<Span> {
|
||||
let span_name_span = cx.tcx
|
||||
.sess
|
||||
.codemap()
|
||||
.with_expn_info(span.expn_id, |expn| expn.map(|ei| (ei.callee.name(), ei.call_site)));
|
||||
pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
|
||||
let span_name_span = span.ctxt.outer()
|
||||
.expn_info().map(|ei| (ei.callee.name(), ei.call_site));
|
||||
|
||||
match span_name_span {
|
||||
Some((mac_name, new_span)) if mac_name == name => Some(new_span),
|
||||
|
@ -50,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
||||
is_copy(cx, vec_type(cx.tables.expr_ty_adjusted(arg)), cx.tcx.hir.get_parent(expr.id)),
|
||||
], {
|
||||
// report the error around the `vec!` not inside `<std macros>:`
|
||||
let span = cx.sess().codemap().source_callsite(arg.span);
|
||||
let span = arg.span.ctxt.outer().expn_info().map(|info| info.call_site).expect("unable to get call_site");
|
||||
check_vec_macro(cx, &vec_args, span);
|
||||
}}
|
||||
}
|
||||
@ -70,7 +70,7 @@ fn check_vec_macro(cx: &LateContext, vec_args: &higher::VecArgs, span: Span) {
|
||||
let span = Span {
|
||||
lo: args[0].span.lo,
|
||||
hi: last.span.hi,
|
||||
expn_id: args[0].span.expn_id,
|
||||
ctxt: args[0].span.ctxt,
|
||||
};
|
||||
|
||||
format!("&[{}]", snippet(cx, span, "..")).into()
|
||||
|
@ -20,13 +20,12 @@ fn main() {
|
||||
lazy_static! {
|
||||
static ref MUT_MAP : HashMap<usize, &'static str> = {
|
||||
let mut m = HashMap::new();
|
||||
let mut zero = &mut &mut "zero";
|
||||
m.insert(0, "zero");
|
||||
m
|
||||
};
|
||||
static ref MUT_COUNT : usize = MUT_MAP.len();
|
||||
}
|
||||
assert!(*MUT_COUNT == 1);
|
||||
assert_eq!(*MUT_COUNT, 1);
|
||||
// FIXME: don't lint in array length, requires `check_body`
|
||||
//let _ = [""; (42.0 < std::f32::NAN) as usize];
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
error: you probably are missing some parameter in your format string
|
||||
--> $DIR/panic.rs:8:16
|
||||
|
|
||||
8 | panic!("{}");
|
||||
| ^^^^
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/panic.rs:4:9
|
||||
|
|
||||
4 | #![deny(panic_params)]
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: you probably are missing some parameter in your format string
|
||||
--> $DIR/panic.rs:10:16
|
||||
|
|
||||
10 | panic!("{:?}");
|
||||
| ^^^^^^
|
||||
|
||||
error: you probably are missing some parameter in your format string
|
||||
--> $DIR/panic.rs:12:23
|
||||
|
|
||||
12 | assert!(true, "here be missing values: {}");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
Loading…
Reference in New Issue
Block a user