Skip to content

Commit a7bf8c7

Browse files
committed
Restrict only Default::default and Foo::default
1 parent 85c6663 commit a7bf8c7

File tree

4 files changed

+15
-29
lines changed

4 files changed

+15
-29
lines changed

clippy_lints/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,6 +985,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
985985
store.register_late_pass(move |_| Box::new(non_std_lazy_statics::NonStdLazyStatic::new(conf)));
986986
store.register_late_pass(|_| Box::new(manual_option_as_slice::ManualOptionAsSlice::new(conf)));
987987
store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap));
988-
store.register_early_pass(|| Box::new(struct_fields_rest_default::StructFieldsDefault));
988+
store.register_late_pass(|_| Box::new(struct_fields_rest_default::StructFieldsDefault));
989989
// add lints here, do not remove this comment, it's used in `new_lint`
990990
}

clippy_lints/src/struct_fields_rest_default.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use clippy_utils::diagnostics::span_lint_and_help;
2+
use clippy_utils::path_def_id;
23
use clippy_utils::source::snippet;
3-
use rustc_ast::Expr;
4-
use rustc_ast::ast::{ExprKind, StructRest};
5-
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
4+
use rustc_hir::{ExprKind, StructTailExpr};
5+
use rustc_lint::{LateLintPass, LintContext};
66
use rustc_session::declare_lint_pass;
7+
use rustc_span::sym;
78

89
declare_clippy_lint! {
910
/// ### What it does
10-
/// Check struct initialization uses `..base` pattern to skip rest of struct field initialization.
11+
/// Check struct initialization uses `..*::default()` pattern to skip rest of struct field initialization.
1112
///
1213
/// ### Why restrict this?
13-
/// Using `..base` can hide field initialization when new fields are added to structs,
14+
/// Using `..*::default()` can hide field initialization when new fields are added to structs,
1415
/// potentially leading to bugs where developers forget to explicitly set values for new fields.
1516
///
1617
/// ### Example
@@ -54,11 +55,13 @@ declare_clippy_lint! {
5455

5556
declare_lint_pass!(StructFieldsDefault => [STRUCT_FIELDS_REST_DEFAULT]);
5657

57-
impl EarlyLintPass for StructFieldsDefault {
58-
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
58+
impl<'tcx> LateLintPass<'tcx> for StructFieldsDefault {
59+
fn check_expr(&mut self, cx: &rustc_lint::LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) {
5960
if !expr.span.in_external_macro(cx.sess().source_map())
60-
&& let ExprKind::Struct(struct_expr) = &expr.kind
61-
&& let StructRest::Base(base) = &struct_expr.rest
61+
&& let ExprKind::Struct(_, _, StructTailExpr::Base(base)) = &expr.kind
62+
&& let ExprKind::Call(func, _) = base.kind
63+
&& let Some(did) = path_def_id(cx, func)
64+
&& cx.tcx.is_diagnostic_item(sym::default_fn, did)
6265
{
6366
span_lint_and_help(
6467
cx,

tests/ui/struct_fields_rest_default.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,11 @@ fn main() {
3030
//~^ struct_fields_rest_default
3131
};
3232

33+
// should not lint
3334
#[rustfmt::skip]
3435
let _ = Foo {
3536
a: 10,
3637
..Foo::get_foo()
37-
//~^ struct_fields_rest_default
3838
};
3939

4040
// should not lint in external macro

tests/ui/struct_fields_rest_default.stderr

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,5 @@ LL | |
3434
LL | | };
3535
| |_____^
3636

37-
error: should not use `..Foo::get_foo()` to omit rest of struct field initialization
38-
--> tests/ui/struct_fields_rest_default.rs:36:11
39-
|
40-
LL | ..Foo::get_foo()
41-
| ^^^^^^^^^^^^^^
42-
|
43-
help: each field's initial value should be explicitly specified
44-
--> tests/ui/struct_fields_rest_default.rs:34:13
45-
|
46-
LL | let _ = Foo {
47-
| _____________^
48-
LL | | a: 10,
49-
LL | | ..Foo::get_foo()
50-
LL | |
51-
LL | | };
52-
| |_____^
53-
54-
error: aborting due to 3 previous errors
37+
error: aborting due to 2 previous errors
5538

0 commit comments

Comments
 (0)