about summary refs log tree commit diff
diff options
context:
space:
mode:
authorllogiq <bogusandre@gmail.com>2024-12-16 05:15:20 +0000
committerGitHub <noreply@github.com>2024-12-16 05:15:20 +0000
commit968669b00a224d6e97439d317e7443b8493e2f1c (patch)
tree09f5541717ec4a12a0d0598e3fe1f0892f2c52f6
parent8da8da8428fcdff68d78e532b09e1b695a9de746 (diff)
parent4c0177cbbc31bb58b3c5c0b24af1ae802353d492 (diff)
downloadrust-968669b00a224d6e97439d317e7443b8493e2f1c.tar.gz
rust-968669b00a224d6e97439d317e7443b8493e2f1c.zip
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
-rw-r--r--clippy_lints/src/functions/mod.rs11
-rw-r--r--clippy_lints/src/functions/result.rs29
-rw-r--r--clippy_utils/src/msrvs.rs2
-rw-r--r--tests/ui/result_unit_error_no_std.rs26
-rw-r--r--tests/ui/result_unit_error_no_std.stderr12
5 files changed, 67 insertions, 13 deletions
diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs
index be3d0f7ad63..243eb5cbfd4 100644
--- a/clippy_lints/src/functions/mod.rs
+++ b/clippy_lints/src/functions/mod.rs
@@ -10,6 +10,7 @@ mod too_many_lines;
 
 use clippy_config::Conf;
 use clippy_utils::def_path_def_ids;
+use clippy_utils::msrvs::Msrv;
 use rustc_hir as hir;
 use rustc_hir::intravisit;
 use rustc_lint::{LateContext, LateLintPass};
@@ -455,6 +456,7 @@ pub struct Functions {
     /// A set of resolved `def_id` of traits that are configured to allow
     /// function params renaming.
     trait_ids: DefIdSet,
+    msrv: Msrv,
 }
 
 impl Functions {
@@ -469,6 +471,7 @@ impl Functions {
                 .iter()
                 .flat_map(|p| def_path_def_ids(tcx, &p.split("::").collect::<Vec<_>>()))
                 .collect(),
+            msrv: conf.msrv.clone(),
         }
     }
 }
@@ -518,12 +521,12 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
 
     fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
         must_use::check_item(cx, item);
-        result::check_item(cx, item, self.large_error_threshold);
+        result::check_item(cx, item, self.large_error_threshold, &self.msrv);
     }
 
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) {
         must_use::check_impl_item(cx, item);
-        result::check_impl_item(cx, item, self.large_error_threshold);
+        result::check_impl_item(cx, item, self.large_error_threshold, &self.msrv);
         impl_trait_in_params::check_impl_item(cx, item);
         renamed_function_params::check_impl_item(cx, item, &self.trait_ids);
     }
@@ -532,8 +535,10 @@ impl<'tcx> LateLintPass<'tcx> for Functions {
         too_many_arguments::check_trait_item(cx, item, self.too_many_arguments_threshold);
         not_unsafe_ptr_arg_deref::check_trait_item(cx, item);
         must_use::check_trait_item(cx, item);
-        result::check_trait_item(cx, item, self.large_error_threshold);
+        result::check_trait_item(cx, item, self.large_error_threshold, &self.msrv);
         impl_trait_in_params::check_trait_item(cx, item, self.avoid_breaking_exported_api);
         ref_option::check_trait_item(cx, item, self.avoid_breaking_exported_api);
     }
+
+    extract_msrv_attr!(LateContext);
 }
diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs
index d4eaa166320..674d78eaae7 100644
--- a/clippy_lints/src/functions/result.rs
+++ b/clippy_lints/src/functions/result.rs
@@ -1,3 +1,4 @@
+use clippy_utils::msrvs::{self, Msrv};
 use rustc_errors::Diag;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LintContext};
@@ -6,8 +7,8 @@ use rustc_middle::ty::{self, Ty};
 use rustc_span::{Span, sym};
 
 use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
-use clippy_utils::trait_ref_of_method;
 use clippy_utils::ty::{AdtVariantInfo, approx_ty_size, is_type_diagnostic_item};
+use clippy_utils::{is_no_std_crate, trait_ref_of_method};
 
 use super::{RESULT_LARGE_ERR, RESULT_UNIT_ERR};
 
@@ -34,19 +35,24 @@ fn result_err_ty<'tcx>(
     }
 }
 
-pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64) {
+pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: &Msrv) {
     if let hir::ItemKind::Fn(ref sig, _generics, _) = item.kind
         && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
     {
         if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
             let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-            check_result_unit_err(cx, err_ty, fn_header_span);
+            check_result_unit_err(cx, err_ty, fn_header_span, msrv);
         }
         check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
     }
 }
 
-pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem<'tcx>, large_err_threshold: u64) {
+pub(super) fn check_impl_item<'tcx>(
+    cx: &LateContext<'tcx>,
+    item: &hir::ImplItem<'tcx>,
+    large_err_threshold: u64,
+    msrv: &Msrv,
+) {
     // Don't lint if method is a trait's implementation, we can't do anything about those
     if let hir::ImplItemKind::Fn(ref sig, _) = item.kind
         && let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span)
@@ -54,26 +60,31 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::ImplItem
     {
         if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
             let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
-            check_result_unit_err(cx, err_ty, fn_header_span);
+            check_result_unit_err(cx, err_ty, fn_header_span, msrv);
         }
         check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
     }
 }
 
-pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::TraitItem<'tcx>, large_err_threshold: u64) {
+pub(super) fn check_trait_item<'tcx>(
+    cx: &LateContext<'tcx>,
+    item: &hir::TraitItem<'tcx>,
+    large_err_threshold: u64,
+    msrv: &Msrv,
+) {
     if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
         let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
         if let Some((hir_ty, err_ty)) = result_err_ty(cx, sig.decl, item.owner_id.def_id, item.span) {
             if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
-                check_result_unit_err(cx, err_ty, fn_header_span);
+                check_result_unit_err(cx, err_ty, fn_header_span, msrv);
             }
             check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
         }
     }
 }
 
-fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span) {
-    if err_ty.is_unit() {
+fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: Span, msrv: &Msrv) {
+    if err_ty.is_unit() && (!is_no_std_crate(cx) || msrv.meets(msrvs::ERROR_IN_CORE)) {
         span_lint_and_help(
             cx,
             RESULT_UNIT_ERR,
diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs
index 35f552c15a3..43ea8d24950 100644
--- a/clippy_utils/src/msrvs.rs
+++ b/clippy_utils/src/msrvs.rs
@@ -20,7 +20,7 @@ macro_rules! msrv_aliases {
 msrv_aliases! {
     1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY }
     1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
-    1,81,0 { LINT_REASONS_STABILIZATION }
+    1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE }
     1,80,0 { BOX_INTO_ITER }
     1,77,0 { C_STR_LITERALS }
     1,76,0 { PTR_FROM_REF, OPTION_RESULT_INSPECT }
diff --git a/tests/ui/result_unit_error_no_std.rs b/tests/ui/result_unit_error_no_std.rs
new file mode 100644
index 00000000000..1e7a028a7fc
--- /dev/null
+++ b/tests/ui/result_unit_error_no_std.rs
@@ -0,0 +1,26 @@
+#![feature(lang_items, start, libc)]
+#![no_std]
+#![warn(clippy::result_unit_err)]
+
+#[clippy::msrv = "1.80"]
+pub fn returns_unit_error_no_lint() -> Result<u32, ()> {
+    Err(())
+}
+
+#[clippy::msrv = "1.81"]
+pub fn returns_unit_error_lint() -> Result<u32, ()> {
+    Err(())
+}
+
+#[start]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+    0
+}
+
+#[panic_handler]
+fn panic(_info: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[lang = "eh_personality"]
+extern "C" fn eh_personality() {}
diff --git a/tests/ui/result_unit_error_no_std.stderr b/tests/ui/result_unit_error_no_std.stderr
new file mode 100644
index 00000000000..33692e60554
--- /dev/null
+++ b/tests/ui/result_unit_error_no_std.stderr
@@ -0,0 +1,12 @@
+error: this returns a `Result<_, ()>`
+  --> tests/ui/result_unit_error_no_std.rs:11:1
+   |
+LL | pub fn returns_unit_error_lint() -> Result<u32, ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a custom `Error` type instead
+   = note: `-D clippy::result-unit-err` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::result_unit_err)]`
+
+error: aborting due to 1 previous error
+