fix: new_without_default misses where clause in new

This commit is contained in:
Linshu Yang 2025-12-20 03:52:46 +00:00
parent 34fab5cd37
commit a2102a528c
4 changed files with 170 additions and 6 deletions

View file

@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_hir_and_then;
use clippy_utils::return_ty;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_applicability};
use clippy_utils::sugg::DiagExt;
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -57,6 +57,7 @@ pub struct NewWithoutDefault {
impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]);
impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
#[expect(clippy::too_many_lines)]
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
let hir::ItemKind::Impl(hir::Impl {
of_trait: None,
@ -140,10 +141,29 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
};
let generics_sugg = snippet_with_applicability(cx, generics.span, "", &mut app);
let where_clause_sugg = if generics.has_where_clause_predicates {
format!(
"\n{}\n",
snippet_with_applicability(cx, generics.where_clause_span, "", &mut app)
)
let where_clause_sugg =
snippet_with_applicability(cx, generics.where_clause_span, "", &mut app).to_string();
let mut where_clause_sugg = reindent_multiline(&where_clause_sugg, true, Some(4));
if impl_item.generics.has_where_clause_predicates {
if !where_clause_sugg.ends_with(',') {
where_clause_sugg.push(',');
}
let additional_where_preds =
snippet_with_applicability(cx, impl_item.generics.where_clause_span, "", &mut app);
let ident = indent_of(cx, generics.where_clause_span).unwrap_or(0);
// Remove the leading `where ` keyword
let additional_where_preds = additional_where_preds.trim_start_matches("where").trim_start();
where_clause_sugg.push('\n');
where_clause_sugg.extend(std::iter::repeat_n(' ', ident));
where_clause_sugg.push_str(additional_where_preds);
}
format!("\n{where_clause_sugg}\n")
} else if impl_item.generics.has_where_clause_predicates {
let where_clause_sugg =
snippet_with_applicability(cx, impl_item.generics.where_clause_span, "", &mut app);
let where_clause_sugg = reindent_multiline(&where_clause_sugg, true, Some(4));
format!("\n{}\n", where_clause_sugg.trim_start())
} else {
String::new()
};

View file

@ -409,3 +409,58 @@ mod issue15778 {
}
}
}
pub mod issue16255 {
use std::fmt::Display;
use std::marker::PhantomData;
pub struct Foo<T> {
marker: PhantomData<T>,
}
impl<T> Default for Foo<T>
where
T: Display,
T: Clone,
{
fn default() -> Self {
Self::new()
}
}
impl<T> Foo<T>
where
T: Display,
{
pub fn new() -> Self
//~^ new_without_default
where
T: Clone,
{
Self { marker: PhantomData }
}
}
pub struct Bar<T> {
marker: PhantomData<T>,
}
impl<T> Default for Bar<T>
where
T: Clone,
{
fn default() -> Self {
Self::new()
}
}
impl<T> Bar<T> {
pub fn new() -> Self
//~^ new_without_default
where
T: Clone,
{
Self { marker: PhantomData }
}
}
}

View file

@ -324,3 +324,39 @@ mod issue15778 {
}
}
}
pub mod issue16255 {
use std::fmt::Display;
use std::marker::PhantomData;
pub struct Foo<T> {
marker: PhantomData<T>,
}
impl<T> Foo<T>
where
T: Display,
{
pub fn new() -> Self
//~^ new_without_default
where
T: Clone,
{
Self { marker: PhantomData }
}
}
pub struct Bar<T> {
marker: PhantomData<T>,
}
impl<T> Bar<T> {
pub fn new() -> Self
//~^ new_without_default
where
T: Clone,
{
Self { marker: PhantomData }
}
}
}

View file

@ -250,5 +250,58 @@ LL + }
LL + }
|
error: aborting due to 13 previous errors
error: you should consider adding a `Default` implementation for `Foo<T>`
--> tests/ui/new_without_default.rs:340:9
|
LL | / pub fn new() -> Self
LL | |
LL | | where
LL | | T: Clone,
LL | | {
LL | | Self { marker: PhantomData }
LL | | }
| |_________^
|
help: try adding this
|
LL ~ impl<T> Default for Foo<T>
LL + where
LL + T: Display,
LL + T: Clone,
LL + {
LL + fn default() -> Self {
LL + Self::new()
LL + }
LL + }
LL +
LL ~ impl<T> Foo<T>
|
error: you should consider adding a `Default` implementation for `Bar<T>`
--> tests/ui/new_without_default.rs:354:9
|
LL | / pub fn new() -> Self
LL | |
LL | | where
LL | | T: Clone,
LL | | {
LL | | Self { marker: PhantomData }
LL | | }
| |_________^
|
help: try adding this
|
LL ~ impl<T> Default for Bar<T>
LL + where
LL + T: Clone,
LL + {
LL + fn default() -> Self {
LL + Self::new()
LL + }
LL + }
LL +
LL ~ impl<T> Bar<T> {
|
error: aborting due to 15 previous errors