about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLzu Tao <taolzu@gmail.com>2019-09-26 08:46:51 +0700
committerLzu Tao <taolzu@gmail.com>2019-09-26 08:46:51 +0700
commit08ce6bc6d9532191e59a49786811a0735ea35f5a (patch)
treecce0481afc9b5ab9cd67c0c5cfc31bd3004e3446
parent3b9e5dfda565224e6f007f379ca1cea4623422d9 (diff)
downloadrust-08ce6bc6d9532191e59a49786811a0735ea35f5a.tar.gz
rust-08ce6bc6d9532191e59a49786811a0735ea35f5a.zip
Fix macro expansion in toplevel_ref_arg lint
-rw-r--r--clippy_lints/src/misc.rs35
-rw-r--r--tests/ui/toplevel_ref_arg.fixed2
-rw-r--r--tests/ui/toplevel_ref_arg.stderr8
3 files changed, 29 insertions, 16 deletions
diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs
index 38fdabaaf7a..980c4caf2c5 100644
--- a/clippy_lints/src/misc.rs
+++ b/clippy_lints/src/misc.rs
@@ -261,40 +261,45 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
         }
     }
 
-    fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, s: &'tcx Stmt) {
+    fn check_stmt(&mut self, cx: &LateContext<'a, 'tcx>, stmt: &'tcx Stmt) {
         if_chain! {
-            if let StmtKind::Local(ref l) = s.node;
-            if let PatKind::Binding(an, .., i, None) = l.pat.node;
-            if let Some(ref init) = l.init;
+            if let StmtKind::Local(ref local) = stmt.node;
+            if let PatKind::Binding(an, .., name, None) = local.pat.node;
+            if let Some(ref init) = local.init;
             then {
                 if an == BindingAnnotation::Ref || an == BindingAnnotation::RefMut {
-                    let sugg_init = Sugg::hir(cx, init, "..");
-                    let (mutopt,initref) = if an == BindingAnnotation::RefMut {
+                    let sugg_init = if init.span.from_expansion() {
+                        Sugg::hir_with_macro_callsite(cx, init, "..")
+                    } else {
+                        Sugg::hir(cx, init, "..")
+                    };
+                    let (mutopt, initref) = if an == BindingAnnotation::RefMut {
                         ("mut ", sugg_init.mut_addr())
                     } else {
                         ("", sugg_init.addr())
                     };
-                    let tyopt = if let Some(ref ty) = l.ty {
+                    let tyopt = if let Some(ref ty) = local.ty {
                         format!(": &{mutopt}{ty}", mutopt=mutopt, ty=snippet(cx, ty.span, "_"))
                     } else {
                         String::new()
                     };
-                    span_lint_hir_and_then(cx,
+                    span_lint_hir_and_then(
+                        cx,
                         TOPLEVEL_REF_ARG,
                         init.hir_id,
-                        l.pat.span,
+                        local.pat.span,
                         "`ref` on an entire `let` pattern is discouraged, take a reference with `&` instead",
                         |db| {
                             db.span_suggestion(
-                                s.span,
+                                stmt.span,
                                 "try",
                                 format!(
                                     "let {name}{tyopt} = {initref};",
-                                    name=snippet(cx, i.span, "_"),
+                                    name=snippet(cx, name.span, "_"),
                                     tyopt=tyopt,
                                     initref=initref,
                                 ),
-                                Applicability::MachineApplicable, // snippet
+                                Applicability::MachineApplicable,
                             );
                         }
                     );
@@ -302,19 +307,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints {
             }
         };
         if_chain! {
-            if let StmtKind::Semi(ref expr) = s.node;
+            if let StmtKind::Semi(ref expr) = stmt.node;
             if let ExprKind::Binary(ref binop, ref a, ref b) = expr.node;
             if binop.node == BinOpKind::And || binop.node == BinOpKind::Or;
             if let Some(sugg) = Sugg::hir_opt(cx, a);
             then {
                 span_lint_and_then(cx,
                     SHORT_CIRCUIT_STATEMENT,
-                    s.span,
+                    stmt.span,
                     "boolean short circuit operator in statement may be clearer using an explicit test",
                     |db| {
                         let sugg = if binop.node == BinOpKind::Or { !sugg } else { sugg };
                         db.span_suggestion(
-                            s.span,
+                            stmt.span,
                             "replace it with",
                             format!(
                                 "if {} {{ {}; }}",
diff --git a/tests/ui/toplevel_ref_arg.fixed b/tests/ui/toplevel_ref_arg.fixed
index 8a4bf530173..df3c15ed59e 100644
--- a/tests/ui/toplevel_ref_arg.fixed
+++ b/tests/ui/toplevel_ref_arg.fixed
@@ -19,6 +19,8 @@ fn main() {
     let (ref x, _) = (1, 2); // ok, not top level
     println!("The answer is {}.", x);
 
+    let x = &vec![1, 2, 3];
+
     // Make sure that allowing the lint works
     #[allow(clippy::toplevel_ref_arg)]
     let ref mut x = 1_234_543;
diff --git a/tests/ui/toplevel_ref_arg.stderr b/tests/ui/toplevel_ref_arg.stderr
index de80a9614de..882e9e558b2 100644
--- a/tests/ui/toplevel_ref_arg.stderr
+++ b/tests/ui/toplevel_ref_arg.stderr
@@ -24,5 +24,11 @@ error: `ref` on an entire `let` pattern is discouraged, take a reference with `&
 LL |     let ref mut z = 1 + 2;
    |     ----^^^^^^^^^--------- help: try: `let z = &mut (1 + 2);`
 
-error: aborting due to 4 previous errors
+error: `ref` on an entire `let` pattern is discouraged, take a reference with `&` instead
+  --> $DIR/toplevel_ref_arg.rs:22:9
+   |
+LL |     let ref x = vec![1, 2, 3];
+   |     ----^^^^^----------------- help: try: `let x = &vec![1, 2, 3];`
+
+error: aborting due to 5 previous errors