summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/len_zero.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/clippy_lints/src/len_zero.rs26
1 files changed, 17 insertions, 9 deletions
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 4c133c06a..3c70c9cf1 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -1,13 +1,13 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed};
+use clippy_utils::{get_item_name, get_parent_as_impl, is_lint_allowed, peel_ref_operators};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::{
def_id::DefId, AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, ImplItem, ImplItemKind, ImplicitSelfKind, Item,
- ItemKind, Mutability, Node, TraitItemRef, TyKind,
+ ItemKind, Mutability, Node, TraitItemRef, TyKind, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -16,6 +16,7 @@ use rustc_span::{
source_map::{Span, Spanned, Symbol},
symbol::sym,
};
+use std::borrow::Cow;
declare_clippy_lint! {
/// ### What it does
@@ -218,7 +219,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, trait_items
let is_empty = sym!(is_empty);
let is_empty_method_found = current_and_super_traits
- .iter()
+ .items()
.flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(is_empty))
.any(|i| {
i.kind == ty::AssocKind::Fn
@@ -360,7 +361,7 @@ fn check_for_is_empty<'tcx>(
db.span_note(span, "`is_empty` defined here");
}
if let Some(self_kind) = self_kind {
- db.note(&output.expected_sig(self_kind));
+ db.note(output.expected_sig(self_kind));
}
});
}
@@ -428,16 +429,23 @@ fn check_len(
fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
let mut applicability = Applicability::MachineApplicable;
+
+ let lit1 = peel_ref_operators(cx, lit1);
+ let mut lit_str = snippet_with_applicability(cx, lit1.span, "_", &mut applicability);
+
+ // Wrap the expression in parentheses if it's a deref expression. Otherwise operator precedence will
+ // cause the code to dereference boolean(won't compile).
+ if let ExprKind::Unary(UnOp::Deref, _) = lit1.kind {
+ lit_str = Cow::from(format!("({lit_str})"));
+ }
+
span_lint_and_sugg(
cx,
COMPARISON_TO_EMPTY,
span,
"comparison to empty slice",
&format!("using `{op}is_empty` is clearer and more explicit"),
- format!(
- "{op}{}.is_empty()",
- snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
- ),
+ format!("{op}{lit_str}.is_empty()"),
applicability,
);
}
@@ -493,7 +501,7 @@ fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
.filter_by_name_unhygienic(is_empty)
.any(|item| is_is_empty(cx, item))
}),
- ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
+ ty::Alias(ty::Projection, ref proj) => has_is_empty_impl(cx, proj.def_id),
ty::Adt(id, _) => has_is_empty_impl(cx, id.did()),
ty::Array(..) | ty::Slice(..) | ty::Str => true,
_ => false,