-use crate::reexport::Name;
use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then};
use rustc_hir::intravisit::FnKind;
use rustc_hir::{
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
+use rustc_span::symbol::Symbol;
declare_clippy_lint! {
/// **What it does:** Checks for bindings that shadow other bindings already in
/// **Example:**
/// ```rust
/// # let x = 1;
- ///
/// // Bad
/// let x = &x;
///
/// names to bindings or introducing more scopes to contain the bindings.
///
/// **Known problems:** This lint, as the other shadowing related lints,
- /// currently only catches very simple patterns.
+ /// currently only catches very simple patterns. Note that
+ /// `allow`/`warn`/`deny`/`forbid` attributes only work on the function level
+ /// for this lint.
///
/// **Example:**
/// ```rust
check_expr(cx, &body.value, &mut bindings);
}
-fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Name, Span)>) {
+fn check_block<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'_>, bindings: &mut Vec<(Symbol, Span)>) {
let len = bindings.len();
for stmt in block.stmts {
match stmt.kind {
bindings.truncate(len);
}
-fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Name, Span)>) {
+fn check_local<'tcx>(cx: &LateContext<'tcx>, local: &'tcx Local<'_>, bindings: &mut Vec<(Symbol, Span)>) {
if in_external_macro(cx.sess(), local.span) {
return;
}
}
fn is_binding(cx: &LateContext<'_>, pat_id: HirId) -> bool {
- let var_ty = cx.tables().node_type_opt(pat_id);
- if let Some(var_ty) = var_ty {
- match var_ty.kind {
- ty::Adt(..) => false,
- _ => true,
- }
- } else {
- false
- }
+ let var_ty = cx.typeck_results().node_type_opt(pat_id);
+ var_ty.map_or(false, |var_ty| !matches!(var_ty.kind(), ty::Adt(..)))
}
fn check_pat<'tcx>(
pat: &'tcx Pat<'_>,
init: Option<&'tcx Expr<'_>>,
span: Span,
- bindings: &mut Vec<(Name, Span)>,
+ bindings: &mut Vec<(Symbol, Span)>,
) {
// TODO: match more stuff / destructuring
match pat.kind {
fn lint_shadow<'tcx>(
cx: &LateContext<'tcx>,
- name: Name,
+ name: Symbol,
span: Span,
pattern_span: Span,
init: Option<&'tcx Expr<'_>>,
cx,
SHADOW_UNRELATED,
pattern_span,
- &format!(
- "`{}` is shadowed by `{}`",
- snippet(cx, pattern_span, "_"),
- snippet(cx, expr.span, "..")
- ),
+ &format!("`{}` is being shadowed", snippet(cx, pattern_span, "_")),
|diag| {
diag.span_note(expr.span, "initialization happens here");
diag.span_note(prev_span, "previous binding is here");
}
}
-fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Name, Span)>) {
+fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, bindings: &mut Vec<(Symbol, Span)>) {
if in_external_macro(cx.sess(), expr.span) {
return;
}
| ExprKind::Field(ref e, _)
| ExprKind::AddrOf(_, _, ref e)
| ExprKind::Box(ref e) => check_expr(cx, e, bindings),
- ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, _, _) => check_block(cx, block, bindings),
+ ExprKind::Block(ref block, _) | ExprKind::Loop(ref block, ..) => check_block(cx, block, bindings),
// ExprKind::Call
// ExprKind::MethodCall
ExprKind::Array(v) | ExprKind::Tup(v) => {
check_expr(cx, e, bindings)
}
},
+ ExprKind::If(ref cond, ref then, ref otherwise) => {
+ check_expr(cx, cond, bindings);
+ check_expr(cx, &**then, bindings);
+ if let Some(ref o) = *otherwise {
+ check_expr(cx, o, bindings);
+ }
+ },
ExprKind::Match(ref init, arms, _) => {
check_expr(cx, init, bindings);
let len = bindings.len();
if let Some(ref guard) = arm.guard {
match guard {
Guard::If(if_expr) => check_expr(cx, if_expr, bindings),
+ Guard::IfLet(guard_pat, guard_expr) => {
+ check_pat(cx, guard_pat, Some(*guard_expr), guard_pat.span, bindings);
+ check_expr(cx, guard_expr, bindings);
+ },
}
}
check_expr(cx, &arm.body, bindings);
}
}
-fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Name, Span)>) {
+fn check_ty<'tcx>(cx: &LateContext<'tcx>, ty: &'tcx Ty<'_>, bindings: &mut Vec<(Symbol, Span)>) {
match ty.kind {
TyKind::Slice(ref sty) => check_ty(cx, sty, bindings),
TyKind::Array(ref fty, ref anon_const) => {
}
}
-fn is_self_shadow(name: Name, expr: &Expr<'_>) -> bool {
+fn is_self_shadow(name: Symbol, expr: &Expr<'_>) -> bool {
match expr.kind {
ExprKind::Box(ref inner) | ExprKind::AddrOf(_, _, ref inner) => is_self_shadow(name, inner),
ExprKind::Block(ref block, _) => {
block.stmts.is_empty() && block.expr.as_ref().map_or(false, |e| is_self_shadow(name, e))
},
- ExprKind::Unary(op, ref inner) => (UnOp::UnDeref == op) && is_self_shadow(name, inner),
+ ExprKind::Unary(op, ref inner) => (UnOp::Deref == op) && is_self_shadow(name, inner),
ExprKind::Path(QPath::Resolved(_, ref path)) => path_eq_name(name, path),
_ => false,
}
}
-fn path_eq_name(name: Name, path: &Path<'_>) -> bool {
- !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.as_str() == name.as_str()
+fn path_eq_name(name: Symbol, path: &Path<'_>) -> bool {
+ !path.is_global() && path.segments.len() == 1 && path.segments[0].ident.name == name
}