From 621e76d2528e0872926305686041f6a935028db8 Mon Sep 17 00:00:00 2001
From: Samuel Tardieu <sam@rfc1149.net>
Date: Mon, 31 Jul 2023 21:57:31 +0200
Subject: [PATCH] [new_without_default]: include `where` clauses in suggestion

Fix #11267
---
 clippy_lints/src/new_without_default.rs | 19 ++++++++++++++++---
 tests/ui/new_without_default.rs         | 18 ++++++++++++++++++
 tests/ui/new_without_default.stderr     | 22 +++++++++++++++++++++-
 3 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs
index cf7cd671dca..6900502e8e1 100644
--- a/clippy_lints/src/new_without_default.rs
+++ b/clippy_lints/src/new_without_default.rs
@@ -130,6 +130,11 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                 }
 
                                 let generics_sugg = snippet(cx, generics.span, "");
+                                let where_clause_sugg = if generics.has_where_clause_predicates {
+                                    format!("\n{}\n", snippet(cx, generics.where_clause_span, ""))
+                                } else {
+                                    String::new()
+                                };
                                 let self_ty_fmt = self_ty.to_string();
                                 let self_type_snip = snippet(cx, impl_self_ty.span, &self_ty_fmt);
                                 span_lint_hir_and_then(
@@ -145,7 +150,11 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
                                             cx,
                                             item.span,
                                             "try adding this",
-                                            &create_new_without_default_suggest_msg(&self_type_snip, &generics_sugg),
+                                            &create_new_without_default_suggest_msg(
+                                                &self_type_snip,
+                                                &generics_sugg,
+                                                &where_clause_sugg
+                                            ),
                                             Applicability::MaybeIncorrect,
                                         );
                                     },
@@ -159,10 +168,14 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
     }
 }
 
-fn create_new_without_default_suggest_msg(self_type_snip: &str, generics_sugg: &str) -> String {
+fn create_new_without_default_suggest_msg(
+    self_type_snip: &str,
+    generics_sugg: &str,
+    where_clause_sugg: &str,
+) -> String {
     #[rustfmt::skip]
     format!(
-"impl{generics_sugg} Default for {self_type_snip} {{
+"impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
     fn default() -> Self {{
         Self::new()
     }}
diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs
index 7dbfa002d3f..bbd7a51d6b9 100644
--- a/tests/ui/new_without_default.rs
+++ b/tests/ui/new_without_default.rs
@@ -230,3 +230,21 @@ impl IgnoreLifetimeNew {
         Self
     }
 }
+
+// From issue #11267
+
+pub struct MyStruct<K, V>
+where
+    K: std::hash::Hash + Eq + PartialEq,
+{
+    _kv: Option<(K, V)>,
+}
+
+impl<K, V> MyStruct<K, V>
+where
+    K: std::hash::Hash + Eq + PartialEq,
+{
+    pub fn new() -> Self {
+        Self { _kv: None }
+    }
+}
diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr
index 7641035d2a6..61973abcde8 100644
--- a/tests/ui/new_without_default.stderr
+++ b/tests/ui/new_without_default.stderr
@@ -120,5 +120,25 @@ LL +
 LL ~     impl<T> Foo<T> {
    |
 
-error: aborting due to 7 previous errors
+error: you should consider adding a `Default` implementation for `MyStruct<K, V>`
+  --> $DIR/new_without_default.rs:247:5
+   |
+LL | /     pub fn new() -> Self {
+LL | |         Self { _kv: None }
+LL | |     }
+   | |_____^
+   |
+help: try adding this
+   |
+LL + impl<K, V> Default for MyStruct<K, V>
+LL + where
+LL +     K: std::hash::Hash + Eq + PartialEq,
+LL +  {
+LL +     fn default() -> Self {
+LL +         Self::new()
+LL +     }
+LL + }
+   |
+
+error: aborting due to 8 previous errors