From c209fc9349ff750dc983ecfe23d8e0bb74f002df Mon Sep 17 00:00:00 2001
From: Jane Lusby <jlusby42@gmail.com>
Date: Fri, 5 Oct 2018 09:06:05 -0700
Subject: [PATCH 1/6] Fix string_lit_as_bytes lint for macros

Prior to this change, string_lit_as_bytes would trigger for constructs
like `include_str!("filename").as_bytes()` and would recommend fixing it
by rewriting as `binclude_str!("filename")`.

This change updates the lint to act as an EarlyLintPass lint. It then
differentiates between string literals and macros that have bytes
yielding alternatives.

Closes #3205
---
 clippy_lints/src/strings.rs | 39 +++++++++++++++++++++++++++++--------
 tests/ui/strings.rs         |  8 +++++---
 tests/ui/strings.stderr     | 12 ------------
 3 files changed, 36 insertions(+), 23 deletions(-)

diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index f4798842205..9b6478fb9cd 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -92,7 +92,14 @@ impl LintPass for StringAdd {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringAdd {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
-        if let ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) = e.node {
+        if let ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Add, ..
+            },
+            ref left,
+            _,
+        ) = e.node
+        {
             if is_string(cx, left) {
                 if !is_allowed(cx, STRING_ADD_ASSIGN, e.id) {
                     let parent = get_parent_expr(cx, e);
@@ -132,13 +139,15 @@ fn is_string(cx: &LateContext<'_, '_>, e: &Expr) -> bool {
 
 fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool {
     match src.node {
-        ExprKind::Binary(Spanned { node: BinOpKind::Add, .. }, ref left, _) => SpanlessEq::new(cx).eq_expr(target, left),
+        ExprKind::Binary(
+            Spanned {
+                node: BinOpKind::Add, ..
+            },
+            ref left,
+            _,
+        ) => SpanlessEq::new(cx).eq_expr(target, left),
         ExprKind::Block(ref block, _) => {
-            block.stmts.is_empty()
-                && block
-                    .expr
-                    .as_ref()
-                    .map_or(false, |expr| is_add(cx, expr, target))
+            block.stmts.is_empty() && block.expr.as_ref().map_or(false, |expr| is_add(cx, expr, target))
         },
         _ => false,
     }
@@ -162,7 +171,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
             if path.ident.name == "as_bytes" {
                 if let ExprKind::Lit(ref lit) = args[0].node {
                     if let LitKind::Str(ref lit_content, _) = lit.node {
-                        if lit_content.as_str().chars().all(|c| c.is_ascii()) && !in_macro(args[0].span) {
+                        let callsite = snippet(cx, args[0].span.source_callsite(), "");
+                        let expanded = format!("\"{}\"", lit_content.as_str());
+                        if callsite.starts_with("include_str!") {
+                            span_lint_and_sugg(
+                                cx,
+                                STRING_LIT_AS_BYTES,
+                                e.span,
+                                "calling `as_bytes()` on `include_str!(..)`",
+                                "consider using `include_bytes!(..)` instead",
+                                snippet(cx, args[0].span, r#""foo""#).replacen("include_str", "include_bytes", 1),
+                            );
+                        } else if callsite == expanded
+                            && lit_content.as_str().chars().all(|c| c.is_ascii())
+                            && !in_macro(args[0].span)
+                        {
                             span_lint_and_sugg(
                                 cx,
                                 STRING_LIT_AS_BYTES,
diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs
index 7bc4e6515f6..6693776a961 100644
--- a/tests/ui/strings.rs
+++ b/tests/ui/strings.rs
@@ -10,10 +10,10 @@
 
 
 
-
 #[warn(clippy::string_add)]
 #[allow(clippy::string_add_assign)]
-fn add_only() { // ignores assignment distinction
+fn add_only() {
+    // ignores assignment distinction
     let mut x = "".to_owned();
 
     for _ in 1..3 {
@@ -63,6 +63,8 @@ fn str_lit_as_bytes() {
     let ubs = "☃".as_bytes();
 
     let strify = stringify!(foobar).as_bytes();
+
+    let includestr = include_str!("entry.rs").as_bytes();
 }
 
 fn main() {
@@ -72,6 +74,6 @@ fn main() {
 
     // the add is only caught for `String`
     let mut x = 1;
-    ; x = x + 1;
+;    x = x + 1;
     assert_eq!(2, x);
 }
diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr
index bcdf91568d2..8a93733732e 100644
--- a/tests/ui/strings.stderr
+++ b/tests/ui/strings.stderr
@@ -60,17 +60,5 @@ error: calling `as_bytes()` on a string literal
    |
    = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings`
 
-error: calling `as_bytes()` on a string literal
-  --> $DIR/strings.rs:65:18
-   |
-65 |     let strify = stringify!(foobar).as_bytes();
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `bstringify!(foobar)`
-
-error: manual implementation of an assign operation
-  --> $DIR/strings.rs:75:7
-   |
-75 |     ; x = x + 1;
-   |       ^^^^^^^^^ help: replace it with: `x += 1`
-
 error: aborting due to 11 previous errors
 

From f9020bb2dded44e97fd997ab71ab4edf6d88033b Mon Sep 17 00:00:00 2001
From: Jane Lusby <jlusby42@gmail.com>
Date: Wed, 24 Oct 2018 11:49:39 -0400
Subject: [PATCH 2/6] fix: extra semicolon, only create callsite once

---
 clippy_lints/src/strings.rs | 2 +-
 tests/ui/strings.rs         | 5 ++++-
 tests/ui/strings.stderr     | 2 --
 3 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 9b6478fb9cd..fe3d461ab43 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -171,7 +171,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
             if path.ident.name == "as_bytes" {
                 if let ExprKind::Lit(ref lit) = args[0].node {
                     if let LitKind::Str(ref lit_content, _) = lit.node {
-                        let callsite = snippet(cx, args[0].span.source_callsite(), "");
+                        let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#);
                         let expanded = format!("\"{}\"", lit_content.as_str());
                         if callsite.starts_with("include_str!") {
                             span_lint_and_sugg(
diff --git a/tests/ui/strings.rs b/tests/ui/strings.rs
index 6693776a961..d2062b356dc 100644
--- a/tests/ui/strings.rs
+++ b/tests/ui/strings.rs
@@ -59,6 +59,8 @@ fn both() {
 fn str_lit_as_bytes() {
     let bs = "hello there".as_bytes();
 
+    let bs = r###"raw string with three ### in it and some " ""###.as_bytes();
+
     // no warning, because this cannot be written as a byte string literal:
     let ubs = "☃".as_bytes();
 
@@ -67,6 +69,7 @@ fn str_lit_as_bytes() {
     let includestr = include_str!("entry.rs").as_bytes();
 }
 
+#[allow(clippy::assign_op_pattern)]
 fn main() {
     add_only();
     add_assign_only();
@@ -74,6 +77,6 @@ fn main() {
 
     // the add is only caught for `String`
     let mut x = 1;
-;    x = x + 1;
+    x = x + 1;
     assert_eq!(2, x);
 }
diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr
index 8a93733732e..2496270ba0d 100644
--- a/tests/ui/strings.stderr
+++ b/tests/ui/strings.stderr
@@ -60,5 +60,3 @@ error: calling `as_bytes()` on a string literal
    |
    = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings`
 
-error: aborting due to 11 previous errors
-

From 19ac2e94c6cb12ae4f9fb410f165e2aa5309e124 Mon Sep 17 00:00:00 2001
From: Jane Lusby <jlusby42@gmail.com>
Date: Fri, 26 Oct 2018 09:10:20 -0700
Subject: [PATCH 3/6] fix: correctly reconstruct raw strings

---
 clippy_lints/src/strings.rs | 12 ++++++++----
 tests/ui/strings.stderr     | 14 ++++++++++++++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index fe3d461ab43..e07b1649a46 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -7,7 +7,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use crate::rustc::hir::*;
 use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
 use crate::rustc::{declare_tool_lint, lint_array};
@@ -164,15 +163,20 @@ impl LintPass for StringLitAsBytes {
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
-        use crate::syntax::ast::LitKind;
+        use crate::syntax::ast::{LitKind, StrStyle};
         use crate::utils::{in_macro, snippet};
 
         if let ExprKind::MethodCall(ref path, _, ref args) = e.node {
             if path.ident.name == "as_bytes" {
                 if let ExprKind::Lit(ref lit) = args[0].node {
-                    if let LitKind::Str(ref lit_content, _) = lit.node {
+                    if let LitKind::Str(ref lit_content, style) = lit.node {
                         let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#);
-                        let expanded = format!("\"{}\"", lit_content.as_str());
+                        let expanded = if let StrStyle::Raw(n) = style {
+                            let term = (0..n).map(|_| '#').collect::<String>();
+                            format!("r{0}\"{1}\"{0}", term, lit_content.as_str())
+                        } else {
+                            format!("\"{}\"", lit_content.as_str())
+                        };
                         if callsite.starts_with("include_str!") {
                             span_lint_and_sugg(
                                 cx,
diff --git a/tests/ui/strings.stderr b/tests/ui/strings.stderr
index 2496270ba0d..21115d8e97e 100644
--- a/tests/ui/strings.stderr
+++ b/tests/ui/strings.stderr
@@ -60,3 +60,17 @@ error: calling `as_bytes()` on a string literal
    |
    = note: `-D clippy::string-lit-as-bytes` implied by `-D warnings`
 
+error: calling `as_bytes()` on a string literal
+  --> $DIR/strings.rs:62:14
+   |
+62 |     let bs = r###"raw string with three ### in it and some " ""###.as_bytes();
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###`
+
+error: calling `as_bytes()` on `include_str!(..)`
+  --> $DIR/strings.rs:69:22
+   |
+69 |     let includestr = include_str!("entry.rs").as_bytes();
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")`
+
+error: aborting due to 11 previous errors
+

From aa7bcb9074f3a7235e43d1da910d80248e53357d Mon Sep 17 00:00:00 2001
From: Philipp Hansch <dev@phansch.net>
Date: Sat, 27 Oct 2018 11:01:27 +0200
Subject: [PATCH 4/6] Don't expand macro in identity_conversion suggestion

---
 clippy_lints/src/identity_conversion.rs | 5 +++--
 clippy_lints/src/utils/mod.rs           | 6 ++++++
 tests/ui/identity_conversion.rs         | 1 +
 tests/ui/identity_conversion.stderr     | 8 +++++++-
 4 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/clippy_lints/src/identity_conversion.rs b/clippy_lints/src/identity_conversion.rs
index e9761616696..00ce58f00b0 100644
--- a/clippy_lints/src/identity_conversion.rs
+++ b/clippy_lints/src/identity_conversion.rs
@@ -12,7 +12,7 @@ use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
 use crate::rustc::{declare_tool_lint, lint_array};
 use crate::rustc::hir::*;
 use crate::syntax::ast::NodeId;
-use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, span_lint_and_then};
+use crate::utils::{in_macro, match_def_path, match_trait_method, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_then};
 use crate::utils::{opt_def_id, paths, resolve_node};
 use crate::rustc_errors::Applicability;
 
@@ -72,7 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
                     let a = cx.tables.expr_ty(e);
                     let b = cx.tables.expr_ty(&args[0]);
                     if same_tys(cx, a, b) {
-                        let sugg = snippet(cx, args[0].span, "<expr>").into_owned();
+                        let sugg = snippet_with_macro_callsite(cx, args[0].span, "<expr>").to_string();
+
                         span_lint_and_then(cx, IDENTITY_CONVERSION, e.span, "identical conversion", |db| {
                             db.span_suggestion_with_applicability(
                                 e.span,
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 1a8db837f32..5ff246630e0 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -362,6 +362,12 @@ pub fn snippet<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str)
     snippet_opt(cx, span).map_or_else(|| Cow::Borrowed(default), From::from)
 }
 
+/// Same as `snippet`, but should only be used when it's clear that the input span is
+/// not a macro argument.
+pub fn snippet_with_macro_callsite<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> {
+    snippet(cx, span.source_callsite(), default)
+}
+
 /// Convert a span to a code snippet. Returns `None` if not available.
 pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option<String> {
     cx.sess().source_map().span_to_snippet(span).ok()
diff --git a/tests/ui/identity_conversion.rs b/tests/ui/identity_conversion.rs
index 9384c9eb206..b5cb92c6d5a 100644
--- a/tests/ui/identity_conversion.rs
+++ b/tests/ui/identity_conversion.rs
@@ -53,4 +53,5 @@ fn main() {
     let _ = String::from(format!("A: {:04}", 123));
     let _ = "".lines().into_iter();
     let _ = vec![1, 2, 3].into_iter().into_iter();
+    let _: String = format!("Hello {}", "world").into();
 }
diff --git a/tests/ui/identity_conversion.stderr b/tests/ui/identity_conversion.stderr
index 2ac74191931..15bef8b125e 100644
--- a/tests/ui/identity_conversion.stderr
+++ b/tests/ui/identity_conversion.stderr
@@ -58,5 +58,11 @@ error: identical conversion
 55 |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
-error: aborting due to 9 previous errors
+error: identical conversion
+  --> $DIR/identity_conversion.rs:56:21
+   |
+56 |     let _: String = format!("Hello {}", "world").into();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
+
+error: aborting due to 10 previous errors
 

From af1548f58f2a9a356a7c122f2fba25c816492a91 Mon Sep 17 00:00:00 2001
From: Philipp Hansch <dev@phansch.net>
Date: Sat, 27 Oct 2018 14:45:02 +0200
Subject: [PATCH 5/6] Don't expand macro in single_match suggestion

---
 clippy_lints/src/matches.rs   |  3 +-
 clippy_lints/src/utils/mod.rs |  5 +++-
 tests/ui/matches.stderr       |  2 +-
 tests/ui/single_match.rs      |  9 ++++++
 tests/ui/single_match.stderr  | 52 +++++++++++++++++++++--------------
 5 files changed, 48 insertions(+), 23 deletions(-)

diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index e46615f4da2..4a704c3d52e 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -19,7 +19,8 @@ use crate::syntax::ast::LitKind;
 use crate::syntax::source_map::Span;
 use crate::utils::paths;
 use crate::utils::{expr_block, is_allowed, is_expn_of, match_qpath, match_type, multispan_sugg,
-            remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty};
+            remove_blocks, snippet, span_lint_and_sugg, span_lint_and_then,
+            span_note_and_lint, walk_ptrs_ty};
 use crate::utils::sugg::Sugg;
 use crate::consts::{constant, Constant};
 use crate::rustc_errors::Applicability;
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 5ff246630e0..72a6bda26c3 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -406,7 +406,10 @@ pub fn expr_block<'a, 'b, T: LintContext<'b>>(
 ) -> Cow<'a, str> {
     let code = snippet_block(cx, expr.span, default);
     let string = option.unwrap_or_default();
-    if let ExprKind::Block(_, _) = expr.node {
+    if in_macro(expr.span) {
+        Cow::Owned(format!("{{ {} }}", snippet_with_macro_callsite(cx, expr.span, default)))
+    }
+    else if let ExprKind::Block(_, _) = expr.node {
         Cow::Owned(format!("{}{}", code, string))
     } else if string.is_empty() {
         Cow::Owned(format!("{{ {} }}", code))
diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr
index bed903faf1a..b5f1f2ab0e7 100644
--- a/tests/ui/matches.stderr
+++ b/tests/ui/matches.stderr
@@ -33,7 +33,7 @@ error: you seem to be trying to use match for destructuring a single pattern. Co
 51 | |         &(v, 1) => println!("{}", v),
 52 | |         _ => println!("none"),
 53 | |     }
-   | |_____^ help: try this: `if let &(v, 1) = tup { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; } else { $ crate :: io :: _print ( format_args_nl ! ( $ ( $ arg ) * ) ) ; }`
+   | |_____^ help: try this: `if let &(v, 1) = tup { println!("{}", v) } else { println!("none") }`
 
 error: you don't need to add `&` to all patterns
   --> $DIR/matches.rs:50:5
diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs
index 5c7cae249b4..dca68e179e7 100644
--- a/tests/ui/single_match.rs
+++ b/tests/ui/single_match.rs
@@ -23,6 +23,15 @@ fn single_match(){
         _ => ()
     };
 
+    let x = Some(1u8);
+    match x {
+        // Note the missing block braces.
+        // We suggest `if let Some(y) = x { .. }` because the macro
+        // is expanded before we can do anything.
+        Some(y) => println!("{:?}", y),
+        _ => ()
+    }
+
     let z = (1u8,1u8);
     match z {
         (2...3, 7...9) => dummy(),
diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr
index 74448391ca5..df614ad201d 100644
--- a/tests/ui/single_match.stderr
+++ b/tests/ui/single_match.stderr
@@ -12,38 +12,50 @@ error: you seem to be trying to use match for destructuring a single pattern. Co
 error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
   --> $DIR/single_match.rs:27:5
    |
-27 | /     match z {
-28 | |         (2...3, 7...9) => dummy(),
-29 | |         _ => {}
-30 | |     };
+27 | /     match x {
+28 | |         // Note the missing block braces.
+29 | |         // We suggest `if let Some(y) = x { .. }` because the macro
+30 | |         // is expanded before we can do anything.
+31 | |         Some(y) => println!("{:?}", y),
+32 | |         _ => ()
+33 | |     }
+   | |_____^ help: try this: `if let Some(y) = x { println!("{:?}", y) }`
+
+error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
+  --> $DIR/single_match.rs:36:5
+   |
+36 | /     match z {
+37 | |         (2...3, 7...9) => dummy(),
+38 | |         _ => {}
+39 | |     };
    | |_____^ help: try this: `if let (2...3, 7...9) = z { dummy() }`
 
 error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:53:5
+  --> $DIR/single_match.rs:62:5
    |
-53 | /     match x {
-54 | |         Some(y) => dummy(),
-55 | |         None => ()
-56 | |     };
+62 | /     match x {
+63 | |         Some(y) => dummy(),
+64 | |         None => ()
+65 | |     };
    | |_____^ help: try this: `if let Some(y) = x { dummy() }`
 
 error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:58:5
+  --> $DIR/single_match.rs:67:5
    |
-58 | /     match y {
-59 | |         Ok(y) => dummy(),
-60 | |         Err(..) => ()
-61 | |     };
+67 | /     match y {
+68 | |         Ok(y) => dummy(),
+69 | |         Err(..) => ()
+70 | |     };
    | |_____^ help: try this: `if let Ok(y) = y { dummy() }`
 
 error: you seem to be trying to use match for destructuring a single pattern. Consider using `if let`
-  --> $DIR/single_match.rs:65:5
+  --> $DIR/single_match.rs:74:5
    |
-65 | /     match c {
-66 | |         Cow::Borrowed(..) => dummy(),
-67 | |         Cow::Owned(..) => (),
-68 | |     };
+74 | /     match c {
+75 | |         Cow::Borrowed(..) => dummy(),
+76 | |         Cow::Owned(..) => (),
+77 | |     };
    | |_____^ help: try this: `if let Cow::Borrowed(..) = c { dummy() }`
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 

From 840e50e97f023c2d0bfeb0222d094fa407f12f2f Mon Sep 17 00:00:00 2001
From: Philipp Hansch <dev@phansch.net>
Date: Sat, 27 Oct 2018 15:37:56 +0200
Subject: [PATCH 6/6] Don't expand macro in or_fun_call suggestion

---
 clippy_lints/src/methods/mod.rs | 8 ++++----
 tests/ui/methods.stderr         | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs
index 01f97264d0b..8d0cd32e23b 100644
--- a/clippy_lints/src/methods/mod.rs
+++ b/clippy_lints/src/methods/mod.rs
@@ -21,7 +21,7 @@ use crate::utils::sugg;
 use crate::utils::{
     get_arg_name, get_trait_def_id, implements_trait, in_macro, is_copy, is_expn_of, is_self, is_self_ty,
     iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method, match_type,
-    match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, span_lint,
+    match_var, method_chain_args, remove_blocks, return_ty, same_tys, single_segment_path, snippet, snippet_with_macro_callsite, span_lint,
     span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth, SpanlessEq,
 };
 use if_chain::if_chain;
@@ -1062,9 +1062,9 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
         }
 
         let sugg: Cow<'_, _> = match (fn_has_arguments, !or_has_args) {
-            (true, _) => format!("|_| {}", snippet(cx, arg.span, "..")).into(),
-            (false, false) => format!("|| {}", snippet(cx, arg.span, "..")).into(),
-            (false, true) => snippet(cx, fun_span, ".."),
+            (true, _) => format!("|_| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(),
+            (false, false) => format!("|| {}", snippet_with_macro_callsite(cx, arg.span, "..")).into(),
+            (false, true) => snippet_with_macro_callsite(cx, fun_span, ".."),
         };
         let span_replace_word = method_span.with_hi(span.hi());
         span_lint_and_sugg(
diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr
index 307814824ea..896b15481bb 100644
--- a/tests/ui/methods.stderr
+++ b/tests/ui/methods.stderr
@@ -297,7 +297,7 @@ error: use of `unwrap_or` followed by a function call
    --> $DIR/methods.rs:339:14
     |
 339 |     with_vec.unwrap_or(vec![]);
-    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))`
+    |              ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])`
 
 error: use of `unwrap_or` followed by a function call
    --> $DIR/methods.rs:344:21