Skip to content

Commit 7a04ada

Browse files
committed
fix(new_without_default): if new has #[cfg], copy that onto impl Default
1 parent 93355f1 commit 7a04ada

File tree

4 files changed

+213
-6
lines changed

4 files changed

+213
-6
lines changed

clippy_lints/src/new_without_default.rs

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
7474
.filter_by_name_unhygienic(sym::new)
7575
{
7676
if let AssocKind::Fn { has_self: false, .. } = assoc_item.kind
77-
&& let impl_item = cx
78-
.tcx
79-
.hir_node_by_def_id(assoc_item.def_id.expect_local())
80-
.expect_impl_item()
77+
&& let assoc_item_hir_id = cx.tcx.local_def_id_to_hir_id(assoc_item.def_id.expect_local())
78+
&& let impl_item = cx.tcx.hir_node(assoc_item_hir_id).expect_impl_item()
8179
&& !impl_item.span.in_external_macro(cx.sess().source_map())
8280
&& let hir::ImplItemKind::Fn(ref sig, _) = impl_item.kind
8381
&& let id = impl_item.owner_id
@@ -120,6 +118,26 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
120118
}
121119

122120
let mut app = Applicability::MachineApplicable;
121+
let attrs_sugg = {
122+
let mut sugg = String::new();
123+
for attr in cx.tcx.hir_attrs(assoc_item_hir_id) {
124+
if !attr.has_name(sym::cfg_trace) {
125+
// This might be some other attribute that the `impl Default` ought to inherit.
126+
// But it could also be one of the many attributes that:
127+
// - can't be put on an impl block -- like `#[inline]`
128+
// - we can't even build a suggestion for, since `Attribute::span` may panic.
129+
//
130+
// Because of all that, remain on the safer side -- don't inherit this attr, and just
131+
// reduce the applicability
132+
app = Applicability::MaybeIncorrect;
133+
continue;
134+
}
135+
136+
sugg.push_str(&snippet_with_applicability(cx.sess(), attr.span(), "_", &mut app));
137+
sugg.push('\n');
138+
}
139+
sugg
140+
};
123141
let generics_sugg = snippet_with_applicability(cx, generics.span, "", &mut app);
124142
let where_clause_sugg = if generics.has_where_clause_predicates {
125143
format!(
@@ -143,6 +161,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
143161
item.span,
144162
"try adding this",
145163
&create_new_without_default_suggest_msg(
164+
&attrs_sugg,
146165
&self_type_snip,
147166
&generics_sugg,
148167
&where_clause_sugg,
@@ -157,13 +176,14 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
157176
}
158177

159178
fn create_new_without_default_suggest_msg(
179+
attrs_sugg: &str,
160180
self_type_snip: &str,
161181
generics_sugg: &str,
162182
where_clause_sugg: &str,
163183
) -> String {
164184
#[rustfmt::skip]
165185
format!(
166-
"impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
186+
"{attrs_sugg}impl{generics_sugg} Default for {self_type_snip}{where_clause_sugg} {{
167187
fn default() -> Self {{
168188
Self::new()
169189
}}

tests/ui/new_without_default.fixed

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,74 @@ where
322322
}
323323
}
324324

325+
// From issue #14552, but with `#[cfg]`s that are actually `true` in the uitest context
326+
327+
pub struct NewWithCfg;
328+
#[cfg(not(test))]
329+
impl Default for NewWithCfg {
330+
fn default() -> Self {
331+
Self::new()
332+
}
333+
}
334+
335+
impl NewWithCfg {
336+
#[cfg(not(test))]
337+
pub fn new() -> Self {
338+
//~^ new_without_default
339+
unimplemented!()
340+
}
341+
}
342+
343+
pub struct NewWith2Cfgs;
344+
#[cfg(not(test))]
345+
#[cfg(panic = "unwind")]
346+
impl Default for NewWith2Cfgs {
347+
fn default() -> Self {
348+
Self::new()
349+
}
350+
}
351+
352+
impl NewWith2Cfgs {
353+
#[cfg(not(test))]
354+
#[cfg(panic = "unwind")]
355+
pub fn new() -> Self {
356+
//~^ new_without_default
357+
unimplemented!()
358+
}
359+
}
360+
361+
pub struct NewWithExtraneous;
362+
impl Default for NewWithExtraneous {
363+
fn default() -> Self {
364+
Self::new()
365+
}
366+
}
367+
368+
impl NewWithExtraneous {
369+
#[inline]
370+
pub fn new() -> Self {
371+
//~^ new_without_default
372+
unimplemented!()
373+
}
374+
}
375+
376+
pub struct NewWithCfgAndExtraneous;
377+
#[cfg(not(test))]
378+
impl Default for NewWithCfgAndExtraneous {
379+
fn default() -> Self {
380+
Self::new()
381+
}
382+
}
383+
384+
impl NewWithCfgAndExtraneous {
385+
#[cfg(not(test))]
386+
#[inline]
387+
pub fn new() -> Self {
388+
//~^ new_without_default
389+
unimplemented!()
390+
}
391+
}
392+
325393
mod issue15778 {
326394
pub struct Foo(Vec<i32>);
327395

tests/ui/new_without_default.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,46 @@ where
265265
}
266266
}
267267

268+
// From issue #14552, but with `#[cfg]`s that are actually `true` in the uitest context
269+
270+
pub struct NewWithCfg;
271+
impl NewWithCfg {
272+
#[cfg(not(test))]
273+
pub fn new() -> Self {
274+
//~^ new_without_default
275+
unimplemented!()
276+
}
277+
}
278+
279+
pub struct NewWith2Cfgs;
280+
impl NewWith2Cfgs {
281+
#[cfg(not(test))]
282+
#[cfg(panic = "unwind")]
283+
pub fn new() -> Self {
284+
//~^ new_without_default
285+
unimplemented!()
286+
}
287+
}
288+
289+
pub struct NewWithExtraneous;
290+
impl NewWithExtraneous {
291+
#[inline]
292+
pub fn new() -> Self {
293+
//~^ new_without_default
294+
unimplemented!()
295+
}
296+
}
297+
298+
pub struct NewWithCfgAndExtraneous;
299+
impl NewWithCfgAndExtraneous {
300+
#[cfg(not(test))]
301+
#[inline]
302+
pub fn new() -> Self {
303+
//~^ new_without_default
304+
unimplemented!()
305+
}
306+
}
307+
268308
mod issue15778 {
269309
pub struct Foo(Vec<i32>);
270310

tests/ui/new_without_default.stderr

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,5 +174,84 @@ LL + }
174174
LL + }
175175
|
176176

177-
error: aborting due to 9 previous errors
177+
error: you should consider adding a `Default` implementation for `NewWithCfg`
178+
--> tests/ui/new_without_default.rs:273:5
179+
|
180+
LL | / pub fn new() -> Self {
181+
LL | |
182+
LL | | unimplemented!()
183+
LL | | }
184+
| |_____^
185+
|
186+
help: try adding this
187+
|
188+
LL + #[cfg(not(test))]
189+
LL + impl Default for NewWithCfg {
190+
LL + fn default() -> Self {
191+
LL + Self::new()
192+
LL + }
193+
LL + }
194+
LL | impl NewWithCfg {
195+
|
196+
197+
error: you should consider adding a `Default` implementation for `NewWith2Cfgs`
198+
--> tests/ui/new_without_default.rs:283:5
199+
|
200+
LL | / pub fn new() -> Self {
201+
LL | |
202+
LL | | unimplemented!()
203+
LL | | }
204+
| |_____^
205+
|
206+
help: try adding this
207+
|
208+
LL + #[cfg(not(test))]
209+
LL + #[cfg(panic = "unwind")]
210+
LL + impl Default for NewWith2Cfgs {
211+
LL + fn default() -> Self {
212+
LL + Self::new()
213+
LL + }
214+
LL + }
215+
LL | impl NewWith2Cfgs {
216+
|
217+
218+
error: you should consider adding a `Default` implementation for `NewWithExtraneous`
219+
--> tests/ui/new_without_default.rs:292:5
220+
|
221+
LL | / pub fn new() -> Self {
222+
LL | |
223+
LL | | unimplemented!()
224+
LL | | }
225+
| |_____^
226+
|
227+
help: try adding this
228+
|
229+
LL + impl Default for NewWithExtraneous {
230+
LL + fn default() -> Self {
231+
LL + Self::new()
232+
LL + }
233+
LL + }
234+
|
235+
236+
error: you should consider adding a `Default` implementation for `NewWithCfgAndExtraneous`
237+
--> tests/ui/new_without_default.rs:302:5
238+
|
239+
LL | / pub fn new() -> Self {
240+
LL | |
241+
LL | | unimplemented!()
242+
LL | | }
243+
| |_____^
244+
|
245+
help: try adding this
246+
|
247+
LL + #[cfg(not(test))]
248+
LL + impl Default for NewWithCfgAndExtraneous {
249+
LL + fn default() -> Self {
250+
LL + Self::new()
251+
LL + }
252+
LL + }
253+
LL | impl NewWithCfgAndExtraneous {
254+
|
255+
256+
error: aborting due to 13 previous errors
178257

0 commit comments

Comments
 (0)