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] 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