/// ### Example
/// ```rust
/// # let x = 1;
- /// // Bad
/// let x = &x;
+ /// ```
///
- /// // Good
+ /// Use instead:
+ /// ```rust
+ /// # let x = 1;
/// let y = &x; // use different variable name
/// ```
#[clippy::version = "pre 1.29.0"]
/// # let y = 1;
/// # let z = 2;
/// let x = y;
- ///
- /// // Bad
/// let x = z; // shadows the earlier binding
+ /// ```
///
- /// // Good
+ /// Use instead:
+ /// ```rust
+ /// # let y = 1;
+ /// # let z = 2;
+ /// let x = y;
/// let w = z; // use different variable name
/// ```
#[clippy::version = "pre 1.29.0"]
#[derive(Default)]
pub(crate) struct Shadow {
- bindings: Vec<FxHashMap<Symbol, Vec<ItemLocalId>>>,
+ bindings: Vec<(FxHashMap<Symbol, Vec<ItemLocalId>>, LocalDefId)>,
}
impl_lint_pass!(Shadow => [SHADOW_SAME, SHADOW_REUSE, SHADOW_UNRELATED]);
impl<'tcx> LateLintPass<'tcx> for Shadow {
fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
- let (id, ident) = match pat.kind {
- PatKind::Binding(_, hir_id, ident, _) => (hir_id, ident),
- _ => return,
- };
+ let PatKind::Binding(_, id, ident, _) = pat.kind else { return };
if pat.span.desugaring_kind().is_some() {
return;
let HirId { owner, local_id } = id;
// get (or insert) the list of items for this owner and symbol
- let data = self.bindings.last_mut().unwrap();
+ let (ref mut data, scope_owner) = *self.bindings.last_mut().unwrap();
let items_with_name = data.entry(ident.name).or_default();
// check other bindings with the same name, most recently seen first
return;
}
- if is_shadow(cx, owner, prev, local_id) {
+ if is_shadow(cx, scope_owner, prev, local_id) {
let prev_hir_id = HirId { owner, local_id: prev };
lint_shadow(cx, pat, prev_hir_id, ident.span);
// only lint against the "nearest" shadowed binding
fn check_body(&mut self, cx: &LateContext<'_>, body: &Body<'_>) {
let hir = cx.tcx.hir();
- if !matches!(
- hir.body_owner_kind(hir.body_owner_def_id(body.id())),
- BodyOwnerKind::Closure
- ) {
- self.bindings.push(FxHashMap::default());
+ let owner_id = hir.body_owner_def_id(body.id());
+ if !matches!(hir.body_owner_kind(owner_id), BodyOwnerKind::Closure) {
+ self.bindings.push((FxHashMap::default(), owner_id));
}
}
fn is_shadow(cx: &LateContext<'_>, owner: LocalDefId, first: ItemLocalId, second: ItemLocalId) -> bool {
let scope_tree = cx.tcx.region_scope_tree(owner.to_def_id());
- let first_scope = scope_tree.var_scope(first);
- let second_scope = scope_tree.var_scope(second);
- scope_tree.is_subscope_of(second_scope, first_scope)
+ if let Some(first_scope) = scope_tree.var_scope(first) {
+ if let Some(second_scope) = scope_tree.var_scope(second) {
+ return scope_tree.is_subscope_of(second_scope, first_scope);
+ }
+ }
+
+ false
}
fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span) {