rustup to rustc 1.15.0-dev (3b248a184 2016-12-05)
This commit is contained in:
parent
2e63a5648a
commit
c6e2967b9c
71 changed files with 517 additions and 335 deletions
|
@ -60,7 +60,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprLit(ref lit) = e.node {
|
if let ExprLit(ref lit) = e.node {
|
||||||
check_lit(cx, lit, e);
|
check_lit(cx, lit, e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,7 @@ impl LintPass for Arithmetic {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Arithmetic {
|
impl LateLintPass for Arithmetic {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
if self.span.is_some() {
|
if self.span.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -82,7 +82,7 @@ impl LateLintPass for Arithmetic {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr_post(&mut self, _: &LateContext, expr: &hir::Expr) {
|
fn check_expr_post<'a, 'tcx: 'a>(&mut self, _: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
if Some(expr.span) == self.span {
|
if Some(expr.span) == self.span {
|
||||||
self.span = None;
|
self.span = None;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl LintPass for ArrayIndexing {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for ArrayIndexing {
|
impl LateLintPass for ArrayIndexing {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
|
||||||
if let hir::ExprIndex(ref array, ref index) = e.node {
|
if let hir::ExprIndex(ref array, ref index) = e.node {
|
||||||
// Array with known size can be checked statically
|
// Array with known size can be checked statically
|
||||||
let ty = cx.tcx.tables().expr_ty(array);
|
let ty = cx.tcx.tables().expr_ty(array);
|
||||||
|
|
|
@ -67,7 +67,7 @@ impl LintPass for AssignOps {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for AssignOps {
|
impl LateLintPass for AssignOps {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
|
hir::ExprAssignOp(op, ref lhs, ref rhs) => {
|
||||||
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
|
span_lint_and_then(cx, ASSIGN_OPS, expr.span, "assign operation detected", |db| {
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl LintPass for AttrPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for AttrPass {
|
impl LateLintPass for AttrPass {
|
||||||
fn check_attribute(&mut self, cx: &LateContext, attr: &Attribute) {
|
fn check_attribute<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) {
|
||||||
if let MetaItemKind::List(ref items) = attr.value.node {
|
if let MetaItemKind::List(ref items) = attr.value.node {
|
||||||
if items.is_empty() || attr.name() != "deprecated" {
|
if items.is_empty() || attr.name() != "deprecated" {
|
||||||
return;
|
return;
|
||||||
|
@ -99,7 +99,7 @@ impl LateLintPass for AttrPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if is_relevant_item(cx, item) {
|
if is_relevant_item(cx, item) {
|
||||||
check_attrs(cx, item.span, &item.name, &item.attrs)
|
check_attrs(cx, item.span, &item.name, &item.attrs)
|
||||||
}
|
}
|
||||||
|
@ -138,13 +138,13 @@ impl LateLintPass for AttrPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
if is_relevant_impl(cx, item) {
|
if is_relevant_impl(cx, item) {
|
||||||
check_attrs(cx, item.span, &item.name, &item.attrs)
|
check_attrs(cx, item.span, &item.name, &item.attrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||||
if is_relevant_trait(cx, item) {
|
if is_relevant_trait(cx, item) {
|
||||||
check_attrs(cx, item.span, &item.name, &item.attrs)
|
check_attrs(cx, item.span, &item.name, &item.attrs)
|
||||||
}
|
}
|
||||||
|
@ -152,8 +152,8 @@ impl LateLintPass for AttrPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
|
fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
|
||||||
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
|
if let ItemFn(_, _, _, _, _, eid) = item.node {
|
||||||
is_relevant_expr(cx, expr)
|
is_relevant_expr(cx, cx.tcx.map.expr(eid))
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,7 @@ fn is_relevant_item(cx: &LateContext, item: &Item) -> bool {
|
||||||
|
|
||||||
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
|
fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
|
||||||
match item.node {
|
match item.node {
|
||||||
ImplItemKind::Method(_, ref expr) => is_relevant_expr(cx, expr),
|
ImplItemKind::Method(_, eid) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ fn is_relevant_impl(cx: &LateContext, item: &ImplItem) -> bool {
|
||||||
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
|
fn is_relevant_trait(cx: &LateContext, item: &TraitItem) -> bool {
|
||||||
match item.node {
|
match item.node {
|
||||||
MethodTraitItem(_, None) => true,
|
MethodTraitItem(_, None) => true,
|
||||||
MethodTraitItem(_, Some(ref expr)) => is_relevant_expr(cx, expr),
|
MethodTraitItem(_, Some(eid)) => is_relevant_expr(cx, cx.tcx.map.expr(eid)),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl LintPass for BitMask {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for BitMask {
|
impl LateLintPass for BitMask {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
|
if let ExprBinary(ref cmp, ref left, ref right) = e.node {
|
||||||
if cmp.node.is_comparison() {
|
if cmp.node.is_comparison() {
|
||||||
if let Some(cmp_opt) = fetch_int_literal(cx, right) {
|
if let Some(cmp_opt) = fetch_int_literal(cx, right) {
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl LintPass for BlackListedName {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for BlackListedName {
|
impl LateLintPass for BlackListedName {
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
fn check_pat<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
|
||||||
if let PatKind::Binding(_, _, ref ident, _) = pat.node {
|
if let PatKind::Binding(_, _, ref ident, _) = pat.node {
|
||||||
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
|
if self.blacklist.iter().any(|s| s == &*ident.node.as_str()) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass};
|
use rustc::lint::{LateLintPass, LateContext, LintArray, LintPass};
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr};
|
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
|
||||||
use utils::*;
|
use utils::*;
|
||||||
|
|
||||||
/// **What it does:** Checks for `if` conditions that use blocks to contain an
|
/// **What it does:** Checks for `if` conditions that use blocks to contain an
|
||||||
|
@ -49,13 +49,15 @@ impl LintPass for BlockInIfCondition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ExVisitor<'v> {
|
struct ExVisitor<'a, 'tcx: 'a> {
|
||||||
found_block: Option<&'v Expr>,
|
found_block: Option<&'tcx Expr>,
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for ExVisitor<'v> {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for ExVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if let ExprClosure(_, _, ref expr, _) = expr.node {
|
if let ExprClosure(_, _, eid, _) = expr.node {
|
||||||
|
let expr = self.cx.tcx.map.expr(eid);
|
||||||
if matches!(expr.node, ExprBlock(_)) {
|
if matches!(expr.node, ExprBlock(_)) {
|
||||||
self.found_block = Some(expr);
|
self.found_block = Some(expr);
|
||||||
return;
|
return;
|
||||||
|
@ -63,6 +65,9 @@ impl<'v> Visitor<'v> for ExVisitor<'v> {
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition";
|
const BRACED_EXPR_MESSAGE: &'static str = "omit braces around single expression condition";
|
||||||
|
@ -70,7 +75,7 @@ const COMPLEX_BLOCK_MESSAGE: &'static str = "in an 'if' condition, avoid complex
|
||||||
instead, move the block or closure higher and bind it with a 'let'";
|
instead, move the block or closure higher and bind it with a 'let'";
|
||||||
|
|
||||||
impl LateLintPass for BlockInIfCondition {
|
impl LateLintPass for BlockInIfCondition {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprIf(ref check, ref then, _) = expr.node {
|
if let ExprIf(ref check, ref then, _) = expr.node {
|
||||||
if let ExprBlock(ref block) = check.node {
|
if let ExprBlock(ref block) = check.node {
|
||||||
if block.rules == DefaultBlock {
|
if block.rules == DefaultBlock {
|
||||||
|
@ -105,7 +110,7 @@ impl LateLintPass for BlockInIfCondition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let mut visitor = ExVisitor { found_block: None };
|
let mut visitor = ExVisitor { found_block: None, cx: cx };
|
||||||
walk_expr(&mut visitor, check);
|
walk_expr(&mut visitor, check);
|
||||||
if let Some(block) = visitor.found_block {
|
if let Some(block) = visitor.found_block {
|
||||||
span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE);
|
span_lint(cx, BLOCK_IN_IF_CONDITION_STMT, block.span, COMPLEX_BLOCK_MESSAGE);
|
||||||
|
|
|
@ -54,12 +54,14 @@ impl LintPass for NonminimalBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for NonminimalBool {
|
impl LateLintPass for NonminimalBool {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
NonminimalBoolVisitor(cx).visit_item(item)
|
NonminimalBoolVisitor { cx: cx }.visit_item(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
|
struct NonminimalBoolVisitor<'a, 'tcx: 'a> {
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
use quine_mc_cluskey::Bool;
|
use quine_mc_cluskey::Bool;
|
||||||
struct Hir2Qmm<'a, 'tcx: 'a, 'v> {
|
struct Hir2Qmm<'a, 'tcx: 'a, 'v> {
|
||||||
|
@ -308,7 +310,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
fn bool_expr(&self, e: &Expr) {
|
fn bool_expr(&self, e: &Expr) {
|
||||||
let mut h2q = Hir2Qmm {
|
let mut h2q = Hir2Qmm {
|
||||||
terminals: Vec::new(),
|
terminals: Vec::new(),
|
||||||
cx: self.0,
|
cx: self.cx,
|
||||||
};
|
};
|
||||||
if let Ok(expr) = h2q.run(e) {
|
if let Ok(expr) = h2q.run(e) {
|
||||||
|
|
||||||
|
@ -343,7 +345,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
continue 'simplified;
|
continue 'simplified;
|
||||||
}
|
}
|
||||||
if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 {
|
if stats.terminals[i] != 0 && simplified_stats.terminals[i] == 0 {
|
||||||
span_lint_and_then(self.0,
|
span_lint_and_then(self.cx,
|
||||||
LOGIC_BUG,
|
LOGIC_BUG,
|
||||||
e.span,
|
e.span,
|
||||||
"this boolean expression contains a logic bug",
|
"this boolean expression contains a logic bug",
|
||||||
|
@ -353,7 +355,7 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
outer expression");
|
outer expression");
|
||||||
db.span_suggestion(e.span,
|
db.span_suggestion(e.span,
|
||||||
"it would look like the following",
|
"it would look like the following",
|
||||||
suggest(self.0, suggestion, &h2q.terminals));
|
suggest(self.cx, suggestion, &h2q.terminals));
|
||||||
});
|
});
|
||||||
// don't also lint `NONMINIMAL_BOOL`
|
// don't also lint `NONMINIMAL_BOOL`
|
||||||
return;
|
return;
|
||||||
|
@ -370,13 +372,13 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !improvements.is_empty() {
|
if !improvements.is_empty() {
|
||||||
span_lint_and_then(self.0,
|
span_lint_and_then(self.cx,
|
||||||
NONMINIMAL_BOOL,
|
NONMINIMAL_BOOL,
|
||||||
e.span,
|
e.span,
|
||||||
"this boolean expression can be simplified",
|
"this boolean expression can be simplified",
|
||||||
|db| {
|
|db| {
|
||||||
for suggestion in &improvements {
|
for suggestion in &improvements {
|
||||||
db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.terminals));
|
db.span_suggestion(e.span, "try", suggest(self.cx, suggestion, &h2q.terminals));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -384,15 +386,15 @@ impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, e: &'v Expr) {
|
fn visit_expr(&mut self, e: &'tcx Expr) {
|
||||||
if in_macro(self.0, e.span) {
|
if in_macro(self.cx, e.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
|
ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
|
||||||
ExprUnary(UnNot, ref inner) => {
|
ExprUnary(UnNot, ref inner) => {
|
||||||
if self.0.tcx.tables.borrow().node_types[&inner.id].is_bool() {
|
if self.cx.tcx.tables.borrow().node_types[&inner.id].is_bool() {
|
||||||
self.bool_expr(e);
|
self.bool_expr(e);
|
||||||
} else {
|
} else {
|
||||||
walk_expr(self, e);
|
walk_expr(self, e);
|
||||||
|
@ -401,4 +403,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
|
||||||
_ => walk_expr(self, e),
|
_ => walk_expr(self, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ impl LintPass for CopyAndPaste {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for CopyAndPaste {
|
impl LateLintPass for CopyAndPaste {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if !in_macro(cx, expr.span) {
|
if !in_macro(cx, expr.span) {
|
||||||
// skip ifs directly in else, it will be checked in the parent if
|
// 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 let Some(&Expr { node: ExprIf(_, _, Some(ref else_expr)), .. }) = get_parent_expr(cx, expr) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use rustc::cfg::CFG;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr};
|
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
|
||||||
use syntax::ast::Attribute;
|
use syntax::ast::Attribute;
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
@ -42,7 +42,7 @@ impl LintPass for CyclomaticComplexity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CyclomaticComplexity {
|
impl CyclomaticComplexity {
|
||||||
fn check<'a, 'tcx>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &Expr, span: Span) {
|
fn check<'a, 'tcx: 'a>(&mut self, cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr, span: Span) {
|
||||||
if in_macro(cx, span) {
|
if in_macro(cx, span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ impl CyclomaticComplexity {
|
||||||
divergence: 0,
|
divergence: 0,
|
||||||
short_circuits: 0,
|
short_circuits: 0,
|
||||||
returns: 0,
|
returns: 0,
|
||||||
tcx: &cx.tcx,
|
cx: cx,
|
||||||
};
|
};
|
||||||
helper.visit_expr(expr);
|
helper.visit_expr(expr);
|
||||||
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
|
let CCHelper { match_arms, divergence, short_circuits, returns, .. } = helper;
|
||||||
|
@ -91,44 +91,44 @@ impl CyclomaticComplexity {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for CyclomaticComplexity {
|
impl LateLintPass for CyclomaticComplexity {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemFn(_, _, _, _, _, ref expr) = item.node {
|
if let ItemFn(_, _, _, _, _, eid) = item.node {
|
||||||
if !attr::contains_name(&item.attrs, "test") {
|
if !attr::contains_name(&item.attrs, "test") {
|
||||||
self.check(cx, expr, item.span);
|
self.check(cx, cx.tcx.map.expr(eid), item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
if let ImplItemKind::Method(_, ref expr) = item.node {
|
if let ImplItemKind::Method(_, eid) = item.node {
|
||||||
self.check(cx, expr, item.span);
|
self.check(cx, cx.tcx.map.expr(eid), item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||||
if let MethodTraitItem(_, Some(ref expr)) = item.node {
|
if let MethodTraitItem(_, Some(eid)) = item.node {
|
||||||
self.check(cx, expr, item.span);
|
self.check(cx, cx.tcx.map.expr(eid), item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enter_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) {
|
fn enter_lint_attrs<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
|
||||||
self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity");
|
self.limit.push_attrs(cx.sess(), attrs, "cyclomatic_complexity");
|
||||||
}
|
}
|
||||||
fn exit_lint_attrs(&mut self, cx: &LateContext, attrs: &[Attribute]) {
|
fn exit_lint_attrs<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, attrs: &'tcx [Attribute]) {
|
||||||
self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity");
|
self.limit.pop_attrs(cx.sess(), attrs, "cyclomatic_complexity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CCHelper<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
|
struct CCHelper<'a, 'tcx: 'a> {
|
||||||
match_arms: u64,
|
match_arms: u64,
|
||||||
divergence: u64,
|
divergence: u64,
|
||||||
returns: u64,
|
returns: u64,
|
||||||
short_circuits: u64, // && and ||
|
short_circuits: u64, // && and ||
|
||||||
tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for CCHelper<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, e: &'a Expr) {
|
fn visit_expr(&mut self, e: &'tcx Expr) {
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprMatch(_, ref arms, _) => {
|
ExprMatch(_, ref arms, _) => {
|
||||||
walk_expr(self, e);
|
walk_expr(self, e);
|
||||||
|
@ -139,7 +139,7 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
ExprCall(ref callee, _) => {
|
ExprCall(ref callee, _) => {
|
||||||
walk_expr(self, e);
|
walk_expr(self, e);
|
||||||
let ty = self.tcx.tables().node_id_to_type(callee.id);
|
let ty = self.cx.tcx.tables().node_id_to_type(callee.id);
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyFnDef(_, _, ty) |
|
ty::TyFnDef(_, _, ty) |
|
||||||
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {
|
ty::TyFnPtr(ty) if ty.sig.skip_binder().output.sty == ty::TyNever => {
|
||||||
|
@ -160,6 +160,9 @@ impl<'a, 'b, 'tcx, 'gcx> Visitor<'a> for CCHelper<'b, 'gcx, 'tcx> {
|
||||||
_ => walk_expr(self, e),
|
_ => walk_expr(self, e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature="debugging")]
|
#[cfg(feature="debugging")]
|
||||||
|
|
|
@ -71,7 +71,7 @@ impl LintPass for Derive {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Derive {
|
impl LateLintPass for Derive {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
|
if let ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
|
||||||
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
|
let ty = cx.tcx.item_type(cx.tcx.map.local_def_id(item.id));
|
||||||
let is_automatically_derived = is_automatically_derived(&*item.attrs);
|
let is_automatically_derived = is_automatically_derived(&*item.attrs);
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprCall(ref path, ref args) = expr.node {
|
if let ExprCall(ref path, ref args) = expr.node {
|
||||||
if let ExprPath(ref qpath) = path.node {
|
if let ExprPath(ref qpath) = path.node {
|
||||||
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path.id).def_id();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block};
|
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, NestedVisitorMap};
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::SpanlessEq;
|
use utils::SpanlessEq;
|
||||||
|
@ -40,7 +40,7 @@ impl LintPass for HashMapLint {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for HashMapLint {
|
impl LateLintPass for HashMapLint {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprIf(ref check, ref then_block, ref else_block) = expr.node {
|
if let ExprIf(ref check, ref then_block, ref else_block) = expr.node {
|
||||||
if let ExprUnary(UnOp::UnNot, ref check) = check.node {
|
if let ExprUnary(UnOp::UnNot, ref check) = check.node {
|
||||||
if let Some((ty, map, key)) = check_cond(cx, check) {
|
if let Some((ty, map, key)) = check_cond(cx, check) {
|
||||||
|
@ -111,8 +111,8 @@ struct InsertVisitor<'a, 'tcx: 'a, 'b> {
|
||||||
sole_expr: bool,
|
sole_expr: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> {
|
impl<'a, 'tcx, 'b> Visitor<'tcx> for InsertVisitor<'a, 'tcx, 'b> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ExprMethodCall(ref name, _, ref params) = expr.node,
|
let ExprMethodCall(ref name, _, ref params) = expr.node,
|
||||||
params.len() == 3,
|
params.len() == 3,
|
||||||
|
@ -144,4 +144,7 @@ impl<'a, 'tcx, 'v, 'b> Visitor<'v> for InsertVisitor<'a, 'tcx, 'b> {
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl LintPass for UnportableVariant {
|
||||||
|
|
||||||
impl LateLintPass for UnportableVariant {
|
impl LateLintPass for UnportableVariant {
|
||||||
#[allow(cast_possible_truncation, cast_sign_loss)]
|
#[allow(cast_possible_truncation, cast_sign_loss)]
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemEnum(ref def, _) = item.node {
|
if let ItemEnum(ref def, _) = item.node {
|
||||||
for var in &def.variants {
|
for var in &def.variants {
|
||||||
let variant = &var.node;
|
let variant = &var.node;
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for EnumGlobUse {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for EnumGlobUse {
|
impl LateLintPass for EnumGlobUse {
|
||||||
fn check_mod(&mut self, cx: &LateContext, m: &Mod, _: Span, _: NodeId) {
|
fn check_mod<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: NodeId) {
|
||||||
// only check top level `use` statements
|
// only check top level `use` statements
|
||||||
for item in &m.item_ids {
|
for item in &m.item_ids {
|
||||||
self.lint_item(cx, cx.krate.item(item.id));
|
self.lint_item(cx, cx.krate.item(item.id));
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for EqOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for EqOp {
|
impl LateLintPass for EqOp {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprBinary(ref op, ref left, ref right) = e.node {
|
if let ExprBinary(ref op, ref left, ref right) = e.node {
|
||||||
if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) {
|
if is_valid_operator(op) && SpanlessEq::new(cx).ignore_fn().eq_expr(left, right) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
|
|
@ -61,7 +61,15 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_fn(&mut self, cx: &LateContext, _: visit::FnKind, decl: &FnDecl, body: &Expr, _: Span, id: NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
_: visit::FnKind<'tcx>,
|
||||||
|
decl: &'tcx FnDecl,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
_: Span,
|
||||||
|
id: NodeId,
|
||||||
|
) {
|
||||||
let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);
|
let param_env = ty::ParameterEnvironment::for_item(cx.tcx, id);
|
||||||
|
|
||||||
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
|
let infcx = cx.tcx.borrowck_fake_infer_ctxt(param_env);
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl LintPass for EtaPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for EtaPass {
|
impl LateLintPass for EtaPass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprCall(_, ref args) |
|
ExprCall(_, ref args) |
|
||||||
ExprMethodCall(_, _, ref args) => {
|
ExprMethodCall(_, _, ref args) => {
|
||||||
|
@ -48,7 +48,8 @@ impl LateLintPass for EtaPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_closure(cx: &LateContext, expr: &Expr) {
|
fn check_closure(cx: &LateContext, expr: &Expr) {
|
||||||
if let ExprClosure(_, ref decl, ref ex, _) = expr.node {
|
if let ExprClosure(_, ref decl, eid, _) = expr.node {
|
||||||
|
let ex = cx.tcx.map.expr(eid);
|
||||||
if let ExprCall(ref caller, ref args) = ex.node {
|
if let ExprCall(ref caller, ref args) = ex.node {
|
||||||
if args.len() != decl.inputs.len() {
|
if args.len() != decl.inputs.len() {
|
||||||
// Not the same number of arguments, there
|
// Not the same number of arguments, there
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr};
|
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
|
@ -57,7 +57,7 @@ impl LintPass for EvalOrderDependence {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for EvalOrderDependence {
|
impl LateLintPass for EvalOrderDependence {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
// Find a write to a local variable.
|
// Find a write to a local variable.
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
|
ExprAssign(ref lhs, _) | ExprAssignOp(_, ref lhs, _) => {
|
||||||
|
@ -79,13 +79,13 @@ impl LateLintPass for EvalOrderDependence {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
|
fn check_stmt<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor(cx).maybe_walk_expr(e),
|
StmtExpr(ref e, _) | StmtSemi(ref e, _) => DivergenceVisitor { cx: cx }.maybe_walk_expr(e),
|
||||||
StmtDecl(ref d, _) => {
|
StmtDecl(ref d, _) => {
|
||||||
if let DeclLocal(ref local) = d.node {
|
if let DeclLocal(ref local) = d.node {
|
||||||
if let Local { init: Some(ref e), .. } = **local {
|
if let Local { init: Some(ref e), .. } = **local {
|
||||||
DivergenceVisitor(cx).visit_expr(e);
|
DivergenceVisitor { cx: cx }.visit_expr(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -93,10 +93,12 @@ impl LateLintPass for EvalOrderDependence {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DivergenceVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);
|
struct DivergenceVisitor<'a, 'tcx: 'a> {
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
||||||
fn maybe_walk_expr(&mut self, e: &Expr) {
|
fn maybe_walk_expr(&mut self, e: &'tcx Expr) {
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprClosure(..) => {},
|
ExprClosure(..) => {},
|
||||||
ExprMatch(ref e, ref arms, _) => {
|
ExprMatch(ref e, ref arms, _) => {
|
||||||
|
@ -114,7 +116,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
fn report_diverging_sub_expr(&mut self, e: &Expr) {
|
fn report_diverging_sub_expr(&mut self, e: &Expr) {
|
||||||
span_lint(
|
span_lint(
|
||||||
self.0,
|
self.cx,
|
||||||
DIVERGING_SUB_EXPRESSION,
|
DIVERGING_SUB_EXPRESSION,
|
||||||
e.span,
|
e.span,
|
||||||
"sub-expression diverges",
|
"sub-expression diverges",
|
||||||
|
@ -122,25 +124,25 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, e: &'v Expr) {
|
fn visit_expr(&mut self, e: &'tcx Expr) {
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprAgain(_) |
|
ExprAgain(_) |
|
||||||
ExprBreak(_, _) |
|
ExprBreak(_, _) |
|
||||||
ExprRet(_) => self.report_diverging_sub_expr(e),
|
ExprRet(_) => self.report_diverging_sub_expr(e),
|
||||||
ExprCall(ref func, _) => match self.0.tcx.tables().expr_ty(func).sty {
|
ExprCall(ref func, _) => match self.cx.tcx.tables().expr_ty(func).sty {
|
||||||
ty::TyFnDef(_, _, fn_ty) |
|
ty::TyFnDef(_, _, fn_ty) |
|
||||||
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty {
|
ty::TyFnPtr(fn_ty) => if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&fn_ty.sig).output.sty {
|
||||||
self.report_diverging_sub_expr(e);
|
self.report_diverging_sub_expr(e);
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
},
|
},
|
||||||
ExprMethodCall(..) => {
|
ExprMethodCall(..) => {
|
||||||
let method_call = ty::MethodCall::expr(e.id);
|
let method_call = ty::MethodCall::expr(e.id);
|
||||||
let borrowed_table = self.0.tcx.tables.borrow();
|
let borrowed_table = self.cx.tcx.tables.borrow();
|
||||||
let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen.");
|
let method_type = borrowed_table.method_map.get(&method_call).expect("This should never happen.");
|
||||||
let result_ty = method_type.ty.fn_ret();
|
let result_ty = method_type.ty.fn_ret();
|
||||||
if let ty::TyNever = self.0.tcx.erase_late_bound_regions(&result_ty).sty {
|
if let ty::TyNever = self.cx.tcx.erase_late_bound_regions(&result_ty).sty {
|
||||||
self.report_diverging_sub_expr(e);
|
self.report_diverging_sub_expr(e);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -150,9 +152,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DivergenceVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
self.maybe_walk_expr(e);
|
self.maybe_walk_expr(e);
|
||||||
}
|
}
|
||||||
fn visit_block(&mut self, _: &'v Block) {
|
fn visit_block(&mut self, _: &'tcx Block) {
|
||||||
// don't continue over blocks, LateLintPass already does that
|
// don't continue over blocks, LateLintPass already does that
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks up the AST from the the given write expression (`vis.write_expr`)
|
/// Walks up the AST from the the given write expression (`vis.write_expr`)
|
||||||
|
@ -209,7 +214,7 @@ enum StopEarly {
|
||||||
Stop,
|
Stop,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr<'v, 't>(vis: & mut ReadVisitor<'v, 't>, expr: &'v Expr) -> StopEarly {
|
fn check_expr<'a, 'tcx: 'a>(vis: & mut ReadVisitor<'a, 'tcx>, expr: &'tcx Expr) -> StopEarly {
|
||||||
if expr.id == vis.last_expr.id {
|
if expr.id == vis.last_expr.id {
|
||||||
return StopEarly::KeepGoing;
|
return StopEarly::KeepGoing;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +263,7 @@ fn check_expr<'v, 't>(vis: & mut ReadVisitor<'v, 't>, expr: &'v Expr) -> StopEar
|
||||||
StopEarly::KeepGoing
|
StopEarly::KeepGoing
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_stmt<'v, 't>(vis: &mut ReadVisitor<'v, 't>, stmt: &'v Stmt) -> StopEarly {
|
fn check_stmt<'a, 'tcx: 'a>(vis: &mut ReadVisitor<'a, 'tcx>, stmt: &'tcx Stmt) -> StopEarly {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
StmtExpr(ref expr, _) |
|
StmtExpr(ref expr, _) |
|
||||||
StmtSemi(ref expr, _) => check_expr(vis, expr),
|
StmtSemi(ref expr, _) => check_expr(vis, expr),
|
||||||
|
@ -276,20 +281,20 @@ fn check_stmt<'v, 't>(vis: &mut ReadVisitor<'v, 't>, stmt: &'v Stmt) -> StopEarl
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A visitor that looks for reads from a variable.
|
/// A visitor that looks for reads from a variable.
|
||||||
struct ReadVisitor<'v, 't: 'v> {
|
struct ReadVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
/// The id of the variable we're looking for.
|
/// The id of the variable we're looking for.
|
||||||
var: DefId,
|
var: DefId,
|
||||||
/// The expressions where the write to the variable occurred (for reporting
|
/// The expressions where the write to the variable occurred (for reporting
|
||||||
/// in the lint).
|
/// in the lint).
|
||||||
write_expr: &'v Expr,
|
write_expr: &'tcx Expr,
|
||||||
/// The last (highest in the AST) expression we've checked, so we know not
|
/// The last (highest in the AST) expression we've checked, so we know not
|
||||||
/// to recheck it.
|
/// to recheck it.
|
||||||
last_expr: &'v Expr,
|
last_expr: &'tcx Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for ReadVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if expr.id == self.last_expr.id {
|
if expr.id == self.last_expr.id {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -336,6 +341,9 @@ impl<'v, 't> Visitor<'v> for ReadVisitor<'v, 't> {
|
||||||
|
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if `expr` is the LHS of an assignment, like `expr = ...`.
|
/// Returns true if `expr` is the LHS of an assignment, like `expr = ...`.
|
||||||
|
|
|
@ -39,7 +39,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&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(cx, expr.span, "format") {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
// `format!("{}", foo)` expansion
|
// `format!("{}", foo)` expansion
|
||||||
|
|
|
@ -69,7 +69,15 @@ impl LintPass for Functions {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Functions {
|
impl LateLintPass for Functions {
|
||||||
fn check_fn(&mut self, cx: &LateContext, kind: intravisit::FnKind, decl: &hir::FnDecl, expr: &hir::Expr, span: Span, nodeid: ast::NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
kind: intravisit::FnKind<'tcx>,
|
||||||
|
decl: &'tcx hir::FnDecl,
|
||||||
|
expr: &'tcx hir::Expr,
|
||||||
|
span: Span,
|
||||||
|
nodeid: ast::NodeId,
|
||||||
|
) {
|
||||||
use rustc::hir::map::Node::*;
|
use rustc::hir::map::Node::*;
|
||||||
|
|
||||||
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
let is_impl = if let Some(NodeItem(item)) = cx.tcx.map.find(cx.tcx.map.get_parent_node(nodeid)) {
|
||||||
|
@ -97,14 +105,15 @@ impl LateLintPass for Functions {
|
||||||
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
|
self.check_raw_ptr(cx, unsafety, decl, expr, nodeid);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
|
||||||
if let hir::MethodTraitItem(ref sig, ref expr) = item.node {
|
if let hir::MethodTraitItem(ref sig, eid) = item.node {
|
||||||
// don't lint extern functions decls, it's not their fault
|
// don't lint extern functions decls, it's not their fault
|
||||||
if sig.abi == Abi::Rust {
|
if sig.abi == Abi::Rust {
|
||||||
self.check_arg_number(cx, &sig.decl, item.span);
|
self.check_arg_number(cx, &sig.decl, item.span);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref expr) = *expr {
|
if let Some(eid) = eid {
|
||||||
|
let expr = cx.tcx.map.expr(eid);
|
||||||
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
|
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, expr, item.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +131,14 @@ impl Functions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, expr: &hir::Expr, nodeid: ast::NodeId) {
|
fn check_raw_ptr<'a, 'tcx: 'a>(
|
||||||
|
&self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
unsafety: hir::Unsafety,
|
||||||
|
decl: &'tcx hir::FnDecl,
|
||||||
|
expr: &'tcx hir::Expr,
|
||||||
|
nodeid: ast::NodeId,
|
||||||
|
) {
|
||||||
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
|
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
|
||||||
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
|
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
|
||||||
|
|
||||||
|
@ -151,8 +167,8 @@ struct DerefVisitor<'a, 'tcx: 'a> {
|
||||||
ptrs: HashSet<hir::def_id::DefId>,
|
ptrs: HashSet<hir::def_id::DefId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for DerefVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprCall(ref f, ref args) => {
|
hir::ExprCall(ref f, ref args) => {
|
||||||
let ty = self.cx.tcx.tables().expr_ty(f);
|
let ty = self.cx.tcx.tables().expr_ty(f);
|
||||||
|
@ -179,6 +195,9 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
hir::intravisit::walk_expr(self, expr);
|
hir::intravisit::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
|
||||||
|
intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
|
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl LintPass for IdentityOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for IdentityOp {
|
impl LateLintPass for IdentityOp {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if in_macro(cx, e.span) {
|
if in_macro(cx, e.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
|
|
||||||
if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar{..}) = expr.node {
|
if let ExprMatch(ref op, ref arms, MatchSource::IfLetDesugar{..}) = expr.node {
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl LintPass for LenZero {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for LenZero {
|
impl LateLintPass for LenZero {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if in_macro(cx, item.span) {
|
if in_macro(cx, item.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ impl LateLintPass for LenZero {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if in_macro(cx, expr.span) {
|
if in_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -208,7 +208,7 @@ fn has_is_empty(cx: &LateContext, expr: &Expr) -> bool {
|
||||||
|
|
||||||
let ty = &walk_ptrs_ty(cx.tcx.tables().expr_ty(expr));
|
let ty = &walk_ptrs_ty(cx.tcx.tables().expr_ty(expr));
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty::TyTrait(_) => {
|
ty::TyDynamic(..) => {
|
||||||
cx.tcx
|
cx.tcx
|
||||||
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
|
.associated_items(ty.ty_to_def_id().expect("trait impl not found"))
|
||||||
.any(|item| is_is_empty(cx, &item))
|
.any(|item| is_is_empty(cx, &item))
|
||||||
|
|
|
@ -58,7 +58,7 @@ impl LintPass for LetIfSeq {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for LetIfSeq {
|
impl LateLintPass for LetIfSeq {
|
||||||
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
|
fn check_block<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) {
|
||||||
let mut it = block.stmts.iter().peekable();
|
let mut it = block.stmts.iter().peekable();
|
||||||
while let Some(stmt) = it.next() {
|
while let Some(stmt) = it.next() {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
|
@ -133,8 +133,8 @@ struct UsedVisitor<'a, 'tcx: 'a> {
|
||||||
used: bool,
|
used: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> hir::intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let hir::ExprPath(ref qpath) = expr.node,
|
let hir::ExprPath(ref qpath) = expr.node,
|
||||||
self.id == self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id(),
|
self.id == self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id(),
|
||||||
|
@ -144,9 +144,16 @@ impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for UsedVisitor<'a, 'tcx> {
|
||||||
}}
|
}}
|
||||||
hir::intravisit::walk_expr(self, expr);
|
hir::intravisit::walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> hir::intravisit::NestedVisitorMap<'this, 'tcx> {
|
||||||
|
hir::intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::Block) -> Option<&'e hir::Expr> {
|
fn check_assign<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
decl: hir::def_id::DefId,
|
||||||
|
block: &'tcx hir::Block,
|
||||||
|
) -> Option<&'tcx hir::Expr> {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
block.expr.is_none(),
|
block.expr.is_none(),
|
||||||
let Some(expr) = block.stmts.iter().last(),
|
let Some(expr) = block.stmts.iter().last(),
|
||||||
|
@ -175,7 +182,11 @@ fn check_assign<'e>(cx: &LateContext, decl: hir::def_id::DefId, block: &'e hir::
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn used_in_expr(cx: &LateContext, id: hir::def_id::DefId, expr: &hir::Expr) -> bool {
|
fn used_in_expr<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
id: hir::def_id::DefId,
|
||||||
|
expr: &'tcx hir::Expr,
|
||||||
|
) -> bool {
|
||||||
let mut v = UsedVisitor {
|
let mut v = UsedVisitor {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
id: id,
|
id: id,
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#![feature(repeat_str)]
|
#![feature(repeat_str)]
|
||||||
|
|
||||||
#![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)]
|
#![allow(indexing_slicing, shadow_reuse, unknown_lints, missing_docs_in_private_items)]
|
||||||
|
#![allow(needless_lifetimes)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate syntax;
|
extern crate syntax;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use reexport::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics};
|
use rustc::hir::intravisit::{Visitor, walk_ty, walk_ty_param_bound, walk_fn_decl, walk_generics, NestedVisitorMap};
|
||||||
use std::collections::{HashSet, HashMap};
|
use std::collections::{HashSet, HashMap};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{in_external_macro, span_lint, last_path_segment};
|
use utils::{in_external_macro, span_lint, last_path_segment};
|
||||||
|
@ -57,19 +57,19 @@ impl LintPass for LifetimePass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for LifetimePass {
|
impl LateLintPass for LifetimePass {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node {
|
if let ItemFn(ref decl, _, _, _, ref generics, _) = item.node {
|
||||||
check_fn_inner(cx, decl, generics, item.span);
|
check_fn_inner(cx, decl, generics, item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
if let ImplItemKind::Method(ref sig, _) = item.node {
|
if let ImplItemKind::Method(ref sig, _) = item.node {
|
||||||
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
|
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||||
if let MethodTraitItem(ref sig, _) = item.node {
|
if let MethodTraitItem(ref sig, _) = item.node {
|
||||||
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
|
check_fn_inner(cx, &sig.decl, &sig.generics, item.span);
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,12 @@ fn bound_lifetimes(bound: &TyParamBound) -> HirVec<&Lifetime> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Span) {
|
fn check_fn_inner<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
decl: &'tcx FnDecl,
|
||||||
|
generics: &'tcx Generics,
|
||||||
|
span: Span,
|
||||||
|
) {
|
||||||
if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) {
|
if in_external_macro(cx, span) || has_where_lifetimes(cx, &generics.where_clause) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -116,9 +121,16 @@ fn check_fn_inner(cx: &LateContext, decl: &FnDecl, generics: &Generics, span: Sp
|
||||||
report_extra_lifetimes(cx, decl, generics);
|
report_extra_lifetimes(cx, decl, generics);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn could_use_elision<'a, T: Iterator<Item = &'a Lifetime>>(cx: &LateContext, func: &FnDecl,
|
fn could_use_elision<
|
||||||
named_lts: &[LifetimeDef], bounds_lts: T)
|
'a,
|
||||||
-> bool {
|
'tcx: 'a,
|
||||||
|
T: Iterator<Item = &'tcx Lifetime>
|
||||||
|
>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
func: &'tcx FnDecl,
|
||||||
|
named_lts: &'tcx [LifetimeDef],
|
||||||
|
bounds_lts: T,
|
||||||
|
) -> bool {
|
||||||
// There are two scenarios where elision works:
|
// There are two scenarios where elision works:
|
||||||
// * no output references, all input references have different LT
|
// * no output references, all input references have different LT
|
||||||
// * output references, exactly one input reference with same LT
|
// * output references, exactly one input reference with same LT
|
||||||
|
@ -210,8 +222,8 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
/// A visitor usable for `rustc_front::visit::walk_ty()`.
|
||||||
struct RefVisitor<'v, 't: 'v> {
|
struct RefVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
lts: Vec<RefLt>,
|
lts: Vec<RefLt>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +265,7 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
Def::Trait(def_id) => {
|
Def::Trait(def_id) => {
|
||||||
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
|
let trait_def = self.cx.tcx.trait_defs.borrow()[&def_id];
|
||||||
for _ in &trait_def.generics.regions {
|
for _ in &self.cx.tcx.item_generics(trait_def.def_id).regions {
|
||||||
self.record(&None);
|
self.record(&None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,13 +276,13 @@ impl<'v, 't> RefVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
|
||||||
// for lifetimes as parameters of generics
|
// for lifetimes as parameters of generics
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||||
self.record(&Some(*lifetime));
|
self.record(&Some(*lifetime));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &'v Ty) {
|
fn visit_ty(&mut self, ty: &'tcx Ty) {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
TyRptr(None, _) => {
|
TyRptr(None, _) => {
|
||||||
self.record(&None);
|
self.record(&None);
|
||||||
|
@ -282,11 +294,14 @@ impl<'v, 't> Visitor<'v> for RefVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
walk_ty(self, ty);
|
walk_ty(self, ty);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to
|
/// Are any lifetimes mentioned in the `where` clause? If yes, we don't try to
|
||||||
/// reason about elision.
|
/// reason about elision.
|
||||||
fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool {
|
fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &'tcx WhereClause) -> bool {
|
||||||
for predicate in &where_clause.predicates {
|
for predicate in &where_clause.predicates {
|
||||||
match *predicate {
|
match *predicate {
|
||||||
WherePredicate::RegionPredicate(..) => return true,
|
WherePredicate::RegionPredicate(..) => return true,
|
||||||
|
@ -323,34 +338,39 @@ fn has_where_lifetimes(cx: &LateContext, where_clause: &WhereClause) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LifetimeChecker(HashMap<Name, Span>);
|
struct LifetimeChecker {
|
||||||
|
map: HashMap<Name, Span>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for LifetimeChecker {
|
impl<'tcx> Visitor<'tcx> for LifetimeChecker {
|
||||||
// for lifetimes as parameters of generics
|
// for lifetimes as parameters of generics
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'tcx Lifetime) {
|
||||||
self.0.remove(&lifetime.name);
|
self.map.remove(&lifetime.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime_def(&mut self, _: &'v LifetimeDef) {
|
fn visit_lifetime_def(&mut self, _: &'tcx LifetimeDef) {
|
||||||
// don't actually visit `<'a>` or `<'a: 'b>`
|
// don't actually visit `<'a>` or `<'a: 'b>`
|
||||||
// we've already visited the `'a` declarations and
|
// we've already visited the `'a` declarations and
|
||||||
// don't want to spuriously remove them
|
// don't want to spuriously remove them
|
||||||
// `'b` in `'a: 'b` is useless unless used elsewhere in
|
// `'b` in `'a: 'b` is useless unless used elsewhere in
|
||||||
// a non-lifetime bound
|
// a non-lifetime bound
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_extra_lifetimes(cx: &LateContext, func: &FnDecl, generics: &Generics) {
|
fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
|
||||||
let hs = generics.lifetimes
|
let hs = generics.lifetimes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|lt| (lt.lifetime.name, lt.lifetime.span))
|
.map(|lt| (lt.lifetime.name, lt.lifetime.span))
|
||||||
.collect();
|
.collect();
|
||||||
let mut checker = LifetimeChecker(hs);
|
let mut checker = LifetimeChecker { map: hs };
|
||||||
|
|
||||||
walk_generics(&mut checker, generics);
|
walk_generics(&mut checker, generics);
|
||||||
walk_fn_decl(&mut checker, func);
|
walk_fn_decl(&mut checker, func);
|
||||||
|
|
||||||
for &v in checker.0.values() {
|
for &v in checker.map.values() {
|
||||||
span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition");
|
span_lint(cx, UNUSED_LIFETIMES, v, "this lifetime isn't used in the function definition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use reexport::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl};
|
use rustc::hir::intravisit::{Visitor, walk_expr, walk_block, walk_decl, NestedVisitorMap};
|
||||||
use rustc::hir::map::Node::NodeBlock;
|
use rustc::hir::map::Node::NodeBlock;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::middle::const_val::ConstVal;
|
use rustc::middle::const_val::ConstVal;
|
||||||
|
@ -308,7 +308,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let Some((pat, arg, body)) = higher::for_loop(expr) {
|
if let Some((pat, arg, body)) = higher::for_loop(expr) {
|
||||||
check_for_loop(cx, pat, arg, body, expr);
|
check_for_loop(cx, pat, arg, body, expr);
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
|
fn check_stmt<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||||
if let StmtSemi(ref expr, _) = stmt.node {
|
if let StmtSemi(ref expr, _) = stmt.node {
|
||||||
if let ExprMethodCall(ref method, _, ref args) = expr.node {
|
if let ExprMethodCall(ref method, _, ref args) = expr.node {
|
||||||
if args.len() == 1 && &*method.node.as_str() == "collect" &&
|
if args.len() == 1 && &*method.node.as_str() == "collect" &&
|
||||||
|
@ -407,7 +407,13 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
|
fn check_for_loop<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
pat: &'tcx Pat,
|
||||||
|
arg: &'tcx Expr,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
expr: &'tcx Expr,
|
||||||
|
) {
|
||||||
check_for_loop_range(cx, pat, arg, body, expr);
|
check_for_loop_range(cx, pat, arg, body, expr);
|
||||||
check_for_loop_reverse_range(cx, arg, expr);
|
check_for_loop_reverse_range(cx, arg, expr);
|
||||||
check_for_loop_arg(cx, pat, arg, expr);
|
check_for_loop_arg(cx, pat, arg, expr);
|
||||||
|
@ -417,7 +423,13 @@ fn check_for_loop(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &E
|
||||||
|
|
||||||
/// Check for looping over a range and then indexing a sequence with it.
|
/// Check for looping over a range and then indexing a sequence with it.
|
||||||
/// The iteratee must be a range literal.
|
/// The iteratee must be a range literal.
|
||||||
fn check_for_loop_range(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
|
fn check_for_loop_range<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
pat: &'tcx Pat,
|
||||||
|
arg: &'tcx Expr,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
expr: &'tcx Expr,
|
||||||
|
) {
|
||||||
if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) {
|
if let Some(higher::Range { start: Some(start), ref end, limits }) = higher::range(arg) {
|
||||||
// the var must be a single name
|
// the var must be a single name
|
||||||
if let PatKind::Binding(_, def_id, ref ident, _) = pat.node {
|
if let PatKind::Binding(_, def_id, ref ident, _) = pat.node {
|
||||||
|
@ -646,7 +658,12 @@ fn check_arg_type(cx: &LateContext, pat: &Pat, arg: &Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, expr: &Expr) {
|
fn check_for_loop_explicit_counter<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
arg: &'tcx Expr,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
expr: &'tcx Expr,
|
||||||
|
) {
|
||||||
// Look for variables that are incremented once per loop iteration.
|
// Look for variables that are incremented once per loop iteration.
|
||||||
let mut visitor = IncrementVisitor {
|
let mut visitor = IncrementVisitor {
|
||||||
cx: cx,
|
cx: cx,
|
||||||
|
@ -691,14 +708,20 @@ fn check_for_loop_explicit_counter(cx: &LateContext, arg: &Expr, body: &Expr, ex
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check for the `FOR_KV_MAP` lint.
|
/// Check for the `FOR_KV_MAP` lint.
|
||||||
fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Expr, expr: &Expr) {
|
fn check_for_loop_over_map_kv<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
pat: &'tcx Pat,
|
||||||
|
arg: &'tcx Expr,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
expr: &'tcx Expr,
|
||||||
|
) {
|
||||||
let pat_span = pat.span;
|
let pat_span = pat.span;
|
||||||
|
|
||||||
if let PatKind::Tuple(ref pat, _) = pat.node {
|
if let PatKind::Tuple(ref pat, _) = pat.node {
|
||||||
if pat.len() == 2 {
|
if pat.len() == 2 {
|
||||||
let (new_pat_span, kind) = match (&pat[0].node, &pat[1].node) {
|
let (new_pat_span, kind) = match (&pat[0].node, &pat[1].node) {
|
||||||
(key, _) if pat_is_wild(key, body) => (pat[1].span, "value"),
|
(key, _) if pat_is_wild(cx, key, body) => (pat[1].span, "value"),
|
||||||
(_, value) if pat_is_wild(value, body) => (pat[0].span, "key"),
|
(_, value) if pat_is_wild(cx, value, body) => (pat[0].span, "key"),
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -728,13 +751,18 @@ fn check_for_loop_over_map_kv(cx: &LateContext, pat: &Pat, arg: &Expr, body: &Ex
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`.
|
/// Return true if the pattern is a `PatWild` or an ident prefixed with `'_'`.
|
||||||
fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
|
fn pat_is_wild<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
pat: &'tcx PatKind,
|
||||||
|
body: &'tcx Expr,
|
||||||
|
) -> bool {
|
||||||
match *pat {
|
match *pat {
|
||||||
PatKind::Wild => true,
|
PatKind::Wild => true,
|
||||||
PatKind::Binding(_, _, ident, None) if ident.node.as_str().starts_with('_') => {
|
PatKind::Binding(_, _, ident, None) if ident.node.as_str().starts_with('_') => {
|
||||||
let mut visitor = UsedVisitor {
|
let mut visitor = UsedVisitor {
|
||||||
var: ident.node,
|
var: ident.node,
|
||||||
used: false,
|
used: false,
|
||||||
|
cx: cx,
|
||||||
};
|
};
|
||||||
walk_expr(&mut visitor, body);
|
walk_expr(&mut visitor, body);
|
||||||
!visitor.used
|
!visitor.used
|
||||||
|
@ -743,13 +771,14 @@ fn pat_is_wild(pat: &PatKind, body: &Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UsedVisitor {
|
struct UsedVisitor<'a, 'tcx: 'a> {
|
||||||
var: ast::Name, // var to look for
|
var: ast::Name, // var to look for
|
||||||
used: bool, // has the var been used otherwise?
|
used: bool, // has the var been used otherwise?
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for UsedVisitor {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if let ExprPath(QPath::Resolved(None, ref path)) = expr.node {
|
if let ExprPath(QPath::Resolved(None, ref path)) = expr.node {
|
||||||
if path.segments.len() == 1 && path.segments[0].name == self.var {
|
if path.segments.len() == 1 && path.segments[0].name == self.var {
|
||||||
self.used = true;
|
self.used = true;
|
||||||
|
@ -759,17 +788,20 @@ impl<'a> Visitor<'a> for UsedVisitor {
|
||||||
|
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VarVisitor<'v, 't: 'v> {
|
struct VarVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>, // context reference
|
cx: &'a LateContext<'a, 'tcx>, // context reference
|
||||||
var: DefId, // var name to look for as index
|
var: DefId, // var name to look for as index
|
||||||
indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global
|
indexed: HashMap<Name, Option<CodeExtent>>, // indexed variables, the extent is None for global
|
||||||
nonindex: bool, // has the var been used otherwise?
|
nonindex: bool, // has the var been used otherwise?
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if let ExprPath(ref qpath) = expr.node {
|
if let ExprPath(ref qpath) = expr.node {
|
||||||
if let QPath::Resolved(None, ref path) = *qpath {
|
if let QPath::Resolved(None, ref path) = *qpath {
|
||||||
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
|
if path.segments.len() == 1 && self.cx.tcx.tables().qpath_def(qpath, expr.id).def_id() == self.var {
|
||||||
|
@ -806,9 +838,12 @@ impl<'v, 't> Visitor<'v> for VarVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool {
|
fn is_iterator_used_after_while_let<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, iter_expr: &'tcx Expr) -> bool {
|
||||||
let def_id = match var_def_id(cx, iter_expr) {
|
let def_id = match var_def_id(cx, iter_expr) {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
None => return false,
|
None => return false,
|
||||||
|
@ -826,16 +861,16 @@ fn is_iterator_used_after_while_let(cx: &LateContext, iter_expr: &Expr) -> bool
|
||||||
visitor.var_used_after_while_let
|
visitor.var_used_after_while_let
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VarUsedAfterLoopVisitor<'v, 't: 'v> {
|
struct VarUsedAfterLoopVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
def_id: NodeId,
|
def_id: NodeId,
|
||||||
iter_expr_id: NodeId,
|
iter_expr_id: NodeId,
|
||||||
past_while_let: bool,
|
past_while_let: bool,
|
||||||
var_used_after_while_let: bool,
|
var_used_after_while_let: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if self.past_while_let {
|
if self.past_while_let {
|
||||||
if Some(self.def_id) == var_def_id(self.cx, expr) {
|
if Some(self.def_id) == var_def_id(self.cx, expr) {
|
||||||
self.var_used_after_while_let = true;
|
self.var_used_after_while_let = true;
|
||||||
|
@ -845,6 +880,9 @@ impl<'v, 't> Visitor<'v> for VarUsedAfterLoopVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -935,15 +973,15 @@ enum VarState {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scan a for loop for variables that are incremented exactly once.
|
/// Scan a for loop for variables that are incremented exactly once.
|
||||||
struct IncrementVisitor<'v, 't: 'v> {
|
struct IncrementVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>, // context reference
|
cx: &'a LateContext<'a, 'tcx>, // context reference
|
||||||
states: HashMap<NodeId, VarState>, // incremented variables
|
states: HashMap<NodeId, VarState>, // incremented variables
|
||||||
depth: u32, // depth of conditional expressions
|
depth: u32, // depth of conditional expressions
|
||||||
done: bool,
|
done: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if self.done {
|
if self.done {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -984,12 +1022,15 @@ impl<'v, 't> Visitor<'v> for IncrementVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether a variable is initialized to zero at the start of a loop.
|
/// Check whether a variable is initialized to zero at the start of a loop.
|
||||||
struct InitializeVisitor<'v, 't: 'v> {
|
struct InitializeVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'v LateContext<'v, 't>, // context reference
|
cx: &'a LateContext<'a, 'tcx>, // context reference
|
||||||
end_expr: &'v Expr, // the for loop. Stop scanning here.
|
end_expr: &'tcx Expr, // the for loop. Stop scanning here.
|
||||||
var_id: NodeId,
|
var_id: NodeId,
|
||||||
state: VarState,
|
state: VarState,
|
||||||
name: Option<Name>,
|
name: Option<Name>,
|
||||||
|
@ -997,8 +1038,8 @@ struct InitializeVisitor<'v, 't: 'v> {
|
||||||
past_loop: bool,
|
past_loop: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
|
impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
|
||||||
fn visit_decl(&mut self, decl: &'v Decl) {
|
fn visit_decl(&mut self, decl: &'tcx Decl) {
|
||||||
// Look for declarations of the variable
|
// Look for declarations of the variable
|
||||||
if let DeclLocal(ref local) = decl.node {
|
if let DeclLocal(ref local) = decl.node {
|
||||||
if local.pat.id == self.var_id {
|
if local.pat.id == self.var_id {
|
||||||
|
@ -1020,7 +1061,7 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
|
||||||
walk_decl(self, decl);
|
walk_decl(self, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
if self.state == VarState::DontWarn {
|
if self.state == VarState::DontWarn {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1068,6 +1109,9 @@ impl<'v, 't> Visitor<'v> for InitializeVisitor<'v, 't> {
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
|
fn var_def_id(cx: &LateContext, expr: &Expr) -> Option<NodeId> {
|
||||||
|
|
|
@ -25,13 +25,13 @@ declare_lint! {
|
||||||
pub struct Pass;
|
pub struct Pass;
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
// call to .map()
|
// call to .map()
|
||||||
if let ExprMethodCall(name, _, ref args) = expr.node {
|
if let ExprMethodCall(name, _, ref args) = expr.node {
|
||||||
if &*name.node.as_str() == "map" && args.len() == 2 {
|
if &*name.node.as_str() == "map" && args.len() == 2 {
|
||||||
match args[1].node {
|
match args[1].node {
|
||||||
ExprClosure(_, ref decl, ref closure_expr, _) => {
|
ExprClosure(_, ref decl, closure_eid, _) => {
|
||||||
let closure_expr = remove_blocks(closure_expr);
|
let closure_expr = remove_blocks(cx.tcx.map.expr(closure_eid));
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
// nothing special in the argument, besides reference bindings
|
// nothing special in the argument, besides reference bindings
|
||||||
// (e.g. .map(|&x| x) )
|
// (e.g. .map(|&x| x) )
|
||||||
|
|
|
@ -130,7 +130,7 @@ impl LintPass for MatchPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for MatchPass {
|
impl LateLintPass for MatchPass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if in_external_macro(cx, expr.span) {
|
if in_external_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl LintPass for MemForget {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for MemForget {
|
impl LateLintPass for MemForget {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprCall(ref path_expr, ref args) = e.node {
|
if let ExprCall(ref path_expr, ref args) = e.node {
|
||||||
if let ExprPath(ref qpath) = path_expr.node {
|
if let ExprPath(ref qpath) = path_expr.node {
|
||||||
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
||||||
|
|
|
@ -553,7 +553,7 @@ impl LateLintPass for Pass {
|
||||||
#[allow(unused_attributes)]
|
#[allow(unused_attributes)]
|
||||||
// ^ required because `cyclomatic_complexity` attribute shows up as unused
|
// ^ required because `cyclomatic_complexity` attribute shows up as unused
|
||||||
#[cyclomatic_complexity = "30"]
|
#[cyclomatic_complexity = "30"]
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
if in_macro(cx, expr.span) {
|
if in_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -629,7 +629,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, implitem: &hir::ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, implitem: &'tcx hir::ImplItem) {
|
||||||
if in_external_macro(cx, implitem.span) {
|
if in_external_macro(cx, implitem.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ impl LintPass for MinMaxPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for MinMaxPass {
|
impl LateLintPass for MinMaxPass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) {
|
if let Some((outer_max, outer_c, oe)) = min_max(cx, expr) {
|
||||||
if let Some((inner_max, inner_c, _)) = min_max(cx, oe) {
|
if let Some((inner_max, inner_c, _)) = min_max(cx, oe) {
|
||||||
if outer_max == inner_max {
|
if outer_max == inner_max {
|
||||||
|
|
|
@ -167,7 +167,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_fn(&mut self, cx: &LateContext, k: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, k: FnKind<'tcx>, decl: &'tcx FnDecl, _: &'tcx Expr, _: Span, _: NodeId) {
|
||||||
if let FnKind::Closure(_) = k {
|
if let FnKind::Closure(_) = k {
|
||||||
// Does not apply to closures
|
// Does not apply to closures
|
||||||
return;
|
return;
|
||||||
|
@ -182,7 +182,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_stmt(&mut self, cx: &LateContext, s: &Stmt) {
|
fn check_stmt<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let StmtDecl(ref d, _) = s.node,
|
let StmtDecl(ref d, _) = s.node,
|
||||||
let DeclLocal(ref l) = d.node,
|
let DeclLocal(ref l) = d.node,
|
||||||
|
@ -216,7 +216,7 @@ impl LateLintPass for Pass {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
|
if let ExprBinary(ref cmp, ref left, ref right) = expr.node {
|
||||||
let op = cmp.node;
|
let op = cmp.node;
|
||||||
if op.is_comparison() {
|
if op.is_comparison() {
|
||||||
|
@ -294,7 +294,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
fn check_pat<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
|
||||||
if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node {
|
if let PatKind::Binding(_, _, ref ident, Some(ref right)) = pat.node {
|
||||||
if right.node == PatKind::Wild {
|
if right.node == PatKind::Wild {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
@ -440,9 +440,7 @@ fn in_attributes_expansion(cx: &LateContext, expr: &Expr) -> bool {
|
||||||
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
fn non_macro_local(cx: &LateContext, def: &def::Def) -> bool {
|
||||||
match *def {
|
match *def {
|
||||||
def::Def::Local(id) | def::Def::Upvar(id, _, _) => {
|
def::Def::Local(id) | def::Def::Upvar(id, _, _) => {
|
||||||
let id = cx.tcx.map.as_local_node_id(id).expect("That DefId should be valid");
|
if let Some(span) = cx.tcx.map.span_if_local(id) {
|
||||||
|
|
||||||
if let Some(span) = cx.tcx.map.opt_span(id) {
|
|
||||||
!in_macro(cx, span)
|
!in_macro(cx, span)
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl LintPass for MissingDoc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for MissingDoc {
|
impl LateLintPass for MissingDoc {
|
||||||
fn enter_lint_attrs(&mut self, _: &LateContext, attrs: &[ast::Attribute]) {
|
fn enter_lint_attrs<'a, 'tcx: 'a>(&mut self, _: &LateContext<'a, 'tcx>, attrs: &'tcx [ast::Attribute]) {
|
||||||
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
|
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
|
||||||
attr.check_name("doc") && match attr.meta_item_list() {
|
attr.check_name("doc") && match attr.meta_item_list() {
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -105,15 +105,15 @@ impl LateLintPass for MissingDoc {
|
||||||
self.doc_hidden_stack.push(doc_hidden);
|
self.doc_hidden_stack.push(doc_hidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit_lint_attrs(&mut self, _: &LateContext, _: &[ast::Attribute]) {
|
fn exit_lint_attrs<'a, 'tcx: 'a>(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx [ast::Attribute]) {
|
||||||
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
|
fn check_crate<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx hir::Crate) {
|
||||||
self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
|
self.check_missing_docs_attrs(cx, &krate.attrs, krate.span, "crate");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) {
|
||||||
let desc = match it.node {
|
let desc = match it.node {
|
||||||
hir::ItemConst(..) => "a constant",
|
hir::ItemConst(..) => "a constant",
|
||||||
hir::ItemEnum(..) => "an enum",
|
hir::ItemEnum(..) => "an enum",
|
||||||
|
@ -134,7 +134,7 @@ impl LateLintPass for MissingDoc {
|
||||||
self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
|
self.check_missing_docs_attrs(cx, &it.attrs, it.span, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, trait_item: &hir::TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, trait_item: &'tcx hir::TraitItem) {
|
||||||
let desc = match trait_item.node {
|
let desc = match trait_item.node {
|
||||||
hir::ConstTraitItem(..) => "an associated constant",
|
hir::ConstTraitItem(..) => "an associated constant",
|
||||||
hir::MethodTraitItem(..) => "a trait method",
|
hir::MethodTraitItem(..) => "a trait method",
|
||||||
|
@ -144,7 +144,7 @@ impl LateLintPass for MissingDoc {
|
||||||
self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
|
self.check_missing_docs_attrs(cx, &trait_item.attrs, trait_item.span, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, impl_item: &hir::ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) {
|
||||||
// If the method is an impl for a trait, don't doc.
|
// If the method is an impl for a trait, don't doc.
|
||||||
let def_id = cx.tcx.map.local_def_id(impl_item.id);
|
let def_id = cx.tcx.map.local_def_id(impl_item.id);
|
||||||
match cx.tcx.associated_item(def_id).container {
|
match cx.tcx.associated_item(def_id).container {
|
||||||
|
@ -164,13 +164,13 @@ impl LateLintPass for MissingDoc {
|
||||||
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
|
self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_struct_field(&mut self, cx: &LateContext, sf: &hir::StructField) {
|
fn check_struct_field<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, sf: &'tcx hir::StructField) {
|
||||||
if !sf.is_positional() {
|
if !sf.is_positional() {
|
||||||
self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
|
self.check_missing_docs_attrs(cx, &sf.attrs, sf.span, "a struct field");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_variant(&mut self, cx: &LateContext, v: &hir::Variant, _: &hir::Generics) {
|
fn check_variant<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, v: &'tcx hir::Variant, _: &hir::Generics) {
|
||||||
self.check_missing_docs_attrs(cx, &v.node.attrs, v.span, "a variant");
|
self.check_missing_docs_attrs(cx, &v.node.attrs, v.span, "a variant");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ impl LintPass for MutMut {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for MutMut {
|
impl LateLintPass for MutMut {
|
||||||
fn check_block(&mut self, cx: &LateContext, block: &hir::Block) {
|
fn check_block<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) {
|
||||||
intravisit::walk_block(&mut MutVisitor { cx: cx }, block);
|
intravisit::walk_block(&mut MutVisitor { cx: cx }, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ty(&mut self, cx: &LateContext, ty: &hir::Ty) {
|
fn check_ty<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty) {
|
||||||
use rustc::hir::intravisit::Visitor;
|
use rustc::hir::intravisit::Visitor;
|
||||||
|
|
||||||
MutVisitor { cx: cx }.visit_ty(ty);
|
MutVisitor { cx: cx }.visit_ty(ty);
|
||||||
|
@ -47,8 +47,8 @@ pub struct MutVisitor<'a, 'tcx: 'a> {
|
||||||
cx: &'a LateContext<'a, 'tcx>,
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v hir::Expr) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
if in_external_macro(self.cx, expr.span) {
|
if in_external_macro(self.cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, ty: &hir::Ty) {
|
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
|
||||||
if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node {
|
if let hir::TyRptr(_, hir::MutTy { ty: ref pty, mutbl: hir::MutMutable }) = ty.node {
|
||||||
if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node {
|
if let hir::TyRptr(_, hir::MutTy { mutbl: hir::MutMutable, .. }) = pty.node {
|
||||||
span_lint(self.cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible");
|
span_lint(self.cx, MUT_MUT, ty.span, "generally you want to avoid `&mut &mut _` if possible");
|
||||||
|
@ -84,4 +84,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for MutVisitor<'a, 'tcx> {
|
||||||
|
|
||||||
intravisit::walk_ty(self, ty);
|
intravisit::walk_ty(self, ty);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
|
||||||
|
intravisit::NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for UnnecessaryMutPassed {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for UnnecessaryMutPassed {
|
impl LateLintPass for UnnecessaryMutPassed {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
let borrowed_table = cx.tcx.tables.borrow();
|
let borrowed_table = cx.tcx.tables.borrow();
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprCall(ref fn_expr, ref arguments) => {
|
ExprCall(ref fn_expr, ref arguments) => {
|
||||||
|
|
|
@ -55,7 +55,7 @@ impl LintPass for MutexAtomic {
|
||||||
pub struct MutexAtomic;
|
pub struct MutexAtomic;
|
||||||
|
|
||||||
impl LateLintPass for MutexAtomic {
|
impl LateLintPass for MutexAtomic {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
let ty = cx.tcx.tables().expr_ty(expr);
|
let ty = cx.tcx.tables().expr_ty(expr);
|
||||||
if let ty::TyAdt(_, subst) = ty.sty {
|
if let ty::TyAdt(_, subst) = ty.sty {
|
||||||
if match_type(cx, ty, &paths::MUTEX) {
|
if match_type(cx, ty, &paths::MUTEX) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ impl LintPass for NeedlessBool {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for NeedlessBool {
|
impl LateLintPass for NeedlessBool {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
use self::Expression::*;
|
use self::Expression::*;
|
||||||
if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node {
|
if let ExprIf(ref pred, ref then_block, Some(ref else_expr)) = e.node {
|
||||||
let reduce = |ret, not| {
|
let reduce = |ret, not| {
|
||||||
|
@ -117,7 +117,7 @@ impl LintPass for BoolComparison {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for BoolComparison {
|
impl LateLintPass for BoolComparison {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
use self::Expression::*;
|
use self::Expression::*;
|
||||||
if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node {
|
if let ExprBinary(Spanned { node: BiEq, .. }, ref left_side, ref right_side) = e.node {
|
||||||
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
|
match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl LintPass for NeedlessBorrow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for NeedlessBorrow {
|
impl LateLintPass for NeedlessBorrow {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if in_macro(cx, e.span) {
|
if in_macro(cx, e.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ impl LateLintPass for NeedlessBorrow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn check_pat(&mut self, cx: &LateContext, pat: &Pat) {
|
fn check_pat<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
|
||||||
if in_macro(cx, pat.span) {
|
if in_macro(cx, pat.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
|
if let ExprStruct(_, ref fields, Some(ref base)) = expr.node {
|
||||||
let ty = cx.tcx.tables().expr_ty(expr);
|
let ty = cx.tcx.tables().expr_ty(expr);
|
||||||
if let TyAdt(def, _) = ty.sty {
|
if let TyAdt(def, _) = ty.sty {
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl LintPass for NegMultiply {
|
||||||
|
|
||||||
#[allow(match_same_arms)]
|
#[allow(match_same_arms)]
|
||||||
impl LateLintPass for NegMultiply {
|
impl LateLintPass for NegMultiply {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
|
if let ExprBinary(Spanned { node: BiMul, .. }, ref l, ref r) = e.node {
|
||||||
match (&l.node, &r.node) {
|
match (&l.node, &r.node) {
|
||||||
(&ExprUnary(..), &ExprUnary(..)) => (),
|
(&ExprUnary(..), &ExprUnary(..)) => (),
|
||||||
|
|
|
@ -90,7 +90,15 @@ impl LintPass for NewWithoutDefault {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for NewWithoutDefault {
|
impl LateLintPass for NewWithoutDefault {
|
||||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, _: &hir::Expr, span: Span, id: ast::NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
kind: FnKind<'tcx>,
|
||||||
|
decl: &'tcx hir::FnDecl,
|
||||||
|
_: &'tcx hir::Expr,
|
||||||
|
span: Span,
|
||||||
|
id: ast::NodeId,
|
||||||
|
) {
|
||||||
if in_external_macro(cx, span) {
|
if in_external_macro(cx, span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,7 +103,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_stmt(&mut self, cx: &LateContext, stmt: &Stmt) {
|
fn check_stmt<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
|
||||||
if let StmtSemi(ref expr, _) = stmt.node {
|
if let StmtSemi(ref expr, _) = stmt.node {
|
||||||
if has_no_effect(cx, expr) {
|
if has_no_effect(cx, expr) {
|
||||||
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
|
span_lint(cx, NO_EFFECT, stmt.span, "statement with no effect");
|
||||||
|
|
|
@ -59,9 +59,9 @@ struct ExistingName {
|
||||||
whitelist: &'static [&'static str],
|
whitelist: &'static [&'static str],
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SimilarNamesLocalVisitor<'a, 'b: 'a> {
|
struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> {
|
||||||
names: Vec<ExistingName>,
|
names: Vec<ExistingName>,
|
||||||
cx: &'a EarlyContext<'b>,
|
cx: &'a EarlyContext<'tcx>,
|
||||||
lint: &'a NonExpressiveNames,
|
lint: &'a NonExpressiveNames,
|
||||||
single_char_names: Vec<char>,
|
single_char_names: Vec<char>,
|
||||||
}
|
}
|
||||||
|
@ -76,10 +76,10 @@ const WHITELIST: &'static [&'static [&'static str]] = &[
|
||||||
&["set", "get"],
|
&["set", "get"],
|
||||||
];
|
];
|
||||||
|
|
||||||
struct SimilarNamesNameVisitor<'a, 'b: 'a, 'c: 'b>(&'a mut SimilarNamesLocalVisitor<'b, 'c>);
|
struct SimilarNamesNameVisitor<'a: 'b, 'tcx: 'a, 'b>(&'b mut SimilarNamesLocalVisitor<'a, 'tcx>);
|
||||||
|
|
||||||
impl<'a, 'b, 'c> Visitor for SimilarNamesNameVisitor<'a, 'b, 'c> {
|
impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> {
|
||||||
fn visit_pat(&mut self, pat: &Pat) {
|
fn visit_pat(&mut self, pat: &'tcx 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, _) => {
|
||||||
|
@ -120,7 +120,7 @@ fn whitelisted(interned_name: &str, list: &[&str]) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, 'c> SimilarNamesNameVisitor<'a, 'b, 'c> {
|
impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
|
||||||
fn check_short_name(&mut self, c: char, span: Span) {
|
fn check_short_name(&mut self, c: char, span: Span) {
|
||||||
// make sure we ignore shadowing
|
// make sure we ignore shadowing
|
||||||
if self.0.single_char_names.contains(&c) {
|
if self.0.single_char_names.contains(&c) {
|
||||||
|
@ -236,18 +236,18 @@ impl<'a, 'b> SimilarNamesLocalVisitor<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> Visitor for SimilarNamesLocalVisitor<'a, 'b> {
|
impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
|
||||||
fn visit_local(&mut self, local: &Local) {
|
fn visit_local(&mut self, local: &'tcx 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: &Block) {
|
fn visit_block(&mut self, blk: &'tcx Block) {
|
||||||
self.apply(|this| walk_block(this, blk));
|
self.apply(|this| walk_block(this, blk));
|
||||||
}
|
}
|
||||||
fn visit_arm(&mut self, arm: &Arm) {
|
fn visit_arm(&mut self, arm: &'tcx 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]);
|
||||||
|
|
|
@ -41,7 +41,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if_let_chain! {[ //begin checking variables
|
if_let_chain! {[ //begin checking variables
|
||||||
let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
|
let ExprMatch(ref op, ref body, ref source) = expr.node, //test if expr is a match
|
||||||
let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
|
let MatchSource::IfLetDesugar { .. } = *source, //test if it is an If Let
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for NonSensical {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for NonSensical {
|
impl LateLintPass for NonSensical {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprMethodCall(ref name, _, ref arguments) = e.node {
|
if let ExprMethodCall(ref name, _, ref arguments) = e.node {
|
||||||
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
|
let (obj_ty, _) = walk_ptrs_ty_depth(cx.tcx.tables().expr_ty(&arguments[0]));
|
||||||
if &*name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
|
if &*name.node.as_str() == "open" && match_type(cx, obj_ty, &paths::OPEN_OPTIONS) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl LintPass for OverflowCheckConditional {
|
||||||
|
|
||||||
impl LateLintPass for OverflowCheckConditional {
|
impl LateLintPass for OverflowCheckConditional {
|
||||||
// a + b < a, a > a + b, a < a - b, a - b > a
|
// a + b < a, a > a + b, a < a - b, a - b > a
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
let Expr_::ExprBinary(ref op, ref first, ref second) = expr.node,
|
||||||
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
|
let Expr_::ExprBinary(ref op2, ref ident1, ref ident2) = first.node,
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ExprBlock(ref block) = expr.node,
|
let ExprBlock(ref block) = expr.node,
|
||||||
let Some(ref ex) = block.expr,
|
let Some(ref ex) = block.expr,
|
||||||
|
|
|
@ -36,7 +36,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
|
let ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) = item.node,
|
||||||
!is_automatically_derived(&*item.attrs),
|
!is_automatically_derived(&*item.attrs),
|
||||||
|
|
|
@ -66,7 +66,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ExprCall(ref fun, ref args) = expr.node,
|
let ExprCall(ref fun, ref args) = expr.node,
|
||||||
let ExprPath(ref qpath) = fun.node,
|
let ExprPath(ref qpath) = fun.node,
|
||||||
|
|
|
@ -55,13 +55,13 @@ impl LintPass for PointerPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for PointerPass {
|
impl LateLintPass for PointerPass {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemFn(ref decl, _, _, _, _, _) = item.node {
|
if let ItemFn(ref decl, _, _, _, _, _) = item.node {
|
||||||
check_fn(cx, decl, item.id);
|
check_fn(cx, decl, item.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
if let ImplItemKind::Method(ref sig, _) = item.node {
|
if let ImplItemKind::Method(ref sig, _) = item.node {
|
||||||
if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) {
|
if let Some(NodeItem(it)) = cx.tcx.map.find(cx.tcx.map.get_parent(item.id)) {
|
||||||
if let ItemImpl(_, _, _, Some(_), _, _) = it.node {
|
if let ItemImpl(_, _, _, Some(_), _, _) = it.node {
|
||||||
|
@ -72,13 +72,13 @@ impl LateLintPass for PointerPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||||
if let MethodTraitItem(ref sig, _) = item.node {
|
if let MethodTraitItem(ref sig, _) = item.node {
|
||||||
check_fn(cx, &sig.decl, item.id);
|
check_fn(cx, &sig.decl, item.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprBinary(ref op, ref l, ref r) = expr.node {
|
if let ExprBinary(ref op, ref l, ref r) = expr.node {
|
||||||
if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) {
|
if (op.node == BiEq || op.node == BiNe) && (is_null_path(l) || is_null_path(r)) {
|
||||||
span_lint(cx,
|
span_lint(cx,
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl LintPass for StepByZero {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for StepByZero {
|
impl LateLintPass for StepByZero {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node {
|
if let ExprMethodCall(Spanned { node: ref name, .. }, _, ref args) = expr.node {
|
||||||
let name = &*name.as_str();
|
let name = &*name.as_str();
|
||||||
|
|
||||||
|
|
|
@ -83,11 +83,11 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_crate(&mut self, _: &LateContext, _: &Crate) {
|
fn check_crate<'a, 'tcx: 'a>(&mut self, _: &LateContext<'a, 'tcx>, _: &'tcx Crate) {
|
||||||
self.spans.clear();
|
self.spans.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_block(&mut self, cx: &LateContext, block: &Block) {
|
fn check_block<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) {
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
self.last.is_none(),
|
self.last.is_none(),
|
||||||
let Some(ref expr) = block.expr,
|
let Some(ref expr) = block.expr,
|
||||||
|
@ -106,13 +106,13 @@ impl LateLintPass for Pass {
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_block_post(&mut self, _: &LateContext, block: &Block) {
|
fn check_block_post<'a, 'tcx: 'a>(&mut self, _: &LateContext<'a, 'tcx>, block: &'tcx Block) {
|
||||||
if self.last.map_or(false, |id| block.id == id) {
|
if self.last.map_or(false, |id| block.id == id) {
|
||||||
self.last = None;
|
self.last = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let ExprCall(ref fun, ref args) = expr.node,
|
let ExprCall(ref fun, ref args) = expr.node,
|
||||||
let ExprPath(ref qpath) = fun.node,
|
let ExprPath(ref qpath) = fun.node,
|
||||||
|
|
|
@ -27,7 +27,7 @@ impl LintPass for Serde {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Serde {
|
impl LateLintPass for Serde {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node {
|
if let ItemImpl(_, _, _, Some(ref trait_ref), _, ref items) = item.node {
|
||||||
let did = trait_ref.path.def.def_id();
|
let did = trait_ref.path.def.def_id();
|
||||||
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
|
if let Some(visit_did) = get_trait_def_id(cx, &paths::SERDE_DE_VISITOR) {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, FnKind};
|
use rustc::hir::intravisit::{Visitor, FnKind, NestedVisitorMap};
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use std::ops::Deref;
|
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
use utils::{higher, in_external_macro, snippet, span_lint_and_then};
|
use utils::{higher, in_external_macro, snippet, span_lint_and_then};
|
||||||
|
|
||||||
|
@ -81,7 +80,15 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, expr: &Expr, _: Span, _: NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
_: FnKind<'tcx>,
|
||||||
|
decl: &'tcx FnDecl,
|
||||||
|
expr: &'tcx Expr,
|
||||||
|
_: Span,
|
||||||
|
_: NodeId,
|
||||||
|
) {
|
||||||
if in_external_macro(cx, expr.span) {
|
if in_external_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +96,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
|
fn check_fn<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl, expr: &'tcx Expr) {
|
||||||
let mut bindings = Vec::new();
|
let mut bindings = Vec::new();
|
||||||
for arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
if let PatKind::Binding(_, _, ident, _) = arg.pat.node {
|
if let PatKind::Binding(_, _, ident, _) = arg.pat.node {
|
||||||
|
@ -99,7 +106,7 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, expr: &Expr) {
|
||||||
check_expr(cx, expr, &mut bindings);
|
check_expr(cx, expr, &mut bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>) {
|
fn check_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, block: &'tcx Block, bindings: &mut Vec<(Name, Span)>) {
|
||||||
let len = bindings.len();
|
let len = bindings.len();
|
||||||
for stmt in &block.stmts {
|
for stmt in &block.stmts {
|
||||||
match stmt.node {
|
match stmt.node {
|
||||||
|
@ -114,7 +121,7 @@ fn check_block(cx: &LateContext, block: &Block, bindings: &mut Vec<(Name, Span)>
|
||||||
bindings.truncate(len);
|
bindings.truncate(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
|
fn check_decl<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl, bindings: &mut Vec<(Name, Span)>) {
|
||||||
if in_external_macro(cx, decl.span) {
|
if in_external_macro(cx, decl.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -128,9 +135,9 @@ fn check_decl(cx: &LateContext, decl: &Decl, bindings: &mut Vec<(Name, Span)>) {
|
||||||
}
|
}
|
||||||
if let Some(ref o) = *init {
|
if let Some(ref o) = *init {
|
||||||
check_expr(cx, o, bindings);
|
check_expr(cx, o, bindings);
|
||||||
check_pat(cx, pat, &Some(o), span, bindings);
|
check_pat(cx, pat, Some(o), span, bindings);
|
||||||
} else {
|
} else {
|
||||||
check_pat(cx, pat, &None, span, bindings);
|
check_pat(cx, pat, None, span, bindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +150,13 @@ fn is_binding(cx: &LateContext, pat_id: NodeId) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bindings: &mut Vec<(Name, Span)>) {
|
fn check_pat<'a, 'tcx: 'a>(
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
pat: &'tcx Pat,
|
||||||
|
init: Option<&'tcx Expr>,
|
||||||
|
span: Span,
|
||||||
|
bindings: &mut Vec<(Name, Span)>,
|
||||||
|
) {
|
||||||
// TODO: match more stuff / destructuring
|
// TODO: match more stuff / destructuring
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Binding(_, _, ref ident, ref inner) => {
|
PatKind::Binding(_, _, ref ident, ref inner) => {
|
||||||
|
@ -167,14 +180,14 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Struct(_, ref pfields, _) => {
|
PatKind::Struct(_, ref pfields, _) => {
|
||||||
if let Some(init_struct) = *init {
|
if let Some(init_struct) = init {
|
||||||
if let ExprStruct(_, ref efields, _) = init_struct.node {
|
if let ExprStruct(_, ref efields, _) = init_struct.node {
|
||||||
for field in pfields {
|
for field in pfields {
|
||||||
let name = field.node.name;
|
let name = field.node.name;
|
||||||
let efield = efields.iter()
|
let efield = efields.iter()
|
||||||
.find(|f| f.name.node == name)
|
.find(|f| f.name.node == name)
|
||||||
.map(|f| &*f.expr);
|
.map(|f| &*f.expr);
|
||||||
check_pat(cx, &field.node.pat, &efield, span, bindings);
|
check_pat(cx, &field.node.pat, efield, span, bindings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for field in pfields {
|
for field in pfields {
|
||||||
|
@ -183,15 +196,15 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for field in pfields {
|
for field in pfields {
|
||||||
check_pat(cx, &field.node.pat, &None, span, bindings);
|
check_pat(cx, &field.node.pat, None, span, bindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Tuple(ref inner, _) => {
|
PatKind::Tuple(ref inner, _) => {
|
||||||
if let Some(init_tup) = *init {
|
if let Some(init_tup) = init {
|
||||||
if let ExprTup(ref tup) = init_tup.node {
|
if let ExprTup(ref tup) = init_tup.node {
|
||||||
for (i, p) in inner.iter().enumerate() {
|
for (i, p) in inner.iter().enumerate() {
|
||||||
check_pat(cx, p, &Some(&tup[i]), p.span, bindings);
|
check_pat(cx, p, Some(&tup[i]), p.span, bindings);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for p in inner {
|
for p in inner {
|
||||||
|
@ -200,14 +213,14 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for p in inner {
|
for p in inner {
|
||||||
check_pat(cx, p, &None, span, bindings);
|
check_pat(cx, p, None, span, bindings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PatKind::Box(ref inner) => {
|
PatKind::Box(ref inner) => {
|
||||||
if let Some(initp) = *init {
|
if let Some(initp) = init {
|
||||||
if let ExprBox(ref inner_init) = initp.node {
|
if let ExprBox(ref inner_init) = initp.node {
|
||||||
check_pat(cx, inner, &Some(&**inner_init), span, bindings);
|
check_pat(cx, inner, Some(&**inner_init), span, bindings);
|
||||||
} else {
|
} else {
|
||||||
check_pat(cx, inner, init, span, bindings);
|
check_pat(cx, inner, init, span, bindings);
|
||||||
}
|
}
|
||||||
|
@ -221,10 +234,15 @@ fn check_pat(cx: &LateContext, pat: &Pat, init: &Option<&Expr>, span: Span, bind
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span, init: &Option<T>, prev_span: Span)
|
fn lint_shadow<'a, 'tcx: 'a>(
|
||||||
where T: Deref<Target = Expr>
|
cx: &LateContext<'a, 'tcx>,
|
||||||
{
|
name: Name,
|
||||||
if let Some(ref expr) = *init {
|
span: Span,
|
||||||
|
pattern_span: Span,
|
||||||
|
init: Option<&'tcx Expr>,
|
||||||
|
prev_span: Span,
|
||||||
|
) {
|
||||||
|
if let Some(expr) = init {
|
||||||
if is_self_shadow(name, expr) {
|
if is_self_shadow(name, expr) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
SHADOW_SAME,
|
SHADOW_SAME,
|
||||||
|
@ -234,7 +252,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span,
|
||||||
snippet(cx, expr.span, "..")),
|
snippet(cx, expr.span, "..")),
|
||||||
|db| { db.span_note(prev_span, "previous binding is here"); },
|
|db| { db.span_note(prev_span, "previous binding is here"); },
|
||||||
);
|
);
|
||||||
} else if contains_self(name, expr) {
|
} else if contains_self(cx, name, expr) {
|
||||||
span_lint_and_then(cx,
|
span_lint_and_then(cx,
|
||||||
SHADOW_REUSE,
|
SHADOW_REUSE,
|
||||||
pattern_span,
|
pattern_span,
|
||||||
|
@ -267,7 +285,7 @@ fn lint_shadow<T>(cx: &LateContext, name: Name, span: Span, pattern_span: Span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
|
fn check_expr<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr, bindings: &mut Vec<(Name, Span)>) {
|
||||||
if in_external_macro(cx, expr.span) {
|
if in_external_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -302,7 +320,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
|
||||||
let len = bindings.len();
|
let len = bindings.len();
|
||||||
for arm in arms {
|
for arm in arms {
|
||||||
for pat in &arm.pats {
|
for pat in &arm.pats {
|
||||||
check_pat(cx, pat, &Some(&**init), pat.span, bindings);
|
check_pat(cx, pat, Some(&**init), pat.span, bindings);
|
||||||
// This is ugly, but needed to get the right type
|
// This is ugly, but needed to get the right type
|
||||||
if let Some(ref guard) = arm.guard {
|
if let Some(ref guard) = arm.guard {
|
||||||
check_expr(cx, guard, bindings);
|
check_expr(cx, guard, bindings);
|
||||||
|
@ -316,7 +334,7 @@ fn check_expr(cx: &LateContext, expr: &Expr, bindings: &mut Vec<(Name, Span)>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_ty(cx: &LateContext, ty: &Ty, bindings: &mut Vec<(Name, Span)>) {
|
fn check_ty<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty, bindings: &mut Vec<(Name, Span)>) {
|
||||||
match ty.node {
|
match ty.node {
|
||||||
TyObjectSum(ref sty, _) |
|
TyObjectSum(ref sty, _) |
|
||||||
TySlice(ref sty) => check_ty(cx, sty, bindings),
|
TySlice(ref sty) => check_ty(cx, sty, bindings),
|
||||||
|
@ -353,23 +371,28 @@ fn path_eq_name(name: Name, path: &Path) -> bool {
|
||||||
!path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
|
!path.global && path.segments.len() == 1 && path.segments[0].name.as_str() == name.as_str()
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ContainsSelf {
|
struct ContainsSelf<'a, 'tcx: 'a> {
|
||||||
name: Name,
|
name: Name,
|
||||||
result: bool,
|
result: bool,
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for ContainsSelf {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for ContainsSelf<'a, 'tcx> {
|
||||||
fn visit_name(&mut self, _: Span, name: Name) {
|
fn visit_name(&mut self, _: Span, name: Name) {
|
||||||
if self.name == name {
|
if self.name == name {
|
||||||
self.result = true;
|
self.result = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn contains_self(name: Name, expr: &Expr) -> bool {
|
fn contains_self<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, name: Name, expr: &'tcx Expr) -> bool {
|
||||||
let mut cs = ContainsSelf {
|
let mut cs = ContainsSelf {
|
||||||
name: name,
|
name: name,
|
||||||
result: false,
|
result: false,
|
||||||
|
cx: cx,
|
||||||
};
|
};
|
||||||
cs.visit_expr(expr);
|
cs.visit_expr(expr);
|
||||||
cs.result
|
cs.result
|
||||||
|
|
|
@ -80,7 +80,7 @@ impl LintPass for StringAdd {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for StringAdd {
|
impl LateLintPass for StringAdd {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node {
|
if let ExprBinary(Spanned { node: BiAdd, .. }, ref left, _) = e.node {
|
||||||
if is_string(cx, left) {
|
if is_string(cx, left) {
|
||||||
if let Allow = cx.current_level(STRING_ADD_ASSIGN) {
|
if let Allow = cx.current_level(STRING_ADD_ASSIGN) {
|
||||||
|
@ -137,7 +137,7 @@ impl LintPass for StringLitAsBytes {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for StringLitAsBytes {
|
impl LateLintPass for StringLitAsBytes {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use syntax::ast::LitKind;
|
use syntax::ast::LitKind;
|
||||||
use utils::{snippet, in_macro};
|
use utils::{snippet, in_macro};
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl LintPass for Swap {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Swap {
|
impl LateLintPass for Swap {
|
||||||
fn check_block(&mut self, cx: &LateContext, block: &Block) {
|
fn check_block<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx Block) {
|
||||||
check_manual_swap(cx, block);
|
check_manual_swap(cx, block);
|
||||||
check_suspicious_swap(cx, block);
|
check_suspicious_swap(cx, block);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprAssign(ref target, _) = expr.node {
|
if let ExprAssign(ref target, _) = expr.node {
|
||||||
match target.node {
|
match target.node {
|
||||||
ExprField(ref base, _) |
|
ExprField(ref base, _) |
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl LintPass for Transmute {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Transmute {
|
impl LateLintPass for Transmute {
|
||||||
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
|
||||||
if let ExprCall(ref path_expr, ref args) = e.node {
|
if let ExprCall(ref path_expr, ref args) = e.node {
|
||||||
if let ExprPath(ref qpath) = path_expr.node {
|
if let ExprPath(ref qpath) = path_expr.node {
|
||||||
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
let def_id = cx.tcx.tables().qpath_def(qpath, path_expr.id).def_id();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use reexport::*;
|
use reexport::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty};
|
use rustc::hir::intravisit::{FnKind, Visitor, walk_ty, NestedVisitorMap};
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::ty;
|
use rustc::ty;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
@ -70,7 +70,7 @@ impl LintPass for TypePass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for TypePass {
|
impl LateLintPass for TypePass {
|
||||||
fn check_ty(&mut self, cx: &LateContext, ast_ty: &Ty) {
|
fn check_ty<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, ast_ty: &'tcx Ty) {
|
||||||
if in_macro(cx, ast_ty.span) {
|
if in_macro(cx, ast_ty.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ impl LintPass for LetPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for LetPass {
|
impl LateLintPass for LetPass {
|
||||||
fn check_decl(&mut self, cx: &LateContext, decl: &Decl) {
|
fn check_decl<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, decl: &'tcx Decl) {
|
||||||
check_let_unit(cx, decl)
|
check_let_unit(cx, decl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ impl LintPass for UnitCmp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for UnitCmp {
|
impl LateLintPass for UnitCmp {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if in_macro(cx, expr.span) {
|
if in_macro(cx, expr.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -448,7 +448,7 @@ impl LintPass for CastPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for CastPass {
|
impl LateLintPass for CastPass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprCast(ref ex, _) = expr.node {
|
if let ExprCast(ref ex, _) = expr.node {
|
||||||
let (cast_from, cast_to) = (cx.tcx.tables().expr_ty(ex), cx.tcx.tables().expr_ty(expr));
|
let (cast_from, cast_to) = (cx.tcx.tables().expr_ty(ex), cx.tcx.tables().expr_ty(expr));
|
||||||
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
|
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
|
||||||
|
@ -536,16 +536,16 @@ impl LintPass for TypeComplexityPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for TypeComplexityPass {
|
impl LateLintPass for TypeComplexityPass {
|
||||||
fn check_fn(&mut self, cx: &LateContext, _: FnKind, decl: &FnDecl, _: &Expr, _: Span, _: NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, _: FnKind<'tcx>, decl: &'tcx FnDecl, _: &'tcx Expr, _: Span, _: NodeId) {
|
||||||
self.check_fndecl(cx, decl);
|
self.check_fndecl(cx, decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_struct_field(&mut self, cx: &LateContext, field: &StructField) {
|
fn check_struct_field<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx StructField) {
|
||||||
// enum variants are also struct fields now
|
// enum variants are also struct fields now
|
||||||
self.check_type(cx, &field.ty);
|
self.check_type(cx, &field.ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ItemStatic(ref ty, _, _) |
|
ItemStatic(ref ty, _, _) |
|
||||||
ItemConst(ref ty, _) => self.check_type(cx, ty),
|
ItemConst(ref ty, _) => self.check_type(cx, ty),
|
||||||
|
@ -554,7 +554,7 @@ impl LateLintPass for TypeComplexityPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx TraitItem) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ConstTraitItem(ref ty, _) |
|
ConstTraitItem(ref ty, _) |
|
||||||
TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty),
|
TypeTraitItem(_, Some(ref ty)) => self.check_type(cx, ty),
|
||||||
|
@ -564,7 +564,7 @@ impl LateLintPass for TypeComplexityPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) {
|
||||||
match item.node {
|
match item.node {
|
||||||
ImplItemKind::Const(ref ty, _) |
|
ImplItemKind::Const(ref ty, _) |
|
||||||
ImplItemKind::Type(ref ty) => self.check_type(cx, ty),
|
ImplItemKind::Type(ref ty) => self.check_type(cx, ty),
|
||||||
|
@ -573,7 +573,7 @@ impl LateLintPass for TypeComplexityPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_local(&mut self, cx: &LateContext, local: &Local) {
|
fn check_local<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, local: &'tcx Local) {
|
||||||
if let Some(ref ty) = local.ty {
|
if let Some(ref ty) = local.ty {
|
||||||
self.check_type(cx, ty);
|
self.check_type(cx, ty);
|
||||||
}
|
}
|
||||||
|
@ -581,7 +581,7 @@ impl LateLintPass for TypeComplexityPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypeComplexityPass {
|
impl TypeComplexityPass {
|
||||||
fn check_fndecl(&self, cx: &LateContext, decl: &FnDecl) {
|
fn check_fndecl<'a, 'tcx: 'a>(&self, cx: &LateContext<'a, 'tcx>, decl: &'tcx FnDecl) {
|
||||||
for arg in &decl.inputs {
|
for arg in &decl.inputs {
|
||||||
self.check_type(cx, &arg.ty);
|
self.check_type(cx, &arg.ty);
|
||||||
}
|
}
|
||||||
|
@ -590,7 +590,7 @@ impl TypeComplexityPass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_type(&self, cx: &LateContext, ty: &Ty) {
|
fn check_type<'a, 'tcx: 'a>(&self, cx: &LateContext<'a, 'tcx>, ty: &'tcx Ty) {
|
||||||
if in_macro(cx, ty.span) {
|
if in_macro(cx, ty.span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -598,6 +598,7 @@ impl TypeComplexityPass {
|
||||||
let mut visitor = TypeComplexityVisitor {
|
let mut visitor = TypeComplexityVisitor {
|
||||||
score: 0,
|
score: 0,
|
||||||
nest: 1,
|
nest: 1,
|
||||||
|
cx: cx,
|
||||||
};
|
};
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
visitor.score
|
visitor.score
|
||||||
|
@ -613,15 +614,16 @@ impl TypeComplexityPass {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Walks a type and assigns a complexity score to it.
|
/// Walks a type and assigns a complexity score to it.
|
||||||
struct TypeComplexityVisitor {
|
struct TypeComplexityVisitor<'a, 'tcx: 'a> {
|
||||||
/// total complexity score of the type
|
/// total complexity score of the type
|
||||||
score: u64,
|
score: u64,
|
||||||
/// current nesting level
|
/// current nesting level
|
||||||
nest: u64,
|
nest: u64,
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for TypeComplexityVisitor {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for TypeComplexityVisitor<'a, 'tcx> {
|
||||||
fn visit_ty(&mut self, ty: &'v Ty) {
|
fn visit_ty(&mut self, ty: &'tcx Ty) {
|
||||||
let (add_score, sub_nest) = match ty.node {
|
let (add_score, sub_nest) = match ty.node {
|
||||||
// _, &x and *x have only small overhead; don't mess with nesting level
|
// _, &x and *x have only small overhead; don't mess with nesting level
|
||||||
TyInfer | TyPtr(..) | TyRptr(..) => (1, 0),
|
TyInfer | TyPtr(..) | TyRptr(..) => (1, 0),
|
||||||
|
@ -646,6 +648,9 @@ impl<'v> Visitor<'v> for TypeComplexityVisitor {
|
||||||
walk_ty(self, ty);
|
walk_ty(self, ty);
|
||||||
self.nest -= sub_nest;
|
self.nest -= sub_nest;
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// **What it does:** Checks for expressions where a character literal is cast
|
/// **What it does:** Checks for expressions where a character literal is cast
|
||||||
|
@ -678,7 +683,7 @@ impl LintPass for CharLitAsU8 {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for CharLitAsU8 {
|
impl LateLintPass for CharLitAsU8 {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
use syntax::ast::{LitKind, UintTy};
|
use syntax::ast::{LitKind, UintTy};
|
||||||
|
|
||||||
if let ExprCast(ref e, _) = expr.node {
|
if let ExprCast(ref e, _) = expr.node {
|
||||||
|
@ -842,7 +847,7 @@ fn detect_extreme_expr<'a>(cx: &LateContext, expr: &'a Expr) -> Option<ExtremeEx
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for AbsurdExtremeComparisons {
|
impl LateLintPass for AbsurdExtremeComparisons {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
use types::ExtremeType::*;
|
use types::ExtremeType::*;
|
||||||
use types::AbsurdComparisonResult::*;
|
use types::AbsurdComparisonResult::*;
|
||||||
|
|
||||||
|
@ -1067,7 +1072,7 @@ fn upcast_comparison_bounds_err(cx: &LateContext, span: &Span, rel: comparisons:
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for InvalidUpcastComparisons {
|
impl LateLintPass for InvalidUpcastComparisons {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node {
|
if let ExprBinary(ref cmp, ref lhs, ref rhs) = expr.node {
|
||||||
|
|
||||||
let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
|
let normalized = comparisons::normalize_comparison(cmp.node, lhs, rhs);
|
||||||
|
|
|
@ -69,7 +69,7 @@ impl LintPass for Unicode {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Unicode {
|
impl LateLintPass for Unicode {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
if let ExprLit(ref lit) = expr.node {
|
if let ExprLit(ref lit) = expr.node {
|
||||||
if let LitKind::Str(_, _) = lit.node {
|
if let LitKind::Str(_, _) = lit.node {
|
||||||
check_str(cx, lit.span)
|
check_str(cx, lit.span)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn};
|
use rustc::hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, NestedVisitorMap};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
@ -29,15 +29,9 @@ declare_lint! {
|
||||||
|
|
||||||
pub struct UnusedLabel;
|
pub struct UnusedLabel;
|
||||||
|
|
||||||
#[derive(Default)]
|
struct UnusedLabelVisitor<'a, 'tcx: 'a> {
|
||||||
struct UnusedLabelVisitor {
|
|
||||||
labels: HashMap<InternedString, Span>,
|
labels: HashMap<InternedString, Span>,
|
||||||
}
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
|
|
||||||
impl UnusedLabelVisitor {
|
|
||||||
pub fn new() -> UnusedLabelVisitor {
|
|
||||||
::std::default::Default::default()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LintPass for UnusedLabel {
|
impl LintPass for UnusedLabel {
|
||||||
|
@ -47,13 +41,24 @@ impl LintPass for UnusedLabel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for UnusedLabel {
|
impl LateLintPass for UnusedLabel {
|
||||||
fn check_fn(&mut self, cx: &LateContext, kind: FnKind, decl: &hir::FnDecl, body: &hir::Expr, span: Span, fn_id: ast::NodeId) {
|
fn check_fn<'a, 'tcx: 'a>(
|
||||||
|
&mut self,
|
||||||
|
cx: &LateContext<'a, 'tcx>,
|
||||||
|
kind: FnKind<'tcx>,
|
||||||
|
decl: &'tcx hir::FnDecl,
|
||||||
|
body: &'tcx hir::Expr,
|
||||||
|
span: Span,
|
||||||
|
fn_id: ast::NodeId,
|
||||||
|
) {
|
||||||
if in_macro(cx, span) {
|
if in_macro(cx, span) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut v = UnusedLabelVisitor::new();
|
let mut v = UnusedLabelVisitor {
|
||||||
walk_fn(&mut v, kind, decl, body, span, fn_id);
|
cx: cx,
|
||||||
|
labels: HashMap::new(),
|
||||||
|
};
|
||||||
|
walk_fn(&mut v, kind, decl, body.expr_id(), span, fn_id);
|
||||||
|
|
||||||
for (label, span) in v.labels {
|
for (label, span) in v.labels {
|
||||||
span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));
|
span_lint(cx, UNUSED_LABEL, span, &format!("unused label `{}`", label));
|
||||||
|
@ -61,8 +66,8 @@ impl LateLintPass for UnusedLabel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &hir::Expr) {
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
hir::ExprBreak(Some(label), _) |
|
hir::ExprBreak(Some(label), _) |
|
||||||
hir::ExprAgain(Some(label)) => {
|
hir::ExprAgain(Some(label)) => {
|
||||||
|
@ -77,4 +82,7 @@ impl<'v> Visitor<'v> for UnusedLabelVisitor {
|
||||||
|
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -376,11 +376,11 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
|
||||||
self.hash_expr(e);
|
self.hash_expr(e);
|
||||||
// TODO: _ty
|
// TODO: _ty
|
||||||
}
|
}
|
||||||
ExprClosure(cap, _, ref e, _) => {
|
ExprClosure(cap, _, eid, _) => {
|
||||||
let c: fn(_, _, _, _) -> _ = ExprClosure;
|
let c: fn(_, _, _, _) -> _ = ExprClosure;
|
||||||
c.hash(&mut self.s);
|
c.hash(&mut self.s);
|
||||||
cap.hash(&mut self.s);
|
cap.hash(&mut self.s);
|
||||||
self.hash_expr(e);
|
self.hash_expr(self.cx.tcx.map.expr(eid));
|
||||||
}
|
}
|
||||||
ExprField(ref e, ref f) => {
|
ExprField(ref e, ref f) => {
|
||||||
let c: fn(_, _) -> _ = ExprField;
|
let c: fn(_, _) -> _ = ExprField;
|
||||||
|
|
|
@ -37,14 +37,14 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
|
||||||
if !has_attr(&item.attrs) {
|
if !has_attr(&item.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
print_item(cx, item);
|
print_item(cx, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_impl_item(&mut self, cx: &LateContext, item: &hir::ImplItem) {
|
fn check_impl_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ImplItem) {
|
||||||
if !has_attr(&item.attrs) {
|
if !has_attr(&item.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -68,33 +68,33 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
|
fn check_trait_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
|
||||||
if !has_attr(&item.attrs) {
|
if !has_attr(&item.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant, _: &hir::Generics) {
|
fn check_variant<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, var: &'tcx hir::Variant, _: &hir::Generics) {
|
||||||
if !has_attr(&var.node.attrs) {
|
if !has_attr(&var.node.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_struct_field(&mut self, cx: &LateContext, field: &hir::StructField) {
|
fn check_struct_field<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, field: &'tcx hir::StructField) {
|
||||||
if !has_attr(&field.attrs) {
|
if !has_attr(&field.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
|
||||||
if !has_attr(&expr.attrs) {
|
if !has_attr(&expr.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
print_expr(cx, expr, 0);
|
print_expr(cx, expr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_arm(&mut self, cx: &LateContext, arm: &hir::Arm) {
|
fn check_arm<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, arm: &'tcx hir::Arm) {
|
||||||
if !has_attr(&arm.attrs) {
|
if !has_attr(&arm.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +109,7 @@ impl LateLintPass for Pass {
|
||||||
print_expr(cx, &arm.body, 1);
|
print_expr(cx, &arm.body, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_stmt(&mut self, cx: &LateContext, stmt: &hir::Stmt) {
|
fn check_stmt<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx hir::Stmt) {
|
||||||
if !has_attr(stmt.node.attrs()) {
|
if !has_attr(stmt.node.attrs()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ impl LateLintPass for Pass {
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
|
||||||
fn check_foreign_item(&mut self, cx: &LateContext, item: &hir::ForeignItem) {
|
fn check_foreign_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::ForeignItem) {
|
||||||
if !has_attr(&item.attrs) {
|
if !has_attr(&item.attrs) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc::lint::*;
|
use rustc::lint::*;
|
||||||
use rustc::hir::*;
|
use rustc::hir::*;
|
||||||
use rustc::hir::intravisit::{Visitor, walk_expr};
|
use rustc::hir::intravisit::{Visitor, walk_expr, NestedVisitorMap};
|
||||||
use utils::{paths, match_path, span_lint};
|
use utils::{paths, match_path, span_lint};
|
||||||
use syntax::symbol::InternedString;
|
use syntax::symbol::InternedString;
|
||||||
use syntax::ast::{Name, NodeId, ItemKind, Crate as AstCrate};
|
use syntax::ast::{Name, NodeId, ItemKind, Crate as AstCrate};
|
||||||
|
@ -105,18 +105,18 @@ impl LintPass for LintWithoutLintPass {
|
||||||
|
|
||||||
|
|
||||||
impl LateLintPass for LintWithoutLintPass {
|
impl LateLintPass for LintWithoutLintPass {
|
||||||
fn check_item(&mut self, _: &LateContext, item: &Item) {
|
fn check_item<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
|
||||||
if let ItemStatic(ref ty, MutImmutable, ref expr) = item.node {
|
if let ItemStatic(ref ty, MutImmutable, ref expr) = item.node {
|
||||||
if is_lint_ref_type(ty) {
|
if is_lint_ref_type(ty) {
|
||||||
self.declared_lints.insert(item.name, item.span);
|
self.declared_lints.insert(item.name, item.span);
|
||||||
} else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" {
|
} else if is_lint_array_type(ty) && item.vis == Visibility::Inherited && item.name == "ARRAY" {
|
||||||
let mut collector = LintCollector { output: &mut self.registered_lints };
|
let mut collector = LintCollector { output: &mut self.registered_lints, cx: cx };
|
||||||
collector.visit_expr(expr);
|
collector.visit_expr(expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_crate_post(&mut self, cx: &LateContext, _: &Crate) {
|
fn check_crate_post<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate) {
|
||||||
for (lint_name, &lint_span) in &self.declared_lints {
|
for (lint_name, &lint_span) in &self.declared_lints {
|
||||||
// When using the `declare_lint!` macro, the original `lint_span`'s
|
// When using the `declare_lint!` macro, the original `lint_span`'s
|
||||||
// file points to "<rustc macros>".
|
// file points to "<rustc macros>".
|
||||||
|
@ -156,18 +156,22 @@ fn is_lint_array_type(ty: &Ty) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LintCollector<'a> {
|
struct LintCollector<'a, 'tcx: 'a> {
|
||||||
output: &'a mut HashSet<Name>,
|
output: &'a mut HashSet<Name>,
|
||||||
|
cx: &'a LateContext<'a, 'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'v, 'a: 'v> Visitor<'v> for LintCollector<'a> {
|
impl<'a, 'tcx: 'a> Visitor<'tcx> for LintCollector<'a, 'tcx> {
|
||||||
fn visit_expr(&mut self, expr: &'v Expr) {
|
fn visit_expr(&mut self, expr: &'tcx Expr) {
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_path(&mut self, path: &'v Path, _: NodeId) {
|
fn visit_path(&mut self, path: &'tcx Path, _: NodeId) {
|
||||||
if path.segments.len() == 1 {
|
if path.segments.len() == 1 {
|
||||||
self.output.insert(path.segments[0].name);
|
self.output.insert(path.segments[0].name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
|
||||||
|
NestedVisitorMap::All(&self.cx.tcx.map)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool {
|
||||||
rhs.expn_id != lhs.expn_id
|
rhs.expn_id != lhs.expn_id
|
||||||
}
|
}
|
||||||
/// Returns true if this `expn_info` was expanded by any macro.
|
/// Returns true if this `expn_info` was expanded by any macro.
|
||||||
pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool {
|
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 {
|
cx.sess().codemap().with_expn_info(span.expn_id, |info| match info {
|
||||||
Some(info) => {
|
Some(info) => {
|
||||||
match info.callee.format {
|
match info.callee.format {
|
||||||
|
@ -109,10 +109,10 @@ pub fn in_macro<T: LintContext>(cx: &T, span: Span) -> bool {
|
||||||
|
|
||||||
/// Returns true if the macro that expanded the crate was outside of the current crate or was a
|
/// Returns true if the macro that expanded the crate was outside of the current crate or was a
|
||||||
/// compiler plugin.
|
/// compiler plugin.
|
||||||
pub fn in_external_macro<T: LintContext>(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
|
/// Invokes `in_macro` with the expansion info of the given span slightly heavy, try to use
|
||||||
/// this after other checks have already happened.
|
/// this after other checks have already happened.
|
||||||
fn in_macro_ext<T: LintContext>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool {
|
fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, opt_info: Option<&ExpnInfo>) -> bool {
|
||||||
// no ExpnInfo = no macro
|
// no ExpnInfo = no macro
|
||||||
opt_info.map_or(false, |info| {
|
opt_info.map_or(false, |info| {
|
||||||
if let ExpnFormat::MacroAttribute(..) = info.callee.format {
|
if let ExpnFormat::MacroAttribute(..) = info.callee.format {
|
||||||
|
@ -371,12 +371,12 @@ pub fn get_item_name(cx: &LateContext, expr: &Expr) -> Option<Name> {
|
||||||
/// ```
|
/// ```
|
||||||
/// snippet(cx, expr.span, "..")
|
/// snippet(cx, expr.span, "..")
|
||||||
/// ```
|
/// ```
|
||||||
pub fn snippet<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||||
cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default))
|
cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or_else(|_| Cow::Borrowed(default))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert a span to a code snippet. Returns `None` if not available.
|
/// Convert a span to a code snippet. Returns `None` if not available.
|
||||||
pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
|
||||||
cx.sess().codemap().span_to_snippet(span).ok()
|
cx.sess().codemap().span_to_snippet(span).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,14 +388,14 @@ pub fn snippet_opt<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
||||||
/// ```
|
/// ```
|
||||||
/// snippet(cx, expr.span, "..")
|
/// snippet(cx, expr.span, "..")
|
||||||
/// ```
|
/// ```
|
||||||
pub fn snippet_block<'a, T: LintContext>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
|
||||||
let snip = snippet(cx, span, default);
|
let snip = snippet(cx, span, default);
|
||||||
trim_multiline(snip, true)
|
trim_multiline(snip, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`.
|
/// Like `snippet_block`, but add braces if the expr is not an `ExprBlock`.
|
||||||
/// Also takes an `Option<String>` which can be put inside the braces.
|
/// Also takes an `Option<String>` which can be put inside the braces.
|
||||||
pub fn expr_block<'a, T: LintContext>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> {
|
pub fn expr_block<'a, 'b, T: LintContext<'b>>(cx: &T, expr: &Expr, option: Option<String>, default: &'a str) -> Cow<'a, str> {
|
||||||
let code = snippet_block(cx, expr.span, default);
|
let code = snippet_block(cx, expr.span, default);
|
||||||
let string = option.unwrap_or_default();
|
let string = option.unwrap_or_default();
|
||||||
if let ExprBlock(_) = expr.node {
|
if let ExprBlock(_) = expr.node {
|
||||||
|
@ -464,15 +464,15 @@ pub fn get_parent_expr<'c>(cx: &'c LateContext, e: &Expr) -> Option<&'c Expr> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_enclosing_block<'c>(cx: &'c LateContext, node: NodeId) -> Option<&'c Block> {
|
pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeId) -> Option<&'tcx Block> {
|
||||||
let map = &cx.tcx.map;
|
let map = &cx.tcx.map;
|
||||||
let enclosing_node = map.get_enclosing_scope(node)
|
let enclosing_node = map.get_enclosing_scope(node)
|
||||||
.and_then(|enclosing_id| map.find(enclosing_id));
|
.and_then(|enclosing_id| map.find(enclosing_id));
|
||||||
if let Some(node) = enclosing_node {
|
if let Some(node) = enclosing_node {
|
||||||
match node {
|
match node {
|
||||||
Node::NodeBlock(block) => Some(block),
|
Node::NodeBlock(block) => Some(block),
|
||||||
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, ref expr), .. }) => {
|
Node::NodeItem(&Item { node: ItemFn(_, _, _, _, _, eid), .. }) => {
|
||||||
match expr.node {
|
match cx.tcx.map.expr(eid).node {
|
||||||
ExprBlock(ref block) => Some(block),
|
ExprBlock(ref block) => Some(block),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -501,15 +501,14 @@ impl<'a> DiagnosticWrapper<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
|
pub fn span_lint<'a, T: LintContext<'a>>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) {
|
||||||
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
|
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
|
||||||
if cx.current_level(lint) != Level::Allow {
|
if cx.current_level(lint) != Level::Allow {
|
||||||
db.wiki_link(lint);
|
db.wiki_link(lint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: needless lifetime doesn't trigger here
|
pub fn span_help_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {
|
||||||
pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) {
|
|
||||||
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
|
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
|
||||||
if cx.current_level(lint) != Level::Allow {
|
if cx.current_level(lint) != Level::Allow {
|
||||||
db.0.help(help);
|
db.0.help(help);
|
||||||
|
@ -517,8 +516,14 @@ pub fn span_help_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, note_span: Span,
|
pub fn span_note_and_lint<'a, 'tcx: 'a, T: LintContext<'tcx>>(
|
||||||
note: &str) {
|
cx: &'a T,
|
||||||
|
lint: &'static Lint,
|
||||||
|
span: Span,
|
||||||
|
msg: &str,
|
||||||
|
note_span: Span,
|
||||||
|
note: &str,
|
||||||
|
) {
|
||||||
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
|
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, span, msg));
|
||||||
if cx.current_level(lint) != Level::Allow {
|
if cx.current_level(lint) != Level::Allow {
|
||||||
if note_span == span {
|
if note_span == span {
|
||||||
|
@ -530,8 +535,8 @@ pub fn span_note_and_lint<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, sp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
|
pub fn span_lint_and_then<'a, 'tcx: 'a, T: LintContext<'tcx>, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
|
||||||
where F: FnOnce(&mut DiagnosticBuilder<'a>)
|
where F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>)
|
||||||
{
|
{
|
||||||
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
|
let mut db = DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg));
|
||||||
if cx.current_level(lint) != Level::Allow {
|
if cx.current_level(lint) != Level::Allow {
|
||||||
|
|
|
@ -384,7 +384,7 @@ fn astbinop2assignop(op: ast::BinOp) -> AssocOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the indentation before `span` if there are nothing but `[ \t]` before it on its line.
|
/// Return the indentation before `span` if there are nothing but `[ \t]` before it on its line.
|
||||||
fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
fn indentation<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
|
||||||
let lo = cx.sess().codemap().lookup_char_pos(span.lo);
|
let lo = cx.sess().codemap().lookup_char_pos(span.lo);
|
||||||
if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) {
|
if let Some(line) = lo.file.get_line(lo.line - 1 /* line numbers in `Loc` are 1-based */) {
|
||||||
if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') {
|
if let Some((pos, _)) = line.char_indices().find(|&(_, c)| c != ' ' && c != '\t') {
|
||||||
|
@ -403,7 +403,7 @@ fn indentation<T: LintContext>(cx: &T, span: Span) -> Option<String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenience extension trait for `DiagnosticBuilder`.
|
/// Convenience extension trait for `DiagnosticBuilder`.
|
||||||
pub trait DiagnosticBuilderExt<T: LintContext> {
|
pub trait DiagnosticBuilderExt<'a, T: LintContext<'a>> {
|
||||||
/// Suggests to add an attribute to an item.
|
/// Suggests to add an attribute to an item.
|
||||||
///
|
///
|
||||||
/// Correctly handles indentation of the attribute and item.
|
/// Correctly handles indentation of the attribute and item.
|
||||||
|
@ -430,7 +430,7 @@ pub trait DiagnosticBuilderExt<T: LintContext> {
|
||||||
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
|
fn suggest_prepend_item(&mut self, cx: &T, item: Span, msg: &str, new_item: &str);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, T: LintContext> DiagnosticBuilderExt<T> for rustc_errors::DiagnosticBuilder<'b> {
|
impl<'a, 'b, 'c, T: LintContext<'c>> DiagnosticBuilderExt<'c, T> for rustc_errors::DiagnosticBuilder<'b> {
|
||||||
fn suggest_item_with_attr<D: Display+?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D) {
|
fn suggest_item_with_attr<D: Display+?Sized>(&mut self, cx: &T, item: Span, msg: &str, attr: &D) {
|
||||||
if let Some(indent) = indentation(cx, item) {
|
if let Some(indent) = indentation(cx, item) {
|
||||||
let span = Span {
|
let span = Span {
|
||||||
|
|
|
@ -33,7 +33,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
|
// search for `&vec![_]` expressions where the adjusted type is `&[_]`
|
||||||
if_let_chain!{[
|
if_let_chain!{[
|
||||||
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.tables().expr_ty_adjusted(expr).sty,
|
let ty::TypeVariants::TyRef(_, ref ty) = cx.tcx.tables().expr_ty_adjusted(expr).sty,
|
||||||
|
|
|
@ -28,7 +28,7 @@ impl LintPass for Pass {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LateLintPass for Pass {
|
impl LateLintPass for Pass {
|
||||||
fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
|
fn check_expr<'a, 'tcx: 'a>(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
|
||||||
// check for instances of 0.0/0.0
|
// check for instances of 0.0/0.0
|
||||||
if_let_chain! {[
|
if_let_chain! {[
|
||||||
let ExprBinary(ref op, ref left, ref right) = expr.node,
|
let ExprBinary(ref op, ref left, ref right) = expr.node,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue