1 // Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution.
4 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7 // option. This file may not be copied, modified, or distributed
8 // except according to those terms.
10 use crate::rustc::hir;
11 use crate::rustc::hir::intravisit;
12 use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
14 use crate::rustc::{declare_tool_lint, lint_array};
15 use crate::utils::{higher, span_lint};
17 /// **What it does:** Checks for instances of `mut mut` references.
19 /// **Why is this bad?** Multiple `mut`s don't add anything meaningful to the
20 /// source. This is either a copy'n'paste error, or it shows a fundamental
21 /// misunderstanding of references.
23 /// **Known problems:** None.
27 /// let x = &mut &mut y;
29 declare_clippy_lint! {
32 "usage of double-mut refs, e.g. `&mut &mut ...`"
35 #[derive(Copy, Clone)]
38 impl LintPass for MutMut {
39 fn get_lints(&self) -> LintArray {
44 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutMut {
45 fn check_block(&mut self, cx: &LateContext<'a, 'tcx>, block: &'tcx hir::Block) {
46 intravisit::walk_block(&mut MutVisitor { cx }, block);
49 fn check_ty(&mut self, cx: &LateContext<'a, 'tcx>, ty: &'tcx hir::Ty) {
50 use crate::rustc::hir::intravisit::Visitor;
52 MutVisitor { cx }.visit_ty(ty);
56 pub struct MutVisitor<'a, 'tcx: 'a> {
57 cx: &'a LateContext<'a, 'tcx>,
60 impl<'a, 'tcx> intravisit::Visitor<'tcx> for MutVisitor<'a, 'tcx> {
61 fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
62 if in_external_macro(self.cx.sess(), expr.span) {
66 if let Some((_, arg, body)) = higher::for_loop(expr) {
67 // A `for` loop lowers to:
69 // match ::std::iter::Iterator::next(&mut iter) {
72 // Let's ignore the generated code.
73 intravisit::walk_expr(self, arg);
74 intravisit::walk_expr(self, body);
75 } else if let hir::ExprKind::AddrOf(hir::MutMutable, ref e) = expr.node {
76 if let hir::ExprKind::AddrOf(hir::MutMutable, _) = e.node {
81 "generally you want to avoid `&mut &mut _` if possible",
83 } else if let ty::Ref(_, _, hir::MutMutable) = self.cx.tables.expr_ty(e).sty {
88 "this expression mutably borrows a mutable reference. Consider reborrowing",
94 fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
95 if let hir::TyKind::Rptr(
99 mutbl: hir::MutMutable,
103 if let hir::TyKind::Rptr(
106 mutbl: hir::MutMutable, ..
114 "generally you want to avoid `&mut &mut _` if possible",
119 intravisit::walk_ty(self, ty);
121 fn nested_visit_map<'this>(&'this mut self) -> intravisit::NestedVisitorMap<'this, 'tcx> {
122 intravisit::NestedVisitorMap::None