Skip to content

Commit

Permalink
Fix lint example
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Dec 15, 2024
1 parent 09693e6 commit 55a1857
Showing 1 changed file with 40 additions and 5 deletions.
45 changes: 40 additions & 5 deletions compiler/rustc_lint/src/default_could_be_derived.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ declare_lint! {
/// }
///
/// #[deny(default_could_be_derived)]
/// impl Default for Foo {
/// fn default() -> Foo {
/// impl Default for A {
/// fn default() -> A {
/// A {
/// b: None,
/// }
Expand Down Expand Up @@ -59,8 +59,9 @@ declare_lint! {
}

declare_lint! {
/// The `default_could_be_derived` lint checks for manual `impl` blocks
/// of the `Default` trait that could have been derived.
/// The `manual_default_for_type_with_default_fields` lint checks for
/// manual `impl` blocks of the `Default` trait of types with default
/// field values.
///
/// ### Example
///
Expand Down Expand Up @@ -114,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
kind:
hir::ItemKind::Struct(hir::VariantData::Struct { fields, recovered: _ }, _generics),
..
})) => {
})) if cx.tcx.features().default_field_values() => {
let fields_with_default_value: Vec<_> =
fields.iter().filter_map(|f| f.default).collect();
let fields_with_default_impl: Vec<_> = fields
Expand All @@ -133,6 +134,10 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
_ => None,
})
.collect();
// FIXME: look at the `Default::default()` implementation and call check_expr and
// check_const_expr on every field. If all are either of those, then we suggest
// adding a default field value for the const-able ones and deriving if the feature
// is enabled.
if !fields_with_default_value.is_empty()
&& fields.len()
== fields_with_default_value.len() + fields_with_default_impl.len()
Expand Down Expand Up @@ -512,3 +517,33 @@ fn check_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
_ => false,
}
}


fn is_const(cx: &LateContext<'_>, def_id: DefId) -> bool {
// FIXME: look at the DefKind as well, as things like struct literals and consts are always true
match cx.tcx.def_kind(def_id) {
DefKind::Ctor(_, CtorKind::Fn) => true
DefKind::Fn | DefKind::AssocFn | DefKind::Closure => cx.tcx.is_const_fn(def_id),
_ => false,
}
}

fn check_constness(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
match expr.kind {
hir::ExprKind::Lit(_) => true,
hir::ExprKind::Call(hir::Expr { kind: hir::ExprKind::Path(path), hir_id, .. }, fields) => {
// `field: foo(),` or `field: Ty::assoc(),`
check_constness(cx, def_id) && fields.iter().all(|f| check_constness(cx, f))
}
hir::ExprKind::Path(path) => {
// `field: qualified::Path,` or `field: <Ty as Trait>::Assoc,`
let res = cx.qpath_res(&path, hir_id);
let Some(def_id) = res.opt_def_id() else { return false };
is_const_fn(cx, def_id)
}
hir::ExprKind::Struct(_path, fields, _base) => {
fields.iter().all(|f| check_constness(cx, f))
}
_ => false,
}
}

0 comments on commit 55a1857

Please sign in to comment.