about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2025-01-27 21:36:12 +0000
committerGitHub <noreply@github.com>2025-01-27 21:36:12 +0000
commit83bde363b633a68a1a94441b685ee5a87c60879c (patch)
tree952d3c3067e5e2b206c99226a3ea78f8ba2e601d
parent85bbba69b0d92a314a0751bcbdaa28e800625f61 (diff)
parent3b0b8b080eedfeadc366c051d1c14307c7a7455e (diff)
downloadrust-83bde363b633a68a1a94441b685ee5a87c60879c.tar.gz
rust-83bde363b633a68a1a94441b685ee5a87c60879c.zip
correct suggestions in `no_std` (#13999)
I opened https://github.com/rust-lang/rust-clippy/pull/13896 before.
However, I found that there're more cases where Clippy suggests to use
modules that belong to the `std` crate even in a `no_std` environment.
Therefore, this PR include the changes I've made in #13896 and new
changes to fix cases I found this time to prevent wrong suggestions in
`no_std` environments as well.

changelog: [`redundant_closure`]: correct suggestion in `no_std`
changelog: [`repeat_vec_with_capacity`]: correct suggestion in `no_std`
changelog: [`single_range_in_vec_init`]: don't emit suggestion to use
`Vec` in `no_std`
changelog: [`drain_collect`]: correct suggestion in `no_std`
changelog: [`map_with_unused_argument_over_ranges`]: correct suggestion
in `no_std`

also close #13895
-rw-r--r--clippy_lints/src/eta_reduction.rs31
-rw-r--r--clippy_lints/src/methods/drain_collect.rs7
-rw-r--r--clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs5
-rw-r--r--clippy_lints/src/repeat_vec_with_capacity.rs8
-rw-r--r--clippy_lints/src/single_range_in_vec_init.rs4
-rw-r--r--tests/ui/drain_collect_nostd.fixed8
-rw-r--r--tests/ui/drain_collect_nostd.rs8
-rw-r--r--tests/ui/drain_collect_nostd.stderr11
-rw-r--r--tests/ui/eta_nostd.fixed10
-rw-r--r--tests/ui/eta_nostd.rs10
-rw-r--r--tests/ui/eta_nostd.stderr11
-rw-r--r--tests/ui/map_with_unused_argument_over_ranges_nostd.fixed8
-rw-r--r--tests/ui/map_with_unused_argument_over_ranges_nostd.rs8
-rw-r--r--tests/ui/map_with_unused_argument_over_ranges_nostd.stderr15
-rw-r--r--tests/ui/repeat_vec_with_capacity_nostd.fixed10
-rw-r--r--tests/ui/repeat_vec_with_capacity_nostd.rs10
-rw-r--r--tests/ui/repeat_vec_with_capacity_nostd.stderr16
17 files changed, 157 insertions, 23 deletions
diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs
index 6cba6e2e9c7..f93dc1a8733 100644
--- a/clippy_lints/src/eta_reduction.rs
+++ b/clippy_lints/src/eta_reduction.rs
@@ -3,7 +3,9 @@ use clippy_utils::higher::VecArgs;
 use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::get_type_diagnostic_name;
 use clippy_utils::usage::{local_used_after_expr, local_used_in};
-use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
+use clippy_utils::{
+    get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
+};
 use rustc_errors::Applicability;
 use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Safety, TyKind};
 use rustc_infer::infer::TyCtxtInferExt;
@@ -101,19 +103,20 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
     };
 
     if body.value.span.from_expansion() {
-        if body.params.is_empty() {
-            if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
-                // replace `|| vec![]` with `Vec::new`
-                span_lint_and_sugg(
-                    cx,
-                    REDUNDANT_CLOSURE,
-                    expr.span,
-                    "redundant closure",
-                    "replace the closure with `Vec::new`",
-                    "std::vec::Vec::new".into(),
-                    Applicability::MachineApplicable,
-                );
-            }
+        if body.params.is_empty()
+            && let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value)
+        {
+            let vec_crate = if is_no_std_crate(cx) { "alloc" } else { "std" };
+            // replace `|| vec![]` with `Vec::new`
+            span_lint_and_sugg(
+                cx,
+                REDUNDANT_CLOSURE,
+                expr.span,
+                "redundant closure",
+                "replace the closure with `Vec::new`",
+                format!("{vec_crate}::vec::Vec::new"),
+                Applicability::MachineApplicable,
+            );
         }
         // skip `foo(|| macro!())`
         return;
diff --git a/clippy_lints/src/methods/drain_collect.rs b/clippy_lints/src/methods/drain_collect.rs
index 10360b4817b..cbf713a3b17 100644
--- a/clippy_lints/src/methods/drain_collect.rs
+++ b/clippy_lints/src/methods/drain_collect.rs
@@ -1,8 +1,8 @@
 use crate::methods::DRAIN_COLLECT;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_range_full;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_lang_item;
+use clippy_utils::{is_range_full, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
 use rustc_lint::LateContext;
@@ -58,12 +58,13 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re
             .then_some("Vec")
             .or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String"))
             .or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs))
+        && let Some(exec_context) = std_or_core(cx)
     {
         let recv = snippet(cx, recv.span, "<expr>");
         let sugg = if let ty::Ref(..) = recv_ty.kind() {
-            format!("std::mem::take({recv})")
+            format!("{exec_context}::mem::take({recv})")
         } else {
-            format!("std::mem::take(&mut {recv})")
+            format!("{exec_context}::mem::take(&mut {recv})")
         };
 
         span_lint_and_sugg(
diff --git a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
index 1ebb71e251a..78656ace831 100644
--- a/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
+++ b/clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::msrvs::{self, Msrv};
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::sugg::Sugg;
-use clippy_utils::{eager_or_lazy, higher, usage};
+use clippy_utils::{eager_or_lazy, higher, std_or_core, usage};
 use rustc_ast::LitKind;
 use rustc_ast::ast::RangeLimits;
 use rustc_data_structures::packed::Pu128;
@@ -75,6 +75,7 @@ pub(super) fn check(
         } = body_hir
         && !usage::BindingUsageFinder::are_params_used(cx, body_hir)
         && let Some(count) = extract_count_with_applicability(cx, range, &mut applicability)
+        && let Some(exec_context) = std_or_core(cx)
     {
         let method_to_use_name;
         let new_span;
@@ -105,7 +106,7 @@ pub(super) fn check(
         let mut parts = vec![
             (
                 receiver.span.to(method_call_span),
-                format!("std::iter::{method_to_use_name}"),
+                format!("{exec_context}::iter::{method_to_use_name}"),
             ),
             new_span,
         ];
diff --git a/clippy_lints/src/repeat_vec_with_capacity.rs b/clippy_lints/src/repeat_vec_with_capacity.rs
index f54cafffb83..5dddf9263a3 100644
--- a/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::source::snippet;
-use clippy_utils::{expr_or_init, fn_def_id};
+use clippy_utils::{expr_or_init, fn_def_id, std_or_core};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -93,6 +93,7 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
         && let ExprKind::Call(_, [repeat_expr]) = expr.kind
         && fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
         && !repeat_expr.span.from_expansion()
+        && let Some(exec_context) = std_or_core(cx)
     {
         emit_lint(
             cx,
@@ -100,7 +101,10 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
             "iter::repeat",
             "none of the yielded `Vec`s will have the requested capacity",
             "if you intended to create an iterator that yields `Vec`s with an initial capacity, try",
-            format!("std::iter::repeat_with(|| {})", snippet(cx, repeat_expr.span, "..")),
+            format!(
+                "{exec_context}::iter::repeat_with(|| {})",
+                snippet(cx, repeat_expr.span, "..")
+            ),
         );
     }
 }
diff --git a/clippy_lints/src/single_range_in_vec_init.rs b/clippy_lints/src/single_range_in_vec_init.rs
index 9737b84cdb9..2d989b1cf0b 100644
--- a/clippy_lints/src/single_range_in_vec_init.rs
+++ b/clippy_lints/src/single_range_in_vec_init.rs
@@ -1,9 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::get_trait_def_id;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::root_macro_call_first_node;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::implements_trait;
+use clippy_utils::{get_trait_def_id, is_no_std_crate};
 use rustc_ast::{LitIntType, LitKind, UintTy};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
@@ -125,7 +125,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
                     span,
                     format!("{suggested_type} of `Range` that is only one element"),
                     |diag| {
-                        if should_emit_every_value {
+                        if should_emit_every_value && !is_no_std_crate(cx) {
                             diag.span_suggestion(
                                 span,
                                 "if you wanted a `Vec` that contains the entire range, try",
diff --git a/tests/ui/drain_collect_nostd.fixed b/tests/ui/drain_collect_nostd.fixed
new file mode 100644
index 00000000000..a4ab2956f2a
--- /dev/null
+++ b/tests/ui/drain_collect_nostd.fixed
@@ -0,0 +1,8 @@
+#![warn(clippy::drain_collect)]
+#![no_std]
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    core::mem::take(v)
+}
diff --git a/tests/ui/drain_collect_nostd.rs b/tests/ui/drain_collect_nostd.rs
new file mode 100644
index 00000000000..a8be1ce6bbd
--- /dev/null
+++ b/tests/ui/drain_collect_nostd.rs
@@ -0,0 +1,8 @@
+#![warn(clippy::drain_collect)]
+#![no_std]
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
+    v.drain(..).collect()
+}
diff --git a/tests/ui/drain_collect_nostd.stderr b/tests/ui/drain_collect_nostd.stderr
new file mode 100644
index 00000000000..91b38932fee
--- /dev/null
+++ b/tests/ui/drain_collect_nostd.stderr
@@ -0,0 +1,11 @@
+error: you seem to be trying to move all elements into a new `Vec`
+  --> tests/ui/drain_collect_nostd.rs:7:5
+   |
+LL |     v.drain(..).collect()
+   |     ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `core::mem::take(v)`
+   |
+   = note: `-D clippy::drain-collect` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::drain_collect)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/eta_nostd.fixed b/tests/ui/eta_nostd.fixed
new file mode 100644
index 00000000000..23059c52b67
--- /dev/null
+++ b/tests/ui/eta_nostd.fixed
@@ -0,0 +1,10 @@
+#![warn(clippy::redundant_closure)]
+#![no_std]
+
+extern crate alloc;
+use alloc::vec;
+use alloc::vec::Vec;
+
+fn issue_13895() {
+    let _: Option<Vec<u8>> = true.then(alloc::vec::Vec::new);
+}
diff --git a/tests/ui/eta_nostd.rs b/tests/ui/eta_nostd.rs
new file mode 100644
index 00000000000..ae44ac348c6
--- /dev/null
+++ b/tests/ui/eta_nostd.rs
@@ -0,0 +1,10 @@
+#![warn(clippy::redundant_closure)]
+#![no_std]
+
+extern crate alloc;
+use alloc::vec;
+use alloc::vec::Vec;
+
+fn issue_13895() {
+    let _: Option<Vec<u8>> = true.then(|| vec![]);
+}
diff --git a/tests/ui/eta_nostd.stderr b/tests/ui/eta_nostd.stderr
new file mode 100644
index 00000000000..4dfef43efa4
--- /dev/null
+++ b/tests/ui/eta_nostd.stderr
@@ -0,0 +1,11 @@
+error: redundant closure
+  --> tests/ui/eta_nostd.rs:9:40
+   |
+LL |     let _: Option<Vec<u8>> = true.then(|| vec![]);
+   |                                        ^^^^^^^^^ help: replace the closure with `Vec::new`: `alloc::vec::Vec::new`
+   |
+   = note: `-D clippy::redundant-closure` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed b/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed
new file mode 100644
index 00000000000..65e59774905
--- /dev/null
+++ b/tests/ui/map_with_unused_argument_over_ranges_nostd.fixed
@@ -0,0 +1,8 @@
+#![warn(clippy::map_with_unused_argument_over_ranges)]
+#![no_std]
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn nostd(v: &mut [i32]) {
+    let _: Vec<_> = core::iter::repeat_n(3 + 1, 10).collect();
+}
diff --git a/tests/ui/map_with_unused_argument_over_ranges_nostd.rs b/tests/ui/map_with_unused_argument_over_ranges_nostd.rs
new file mode 100644
index 00000000000..dda7a69b33f
--- /dev/null
+++ b/tests/ui/map_with_unused_argument_over_ranges_nostd.rs
@@ -0,0 +1,8 @@
+#![warn(clippy::map_with_unused_argument_over_ranges)]
+#![no_std]
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn nostd(v: &mut [i32]) {
+    let _: Vec<_> = (0..10).map(|_| 3 + 1).collect();
+}
diff --git a/tests/ui/map_with_unused_argument_over_ranges_nostd.stderr b/tests/ui/map_with_unused_argument_over_ranges_nostd.stderr
new file mode 100644
index 00000000000..d47f3d09175
--- /dev/null
+++ b/tests/ui/map_with_unused_argument_over_ranges_nostd.stderr
@@ -0,0 +1,15 @@
+error: map of a closure that does not depend on its parameter over a range
+  --> tests/ui/map_with_unused_argument_over_ranges_nostd.rs:7:21
+   |
+LL |     let _: Vec<_> = (0..10).map(|_| 3 + 1).collect();
+   |                     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::map-with-unused-argument-over-ranges` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::map_with_unused_argument_over_ranges)]`
+help: remove the explicit range and use `repeat_n`
+   |
+LL |     let _: Vec<_> = core::iter::repeat_n(3 + 1, 10).collect();
+   |                     ~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/repeat_vec_with_capacity_nostd.fixed b/tests/ui/repeat_vec_with_capacity_nostd.fixed
new file mode 100644
index 00000000000..ef316f1def4
--- /dev/null
+++ b/tests/ui/repeat_vec_with_capacity_nostd.fixed
@@ -0,0 +1,10 @@
+#![warn(clippy::repeat_vec_with_capacity)]
+#![allow(clippy::manual_repeat_n)]
+#![no_std]
+use core::iter;
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn nostd() {
+    let _: Vec<Vec<u8>> = core::iter::repeat_with(|| Vec::with_capacity(42)).take(123).collect();
+}
diff --git a/tests/ui/repeat_vec_with_capacity_nostd.rs b/tests/ui/repeat_vec_with_capacity_nostd.rs
new file mode 100644
index 00000000000..83b418a5667
--- /dev/null
+++ b/tests/ui/repeat_vec_with_capacity_nostd.rs
@@ -0,0 +1,10 @@
+#![warn(clippy::repeat_vec_with_capacity)]
+#![allow(clippy::manual_repeat_n)]
+#![no_std]
+use core::iter;
+extern crate alloc;
+use alloc::vec::Vec;
+
+fn nostd() {
+    let _: Vec<Vec<u8>> = iter::repeat(Vec::with_capacity(42)).take(123).collect();
+}
diff --git a/tests/ui/repeat_vec_with_capacity_nostd.stderr b/tests/ui/repeat_vec_with_capacity_nostd.stderr
new file mode 100644
index 00000000000..39364d09b96
--- /dev/null
+++ b/tests/ui/repeat_vec_with_capacity_nostd.stderr
@@ -0,0 +1,16 @@
+error: repeating `Vec::with_capacity` using `iter::repeat`, which does not retain capacity
+  --> tests/ui/repeat_vec_with_capacity_nostd.rs:9:27
+   |
+LL |     let _: Vec<Vec<u8>> = iter::repeat(Vec::with_capacity(42)).take(123).collect();
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: none of the yielded `Vec`s will have the requested capacity
+   = note: `-D clippy::repeat-vec-with-capacity` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::repeat_vec_with_capacity)]`
+help: if you intended to create an iterator that yields `Vec`s with an initial capacity, try
+   |
+LL |     let _: Vec<Vec<u8>> = core::iter::repeat_with(|| Vec::with_capacity(42)).take(123).collect();
+   |                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+