about summary refs log tree commit diff
diff options
context:
space:
mode:
authordswij <dswijj@gmail.com>2021-10-25 12:29:05 +0800
committerdswij <dswijj@gmail.com>2021-11-11 12:30:07 +0800
commit2d037aa4a66edb601fb65fb3efdc573771cba3e2 (patch)
treed7951f9baabccf11f9aa1299413fa629ef74c289
parent847a95b68283ee682eca9d01067ae9620d1bd296 (diff)
downloadrust-2d037aa4a66edb601fb65fb3efdc573771cba3e2.tar.gz
rust-2d037aa4a66edb601fb65fb3efdc573771cba3e2.zip
Check for no_std and no_core attribute in `swap` lint
This commit adds a `no_std` and `no_core` check on `swap` lint and additionally suggest `core::mem::swap` whenever possible.
Remove warning if both `std` and `core` is not present.
-rw-r--r--clippy_lints/src/lib.rs1
-rw-r--r--clippy_lints/src/swap.rs48
-rw-r--r--clippy_utils/src/lib.rs20
3 files changed, 48 insertions, 21 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index d91b2e1f448..02fb6b79dc4 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -8,6 +8,7 @@
 #![feature(rustc_private)]
 #![feature(stmt_expr_attributes)]
 #![feature(control_flow_enum)]
+#![feature(let_else)]
 #![recursion_limit = "512"]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)]
diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs
index ef26de5b6b9..bd779124dee 100644
--- a/clippy_lints/src/swap.rs
+++ b/clippy_lints/src/swap.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{can_mut_borrow_both, differing_macro_contexts, eq_expr_value};
+use clippy_utils::{can_mut_borrow_both, differing_macro_contexts, eq_expr_value, std_or_core};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, PatKind, QPath, Stmt, StmtKind};
@@ -113,6 +113,8 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
 
     let first = Sugg::hir_with_applicability(cx, e1, "..", &mut applicability);
     let second = Sugg::hir_with_applicability(cx, e2, "..", &mut applicability);
+    let Some(sugg) = std_or_core(cx) else { return };
+
     span_lint_and_then(
         cx,
         MANUAL_SWAP,
@@ -122,11 +124,11 @@ fn generate_swap_warning(cx: &LateContext<'_>, e1: &Expr<'_>, e2: &Expr<'_>, spa
             diag.span_suggestion(
                 span,
                 "try",
-                format!("std::mem::swap({}, {})", first.mut_addr(), second.mut_addr()),
+                format!("{}::mem::swap({}, {})", sugg, first.mut_addr(), second.mut_addr()),
                 applicability,
             );
             if !is_xor_based {
-                diag.note("or maybe you should use `std::mem::replace`?");
+                diag.note(&format!("or maybe you should use `{}::mem::replace`?", sugg));
             }
         },
     );
@@ -187,26 +189,30 @@ fn check_suspicious_swap(cx: &LateContext<'_>, block: &Block<'_>) {
                 };
 
                 let span = first.span.to(second.span);
+                let Some(sugg) = std_or_core(cx) else { return };
 
                 span_lint_and_then(cx,
-                                   ALMOST_SWAPPED,
-                                   span,
-                                   &format!("this looks like you are trying to swap{}", what),
-                                   |diag| {
-                                       if !what.is_empty() {
-                                           diag.span_suggestion(
-                                               span,
-                                               "try",
-                                               format!(
-                                                   "std::mem::swap({}, {})",
-                                                   lhs,
-                                                   rhs,
-                                               ),
-                                               Applicability::MaybeIncorrect,
-                                           );
-                                           diag.note("or maybe you should use `std::mem::replace`?");
-                                       }
-                                   });
+                    ALMOST_SWAPPED,
+                    span,
+                    &format!("this looks like you are trying to swap{}", what),
+                    |diag| {
+                        if !what.is_empty() {
+                            diag.span_suggestion(
+                                span,
+                                "try",
+                                format!(
+                                    "{}::mem::swap({}, {})",
+                                    sugg,
+                                    lhs,
+                                    rhs,
+                                ),
+                                Applicability::MaybeIncorrect,
+                            );
+                            diag.note(
+                                &format!("or maybe you should use `{}::mem::replace`?", sugg)
+                            );
+                        }
+                    });
             }
         }
     }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 95642adeff6..3fdea55aaa1 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -1809,6 +1809,16 @@ pub fn is_expr_final_block_expr(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool {
     matches!(get_parent_node(tcx, expr.hir_id), Some(Node::Block(..)))
 }
 
+pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> {
+    if !is_no_std_crate(cx) {
+        Some("std")
+    } else if !is_no_core_crate(cx) {
+        Some("core")
+    } else {
+        None
+    }
+}
+
 pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
     cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
         if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
@@ -1819,6 +1829,16 @@ pub fn is_no_std_crate(cx: &LateContext<'_>) -> bool {
     })
 }
 
+pub fn is_no_core_crate(cx: &LateContext<'_>) -> bool {
+    cx.tcx.hir().attrs(hir::CRATE_HIR_ID).iter().any(|attr| {
+        if let ast::AttrKind::Normal(ref attr, _) = attr.kind {
+            attr.path == sym::no_core
+        } else {
+            false
+        }
+    })
+}
+
 /// Check if parent of a hir node is a trait implementation block.
 /// For example, `f` in
 /// ```rust,ignore