Skip to content

Commit 0c9016a

Browse files
committed
Auto merge of #13055 - Jarcho:auto_derive, r=Alexendoo
Only check for `automatically_derived` on impl blocks This brings us in line with how rustc checks for the attribute. Also note that `unused_attributes` will trigger if it's placed anywhere else. See: https://github.com/rust-lang/rust/blob/9a21ac8e7efe9ea26a8065d0959a976ca32039bb/compiler/rustc_passes/src/dead.rs#L400-L403 https://github.com/rust-lang/rust/blob/9a21ac8e7efe9ea26a8065d0959a976ca32039bb/compiler/rustc_passes/src/liveness.rs#L143-L148 changelog: none
2 parents 3ed690f + d8fb164 commit 0c9016a

File tree

4 files changed

+25
-14
lines changed

4 files changed

+25
-14
lines changed

clippy_lints/src/default.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
22
use clippy_utils::source::snippet_with_context;
33
use clippy_utils::ty::{has_drop, is_copy};
4-
use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
4+
use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_from_proc_macro};
55
use rustc_data_structures::fx::FxHashSet;
66
use rustc_errors::Applicability;
77
use rustc_hir::def::Res;
@@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
8484
// Avoid cases already linted by `field_reassign_with_default`
8585
&& !self.reassigned_linted.contains(&expr.span)
8686
&& let ExprKind::Call(path, ..) = expr.kind
87-
&& !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
87+
&& !in_automatically_derived(cx.tcx, expr.hir_id)
8888
&& let ExprKind::Path(ref qpath) = path.kind
8989
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
9090
&& cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
@@ -113,9 +113,9 @@ impl<'tcx> LateLintPass<'tcx> for Default {
113113
// start from the `let mut _ = _::default();` and look at all the following
114114
// statements, see if they re-assign the fields of the binding
115115
let stmts_head = match block.stmts {
116+
[] | [_] => return,
116117
// Skip the last statement since there cannot possibly be any following statements that re-assign fields.
117-
[head @ .., _] if !head.is_empty() => head,
118-
_ => return,
118+
[head @ .., _] => head,
119119
};
120120
for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
121121
// find all binding statements like `let mut _ = T::default()` where `T::default()` is the
@@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
124124
let (local, variant, binding_name, binding_type, span) = if let StmtKind::Let(local) = stmt.kind
125125
// only take `let ...` statements
126126
&& let Some(expr) = local.init
127-
&& !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
127+
&& !in_automatically_derived(cx.tcx, expr.hir_id)
128128
&& !expr.span.from_expansion()
129129
// only take bindings to identifiers
130130
&& let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind

clippy_lints/src/misc.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and
22
use clippy_utils::source::{snippet, snippet_with_context};
33
use clippy_utils::sugg::Sugg;
44
use clippy_utils::{
5-
any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats,
6-
last_path_segment, SpanlessEq,
5+
fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats, last_path_segment,
6+
SpanlessEq,
77
};
88
use rustc_errors::Applicability;
99
use rustc_hir::def::Res;
@@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
206206
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
207207
if in_external_macro(cx.sess(), expr.span)
208208
|| expr.span.desugaring_kind().is_some()
209-
|| any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
209+
|| in_automatically_derived(cx.tcx, expr.hir_id)
210210
{
211211
return;
212212
}

clippy_lints/src/no_effect.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
22
use clippy_utils::source::snippet_opt;
33
use clippy_utils::ty::has_drop;
44
use clippy_utils::{
5-
any_parent_is_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks,
5+
in_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks,
66
};
77
use rustc_errors::Applicability;
88
use rustc_hir::def::{DefKind, Res};
@@ -187,7 +187,7 @@ impl NoEffect {
187187
&& has_no_effect(cx, init)
188188
&& let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
189189
&& ident.name.to_ident_string().starts_with('_')
190-
&& !any_parent_is_automatically_derived(cx.tcx, local.hir_id)
190+
&& !in_automatically_derived(cx.tcx, local.hir_id)
191191
{
192192
if let Some(l) = self.local_bindings.last_mut() {
193193
l.push(hir_id);

clippy_utils/src/lib.rs

+15-4
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,9 @@ use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
103103
use rustc_hir::{
104104
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
105105
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
106-
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path,
107-
PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
106+
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
107+
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
108+
TyKind, UnOp,
108109
};
109110
use rustc_lexer::{tokenize, TokenKind};
110111
use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -1924,8 +1925,18 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool
19241925
false
19251926
}
19261927

1927-
pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
1928-
any_parent_has_attr(tcx, node, sym::automatically_derived)
1928+
/// Checks if the given HIR node is inside an `impl` block with the `automatically_derived`
1929+
/// attribute.
1930+
pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
1931+
tcx.hir()
1932+
.parent_owner_iter(id)
1933+
.filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
1934+
.any(|(id, _)| {
1935+
has_attr(
1936+
tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
1937+
sym::automatically_derived,
1938+
)
1939+
})
19291940
}
19301941

19311942
/// Matches a function call with the given path and returns the arguments.

0 commit comments

Comments
 (0)