+use crate::consts::{constant, Constant};
use crate::reexport::*;
+use crate::utils::paths;
+use crate::utils::usage::{is_unused, mutated_variables};
+use crate::utils::{
+ get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
+ is_integer_const, is_no_std_crate, is_refutable, last_path_segment, match_trait_method, match_type, match_var,
+ multispan_sugg, snippet, snippet_opt, snippet_with_applicability, span_lint, span_lint_and_help,
+ span_lint_and_sugg, span_lint_and_then, SpanlessEq,
+};
+use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg};
use if_chain::if_chain;
use itertools::Itertools;
-use rustc::declare_lint_pass;
-use rustc::hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
-use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
+use rustc::hir::map::Map;
+use rustc::lint::in_external_macro;
use rustc::middle::region;
-use rustc_hir::def::{DefKind, Res};
-use rustc_hir::def_id;
-use rustc_hir::*;
-use rustc_session::declare_tool_lint;
-// use rustc::middle::region::CodeExtent;
-use crate::consts::{constant, Constant};
-use crate::utils::usage::mutated_variables;
-use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg};
use rustc::ty::{self, Ty};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id;
+use rustc_hir::intravisit::{walk_block, walk_expr, walk_pat, walk_stmt, NestedVisitorMap, Visitor};
+use rustc_hir::*;
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::{BytePos, Symbol};
use rustc_typeck::expr_use_visitor::*;
use std::mem;
use syntax::ast;
-use crate::utils::paths;
-use crate::utils::{
- get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
- is_integer_const, is_refutable, last_path_segment, match_trait_method, match_type, match_var, multispan_sugg,
- snippet, snippet_opt, snippet_with_applicability, span_help_and_lint, span_lint, span_lint_and_sugg,
- span_lint_and_then, SpanlessEq,
-};
-
declare_clippy_lint! {
/// **What it does:** Checks for for-loops that manually copy items between
/// slices that could be optimized by having a memcpy.
// (even if the "match" or "if let" is used for declaration)
if let ExprKind::Loop(ref block, _, LoopSource::Loop) = expr.kind {
// also check for empty `loop {}` statements
- if block.stmts.is_empty() && block.expr.is_none() {
+ if block.stmts.is_empty() && block.expr.is_none() && !is_no_std_crate(cx.tcx.hir().krate()) {
span_lint(
cx,
EMPTY_LOOP,
EXPLICIT_INTO_ITER_LOOP,
arg.span,
"it is more concise to loop over containers instead of using explicit \
- iteration methods`",
+ iteration methods",
"to write this more concisely, try",
object.to_string(),
applicability,
fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) {
let ty = cx.tables.expr_ty(arg);
if match_type(cx, ty, &paths::OPTION) {
- span_help_and_lint(
+ span_lint_and_help(
cx,
FOR_LOOP_OVER_OPTION,
arg.span,
),
);
} else if match_type(cx, ty, &paths::RESULT) {
- span_help_and_lint(
+ span_lint_and_help(
cx,
FOR_LOOP_OVER_RESULT,
arg.span,
fn pat_is_wild<'tcx>(pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
match *pat {
PatKind::Wild => true,
- PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => {
- let mut visitor = UsedVisitor {
- var: ident.name,
- used: false,
- };
- walk_expr(&mut visitor, body);
- !visitor.used
- },
+ PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => is_unused(&ident, body),
_ => false,
}
}
-struct UsedVisitor {
- var: ast::Name, // var to look for
- used: bool, // has the var been used otherwise?
-}
-
-impl<'tcx> Visitor<'tcx> for UsedVisitor {
- fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
- if match_var(expr, self.var) {
- self.used = true;
- } else {
- walk_expr(self, expr);
- }
- }
-
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
- NestedVisitorMap::None
- }
-}
-
struct LocalUsedVisitor<'a, 'tcx> {
cx: &'a LateContext<'a, 'tcx>,
local: HirId,
}
impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if same_var(self.cx, expr, self.local) {
self.used = true;
}
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if_chain! {
// a range index op
}
self.prefer_mutable = old;
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for VarUsedAfterLoopVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if self.past_while_let {
if Some(self.def_id) == var_def_id(self.cx, expr) {
}
walk_expr(self, expr);
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if self.done {
return;
}
walk_expr(self, expr);
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
// Look for declarations of the variable
if let StmtKind::Local(ref local) = stmt.kind {
walk_expr(self, expr);
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::OnlyBodies(&self.cx.tcx.hir())
}
}
}
impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
+ type Map = Map<'tcx>;
+
fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
if stmt.hir_id == self.hir_id {
self.nesting = LookFurther;
walk_pat(self, pat)
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for HasBreakOrReturnVisitor {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if self.has_break_or_return {
return;
walk_expr(self, expr);
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}
}
impl<'a, 'tcx> Visitor<'tcx> for VarCollectorVisitor<'a, 'tcx> {
+ type Map = Map<'tcx>;
+
fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
match ex.kind {
ExprKind::Path(_) => self.insert_def_id(ex),
}
}
- fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
+ fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> {
NestedVisitorMap::None
}
}