summary refs log tree commit diff
path: root/src/tools/clippy/clippy_lints
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints')
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs33
-rw-r--r--src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/ptr.rs35
3 files changed, 41 insertions, 29 deletions
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index dcfee0b6d3c..182cb4e46d2 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -95,14 +95,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 return;
             };
 
-            if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
-                span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
-                return;
-            }
-
             if then_search.edits.is_empty() && else_search.edits.is_empty() {
                 // No insertions
                 return;
+            } else if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
+                // If there are other uses of the key, and the key is not copy,
+                // we cannot perform a fix automatically, but continue to emit a lint.
+                None
             } else if then_search.edits.is_empty() || else_search.edits.is_empty() {
                 // if .. { insert } else { .. } or if .. { .. } else { insert }
                 let ((then_str, entry_kind), else_str) = match (else_search.edits.is_empty(), contains_expr.negated) {
@@ -123,10 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                         snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app),
                     ),
                 };
-                format!(
+                Some(format!(
                     "if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
                     map_ty.entry_path(),
-                )
+                ))
             } else {
                 // if .. { insert } else { insert }
                 let ((then_str, then_entry), (else_str, else_entry)) = if contains_expr.negated {
@@ -142,13 +141,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 };
                 let indent_str = snippet_indent(cx, expr.span);
                 let indent_str = indent_str.as_deref().unwrap_or("");
-                format!(
+                Some(format!(
                     "match {map_str}.entry({key_str}) {{\n{indent_str}    {entry}::{then_entry} => {}\n\
                         {indent_str}    {entry}::{else_entry} => {}\n{indent_str}}}",
                     reindent_multiline(&then_str, true, Some(4 + indent_str.len())),
                     reindent_multiline(&else_str, true, Some(4 + indent_str.len())),
                     entry = map_ty.entry_path(),
-                )
+                ))
             }
         } else {
             if then_search.edits.is_empty() {
@@ -163,17 +162,17 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
                 } else {
                     then_search.snippet_occupied(cx, then_expr.span, &mut app)
                 };
-                format!(
+                Some(format!(
                     "if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
                     map_ty.entry_path(),
-                )
+                ))
             } else if let Some(insertion) = then_search.as_single_insertion() {
                 let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
                 if contains_expr.negated {
                     if insertion.value.can_have_side_effects() {
-                        format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
+                        Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});"))
                     } else {
-                        format!("{map_str}.entry({key_str}).or_insert({value_str});")
+                        Some(format!("{map_str}.entry({key_str}).or_insert({value_str});"))
                     }
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@@ -183,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             } else {
                 let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
                 if contains_expr.negated {
-                    format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
+                    Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});"))
                 } else {
                     // TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
                     // This would need to be a different lint.
@@ -192,7 +191,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
             }
         };
 
-        span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
+        if let Some(sugg) = sugg {
+            span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
+        } else {
+            span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
+        }
     }
 }
 
diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
index 576e42a564c..026b00e3aa2 100644
--- a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs
@@ -85,7 +85,7 @@ fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool
 /// contains `Err(IDENT)`, `None` otherwise.
 fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'hir Ident)> {
     if let PatKind::TupleStruct(qpath, [arg], _) = &pat.kind
-        && let PatKind::Binding(BindingMode::NONE, _, ident, _) = &arg.kind
+        && let PatKind::Binding(BindingMode::NONE, _, ident, None) = &arg.kind
         && let res = cx.qpath_res(qpath, pat.hir_id)
         && let Res::Def(DefKind::Ctor(..), id) = res
         && let id @ Some(_) = cx.tcx.opt_parent(id)
diff --git a/src/tools/clippy/clippy_lints/src/ptr.rs b/src/tools/clippy/clippy_lints/src/ptr.rs
index 55f1ece0559..596f1e3471f 100644
--- a/src/tools/clippy/clippy_lints/src/ptr.rs
+++ b/src/tools/clippy/clippy_lints/src/ptr.rs
@@ -786,9 +786,9 @@ fn check_ptr_eq<'tcx>(
     }
 
     // Remove one level of usize conversion if any
-    let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
-        (Some(lhs), Some(rhs)) => (lhs, rhs),
-        _ => (left, right),
+    let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
+        (Some(lhs), Some(rhs)) => (lhs, rhs, true),
+        _ => (left, right, false),
     };
 
     // This lint concerns raw pointers
@@ -797,10 +797,16 @@ fn check_ptr_eq<'tcx>(
         return;
     }
 
-    let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
+    let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
+        (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
 
-    if let Some(left_snip) = left_var.span.get_source_text(cx)
-        && let Some(right_snip) = right_var.span.get_source_text(cx)
+    if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
+        return;
+    }
+
+    let mut app = Applicability::MachineApplicable;
+    let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
+    let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app);
     {
         let Some(top_crate) = std_or_core(cx) else { return };
         let invert = if op == BinOpKind::Eq { "" } else { "!" };
@@ -811,7 +817,7 @@ fn check_ptr_eq<'tcx>(
             format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
             "try",
             format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"),
-            Applicability::MachineApplicable,
+            app,
         );
     }
 }
@@ -819,7 +825,8 @@ fn check_ptr_eq<'tcx>(
 // If the given expression is a cast to a usize, return the lhs of the cast
 // E.g., `foo as *const _ as usize` returns `foo as *const _`.
 fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
-    if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
+    if !cast_expr.span.from_expansion()
+        && cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
         && let ExprKind::Cast(expr, _) = cast_expr.kind
     {
         Some(expr)
@@ -828,16 +835,18 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
     }
 }
 
-// Peel raw casts if the remaining expression can be coerced to it
-fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
-    if let ExprKind::Cast(inner, _) = expr.kind
+// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
+// peeled or not.
+fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
+    if !expr.span.from_expansion()
+        && let ExprKind::Cast(inner, _) = expr.kind
         && let ty::RawPtr(target_ty, _) = expr_ty.kind()
         && let inner_ty = cx.typeck_results().expr_ty(inner)
         && let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
         && target_ty == inner_target_ty
     {
-        peel_raw_casts(cx, inner, inner_ty)
+        (peel_raw_casts(cx, inner, inner_ty).0, true)
     } else {
-        expr
+        (expr, false)
     }
 }