Skip to content

Commit 55a1857

Browse files
committed
Fix lint example
1 parent 09693e6 commit 55a1857

File tree

1 file changed

+40
-5
lines changed

1 file changed

+40
-5
lines changed

compiler/rustc_lint/src/default_could_be_derived.rs

+40-5
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ declare_lint! {
2020
/// }
2121
///
2222
/// #[deny(default_could_be_derived)]
23-
/// impl Default for Foo {
24-
/// fn default() -> Foo {
23+
/// impl Default for A {
24+
/// fn default() -> A {
2525
/// A {
2626
/// b: None,
2727
/// }
@@ -59,8 +59,9 @@ declare_lint! {
5959
}
6060

6161
declare_lint! {
62-
/// The `default_could_be_derived` lint checks for manual `impl` blocks
63-
/// of the `Default` trait that could have been derived.
62+
/// The `manual_default_for_type_with_default_fields` lint checks for
63+
/// manual `impl` blocks of the `Default` trait of types with default
64+
/// field values.
6465
///
6566
/// ### Example
6667
///
@@ -114,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
114115
kind:
115116
hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics),
116117
..
117-
})) => {
118+
})) if cx.tcx.features().default_field_values() => {
118119
let fields_with_default_value: Vec<_> =
119120
fields.iter().filter_map(|f| f.default).collect();
120121
let fields_with_default_impl: Vec<_> = fields
@@ -133,6 +134,10 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
133134
_ => None,
134135
})
135136
.collect();
137+
// FIXME: look at the `Default::default()` implementation and call check_expr and
138+
// check_const_expr on every field. If all are either of those, then we suggest
139+
// adding a default field value for the const-able ones and deriving if the feature
140+
// is enabled.
136141
if !fields_with_default_value.is_empty()
137142
&& fields.len()
138143
== fields_with_default_value.len() + fields_with_default_impl.len()
@@ -512,3 +517,33 @@ fn check_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
512517
_ => false,
513518
}
514519
}
520+
521+
522+
fn is_const(cx: &LateContext<'_>, def_id: DefId) -> bool {
523+
// FIXME: look at the DefKind as well, as things like struct literals and consts are always true
524+
match cx.tcx.def_kind(def_id) {
525+
DefKind::Ctor(_, CtorKind::Fn) => true
526+
DefKind::Fn | DefKind::AssocFn | DefKind::Closure => cx.tcx.is_const_fn(def_id),
527+
_ => false,
528+
}
529+
}
530+
531+
fn check_constness(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
532+
match expr.kind {
533+
hir::ExprKind::Lit(_) => true,
534+
hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), hir_id, .. }, fields) => {
535+
// `field: foo(),` or `field: Ty::assoc(),`
536+
check_constness(cx, def_id) && fields.iter().all(|f| check_constness(cx, f))
537+
}
538+
hir::ExprKind::Path(path) => {
539+
// `field: qualified::Path,` or `field: <Ty as Trait>::Assoc,`
540+
let res = cx.qpath_res(&path, hir_id);
541+
let Some(def_id) = res.opt_def_id() else { return false };
542+
is_const_fn(cx, def_id)
543+
}
544+
hir::ExprKind::Struct(_path, fields, _base) => {
545+
fields.iter().all(|f| check_constness(cx, f))
546+
}
547+
_ => false,
548+
}
549+
}

0 commit comments

Comments
 (0)