Skip to content

Commit 968669b

Browse files
authored
Do not suggest using Error in no_std before Rust 1.81 (#13834)
changelog: [`result_unit_err`]: do not suggest using `Error` in `no_std` mode before Rust 1.81 Fix #9767
2 parents 8da8da8 + 4c0177c commit 968669b

File tree

5 files changed

+67
-13
lines changed

5 files changed

+67
-13
lines changed

clippy_lints/src/functions/mod.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ mod too_many_lines;
1010

1111
use clippy_config::Conf;
1212
use clippy_utils::def_path_def_ids;
13+
use clippy_utils::msrvs::Msrv;
1314
use rustc_hir as hir;
1415
use rustc_hir::intravisit;
1516
use rustc_lint::{LateContext, LateLintPass};
@@ -455,6 +456,7 @@ pub struct Functions {
455456
/// A set of resolved `def_id` of traits that are configured to allow
456457
/// function params renaming.
457458
trait_ids: DefIdSet,
459+
msrv: Msrv,
458460
}
459461

460462
impl Functions {
@@ -469,6 +471,7 @@ impl Functions {
469471
.iter()
470472
.flat_map(|p| def_path_def_ids(tcx, &p.split("::").collect::<Vec<_>>()))
471473
.collect(),
474+
msrv: conf.msrv.clone(),
472475
}
473476
}
474477
}
@@ -518,12 +521,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
518521

519522
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
520523
must_use::check_item(cx, item);
521-
result::check_item(cx, item, self.large_error_threshold);
524+
result::check_item(cx, item, self.large_error_threshold, &self.msrv);
522525
}
523526

524527
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
525528
must_use::check_impl_item(cx, item);
526-
result::check_impl_item(cx, item, self.large_error_threshold);
529+
result::check_impl_item(cx, item, self.large_error_threshold, &self.msrv);
527530
impl_trait_in_params::check_impl_item(cx, item);
528531
renamed_function_params::check_impl_item(cx, item, &self.trait_ids);
529532
}
@@ -532,8 +535,10 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
532535
too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
533536
not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
534537
must_use::check_trait_item(cx, item);
535-
result::check_trait_item(cx, item, self.large_error_threshold);
538+
result::check_trait_item(cx, item, self.large_error_threshold, &self.msrv);
536539
impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api);
537540
ref_option::check_trait_item(cx, item, self.avoid_breaking_exported_api);
538541
}
542+
543+
extract_msrv_attr!(LateContext);
539544
}

clippy_lints/src/functions/result.rs

+20-9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use clippy_utils::msrvs::{self, Msrv};
12
use rustc_errors::Diag;
23
use rustc_hir as hir;
34
use rustc_lint::{LateContext, LintContext};
@@ -6,8 +7,8 @@ use rustc_middle::ty::{self, Ty};
67
use rustc_span::{Span, sym};
78

89
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
9-
use clippy_utils::trait_ref_of_method;
1010
use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
11+
use clippy_utils::{is_no_std_crate, trait_ref_of_method};
1112

1213
use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
1314

@@ -34,46 +35,56 @@ fn result_err_ty<'tcx>(
3435
}
3536
}
3637

37-
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) {
38+
pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: &Msrv) {
3839
if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind
3940
&& let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
4041
{
4142
if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
4243
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
43-
check_result_unit_err(cx, err_ty, fn_header_span);
44+
check_result_unit_err(cx, err_ty, fn_header_span, msrv);
4445
}
4546
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
4647
}
4748
}
4849

49-
pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) {
50+
pub(super) fn check_impl_item<'tcx>(
51+
cx: &LateContext<'tcx>,
52+
item: &hir::ImplItem<'tcx>,
53+
large_err_threshold: u64,
54+
msrv: &Msrv,
55+
) {
5056
// Don't lint if method is a trait's implementation, we can't do anything about those
5157
if let hir::ImplItemKind::Fn(ref sig, _) = item.kind
5258
&& let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
5359
&& trait_ref_of_method(cx, item.owner_id.def_id).is_none()
5460
{
5561
if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
5662
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
57-
check_result_unit_err(cx, err_ty, fn_header_span);
63+
check_result_unit_err(cx, err_ty, fn_header_span, msrv);
5864
}
5965
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
6066
}
6167
}
6268

63-
pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) {
69+
pub(super) fn check_trait_item<'tcx>(
70+
cx: &LateContext<'tcx>,
71+
item: &hir::TraitItem<'tcx>,
72+
large_err_threshold: u64,
73+
msrv: &Msrv,
74+
) {
6475
if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
6576
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
6677
if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) {
6778
if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
68-
check_result_unit_err(cx, err_ty, fn_header_span);
79+
check_result_unit_err(cx, err_ty, fn_header_span, msrv);
6980
}
7081
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
7182
}
7283
}
7384
}
7485

75-
fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span) {
76-
if err_ty.is_unit() {
86+
fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span, msrv: &Msrv) {
87+
if err_ty.is_unit() && (!is_no_std_crate(cx) || msrv.meets(msrvs::ERROR_IN_CORE)) {
7788
span_lint_and_help(
7889
cx,
7990
RESULT_UNIT_ERR,

clippy_utils/src/msrvs.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
2020
msrv_aliases! {
2121
1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY }
2222
1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
23-
1,81,0 { LINT_REASONS_STABILIZATION }
23+
1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE }
2424
1,80,0 { BOX_INTO_ITER }
2525
1,77,0 { C_STR_LITERALS }
2626
1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }

tests/ui/result_unit_error_no_std.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#![feature(lang_items, start, libc)]
2+
#![no_std]
3+
#![warn(clippy::result_unit_err)]
4+
5+
#[clippy::msrv = "1.80"]
6+
pub fn returns_unit_error_no_lint() -> Result<u32, ()> {
7+
Err(())
8+
}
9+
10+
#[clippy::msrv = "1.81"]
11+
pub fn returns_unit_error_lint() -> Result<u32, ()> {
12+
Err(())
13+
}
14+
15+
#[start]
16+
fn main(_argc: isize, _argv: *const *const u8) -> isize {
17+
0
18+
}
19+
20+
#[panic_handler]
21+
fn panic(_info: &core::panic::PanicInfo) -> ! {
22+
loop {}
23+
}
24+
25+
#[lang = "eh_personality"]
26+
extern "C" fn eh_personality() {}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error: this returns a `Result<_, ()>`
2+
--> tests/ui/result_unit_error_no_std.rs:11:1
3+
|
4+
LL | pub fn returns_unit_error_lint() -> Result<u32, ()> {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= help: use a custom `Error` type instead
8+
= note: `-D clippy::result-unit-err` implied by `-D warnings`
9+
= help: to override `-D warnings` add `#[allow(clippy::result_unit_err)]`
10+
11+
error: aborting due to 1 previous error
12+

0 commit comments

Comments
 (0)