Skip to content

Commit 9b2c9a8

Browse files
committed
Refactor default_could_be_derived
1 parent 4d03de6 commit 9b2c9a8

File tree

2 files changed

+26
-36
lines changed

2 files changed

+26
-36
lines changed

compiler/rustc_lint/src/default_could_be_derived.rs

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_errors::{Applicability, Diag};
33
use rustc_hir as hir;
4-
use rustc_hir::attrs::AttributeKind;
5-
use rustc_hir::find_attr;
64
use rustc_middle::ty;
75
use rustc_middle::ty::TyCtxt;
8-
use rustc_session::{declare_lint, impl_lint_pass};
9-
use rustc_span::Symbol;
6+
use rustc_session::{declare_lint, declare_lint_pass};
107
use rustc_span::def_id::DefId;
118
use rustc_span::symbol::sym;
9+
use rustc_span::{Span, Symbol};
1210

1311
use crate::{LateContext, LateLintPass};
1412

@@ -52,27 +50,24 @@ declare_lint! {
5250
@feature_gate = default_field_values;
5351
}
5452

55-
#[derive(Default)]
56-
pub(crate) struct DefaultCouldBeDerived;
57-
58-
impl_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]);
53+
declare_lint_pass!(DefaultCouldBeDerived => [DEFAULT_OVERRIDES_DEFAULT_FIELDS]);
5954

6055
impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
6156
fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {
6257
// Look for manual implementations of `Default`.
63-
let Some(default_def_id) = cx.tcx.get_diagnostic_item(sym::Default) else { return };
64-
let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return };
65-
let parent = cx.tcx.parent(impl_item.owner_id.to_def_id());
66-
if find_attr!(cx.tcx.get_all_attrs(parent), AttributeKind::AutomaticallyDerived(..)) {
67-
// We don't care about what `#[derive(Default)]` produces in this lint.
58+
let hir::ImplItemImplKind::Trait { trait_item_def_id, .. } = impl_item.impl_kind else {
59+
return;
60+
};
61+
if !trait_item_def_id.is_ok_and(|id| cx.tcx.is_diagnostic_item(sym::default_fn, id)) {
6862
return;
6963
}
70-
let Some(trait_ref) = cx.tcx.impl_trait_ref(parent) else { return };
71-
let trait_ref = trait_ref.instantiate_identity();
72-
if trait_ref.def_id != default_def_id {
64+
let hir::ImplItemKind::Fn(_sig, body_id) = impl_item.kind else { return };
65+
let impl_id = cx.tcx.local_parent(impl_item.owner_id.def_id);
66+
if cx.tcx.is_automatically_derived(impl_id.to_def_id()) {
67+
// We don't care about what `#[derive(Default)]` produces in this lint.
7368
return;
7469
}
75-
let ty = trait_ref.self_ty();
70+
let ty = cx.tcx.type_of(impl_id).instantiate_identity();
7671
let ty::Adt(def, _) = ty.kind() else { return };
7772

7873
// We now know we have a manually written definition of a `<Type as Default>::default()`.
@@ -150,11 +145,10 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
150145
return;
151146
}
152147

153-
let Some(local) = parent.as_local() else { return };
154-
let hir_id = cx.tcx.local_def_id_to_hir_id(local);
155-
let hir::Node::Item(item) = cx.tcx.hir_node(hir_id) else { return };
156-
cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, item.span, |diag| {
157-
mk_lint(cx.tcx, diag, type_def_id, parent, orig_fields, fields);
148+
let hir_id = cx.tcx.local_def_id_to_hir_id(impl_id);
149+
let span = cx.tcx.hir_span_with_body(hir_id);
150+
cx.tcx.node_span_lint(DEFAULT_OVERRIDES_DEFAULT_FIELDS, hir_id, span, |diag| {
151+
mk_lint(cx.tcx, diag, type_def_id, orig_fields, fields, span);
158152
});
159153
}
160154
}
@@ -163,9 +157,9 @@ fn mk_lint(
163157
tcx: TyCtxt<'_>,
164158
diag: &mut Diag<'_, ()>,
165159
type_def_id: DefId,
166-
impl_def_id: DefId,
167160
orig_fields: FxHashMap<Symbol, &hir::FieldDef<'_>>,
168161
fields: &[hir::ExprField<'_>],
162+
impl_span: Span,
169163
) {
170164
diag.primary_message("`Default` impl doesn't use the declared default field values");
171165

@@ -186,18 +180,14 @@ fn mk_lint(
186180
if removed_all_fields {
187181
let msg = "to avoid divergence in behavior between `Struct { .. }` and \
188182
`<Struct as Default>::default()`, derive the `Default`";
189-
if let Some(hir::Node::Item(impl_)) = tcx.hir_get_if_local(impl_def_id) {
190-
diag.multipart_suggestion_verbose(
191-
msg,
192-
vec![
193-
(tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()),
194-
(impl_.span, String::new()),
195-
],
196-
Applicability::MachineApplicable,
197-
);
198-
} else {
199-
diag.help(msg);
200-
}
183+
diag.multipart_suggestion_verbose(
184+
msg,
185+
vec![
186+
(tcx.def_span(type_def_id).shrink_to_lo(), "#[derive(Default)] ".to_string()),
187+
(impl_span, String::new()),
188+
],
189+
Applicability::MachineApplicable,
190+
);
201191
} else {
202192
let msg = "use the default values in the `impl` with `Struct { mandatory_field, .. }` to \
203193
avoid them diverging over time";

compiler/rustc_lint/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ late_lint_methods!(
191191
BuiltinCombinedModuleLateLintPass,
192192
[
193193
ForLoopsOverFallibles: ForLoopsOverFallibles,
194-
DefaultCouldBeDerived: DefaultCouldBeDerived::default(),
194+
DefaultCouldBeDerived: DefaultCouldBeDerived,
195195
DerefIntoDynSupertrait: DerefIntoDynSupertrait,
196196
DropForgetUseless: DropForgetUseless,
197197
ImproperCTypesLint: ImproperCTypesLint,

0 commit comments

Comments
 (0)