mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-23 13:13:34 +00:00
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:9a21ac8e7e/compiler/rustc_passes/src/dead.rs (L400-L403)
9a21ac8e7e/compiler/rustc_passes/src/liveness.rs (L143-L148)
changelog: none
This commit is contained in:
commit
0c9016aa1e
4 changed files with 25 additions and 14 deletions
|
@ -1,7 +1,7 @@
|
|||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::snippet_with_context;
|
||||
use clippy_utils::ty::{has_drop, is_copy};
|
||||
use clippy_utils::{any_parent_is_automatically_derived, contains_name, get_parent_expr, is_from_proc_macro};
|
||||
use clippy_utils::{contains_name, get_parent_expr, in_automatically_derived, is_from_proc_macro};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
|
@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
// Avoid cases already linted by `field_reassign_with_default`
|
||||
&& !self.reassigned_linted.contains(&expr.span)
|
||||
&& let ExprKind::Call(path, ..) = expr.kind
|
||||
&& !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
|
||||
&& !in_automatically_derived(cx.tcx, expr.hir_id)
|
||||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::default_fn, def_id)
|
||||
|
@ -113,9 +113,9 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
// start from the `let mut _ = _::default();` and look at all the following
|
||||
// statements, see if they re-assign the fields of the binding
|
||||
let stmts_head = match block.stmts {
|
||||
[] | [_] => return,
|
||||
// Skip the last statement since there cannot possibly be any following statements that re-assign fields.
|
||||
[head @ .., _] if !head.is_empty() => head,
|
||||
_ => return,
|
||||
[head @ .., _] => head,
|
||||
};
|
||||
for (stmt_idx, stmt) in stmts_head.iter().enumerate() {
|
||||
// find all binding statements like `let mut _ = T::default()` where `T::default()` is the
|
||||
|
@ -124,7 +124,7 @@ impl<'tcx> LateLintPass<'tcx> for Default {
|
|||
let (local, variant, binding_name, binding_type, span) = if let StmtKind::Let(local) = stmt.kind
|
||||
// only take `let ...` statements
|
||||
&& let Some(expr) = local.init
|
||||
&& !any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
|
||||
&& !in_automatically_derived(cx.tcx, expr.hir_id)
|
||||
&& !expr.span.from_expansion()
|
||||
// only take bindings to identifiers
|
||||
&& let PatKind::Binding(_, binding_id, ident, _) = local.pat.kind
|
||||
|
|
|
@ -2,8 +2,8 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then, span_lint_hir_and
|
|||
use clippy_utils::source::{snippet, snippet_with_context};
|
||||
use clippy_utils::sugg::Sugg;
|
||||
use clippy_utils::{
|
||||
any_parent_is_automatically_derived, fulfill_or_allowed, get_parent_expr, is_lint_allowed, iter_input_pats,
|
||||
last_path_segment, SpanlessEq,
|
||||
fulfill_or_allowed, get_parent_expr, in_automatically_derived, is_lint_allowed, iter_input_pats, last_path_segment,
|
||||
SpanlessEq,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::Res;
|
||||
|
@ -206,7 +206,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass {
|
|||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||
if in_external_macro(cx.sess(), expr.span)
|
||||
|| expr.span.desugaring_kind().is_some()
|
||||
|| any_parent_is_automatically_derived(cx.tcx, expr.hir_id)
|
||||
|| in_automatically_derived(cx.tcx, expr.hir_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
|
|||
use clippy_utils::source::snippet_opt;
|
||||
use clippy_utils::ty::has_drop;
|
||||
use clippy_utils::{
|
||||
any_parent_is_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks,
|
||||
in_automatically_derived, is_inside_always_const_context, is_lint_allowed, path_to_local, peel_blocks,
|
||||
};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
|
@ -187,7 +187,7 @@ impl NoEffect {
|
|||
&& has_no_effect(cx, init)
|
||||
&& let PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
|
||||
&& ident.name.to_ident_string().starts_with('_')
|
||||
&& !any_parent_is_automatically_derived(cx.tcx, local.hir_id)
|
||||
&& !in_automatically_derived(cx.tcx, local.hir_id)
|
||||
{
|
||||
if let Some(l) = self.local_bindings.last_mut() {
|
||||
l.push(hir_id);
|
||||
|
|
|
@ -103,8 +103,9 @@ use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
|||
use rustc_hir::{
|
||||
self as hir, def, Arm, ArrayLen, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstContext,
|
||||
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
|
||||
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, Param, Pat, PatKind, Path,
|
||||
PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, TyKind, UnOp,
|
||||
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
|
||||
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
|
||||
TyKind, UnOp,
|
||||
};
|
||||
use rustc_lexer::{tokenize, TokenKind};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
|
@ -1924,8 +1925,18 @@ pub fn any_parent_has_attr(tcx: TyCtxt<'_>, node: HirId, symbol: Symbol) -> bool
|
|||
false
|
||||
}
|
||||
|
||||
pub fn any_parent_is_automatically_derived(tcx: TyCtxt<'_>, node: HirId) -> bool {
|
||||
any_parent_has_attr(tcx, node, sym::automatically_derived)
|
||||
/// Checks if the given HIR node is inside an `impl` block with the `automatically_derived`
|
||||
/// attribute.
|
||||
pub fn in_automatically_derived(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||
tcx.hir()
|
||||
.parent_owner_iter(id)
|
||||
.filter(|(_, node)| matches!(node, OwnerNode::Item(item) if matches!(item.kind, ItemKind::Impl(_))))
|
||||
.any(|(id, _)| {
|
||||
has_attr(
|
||||
tcx.hir().attrs(tcx.local_def_id_to_hir_id(id.def_id)),
|
||||
sym::automatically_derived,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/// Matches a function call with the given path and returns the arguments.
|
||||
|
|
Loading…
Reference in a new issue