Skip to content

Commit df1baed

Browse files
committed
Auto merge of #13050 - Jarcho:misc_small, r=xFrednet
Misc refactorings Various small re-orderings to check the HIR tree or AST before doing other checks. Also includes a small bug fix for `arc_with_small_send_sync` not actually checking for `Arc::new`. changelog: none
2 parents f9c2407 + 9f59e9a commit df1baed

14 files changed

+98
-121
lines changed

clippy_lints/src/arc_with_non_send_sync.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::is_from_proc_macro;
23
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
3-
use clippy_utils::{is_from_proc_macro, last_path_segment};
4-
use rustc_hir::{Expr, ExprKind};
4+
use rustc_hir::{Expr, ExprKind, QPath};
55
use rustc_lint::{LateContext, LateLintPass};
66
use rustc_middle::ty;
77
use rustc_middle::ty::print::with_forced_trimmed_paths;
@@ -42,12 +42,11 @@ declare_lint_pass!(ArcWithNonSendSync => [ARC_WITH_NON_SEND_SYNC]);
4242

4343
impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
4444
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
45-
if !expr.span.from_expansion()
46-
&& let ty = cx.typeck_results().expr_ty(expr)
47-
&& is_type_diagnostic_item(cx, ty, sym::Arc)
48-
&& let ExprKind::Call(func, [arg]) = expr.kind
49-
&& let ExprKind::Path(func_path) = func.kind
50-
&& last_path_segment(&func_path).ident.name == sym::new
45+
if let ExprKind::Call(func, [arg]) = expr.kind
46+
&& let ExprKind::Path(QPath::TypeRelative(func_ty, func_name)) = func.kind
47+
&& func_name.ident.name == sym::new
48+
&& !expr.span.from_expansion()
49+
&& is_type_diagnostic_item(cx, cx.typeck_results().node_type(func_ty.hir_id), sym::Arc)
5150
&& let arg_ty = cx.typeck_results().expr_ty(arg)
5251
// make sure that the type is not and does not contain any type parameters
5352
&& arg_ty.walk().all(|arg| {

clippy_lints/src/borrow_deref_ref.rs

+20-24
Original file line numberDiff line numberDiff line change
@@ -49,35 +49,31 @@ declare_lint_pass!(BorrowDerefRef => [BORROW_DEREF_REF]);
4949

5050
impl<'tcx> LateLintPass<'tcx> for BorrowDerefRef {
5151
fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &rustc_hir::Expr<'tcx>) {
52-
if !e.span.from_expansion()
53-
&& let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind
54-
&& !addrof_target.span.from_expansion()
52+
if let ExprKind::AddrOf(_, Mutability::Not, addrof_target) = e.kind
5553
&& let ExprKind::Unary(UnOp::Deref, deref_target) = addrof_target.kind
56-
&& !deref_target.span.from_expansion()
5754
&& !matches!(deref_target.kind, ExprKind::Unary(UnOp::Deref, ..))
55+
&& !e.span.from_expansion()
56+
&& !deref_target.span.from_expansion()
57+
&& !addrof_target.span.from_expansion()
5858
&& let ref_ty = cx.typeck_results().expr_ty(deref_target)
5959
&& let ty::Ref(_, inner_ty, Mutability::Not) = ref_ty.kind()
60-
{
61-
if let Some(parent_expr) = get_parent_expr(cx, e) {
62-
if matches!(parent_expr.kind, ExprKind::Unary(UnOp::Deref, ..))
63-
&& !is_lint_allowed(cx, DEREF_ADDROF, parent_expr.hir_id)
64-
{
65-
return;
60+
&& get_parent_expr(cx, e).map_or(true, |parent| {
61+
match parent.kind {
62+
// `*&*foo` should lint `deref_addrof` instead.
63+
ExprKind::Unary(UnOp::Deref, _) => is_lint_allowed(cx, DEREF_ADDROF, parent.hir_id),
64+
// `&*foo` creates a distinct temporary from `foo`
65+
ExprKind::AddrOf(_, Mutability::Mut, _) => !matches!(
66+
deref_target.kind,
67+
ExprKind::Path(..)
68+
| ExprKind::Field(..)
69+
| ExprKind::Index(..)
70+
| ExprKind::Unary(UnOp::Deref, ..)
71+
),
72+
_ => true,
6673
}
67-
68-
// modification to `&mut &*x` is different from `&mut x`
69-
if matches!(
70-
deref_target.kind,
71-
ExprKind::Path(..) | ExprKind::Field(..) | ExprKind::Index(..) | ExprKind::Unary(UnOp::Deref, ..)
72-
) && matches!(parent_expr.kind, ExprKind::AddrOf(_, Mutability::Mut, _))
73-
{
74-
return;
75-
}
76-
}
77-
if is_from_proc_macro(cx, e) {
78-
return;
79-
}
80-
74+
})
75+
&& !is_from_proc_macro(cx, e)
76+
{
8177
span_lint_and_then(
8278
cx,
8379
BORROW_DEREF_REF,

clippy_lints/src/collapsible_if.rs

+12-21
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,14 @@ declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
9393

9494
impl EarlyLintPass for CollapsibleIf {
9595
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
96-
if !expr.span.from_expansion() {
97-
check_if(cx, expr);
98-
}
99-
}
100-
}
101-
102-
fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
103-
if let ast::ExprKind::If(check, then, else_) = &expr.kind {
104-
if let Some(else_) = else_ {
105-
check_collapsible_maybe_if_let(cx, then.span, else_);
106-
} else if let ast::ExprKind::Let(..) = check.kind {
107-
// Prevent triggering on `if let a = b { if c { .. } }`.
108-
} else {
109-
check_collapsible_no_if_let(cx, expr, check, then);
96+
if let ast::ExprKind::If(cond, then, else_) = &expr.kind
97+
&& !expr.span.from_expansion()
98+
{
99+
if let Some(else_) = else_ {
100+
check_collapsible_maybe_if_let(cx, then.span, else_);
101+
} else if !matches!(cond.kind, ast::ExprKind::Let(..)) {
102+
check_collapsible_no_if_let(cx, expr, cond, then);
103+
}
110104
}
111105
}
112106
}
@@ -189,13 +183,10 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
189183

190184
/// If the block contains only one expression, return it.
191185
fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
192-
let mut it = block.stmts.iter();
193-
194-
if let (Some(stmt), None) = (it.next(), it.next()) {
195-
match stmt.kind {
196-
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => Some(expr),
197-
_ => None,
198-
}
186+
if let [stmt] = &*block.stmts
187+
&& let ast::StmtKind::Expr(expr) | ast::StmtKind::Semi(expr) = &stmt.kind
188+
{
189+
Some(expr)
199190
} else {
200191
None
201192
}

clippy_lints/src/collection_is_never_read.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ static COLLECTIONS: [Symbol; 9] = [
5959

6060
impl<'tcx> LateLintPass<'tcx> for CollectionIsNeverRead {
6161
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &'tcx LetStmt<'tcx>) {
62-
// Look for local variables whose type is a container. Search surrounding bock for read access.
63-
if match_acceptable_type(cx, local, &COLLECTIONS)
64-
&& let PatKind::Binding(_, local_id, _, _) = local.pat.kind
62+
// Look for local variables whose type is a container. Search surrounding block for read access.
63+
if let PatKind::Binding(_, local_id, _, _) = local.pat.kind
64+
&& match_acceptable_type(cx, local, &COLLECTIONS)
6565
&& let Some(enclosing_block) = get_enclosing_block(cx, local.hir_id)
6666
&& has_no_read_access(cx, local_id, enclosing_block)
6767
{

clippy_lints/src/crate_in_macro_def.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,9 @@ declare_lint_pass!(CrateInMacroDef => [CRATE_IN_MACRO_DEF]);
5353

5454
impl EarlyLintPass for CrateInMacroDef {
5555
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
56-
if item.attrs.iter().any(is_macro_export)
57-
&& let ItemKind::MacroDef(macro_def) = &item.kind
58-
&& let tts = macro_def.body.tokens.clone()
59-
&& let Some(span) = contains_unhygienic_crate_reference(&tts)
56+
if let ItemKind::MacroDef(macro_def) = &item.kind
57+
&& item.attrs.iter().any(is_macro_export)
58+
&& let Some(span) = contains_unhygienic_crate_reference(&macro_def.body.tokens)
6059
{
6160
span_lint_and_sugg(
6261
cx,

clippy_lints/src/else_if_without_else.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,9 @@ declare_lint_pass!(ElseIfWithoutElse => [ELSE_IF_WITHOUT_ELSE]);
5050

5151
impl EarlyLintPass for ElseIfWithoutElse {
5252
fn check_expr(&mut self, cx: &EarlyContext<'_>, item: &Expr) {
53-
if in_external_macro(cx.sess(), item.span) {
54-
return;
55-
}
56-
5753
if let ExprKind::If(_, _, Some(ref els)) = item.kind
5854
&& let ExprKind::If(_, _, None) = els.kind
55+
&& !in_external_macro(cx.sess(), item.span)
5956
{
6057
span_lint_and_help(
6158
cx,

clippy_lints/src/empty_enum.rs

+15-19
Original file line numberDiff line numberDiff line change
@@ -64,25 +64,21 @@ declare_lint_pass!(EmptyEnum => [EMPTY_ENUM]);
6464

6565
impl<'tcx> LateLintPass<'tcx> for EmptyEnum {
6666
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
67-
// Only suggest the `never_type` if the feature is enabled
68-
if !cx.tcx.features().never_type {
69-
return;
70-
}
71-
72-
if let ItemKind::Enum(..) = item.kind {
73-
let ty = cx.tcx.type_of(item.owner_id).instantiate_identity();
74-
let adt = ty.ty_adt_def().expect("already checked whether this is an enum");
75-
if adt.variants().is_empty() {
76-
span_lint_and_help(
77-
cx,
78-
EMPTY_ENUM,
79-
item.span,
80-
"enum with no variants",
81-
None,
82-
"consider using the uninhabited type `!` (never type) or a wrapper \
83-
around it to introduce a type which can't be instantiated",
84-
);
85-
}
67+
if let ItemKind::Enum(..) = item.kind
68+
// Only suggest the `never_type` if the feature is enabled
69+
&& cx.tcx.features().never_type
70+
&& let Some(adt) = cx.tcx.type_of(item.owner_id).instantiate_identity().ty_adt_def()
71+
&& adt.variants().is_empty()
72+
{
73+
span_lint_and_help(
74+
cx,
75+
EMPTY_ENUM,
76+
item.span,
77+
"enum with no variants",
78+
None,
79+
"consider using the uninhabited type `!` (never type) or a wrapper \
80+
around it to introduce a type which can't be instantiated",
81+
);
8682
}
8783
}
8884
}

clippy_lints/src/equatable_if_let.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,9 @@ fn is_structural_partial_eq<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, other: T
7070

7171
impl<'tcx> LateLintPass<'tcx> for PatternEquality {
7272
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
73-
if !in_external_macro(cx.sess(), expr.span)
74-
&& let ExprKind::Let(let_expr) = expr.kind
73+
if let ExprKind::Let(let_expr) = expr.kind
7574
&& unary_pattern(let_expr.pat)
75+
&& !in_external_macro(cx.sess(), expr.span)
7676
{
7777
let exp_ty = cx.typeck_results().expr_ty(let_expr.init);
7878
let pat_ty = cx.typeck_results().pat_ty(let_expr.pat);

clippy_lints/src/error_impl_error.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,12 @@ declare_lint_pass!(ErrorImplError => [ERROR_IMPL_ERROR]);
3636

3737
impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
3838
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
39-
let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error) else {
40-
return;
41-
};
42-
4339
match item.kind {
4440
ItemKind::TyAlias(..)
4541
if item.ident.name == sym::Error
4642
&& is_visible_outside_module(cx, item.owner_id.def_id)
4743
&& let ty = cx.tcx.type_of(item.owner_id).instantiate_identity()
44+
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
4845
&& implements_trait(cx, ty, error_def_id, &[]) =>
4946
{
5047
span_lint(
@@ -56,17 +53,17 @@ impl<'tcx> LateLintPass<'tcx> for ErrorImplError {
5653
},
5754
ItemKind::Impl(imp)
5855
if let Some(trait_def_id) = imp.of_trait.and_then(|t| t.trait_def_id())
56+
&& let Some(error_def_id) = cx.tcx.get_diagnostic_item(sym::Error)
5957
&& error_def_id == trait_def_id
6058
&& let Some(def_id) = path_res(cx, imp.self_ty).opt_def_id().and_then(DefId::as_local)
61-
&& let hir_id = cx.tcx.local_def_id_to_hir_id(def_id)
6259
&& let Some(ident) = cx.tcx.opt_item_ident(def_id.to_def_id())
6360
&& ident.name == sym::Error
6461
&& is_visible_outside_module(cx, def_id) =>
6562
{
6663
span_lint_hir_and_then(
6764
cx,
6865
ERROR_IMPL_ERROR,
69-
hir_id,
66+
cx.tcx.local_def_id_to_hir_id(def_id),
7067
ident.span,
7168
"exported type named `Error` that implements `Error`",
7269
|diag| {

clippy_lints/src/exhaustive_items.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,24 @@ declare_lint_pass!(ExhaustiveItems => [EXHAUSTIVE_ENUMS, EXHAUSTIVE_STRUCTS]);
7070

7171
impl LateLintPass<'_> for ExhaustiveItems {
7272
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
73-
if let ItemKind::Enum(..) | ItemKind::Struct(..) = item.kind
74-
&& cx.effective_visibilities.is_exported(item.owner_id.def_id)
73+
let (lint, msg, fields) = match item.kind {
74+
ItemKind::Enum(..) => (
75+
EXHAUSTIVE_ENUMS,
76+
"exported enums should not be exhaustive",
77+
[].as_slice(),
78+
),
79+
ItemKind::Struct(v, ..) => (
80+
EXHAUSTIVE_STRUCTS,
81+
"exported structs should not be exhaustive",
82+
v.fields(),
83+
),
84+
_ => return,
85+
};
86+
if cx.effective_visibilities.is_exported(item.owner_id.def_id)
7587
&& let attrs = cx.tcx.hir().attrs(item.hir_id())
7688
&& !attrs.iter().any(|a| a.has_name(sym::non_exhaustive))
89+
&& fields.iter().all(|f| cx.tcx.visibility(f.def_id).is_public())
7790
{
78-
let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
79-
if v.fields().iter().any(|f| !cx.tcx.visibility(f.def_id).is_public()) {
80-
// skip structs with private fields
81-
return;
82-
}
83-
(EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive")
84-
} else {
85-
(EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive")
86-
};
8791
let suggestion_span = item.span.shrink_to_lo();
8892
let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));
8993
span_lint_and_then(cx, lint, item.span, msg, |diag| {

clippy_lints/src/exit.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint;
22
use clippy_utils::is_entrypoint_fn;
3-
use rustc_hir::{Expr, ExprKind, Item, ItemKind, Node};
3+
use rustc_hir::{Expr, ExprKind, Item, ItemKind, OwnerNode};
44
use rustc_lint::{LateContext, LateLintPass};
55
use rustc_session::declare_lint_pass;
66
use rustc_span::sym;
@@ -47,8 +47,8 @@ impl<'tcx> LateLintPass<'tcx> for Exit {
4747
&& let ExprKind::Path(ref path) = path_expr.kind
4848
&& let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id()
4949
&& cx.tcx.is_diagnostic_item(sym::process_exit, def_id)
50-
&& let parent = cx.tcx.hir().get_parent_item(e.hir_id).def_id
51-
&& let Node::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_node_by_def_id(parent)
50+
&& let parent = cx.tcx.hir().get_parent_item(e.hir_id)
51+
&& let OwnerNode::Item(Item{kind: ItemKind::Fn(..), ..}) = cx.tcx.hir_owner_node(parent)
5252
// If the next item up is a function we check if it is an entry point
5353
// and only then emit a linter warning
5454
&& !is_entrypoint_fn(cx, parent.to_def_id())

clippy_lints/src/float_literal.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,9 @@ declare_lint_pass!(FloatLiteral => [EXCESSIVE_PRECISION, LOSSY_FLOAT_LITERAL]);
6262

6363
impl<'tcx> LateLintPass<'tcx> for FloatLiteral {
6464
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
65-
let ty = cx.typeck_results().expr_ty(expr);
66-
if let ty::Float(fty) = *ty.kind()
67-
&& let hir::ExprKind::Lit(lit) = expr.kind
65+
if let hir::ExprKind::Lit(lit) = expr.kind
6866
&& let LitKind::Float(sym, lit_float_ty) = lit.node
67+
&& let ty::Float(fty) = *cx.typeck_results().expr_ty(expr).kind()
6968
{
7069
let sym_str = sym.as_str();
7170
let formatter = FloatFormat::new(sym_str);

clippy_lints/src/from_over_into.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,6 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
6666

6767
impl<'tcx> LateLintPass<'tcx> for FromOverInto {
6868
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
69-
if !self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) {
70-
return;
71-
}
72-
7369
if let ItemKind::Impl(Impl {
7470
of_trait: Some(hir_trait_ref),
7571
self_ty,
@@ -79,6 +75,8 @@ impl<'tcx> LateLintPass<'tcx> for FromOverInto {
7975
&& let Some(into_trait_seg) = hir_trait_ref.path.segments.last()
8076
// `impl Into<target_ty> for self_ty`
8177
&& let Some(GenericArgs { args: [GenericArg::Type(target_ty)], .. }) = into_trait_seg.args
78+
&& self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE)
79+
&& span_is_local(item.span)
8280
&& let Some(middle_trait_ref) = cx.tcx.impl_trait_ref(item.owner_id)
8381
.map(ty::EarlyBinder::instantiate_identity)
8482
&& cx.tcx.is_diagnostic_item(sym::Into, middle_trait_ref.def_id)

clippy_lints/src/from_str_radix_10.rs

+10-9
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,23 @@ impl<'tcx> LateLintPass<'tcx> for FromStrRadix10 {
4747
fn check_expr(&mut self, cx: &LateContext<'tcx>, exp: &Expr<'tcx>) {
4848
if let ExprKind::Call(maybe_path, [src, radix]) = &exp.kind
4949
&& let ExprKind::Path(QPath::TypeRelative(ty, pathseg)) = &maybe_path.kind
50-
// do not lint in constant context, because the suggestion won't work.
51-
// NB: keep this check until a new `const_trait_impl` is available and stablized.
52-
&& !in_constant(cx, exp.hir_id)
50+
51+
// check if the second argument is a primitive `10`
52+
&& is_integer_literal(radix, 10)
53+
54+
// check if the second part of the path indeed calls the associated
55+
// function `from_str_radix`
56+
&& pathseg.ident.name.as_str() == "from_str_radix"
5357

5458
// check if the first part of the path is some integer primitive
5559
&& let TyKind::Path(ty_qpath) = &ty.kind
5660
&& let ty_res = cx.qpath_res(ty_qpath, ty.hir_id)
5761
&& let def::Res::PrimTy(prim_ty) = ty_res
5862
&& matches!(prim_ty, PrimTy::Int(_) | PrimTy::Uint(_))
5963

60-
// check if the second part of the path indeed calls the associated
61-
// function `from_str_radix`
62-
&& pathseg.ident.name.as_str() == "from_str_radix"
63-
64-
// check if the second argument is a primitive `10`
65-
&& is_integer_literal(radix, 10)
64+
// do not lint in constant context, because the suggestion won't work.
65+
// NB: keep this check until a new `const_trait_impl` is available and stablized.
66+
&& !in_constant(cx, exp.hir_id)
6667
{
6768
let expr = if let ExprKind::AddrOf(_, _, expr) = &src.kind {
6869
let ty = cx.typeck_results().expr_ty(expr);

0 commit comments

Comments
 (0)