Skip to content

Commit 83bde36

Browse files
authored
correct suggestions in no_std (#13999)
I opened #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
2 parents 85bbba6 + 3b0b8b0 commit 83bde36

17 files changed

+157
-23
lines changed

clippy_lints/src/eta_reduction.rs

+17-14
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use clippy_utils::higher::VecArgs;
33
use clippy_utils::source::snippet_opt;
44
use clippy_utils::ty::get_type_diagnostic_name;
55
use clippy_utils::usage::{local_used_after_expr, local_used_in};
6-
use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, path_to_local, path_to_local_id};
6+
use clippy_utils::{
7+
get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate, path_to_local, path_to_local_id,
8+
};
79
use rustc_errors::Applicability;
810
use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, Param, PatKind, QPath, Safety, TyKind};
911
use rustc_infer::infer::TyCtxtInferExt;
@@ -101,19 +103,20 @@ fn check_closure<'tcx>(cx: &LateContext<'tcx>, outer_receiver: Option<&Expr<'tcx
101103
};
102104

103105
if body.value.span.from_expansion() {
104-
if body.params.is_empty() {
105-
if let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value) {
106-
// replace `|| vec![]` with `Vec::new`
107-
span_lint_and_sugg(
108-
cx,
109-
REDUNDANT_CLOSURE,
110-
expr.span,
111-
"redundant closure",
112-
"replace the closure with `Vec::new`",
113-
"std::vec::Vec::new".into(),
114-
Applicability::MachineApplicable,
115-
);
116-
}
106+
if body.params.is_empty()
107+
&& let Some(VecArgs::Vec(&[])) = VecArgs::hir(cx, body.value)
108+
{
109+
let vec_crate = if is_no_std_crate(cx) { "alloc" } else { "std" };
110+
// replace `|| vec![]` with `Vec::new`
111+
span_lint_and_sugg(
112+
cx,
113+
REDUNDANT_CLOSURE,
114+
expr.span,
115+
"redundant closure",
116+
"replace the closure with `Vec::new`",
117+
format!("{vec_crate}::vec::Vec::new"),
118+
Applicability::MachineApplicable,
119+
);
117120
}
118121
// skip `foo(|| macro!())`
119122
return;

clippy_lints/src/methods/drain_collect.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use crate::methods::DRAIN_COLLECT;
22
use clippy_utils::diagnostics::span_lint_and_sugg;
3-
use clippy_utils::is_range_full;
43
use clippy_utils::source::snippet;
54
use clippy_utils::ty::is_type_lang_item;
5+
use clippy_utils::{is_range_full, std_or_core};
66
use rustc_errors::Applicability;
77
use rustc_hir::{Expr, ExprKind, LangItem, Path, QPath};
88
use rustc_lint::LateContext;
@@ -58,12 +58,13 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re
5858
.then_some("Vec")
5959
.or_else(|| check_string(cx, args, expr_ty, recv_ty_no_refs, recv_path).then_some("String"))
6060
.or_else(|| check_collections(cx, expr_ty, recv_ty_no_refs))
61+
&& let Some(exec_context) = std_or_core(cx)
6162
{
6263
let recv = snippet(cx, recv.span, "<expr>");
6364
let sugg = if let ty::Ref(..) = recv_ty.kind() {
64-
format!("std::mem::take({recv})")
65+
format!("{exec_context}::mem::take({recv})")
6566
} else {
66-
format!("std::mem::take(&mut {recv})")
67+
format!("{exec_context}::mem::take(&mut {recv})")
6768
};
6869

6970
span_lint_and_sugg(

clippy_lints/src/methods/map_with_unused_argument_over_ranges.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::msrvs::{self, Msrv};
44
use clippy_utils::source::snippet_with_applicability;
55
use clippy_utils::sugg::Sugg;
6-
use clippy_utils::{eager_or_lazy, higher, usage};
6+
use clippy_utils::{eager_or_lazy, higher, std_or_core, usage};
77
use rustc_ast::LitKind;
88
use rustc_ast::ast::RangeLimits;
99
use rustc_data_structures::packed::Pu128;
@@ -75,6 +75,7 @@ pub(super) fn check(
7575
} = body_hir
7676
&& !usage::BindingUsageFinder::are_params_used(cx, body_hir)
7777
&& let Some(count) = extract_count_with_applicability(cx, range, &mut applicability)
78+
&& let Some(exec_context) = std_or_core(cx)
7879
{
7980
let method_to_use_name;
8081
let new_span;
@@ -105,7 +106,7 @@ pub(super) fn check(
105106
let mut parts = vec![
106107
(
107108
receiver.span.to(method_call_span),
108-
format!("std::iter::{method_to_use_name}"),
109+
format!("{exec_context}::iter::{method_to_use_name}"),
109110
),
110111
new_span,
111112
];

clippy_lints/src/repeat_vec_with_capacity.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
33
use clippy_utils::higher::VecArgs;
44
use clippy_utils::macros::matching_root_macro_call;
55
use clippy_utils::source::snippet;
6-
use clippy_utils::{expr_or_init, fn_def_id};
6+
use clippy_utils::{expr_or_init, fn_def_id, std_or_core};
77
use rustc_errors::Applicability;
88
use rustc_hir::{Expr, ExprKind};
99
use rustc_lint::{LateContext, LateLintPass};
@@ -93,14 +93,18 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
9393
&& let ExprKind::Call(_, [repeat_expr]) = expr.kind
9494
&& fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
9595
&& !repeat_expr.span.from_expansion()
96+
&& let Some(exec_context) = std_or_core(cx)
9697
{
9798
emit_lint(
9899
cx,
99100
expr.span,
100101
"iter::repeat",
101102
"none of the yielded `Vec`s will have the requested capacity",
102103
"if you intended to create an iterator that yields `Vec`s with an initial capacity, try",
103-
format!("std::iter::repeat_with(|| {})", snippet(cx, repeat_expr.span, "..")),
104+
format!(
105+
"{exec_context}::iter::repeat_with(|| {})",
106+
snippet(cx, repeat_expr.span, "..")
107+
),
104108
);
105109
}
106110
}

clippy_lints/src/single_range_in_vec_init.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::get_trait_def_id;
32
use clippy_utils::higher::VecArgs;
43
use clippy_utils::macros::root_macro_call_first_node;
54
use clippy_utils::source::SpanRangeExt;
65
use clippy_utils::ty::implements_trait;
6+
use clippy_utils::{get_trait_def_id, is_no_std_crate};
77
use rustc_ast::{LitIntType, LitKind, UintTy};
88
use rustc_errors::Applicability;
99
use rustc_hir::{Expr, ExprKind, LangItem, QPath, StructTailExpr};
@@ -125,7 +125,7 @@ impl LateLintPass<'_> for SingleRangeInVecInit {
125125
span,
126126
format!("{suggested_type} of `Range` that is only one element"),
127127
|diag| {
128-
if should_emit_every_value {
128+
if should_emit_every_value && !is_no_std_crate(cx) {
129129
diag.span_suggestion(
130130
span,
131131
"if you wanted a `Vec` that contains the entire range, try",

tests/ui/drain_collect_nostd.fixed

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![warn(clippy::drain_collect)]
2+
#![no_std]
3+
extern crate alloc;
4+
use alloc::vec::Vec;
5+
6+
fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
7+
core::mem::take(v)
8+
}

tests/ui/drain_collect_nostd.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![warn(clippy::drain_collect)]
2+
#![no_std]
3+
extern crate alloc;
4+
use alloc::vec::Vec;
5+
6+
fn remove_all(v: &mut Vec<i32>) -> Vec<i32> {
7+
v.drain(..).collect()
8+
}

tests/ui/drain_collect_nostd.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: you seem to be trying to move all elements into a new `Vec`
2+
--> tests/ui/drain_collect_nostd.rs:7:5
3+
|
4+
LL | v.drain(..).collect()
5+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using `mem::take`: `core::mem::take(v)`
6+
|
7+
= note: `-D clippy::drain-collect` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::drain_collect)]`
9+
10+
error: aborting due to 1 previous error
11+

tests/ui/eta_nostd.fixed

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![warn(clippy::redundant_closure)]
2+
#![no_std]
3+
4+
extern crate alloc;
5+
use alloc::vec;
6+
use alloc::vec::Vec;
7+
8+
fn issue_13895() {
9+
let _: Option<Vec<u8>> = true.then(alloc::vec::Vec::new);
10+
}

tests/ui/eta_nostd.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![warn(clippy::redundant_closure)]
2+
#![no_std]
3+
4+
extern crate alloc;
5+
use alloc::vec;
6+
use alloc::vec::Vec;
7+
8+
fn issue_13895() {
9+
let _: Option<Vec<u8>> = true.then(|| vec![]);
10+
}

tests/ui/eta_nostd.stderr

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error: redundant closure
2+
--> tests/ui/eta_nostd.rs:9:40
3+
|
4+
LL | let _: Option<Vec<u8>> = true.then(|| vec![]);
5+
| ^^^^^^^^^ help: replace the closure with `Vec::new`: `alloc::vec::Vec::new`
6+
|
7+
= note: `-D clippy::redundant-closure` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]`
9+
10+
error: aborting due to 1 previous error
11+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![warn(clippy::map_with_unused_argument_over_ranges)]
2+
#![no_std]
3+
extern crate alloc;
4+
use alloc::vec::Vec;
5+
6+
fn nostd(v: &mut [i32]) {
7+
let _: Vec<_> = core::iter::repeat_n(3 + 1, 10).collect();
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![warn(clippy::map_with_unused_argument_over_ranges)]
2+
#![no_std]
3+
extern crate alloc;
4+
use alloc::vec::Vec;
5+
6+
fn nostd(v: &mut [i32]) {
7+
let _: Vec<_> = (0..10).map(|_| 3 + 1).collect();
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: map of a closure that does not depend on its parameter over a range
2+
--> tests/ui/map_with_unused_argument_over_ranges_nostd.rs:7:21
3+
|
4+
LL | let _: Vec<_> = (0..10).map(|_| 3 + 1).collect();
5+
| ^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::map-with-unused-argument-over-ranges` implied by `-D warnings`
8+
= help: to override `-D warnings` add `#[allow(clippy::map_with_unused_argument_over_ranges)]`
9+
help: remove the explicit range and use `repeat_n`
10+
|
11+
LL | let _: Vec<_> = core::iter::repeat_n(3 + 1, 10).collect();
12+
| ~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
13+
14+
error: aborting due to 1 previous error
15+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![warn(clippy::repeat_vec_with_capacity)]
2+
#![allow(clippy::manual_repeat_n)]
3+
#![no_std]
4+
use core::iter;
5+
extern crate alloc;
6+
use alloc::vec::Vec;
7+
8+
fn nostd() {
9+
let _: Vec<Vec<u8>> = core::iter::repeat_with(|| Vec::with_capacity(42)).take(123).collect();
10+
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![warn(clippy::repeat_vec_with_capacity)]
2+
#![allow(clippy::manual_repeat_n)]
3+
#![no_std]
4+
use core::iter;
5+
extern crate alloc;
6+
use alloc::vec::Vec;
7+
8+
fn nostd() {
9+
let _: Vec<Vec<u8>> = iter::repeat(Vec::with_capacity(42)).take(123).collect();
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: repeating `Vec::with_capacity` using `iter::repeat`, which does not retain capacity
2+
--> tests/ui/repeat_vec_with_capacity_nostd.rs:9:27
3+
|
4+
LL | let _: Vec<Vec<u8>> = iter::repeat(Vec::with_capacity(42)).take(123).collect();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: none of the yielded `Vec`s will have the requested capacity
8+
= note: `-D clippy::repeat-vec-with-capacity` implied by `-D warnings`
9+
= help: to override `-D warnings` add `#[allow(clippy::repeat_vec_with_capacity)]`
10+
help: if you intended to create an iterator that yields `Vec`s with an initial capacity, try
11+
|
12+
LL | let _: Vec<Vec<u8>> = core::iter::repeat_with(|| Vec::with_capacity(42)).take(123).collect();
13+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
14+
15+
error: aborting due to 1 previous error
16+

0 commit comments

Comments
 (0)