use clippy_utils::diagnostics::{
multispan_sugg, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then,
};
-use clippy_utils::higher;
+use clippy_utils::macros::{is_panic, root_macro_call};
use clippy_utils::source::{expr_block, indent_of, snippet, snippet_block, snippet_opt, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type, peel_mid_ty_refs};
use clippy_utils::visitors::is_local_used;
use clippy_utils::{
- get_parent_expr, is_expn_of, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs,
- path_to_local, path_to_local_id, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns, remove_blocks,
+ get_parent_expr, is_lang_ctor, is_lint_allowed, is_refutable, is_unit_expr, is_wild, meets_msrv, msrvs,
+ path_to_local, path_to_local_id, peel_blocks, peel_hir_pat_refs, peel_n_hir_expr_refs, recurse_or_patterns,
strip_pat_refs,
};
+use clippy_utils::{higher, peel_blocks_with_stmt};
use clippy_utils::{paths, search_same, SpanlessEq, SpanlessHash};
-use core::array;
use core::iter::{once, ExactSizeIterator};
use if_chain::if_chain;
use rustc_ast::ast::{Attribute, LitKind};
Mutability, Node, Pat, PatKind, PathSegment, QPath, RangeEnd, TyKind,
};
use rustc_hir::{HirIdMap, HirIdSet};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty, TyS, VariantDef};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{Span, Spanned};
-use rustc_span::sym;
+use rustc_span::{sym, symbol::kw};
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
QPath::Resolved(None, variant_name), args, _) = arms[0].pat.kind;
if args.len() == 1;
if let PatKind::Binding(_, arg, ..) = strip_pat_refs(&args[0]).kind;
- let body = remove_blocks(arms[0].body);
+ let body = peel_blocks(arms[0].body);
if path_to_local_id(body, arg);
then {
return;
}
let els = arms[1].body;
- let els = if is_unit_expr(remove_blocks(els)) {
+ let els = if is_unit_expr(peel_blocks(els)) {
None
} else if let ExprKind::Block(Block { stmts, expr: block_expr, .. }, _) = els.kind {
if stmts.len() == 1 && block_expr.is_none() || stmts.is_empty() && block_expr.is_some() {
let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false));
if path_str == "Err" {
let mut matching_wild = inner.iter().any(is_wild);
- let mut ident_bind_name = String::from("_");
+ let mut ident_bind_name = kw::Underscore;
if !matching_wild {
// Looking for unused bindings (i.e.: `_e`)
for pat in inner.iter() {
if let PatKind::Binding(_, id, ident, None) = pat.kind {
if ident.as_str().starts_with('_') && !is_local_used(cx, arm.body, id) {
- ident_bind_name = (&ident.name.as_str()).to_string();
+ ident_bind_name = ident.name;
matching_wild = true;
}
}
}
if_chain! {
if matching_wild;
- if is_panic_call(arm.body);
+ if let Some(macro_call) = root_macro_call(peel_blocks_with_stmt(arm.body).span);
+ if is_panic(cx, macro_call.def_id);
then {
// `Err(_)` or `Err(_e)` arm with `panic!` found
span_lint_and_note(cx,
MATCH_WILD_ERR_ARM,
arm.pat.span,
- &format!("`Err({})` matches all errors", &ident_bind_name),
+ &format!("`Err({})` matches all errors", ident_bind_name),
None,
"match each error separately or use the error output, or use `.except(msg)` if the error case is unreachable",
);
Path(&'a [PathSegment<'a>]),
Mixed,
}
-impl CommonPrefixSearcher<'a> {
+impl<'a> CommonPrefixSearcher<'a> {
fn with_path(&mut self, path: &'a [PathSegment<'a>]) {
match path {
[path @ .., _] => self.with_prefix(path),
PatKind::Path(path) => {
#[allow(clippy::match_same_arms)]
let id = match cx.qpath_res(path, pat.hir_id) {
- Res::Def(DefKind::Const | DefKind::ConstParam | DefKind::AnonConst, _) => return,
+ Res::Def(
+ DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
+ _,
+ ) => return,
Res::Def(_, id) => id,
_ => return,
};
if let CommonPrefixSearcher::Path(path_prefix) = path_prefix {
let mut s = String::new();
for seg in path_prefix {
- s.push_str(&seg.ident.as_str());
+ s.push_str(seg.ident.as_str());
s.push_str("::");
}
s
s.push_str("::");
s
},
- variant.ident.name,
+ variant.name,
match variant.ctor_kind {
CtorKind::Fn if variant.fields.len() == 1 => "(_)",
CtorKind::Fn => "(..)",
};
}
-// If the block contains only a `panic!` macro (as expression or statement)
-fn is_panic_call(expr: &Expr<'_>) -> bool {
- // Unwrap any wrapping blocks
- let span = if let ExprKind::Block(block, _) = expr.kind {
- match (&block.expr, block.stmts.len(), block.stmts.first()) {
- (&Some(exp), 0, _) => exp.span,
- (&None, 1, Some(stmt)) => stmt.span,
- _ => return false,
- }
- } else {
- expr.span
- };
-
- is_expn_of(span, "panic").is_some() && is_expn_of(span, "unreachable").is_none()
-}
-
fn check_match_ref_pats<'a, 'b, I>(cx: &LateContext<'_>, ex: &Expr<'_>, pats: I, expr: &Expr<'_>)
where
'b: 'a,
return find_matches_sugg(
cx,
let_expr,
- array::IntoIter::new([(&[][..], Some(let_pat), if_then, None), (&[][..], None, if_else, None)]),
+ IntoIterator::into_iter([(&[][..], Some(let_pat), if_then, None), (&[][..], None, if_else, None)]),
expr,
true,
);
let matched_vars = ex.span;
let bind_names = arms[0].pat.span;
- let match_body = remove_blocks(arms[0].body);
+ let match_body = peel_blocks(arms[0].body);
let mut snippet_body = if match_body.span.from_expansion() {
Sugg::hir_with_macro_callsite(cx, match_body, "..").to_string()
} else {
if is_lang_ctor(cx, qpath, OptionSome);
if let PatKind::Binding(rb, .., ident, _) = first_pat.kind;
if rb == BindingAnnotation::Ref || rb == BindingAnnotation::RefMut;
- if let ExprKind::Call(e, args) = remove_blocks(arm.body).kind;
+ if let ExprKind::Call(e, args) = peel_blocks(arm.body).kind;
if let ExprKind::Path(ref some_path) = e.kind;
if is_lang_ctor(cx, some_path, OptionSome) && args.len() == 1;
if let ExprKind::Path(QPath::Resolved(_, path2)) = args[0].kind;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
use rustc_hir::{
- intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor},
+ intravisit::{walk_expr, Visitor},
Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, Pat, PatKind, QPath, UnOp,
};
use rustc_lint::LateContext;
/// Checks if the drop order for a type matters. Some std types implement drop solely to
/// deallocate memory. For these types, and composites containing them, changing the drop order
/// won't result in any observable side effects.
- fn type_needs_ordered_drop(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
+ fn type_needs_ordered_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
type_needs_ordered_drop_inner(cx, ty, &mut FxHashSet::default())
}
- fn type_needs_ordered_drop_inner(cx: &LateContext<'tcx>, ty: Ty<'tcx>, seen: &mut FxHashSet<Ty<'tcx>>) -> bool {
+ fn type_needs_ordered_drop_inner<'tcx>(
+ cx: &LateContext<'tcx>,
+ ty: Ty<'tcx>,
+ seen: &mut FxHashSet<Ty<'tcx>>,
+ ) -> bool {
if !seen.insert(ty) {
return false;
}
// Checks if there are any temporaries created in the given expression for which drop order
// matters.
- fn temporaries_need_ordered_drop(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
+ fn temporaries_need_ordered_drop<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> bool {
struct V<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
res: bool,
}
impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> {
- type Map = ErasedMap<'tcx>;
- fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
- NestedVisitorMap::None
- }
-
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
match expr.kind {
// Taking the reference of a value leaves a temporary
},
// Method calls can take self by reference.
// e.g. In `String::new().len()` the string is a temporary value.
- ExprKind::MethodCall(_, _, [self_arg, args @ ..], _) => {
+ ExprKind::MethodCall(_, [self_arg, args @ ..], _) => {
if !matches!(self_arg.kind, ExprKind::Path(_)) {
let self_by_ref = self
.cx
// check that `while_let_on_iterator` lint does not trigger
if_chain! {
if keyword == "while";
- if let ExprKind::MethodCall(method_path, _, _, _) = let_expr.kind;
+ if let ExprKind::MethodCall(method_path, _, _) = let_expr.kind;
if method_path.ident.name == sym::next;
if is_trait_method(cx, let_expr, sym::Iterator);
then {