diff options
Diffstat (limited to 'clippy_utils/src')
| -rw-r--r-- | clippy_utils/src/ast_utils.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/attrs.rs | 4 | ||||
| -rw-r--r-- | clippy_utils/src/consts.rs | 13 | ||||
| -rw-r--r-- | clippy_utils/src/diagnostics.rs | 19 | ||||
| -rw-r--r-- | clippy_utils/src/eager_or_lazy.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/higher.rs | 19 | ||||
| -rw-r--r-- | clippy_utils/src/hir_utils.rs | 8 | ||||
| -rw-r--r-- | clippy_utils/src/lib.rs | 38 | ||||
| -rw-r--r-- | clippy_utils/src/numeric_literal.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/paths.rs | 22 | ||||
| -rw-r--r-- | clippy_utils/src/qualify_min_const_fn.rs | 8 | ||||
| -rw-r--r-- | clippy_utils/src/source.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/sugg.rs | 5 | ||||
| -rw-r--r-- | clippy_utils/src/ty.rs | 2 | ||||
| -rw-r--r-- | clippy_utils/src/usage.rs | 1 | ||||
| -rw-r--r-- | clippy_utils/src/visitors.rs | 60 |
16 files changed, 131 insertions, 76 deletions
diff --git a/clippy_utils/src/ast_utils.rs b/clippy_utils/src/ast_utils.rs index 7919800483f..b379f8c06c6 100644 --- a/clippy_utils/src/ast_utils.rs +++ b/clippy_utils/src/ast_utils.rs @@ -242,7 +242,7 @@ pub fn eq_item<K>(l: &Item<K>, r: &Item<K>, mut eq_kind: impl FnMut(&K, &K) -> b eq_id(l.ident, r.ident) && over(&l.attrs, &r.attrs, eq_attr) && eq_vis(&l.vis, &r.vis) && eq_kind(&l.kind, &r.kind) } -#[allow(clippy::too_many_lines)] // Just a big match statement +#[expect(clippy::too_many_lines)] // Just a big match statement pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool { use ItemKind::*; match (l, r) { diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 904b1a05ccc..49318849d58 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -1,12 +1,11 @@ use rustc_ast::ast; +use rustc_ast::attr; use rustc_errors::Applicability; use rustc_session::Session; -use rustc_ast::attr; use rustc_span::sym; use std::str::FromStr; /// Deprecation status of attributes known by Clippy. -#[allow(dead_code)] pub enum DeprecationStatus { /// Attribute is deprecated Deprecated, @@ -158,4 +157,3 @@ pub fn is_doc_hidden(attrs: &[ast::Attribute]) -> bool { .filter_map(ast::Attribute::meta_item_list) .any(|l| attr::list_contains_name(&l, sym::hidden)) } - diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index a80c7ee4929..9f162a117b2 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -13,7 +13,6 @@ use rustc_middle::ty::{self, EarlyBinder, FloatTy, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; -use std::convert::TryInto; use std::hash::{Hash, Hasher}; use std::iter; @@ -130,12 +129,10 @@ impl Constant { match (left, right) { (&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)), (&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)), - (&Self::Int(l), &Self::Int(r)) => { - if let ty::Int(int_ty) = *cmp_type.kind() { - Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))) - } else { - Some(l.cmp(&r)) - } + (&Self::Int(l), &Self::Int(r)) => match *cmp_type.kind() { + ty::Int(int_ty) => Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))), + ty::Uint(_) => Some(l.cmp(&r)), + _ => bug!("Not an int type"), }, (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r), (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r), @@ -352,7 +349,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> { } } - #[allow(clippy::cast_possible_wrap)] + #[expect(clippy::cast_possible_wrap)] fn constant_not(&self, o: &Constant, ty: Ty<'_>) -> Option<Constant> { use self::Constant::{Bool, Int}; match *o { diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index b142397f71b..04afe5ac373 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -77,7 +77,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult pub fn span_lint_and_help<'a, T: LintContext>( cx: &'a T, lint: &'static Lint, - span: Span, + span: impl Into<MultiSpan>, msg: &str, help_span: Option<Span>, help: &str, @@ -155,13 +155,7 @@ where }); } -pub fn span_lint_hir( - cx: &LateContext<'_>, - lint: &'static Lint, - hir_id: HirId, - sp: Span, - msg: &str, -) { +pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { cx.tcx.struct_span_lint_hir(lint, hir_id, sp, |diag| { let mut diag = diag.build(msg); docs_link(&mut diag, lint); @@ -278,14 +272,9 @@ pub fn span_lint_and_sugg_for_edges( let sugg_lines_count = sugg.lines().count(); if sugg_lines_count > MAX_SUGGESTION_HIGHLIGHT_LINES { let sm = cx.sess().source_map(); - if let (Ok(line_upper), Ok(line_bottom)) = - (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi())) - { + if let (Ok(line_upper), Ok(line_bottom)) = (sm.lookup_line(sp.lo()), sm.lookup_line(sp.hi())) { let split_idx = MAX_SUGGESTION_HIGHLIGHT_LINES / 2; - let span_upper = sm.span_until_char( - sp.with_hi(line_upper.sf.lines[line_upper.line + split_idx]), - '\n', - ); + let span_upper = sm.span_until_char(sp.with_hi(line_upper.sf.lines[line_upper.line + split_idx]), '\n'); let span_bottom = sp.with_lo(line_bottom.sf.lines[line_bottom.line - split_idx]); let sugg_lines_vec = sugg.lines().collect::<Vec<&str>>(); diff --git a/clippy_utils/src/eager_or_lazy.rs b/clippy_utils/src/eager_or_lazy.rs index a6ef6d79fc0..1a784b6cdda 100644 --- a/clippy_utils/src/eager_or_lazy.rs +++ b/clippy_utils/src/eager_or_lazy.rs @@ -96,7 +96,7 @@ fn fn_eagerness<'tcx>( } } -#[allow(clippy::too_many_lines)] +#[expect(clippy::too_many_lines)] fn expr_eagerness<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) -> EagernessSuggestion { struct V<'cx, 'tcx> { cx: &'cx LateContext<'tcx>, diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 2095fc966c5..1e0fc789af2 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -2,10 +2,11 @@ #![deny(clippy::missing_docs_in_private_items)] +use crate::consts::{constant_simple, Constant}; use crate::ty::is_type_diagnostic_item; use crate::{is_expn_of, match_def_path, paths}; use if_chain::if_chain; -use rustc_ast::ast::{self, LitKind}; +use rustc_ast::ast; use rustc_hir as hir; use rustc_hir::{Arm, Block, Expr, ExprKind, HirId, LoopSource, MatchSource, Node, Pat, QPath}; use rustc_lint::LateContext; @@ -431,7 +432,7 @@ pub enum VecInitKind { /// `Vec::default()` or `Default::default()` Default, /// `Vec::with_capacity(123)` - WithLiteralCapacity(u64), + WithConstCapacity(u128), /// `Vec::with_capacity(slice.len())` WithExprCapacity(HirId), } @@ -449,15 +450,11 @@ pub fn get_vec_init_kind<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) - return Some(VecInitKind::Default); } else if name.ident.name.as_str() == "with_capacity" { let arg = args.get(0)?; - if_chain! { - if let ExprKind::Lit(lit) = &arg.kind; - if let LitKind::Int(num, _) = lit.node; - then { - return Some(VecInitKind::WithLiteralCapacity(num.try_into().ok()?)); - } - } - return Some(VecInitKind::WithExprCapacity(arg.hir_id)); - } + return match constant_simple(cx, cx.typeck_results(), arg) { + Some(Constant::Int(num)) => Some(VecInitKind::WithConstCapacity(num)), + _ => Some(VecInitKind::WithExprCapacity(arg.hir_id)), + }; + }; }, ExprKind::Path(QPath::Resolved(_, path)) if match_def_path(cx, path.res.opt_def_id()?, &paths::DEFAULT_TRAIT_METHOD) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index aa21f15ee5d..c440793b90e 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -64,7 +64,6 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } } - #[allow(dead_code)] pub fn eq_block(&mut self, left: &Block<'_>, right: &Block<'_>) -> bool { self.inter_expr().eq_block(left, right) } @@ -194,7 +193,7 @@ impl HirEqInterExpr<'_, '_, '_> { res } - #[allow(clippy::similar_names)] + #[expect(clippy::similar_names)] pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool { if !self.inner.allow_side_effects && left.span.ctxt() != right.span.ctxt() { return false; @@ -361,7 +360,7 @@ impl HirEqInterExpr<'_, '_, '_> { } } - #[allow(clippy::similar_names)] + #[expect(clippy::similar_names)] fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool { match (left, right) { (&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => { @@ -407,7 +406,6 @@ impl HirEqInterExpr<'_, '_, '_> { left.ident.name == right.ident.name && both(&left.args, &right.args, |l, r| self.eq_path_parameters(l, r)) } - #[allow(clippy::similar_names)] pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool { match (&left.kind, &right.kind) { (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), @@ -562,7 +560,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&b.rules).hash(&mut self.s); } - #[allow(clippy::too_many_lines)] + #[expect(clippy::too_many_lines)] pub fn hash_expr(&mut self, e: &Expr<'_>) { let simple_const = self .maybe_typeck_results diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 6db7f247a99..adb37cc9d75 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2,6 +2,7 @@ #![feature(control_flow_enum)] #![feature(let_else)] #![feature(let_chains)] +#![feature(lint_reasons)] #![feature(once_cell)] #![feature(rustc_private)] #![recursion_limit = "512"] @@ -35,7 +36,6 @@ extern crate rustc_typeck; #[macro_use] pub mod sym_helper; -#[allow(clippy::module_name_repetitions)] pub mod ast_utils; pub mod attrs; pub mod comparisons; @@ -67,6 +67,7 @@ use std::sync::{Mutex, MutexGuard}; use if_chain::if_chain; use rustc_ast::ast::{self, LitKind}; +use rustc_ast::Attribute; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::unhash::UnhashMap; use rustc_hir as hir; @@ -77,9 +78,9 @@ use rustc_hir::intravisit::{walk_expr, FnKind, Visitor}; use rustc_hir::LangItem::{OptionNone, ResultErr, ResultOk}; use rustc_hir::{ def, Arm, ArrayLen, BindingAnnotation, Block, BlockCheckMode, Body, Constness, Destination, Expr, ExprKind, FnDecl, - HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, - Mutability, Node, Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, - TraitRef, TyKind, UnOp, + HirId, Impl, ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Mutability, Node, + Param, Pat, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, + UnOp, }; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::place::PlaceBase; @@ -116,8 +117,8 @@ pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Opt None } -pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool { - msrv.map_or(true, |msrv| msrv.meets(*lint_msrv)) +pub fn meets_msrv(msrv: Option<RustcVersion>, lint_msrv: RustcVersion) -> bool { + msrv.map_or(true, |msrv| msrv.meets(lint_msrv)) } #[macro_export] @@ -1554,14 +1555,14 @@ pub fn int_bits(tcx: TyCtxt<'_>, ity: rustc_ty::IntTy) -> u64 { Integer::from_int_ty(&tcx, ity).size().bits() } -#[allow(clippy::cast_possible_wrap)] +#[expect(clippy::cast_possible_wrap)] /// Turn a constant int byte representation into an i128 pub fn sext(tcx: TyCtxt<'_>, u: u128, ity: rustc_ty::IntTy) -> i128 { let amt = 128 - int_bits(tcx, ity); ((u as i128) << amt) >> amt } -#[allow(clippy::cast_sign_loss)] +#[expect(clippy::cast_sign_loss)] /// clip unused bytes pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: rustc_ty::IntTy) -> u128 { let amt = 128 - int_bits(tcx, ity); @@ -2123,6 +2124,27 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { }) } +/// Checks if the item containing the given `HirId` has `#[cfg(test)]` attribute applied +/// +/// Note: Add `// compile-flags: --test` to UI tests with a `#[cfg(test)]` function +pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { + fn is_cfg_test(attr: &Attribute) -> bool { + if attr.has_name(sym::cfg) + && let Some(items) = attr.meta_item_list() + && let [item] = &*items + && item.has_name(sym::test) + { + true + } else { + false + } + } + tcx.hir() + .parent_iter(id) + .flat_map(|(parent_id, _)| tcx.hir().attrs(parent_id)) + .any(is_cfg_test) +} + /// Checks whether item either has `test` attribute applied, or /// is a module with `test` in its name. /// diff --git a/clippy_utils/src/numeric_literal.rs b/clippy_utils/src/numeric_literal.rs index b92d42e8323..3fb5415ce02 100644 --- a/clippy_utils/src/numeric_literal.rs +++ b/clippy_utils/src/numeric_literal.rs @@ -1,7 +1,7 @@ use rustc_ast::ast::{Lit, LitFloatType, LitIntType, LitKind}; use std::iter; -#[derive(Debug, PartialEq, Copy, Clone)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum Radix { Binary, Octal, diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index 60971fb716d..9b9cbff2d14 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -43,9 +43,9 @@ pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_ITERATOR_METHOD: [&str; 6] = ["core", "iter", "traits", "collect", "FromIterator", "from_iter"]; pub const FROM_STR_METHOD: [&str; 5] = ["core", "str", "traits", "FromStr", "from_str"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"]; pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; @@ -63,7 +63,7 @@ pub const IPADDR_V4: [&str; 5] = ["std", "net", "ip", "IpAddr", "V4"]; pub const IPADDR_V6: [&str; 5] = ["std", "net", "ip", "IpAddr", "V6"]; pub const ITER_COUNT: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "count"]; pub const ITER_REPEAT: [&str; 5] = ["core", "iter", "sources", "repeat", "repeat"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"]; #[cfg(feature = "internal")] pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"]; @@ -117,17 +117,17 @@ pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; pub const REFCELL_REF: [&str; 3] = ["core", "cell", "Ref"]; pub const REFCELL_REFMUT: [&str; 3] = ["core", "cell", "RefMut"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_BYTES_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "bytes", "RegexBuilder", "new"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"]; /// Preferably use the diagnostic item `sym::Result` where possible pub const RESULT: [&str; 3] = ["core", "result", "Result"]; @@ -169,9 +169,9 @@ pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"]; pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]; pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"]; pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCREADEXT: [&str; 5] = ["tokio", "io", "util", "async_read_ext", "AsyncReadExt"]; -#[allow(clippy::invalid_paths)] // internal lints do not know about all external crates +#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_write_ext", "AsyncWriteExt"]; pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"]; pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 66d373a1bf8..a6d7042fabc 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -18,7 +18,7 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; -pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<&RustcVersion>) -> McfResult { +pub fn is_min_const_fn<'a, 'tcx>(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, msrv: Option<RustcVersion>) -> McfResult { let def_id = body.source.def_id(); let mut current = def_id; loop { @@ -268,7 +268,7 @@ fn check_terminator<'a, 'tcx>( tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Terminator<'tcx>, - msrv: Option<&RustcVersion>, + msrv: Option<RustcVersion>, ) -> McfResult { let span = terminator.source_info.span; match &terminator.kind { @@ -352,7 +352,7 @@ fn check_terminator<'a, 'tcx>( } } -fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> bool { +fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<RustcVersion>) -> bool { tcx.is_const_fn(def_id) && tcx.lookup_const_stability(def_id).map_or(true, |const_stab| { if let rustc_attr::StabilityLevel::Stable { since } = const_stab.level { @@ -361,7 +361,7 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<&RustcVersion>) -> b // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. crate::meets_msrv( msrv, - &RustcVersion::parse(since.as_str()) + RustcVersion::parse(since.as_str()) .expect("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted"), ) } else { diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index c69a3d8d2a1..04ef2f57447 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -137,7 +137,7 @@ pub fn position_before_rarrow(s: &str) -> Option<usize> { } /// Reindent a multiline string with possibility of ignoring the first line. -#[allow(clippy::needless_pass_by_value)] +#[expect(clippy::needless_pass_by_value)] pub fn reindent_multiline(s: Cow<'_, str>, ignore_first: bool, indent: Option<usize>) -> Cow<'_, str> { let s_space = reindent_multiline_inner(&s, ignore_first, indent, ' '); let s_tab = reindent_multiline_inner(&s_space, ignore_first, indent, '\t'); diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 18915553e61..1de73a80ad2 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -17,7 +17,6 @@ use rustc_middle::ty; use rustc_span::source_map::{BytePos, CharPos, Pos, Span, SyntaxContext}; use rustc_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use std::borrow::Cow; -use std::convert::TryInto; use std::fmt::{Display, Write as _}; use std::iter; use std::ops::{Add, Neg, Not, Sub}; @@ -50,7 +49,7 @@ impl Display for Sugg<'_> { } } -#[allow(clippy::wrong_self_convention)] // ok, because of the function `as_ty` method +#[expect(clippy::wrong_self_convention)] // ok, because of the function `as_ty` method impl<'a> Sugg<'a> { /// Prepare a suggestion from an expression. pub fn hir_opt(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Self> { @@ -318,7 +317,6 @@ impl<'a> Sugg<'a> { /// Convenience method to create the `<lhs>..<rhs>` or `<lhs>...<rhs>` /// suggestion. - #[allow(dead_code)] pub fn range(self, end: &Self, limit: ast::RangeLimits) -> Sugg<'static> { match limit { ast::RangeLimits::HalfOpen => make_assoc(AssocOp::DotDot, &self, end), @@ -886,7 +884,6 @@ impl<'tcx> DerefDelegate<'_, 'tcx> { impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> { fn consume(&mut self, _: &PlaceWithHirId<'tcx>, _: HirId) {} - #[allow(clippy::too_many_lines)] fn borrow(&mut self, cmt: &PlaceWithHirId<'tcx>, _: HirId, _: ty::BorrowKind) { if let PlaceBase::Local(id) = cmt.place.base { let map = self.cx.tcx.hir(); diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs index b09eb8c6cd1..07d3d280763 100644 --- a/clippy_utils/src/ty.rs +++ b/clippy_utils/src/ty.rs @@ -603,7 +603,7 @@ impl core::ops::Add<u32> for EnumValue { } /// Attempts to read the given constant as though it were an an enum value. -#[allow(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] +#[expect(clippy::cast_possible_truncation, clippy::cast_possible_wrap)] pub fn read_explicit_enum_value(tcx: TyCtxt<'_>, id: DefId) -> Option<EnumValue> { if let Ok(ConstValue::Scalar(Scalar::Int(value))) = tcx.const_eval_poly(id) { match tcx.type_of(id).kind() { diff --git a/clippy_utils/src/usage.rs b/clippy_utils/src/usage.rs index 4236e3aae2f..abba9b00558 100644 --- a/clippy_utils/src/usage.rs +++ b/clippy_utils/src/usage.rs @@ -44,7 +44,6 @@ struct MutVarsDelegate { } impl<'tcx> MutVarsDelegate { - #[allow(clippy::similar_names)] fn update(&mut self, cat: &PlaceWithHirId<'tcx>) { match cat.place.base { PlaceBase::Local(id) => { diff --git a/clippy_utils/src/visitors.rs b/clippy_utils/src/visitors.rs index c00bc2bd213..b6c8f1d516e 100644 --- a/clippy_utils/src/visitors.rs +++ b/clippy_utils/src/visitors.rs @@ -1,4 +1,4 @@ -use crate::path_to_local_id; +use crate::{get_enclosing_block, path_to_local_id}; use core::ops::ControlFlow; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -436,3 +436,61 @@ pub fn for_each_value_source<'tcx, B>( _ => f(e), } } + +/// Runs the given function for each path expression referencing the given local which occur after +/// the given expression. +pub fn for_each_local_use_after_expr<'tcx, B>( + cx: &LateContext<'tcx>, + local_id: HirId, + expr_id: HirId, + f: impl FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, +) -> ControlFlow<B> { + struct V<'cx, 'tcx, F, B> { + cx: &'cx LateContext<'tcx>, + local_id: HirId, + expr_id: HirId, + found: bool, + res: ControlFlow<B>, + f: F, + } + impl<'cx, 'tcx, F: FnMut(&'tcx Expr<'tcx>) -> ControlFlow<B>, B> Visitor<'tcx> for V<'cx, 'tcx, F, B> { + type NestedFilter = nested_filter::OnlyBodies; + fn nested_visit_map(&mut self) -> Self::Map { + self.cx.tcx.hir() + } + + fn visit_expr(&mut self, e: &'tcx Expr<'tcx>) { + if !self.found { + if e.hir_id == self.expr_id { + self.found = true; + } else { + walk_expr(self, e); + } + return; + } + if self.res.is_break() { + return; + } + if path_to_local_id(e, self.local_id) { + self.res = (self.f)(e); + } else { + walk_expr(self, e); + } + } + } + + if let Some(b) = get_enclosing_block(cx, local_id) { + let mut v = V { + cx, + local_id, + expr_id, + found: false, + res: ControlFlow::Continue(()), + f, + }; + v.visit_block(b); + v.res + } else { + ControlFlow::Continue(()) + } +} |
