about summary refs log tree commit diff
path: root/clippy_utils/src
diff options
context:
space:
mode:
Diffstat (limited to 'clippy_utils/src')
-rw-r--r--clippy_utils/src/consts.rs2
-rw-r--r--clippy_utils/src/higher.rs2
-rw-r--r--clippy_utils/src/hir_utils.rs6
-rw-r--r--clippy_utils/src/lib.rs19
-rw-r--r--clippy_utils/src/msrvs.rs1
-rw-r--r--clippy_utils/src/paths.rs2
-rw-r--r--clippy_utils/src/qualify_min_const_fn.rs21
-rw-r--r--clippy_utils/src/source.rs23
-rw-r--r--clippy_utils/src/ty.rs22
9 files changed, 71 insertions, 27 deletions
diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs
index 9f162a117b2..d487868cafe 100644
--- a/clippy_utils/src/consts.rs
+++ b/clippy_utils/src/consts.rs
@@ -478,7 +478,7 @@ impl<'a, 'tcx> ConstEvalLateContext<'a, 'tcx> {
     fn ifthenelse(&mut self, cond: &Expr<'_>, then: &Expr<'_>, otherwise: Option<&Expr<'_>>) -> Option<Constant> {
         if let Some(Constant::Bool(b)) = self.expr(cond) {
             if b {
-                self.expr(&*then)
+                self.expr(then)
             } else {
                 otherwise.as_ref().and_then(|expr| self.expr(expr))
             }
diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs
index 1e0fc789af2..4604ae5c2c7 100644
--- a/clippy_utils/src/higher.rs
+++ b/clippy_utils/src/higher.rs
@@ -35,7 +35,7 @@ impl<'tcx> ForLoop<'tcx> {
             if let hir::ExprKind::Match(iterexpr, [arm], hir::MatchSource::ForLoopDesugar) = e.kind;
             if let hir::ExprKind::Call(_, [arg]) = iterexpr.kind;
             if let hir::ExprKind::Loop(block, ..) = arm.body.kind;
-            if let [stmt] = &*block.stmts;
+            if let [stmt] = block.stmts;
             if let hir::StmtKind::Expr(e) = stmt.kind;
             if let hir::ExprKind::Match(_, [_, some_arm], _) = e.kind;
             if let hir::PatKind::Struct(_, [field], _) = some_arm.pat.kind;
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index fc1a4e1f602..0603471c343 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -411,10 +411,10 @@ impl HirEqInterExpr<'_, '_, '_> {
             (&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
             (&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_array_length(ll, rl),
             (&TyKind::Ptr(ref l_mut), &TyKind::Ptr(ref r_mut)) => {
-                l_mut.mutbl == r_mut.mutbl && self.eq_ty(&*l_mut.ty, &*r_mut.ty)
+                l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty)
             },
             (&TyKind::Rptr(_, ref l_rmut), &TyKind::Rptr(_, ref r_rmut)) => {
-                l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(&*l_rmut.ty, &*r_rmut.ty)
+                l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
             },
             (&TyKind::Path(ref l), &TyKind::Path(ref r)) => self.eq_qpath(l, r),
             (&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
@@ -608,7 +608,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_name(i.ident.name);
                 }
                 if let Some(j) = *j {
-                    self.hash_expr(&*j);
+                    self.hash_expr(j);
                 }
             },
             ExprKind::Box(e) | ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 833f8cde63a..5f051e3f444 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1443,7 +1443,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         },
         PatKind::Tuple(pats, _) => are_refutable(cx, pats),
         PatKind::Struct(ref qpath, fields, _) => {
-            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat))
+            is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| field.pat))
         },
         PatKind::TupleStruct(ref qpath, pats, _) => is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats),
         PatKind::Slice(head, middle, tail) => {
@@ -1658,7 +1658,7 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
     let mut blocks: Vec<&Block<'_>> = Vec::new();
 
     while let Some(higher::IfOrIfLet { cond, then, r#else }) = higher::IfOrIfLet::hir(expr) {
-        conds.push(&*cond);
+        conds.push(cond);
         if let ExprKind::Block(block, _) = then.kind {
             blocks.push(block);
         } else {
@@ -1916,7 +1916,17 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
                 ..
             },
             ..,
-        ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
+        ) => {
+            // Only return Fn-like DefIds, not the DefIds of statics/consts/etc that contain or
+            // deref to fn pointers, dyn Fn, impl Fn - #8850
+            if let Res::Def(DefKind::Fn | DefKind::Ctor(..) | DefKind::AssocFn, id) =
+                cx.typeck_results().qpath_res(qpath, *path_hir_id)
+            {
+                Some(id)
+            } else {
+                None
+            }
+        },
         _ => None,
     }
 }
@@ -2073,7 +2083,8 @@ static TEST_ITEM_NAMES_CACHE: SyncOnceCell<Mutex<FxHashMap<LocalDefId, Vec<Symbo
 fn with_test_item_names<'tcx>(tcx: TyCtxt<'tcx>, module: LocalDefId, f: impl Fn(&[Symbol]) -> bool) -> bool {
     let cache = TEST_ITEM_NAMES_CACHE.get_or_init(|| Mutex::new(FxHashMap::default()));
     let mut map: MutexGuard<'_, FxHashMap<LocalDefId, Vec<Symbol>>> = cache.lock().unwrap();
-    match map.entry(module) {
+    let value = map.entry(module);
+    match value {
         Entry::Occupied(entry) => f(entry.get()),
         Entry::Vacant(entry) => {
             let mut names = Vec::new();
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index 134fd1ce505..b9ec2c19fdd 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -30,6 +30,7 @@ msrv_aliases! {
     1,34,0 { TRY_FROM }
     1,30,0 { ITERATOR_FIND_MAP, TOOL_ATTRIBUTES }
     1,28,0 { FROM_BOOL }
+    1,26,0 { RANGE_INCLUSIVE }
     1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
     1,16,0 { STR_REPEAT }
     1,24,0 { IS_ASCII_DIGIT }
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 9b9cbff2d14..89789c3d851 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -73,6 +73,7 @@ pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 #[cfg(feature = "internal")]
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
+pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
 pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
 pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 /// Preferably use the diagnostic item `sym::Option` where possible
@@ -141,6 +142,7 @@ pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
 pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
 pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
+pub const SLICE_GET: [&str; 4] = ["core", "slice", "<impl [T]>", "get"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
 pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs
index 58abef38ea8..498dcbb8900 100644
--- a/clippy_utils/src/qualify_min_const_fn.rs
+++ b/clippy_utils/src/qualify_min_const_fn.rs
@@ -121,24 +121,18 @@ fn check_rvalue<'tcx>(
 ) -> McfResult {
     match rvalue {
         Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
-        Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => check_operand(tcx, operand, span, body),
         Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
             check_place(tcx, *place, span, body)
         },
-        Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
-            Err((span, "casting pointers to ints is unstable in const fn".into()))
-        },
-        Rvalue::Cast(CastKind::Misc, operand, _) => {
-            check_operand(tcx, operand, span, body)
-        },
-        Rvalue::Cast(
+        Rvalue::Repeat(operand, _)
+        | Rvalue::Use(operand)
+        | Rvalue::Cast(
             CastKind::PointerFromExposedAddress
+            | CastKind::Misc
             | CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
             operand,
-            _
-        ) => {
-            check_operand(tcx, operand, span, body)
-        },
+            _,
+        ) => check_operand(tcx, operand, span, body),
         Rvalue::Cast(
             CastKind::Pointer(
                 PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer,
@@ -163,6 +157,9 @@ fn check_rvalue<'tcx>(
                 Err((span, "unsizing casts are not allowed in const fn".into()))
             }
         },
+        Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => {
+            Err((span, "casting pointers to ints is unstable in const fn".into()))
+        },
         // binops are fine on integers
         Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => {
             check_operand(tcx, lhs, span, body)?;
diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs
index 04ef2f57447..f88a92fb11c 100644
--- a/clippy_utils/src/source.rs
+++ b/clippy_utils/src/source.rs
@@ -8,7 +8,7 @@ use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_span::hygiene;
 use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, Pos, Span, SyntaxContext};
+use rustc_span::{BytePos, Pos, Span, SpanData, SyntaxContext};
 use std::borrow::Cow;
 
 /// Checks if the span starts with the given text. This will return false if the span crosses
@@ -389,6 +389,27 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
     without
 }
 
+/// Trims the whitespace from the start and the end of the span.
+pub fn trim_span(sm: &SourceMap, span: Span) -> Span {
+    let data = span.data();
+    let sf: &_ = &sm.lookup_source_file(data.lo);
+    let Some(src) = sf.src.as_deref() else {
+        return span;
+    };
+    let Some(snip) = &src.get((data.lo - sf.start_pos).to_usize()..(data.hi - sf.start_pos).to_usize()) else {
+        return span;
+    };
+    let trim_start = snip.len() - snip.trim_start().len();
+    let trim_end = snip.len() - snip.trim_end().len();
+    SpanData {
+        lo: data.lo + BytePos::from_usize(trim_start),
+        hi: data.hi - BytePos::from_usize(trim_end),
+        ctxt: data.ctxt,
+        parent: data.parent,
+    }
+    .span()
+}
+
 #[cfg(test)]
 mod test {
     use super::{reindent_multiline, without_block_comments};
diff --git a/clippy_utils/src/ty.rs b/clippy_utils/src/ty.rs
index 75d27d3b594..a10515d2fec 100644
--- a/clippy_utils/src/ty.rs
+++ b/clippy_utils/src/ty.rs
@@ -13,7 +13,8 @@ use rustc_lint::LateContext;
 use rustc_middle::mir::interpret::{ConstValue, Scalar};
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
 use rustc_middle::ty::{
-    self, AdtDef, Binder, FnSig, IntTy, Predicate, PredicateKind, Ty, TyCtxt, TypeFoldable, UintTy, VariantDiscr,
+    self, AdtDef, Binder, FnSig, IntTy, ParamEnv, Predicate, PredicateKind, Ty, TyCtxt, TypeFoldable, UintTy,
+    VariantDiscr,
 };
 use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol, DUMMY_SP};
@@ -152,17 +153,28 @@ pub fn implements_trait<'tcx>(
     trait_id: DefId,
     ty_params: &[GenericArg<'tcx>],
 ) -> bool {
+    implements_trait_with_env(cx.tcx, cx.param_env, ty, trait_id, ty_params)
+}
+
+/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
+pub fn implements_trait_with_env<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ParamEnv<'tcx>,
+    ty: Ty<'tcx>,
+    trait_id: DefId,
+    ty_params: &[GenericArg<'tcx>],
+) -> bool {
     // Clippy shouldn't have infer types
     assert!(!ty.needs_infer());
 
-    let ty = cx.tcx.erase_regions(ty);
+    let ty = tcx.erase_regions(ty);
     if ty.has_escaping_bound_vars() {
         return false;
     }
-    let ty_params = cx.tcx.mk_substs(ty_params.iter());
-    cx.tcx.infer_ctxt().enter(|infcx| {
+    let ty_params = tcx.mk_substs(ty_params.iter());
+    tcx.infer_ctxt().enter(|infcx| {
         infcx
-            .type_implements_trait(trait_id, ty, ty_params, cx.param_env)
+            .type_implements_trait(trait_id, ty, ty_params, param_env)
             .must_apply_modulo_regions()
     })
 }