Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6871,6 +6871,7 @@ Released 2018-09-13
[`excessive-nesting-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#excessive-nesting-threshold
[`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
[`large-error-ignored`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-ignored
[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
[`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code
[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
Expand Down
11 changes: 11 additions & 0 deletions book/src/lint_configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,17 @@ A list of paths to types that should be treated as if they do not contain interi
* [`mutable_key_type`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type)


## `large-error-ignored`
A list of paths to types that should be ignored as overly large `Err`-variants in a
`Result` returned from a function

**Default Value:** `[]`

---
**Affected lints:**
* [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)


## `large-error-threshold`
The maximum size of the `Err`-variant in a `Result` returned from a function

Expand Down
4 changes: 4 additions & 0 deletions clippy_config/src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,10 @@ define_Conf! {
/// A list of paths to types that should be treated as if they do not contain interior mutability
#[lints(borrow_interior_mutable_const, declare_interior_mutable_const, ifs_same_cond, mutable_key_type)]
ignore_interior_mutability: Vec<String> = Vec::from(["bytes::Bytes".into()]),
/// A list of paths to types that should be ignored as overly large `Err`-variants in a
/// `Result` returned from a function
#[lints(result_large_err)]
large_error_ignored: Vec<String> = Vec::default(),
/// The maximum size of the `Err`-variant in a `Result` returned from a function
#[lints(result_large_err)]
large_error_threshold: u64 = 128,
Expand Down
30 changes: 27 additions & 3 deletions clippy_lints/src/functions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ pub struct Functions {
too_many_arguments_threshold: u64,
too_many_lines_threshold: u64,
large_error_threshold: u64,
large_error_ignored: DefIdSet,
avoid_breaking_exported_api: bool,
/// A set of resolved `def_id` of traits that are configured to allow
/// function params renaming.
Expand All @@ -498,6 +499,11 @@ impl Functions {
too_many_arguments_threshold: conf.too_many_arguments_threshold,
too_many_lines_threshold: conf.too_many_lines_threshold,
large_error_threshold: conf.large_error_threshold,
large_error_ignored: conf
.large_error_ignored
.iter()
.flat_map(|ignored_ty| lookup_path_str(tcx, PathNS::Type, ignored_ty))
.collect(),
avoid_breaking_exported_api: conf.avoid_breaking_exported_api,
trait_ids: conf
.allow_renamed_params_for
Expand Down Expand Up @@ -554,12 +560,24 @@ 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, self.msrv);
result::check_item(
cx,
item,
self.large_error_threshold,
&self.large_error_ignored,
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, self.msrv);
result::check_impl_item(
cx,
item,
self.large_error_threshold,
&self.large_error_ignored,
self.msrv,
);
impl_trait_in_params::check_impl_item(cx, item);
renamed_function_params::check_impl_item(cx, item, &self.trait_ids);
}
Expand All @@ -568,7 +586,13 @@ 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, self.msrv);
result::check_trait_item(
cx,
item,
self.large_error_threshold,
&self.large_error_ignored,
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);
}
Expand Down
30 changes: 25 additions & 5 deletions clippy_lints/src/functions/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use rustc_errors::Diag;
use rustc_hir as hir;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty::{self, Ty};
use rustc_span::def_id::DefIdSet;
use rustc_span::{Span, sym};

use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
Expand Down Expand Up @@ -34,22 +35,29 @@ fn result_err_ty<'tcx>(
}
}

pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &hir::Item<'tcx>, large_err_threshold: u64, msrv: Msrv) {
pub(super) fn check_item<'tcx>(
cx: &LateContext<'tcx>,
item: &hir::Item<'tcx>,
large_err_threshold: u64,
large_err_ignored: &DefIdSet,
msrv: Msrv,
) {
if let hir::ItemKind::Fn { ref sig, .. } = 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, msrv);
}
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold, large_err_ignored);
}
}

pub(super) fn check_impl_item<'tcx>(
cx: &LateContext<'tcx>,
item: &hir::ImplItem<'tcx>,
large_err_threshold: u64,
large_err_ignored: &DefIdSet,
msrv: Msrv,
) {
// Don't lint if method is a trait's implementation, we can't do anything about those
Expand All @@ -61,14 +69,15 @@ pub(super) fn check_impl_item<'tcx>(
let fn_header_span = item.span.with_hi(sig.decl.output.span().hi());
check_result_unit_err(cx, err_ty, fn_header_span, msrv);
}
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold, large_err_ignored);
}
}

pub(super) fn check_trait_item<'tcx>(
cx: &LateContext<'tcx>,
item: &hir::TraitItem<'tcx>,
large_err_threshold: u64,
large_err_ignored: &DefIdSet,
msrv: Msrv,
) {
if let hir::TraitItemKind::Fn(ref sig, _) = item.kind {
Expand All @@ -77,7 +86,7 @@ pub(super) fn check_trait_item<'tcx>(
if cx.effective_visibilities.is_exported(item.owner_id.def_id) {
check_result_unit_err(cx, err_ty, fn_header_span, msrv);
}
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold);
check_result_large_err(cx, err_ty, hir_ty.span, large_err_threshold, large_err_ignored);
}
}
}
Expand All @@ -95,7 +104,18 @@ fn check_result_unit_err(cx: &LateContext<'_>, err_ty: Ty<'_>, fn_header_span: S
}
}

fn check_result_large_err<'tcx>(cx: &LateContext<'tcx>, err_ty: Ty<'tcx>, hir_ty_span: Span, large_err_threshold: u64) {
fn check_result_large_err<'tcx>(
cx: &LateContext<'tcx>,
err_ty: Ty<'tcx>,
hir_ty_span: Span,
large_err_threshold: u64,
large_err_ignored: &DefIdSet,
) {
if let ty::Adt(adt, _) = err_ty.kind()
&& large_err_ignored.contains(&adt.did())
{
return;
}
if let ty::Adt(adt, subst) = err_ty.kind()
Comment on lines +114 to 119
Copy link
Contributor

@ada4a ada4a Sep 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe integrate this check into the let-chain?

if let ty::Adt(adt, subst) = err_ty.kind()
    && !large_err_ignored.contains(&adt.did())
    && /* rest of the let-chain.. */

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpicked about that, but that would complicate the else-clause

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see what you mean. Then maybe put this check inside the then-block?

This doesn't really matter of course – it's just that it looks a bit strange to me to check for err_ty being an ADT twice

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, yet all variants come down to some duplication, so I'd rather leave it as it

&& let Some(local_def_id) = adt.did().as_local()
&& let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_def_id)
Expand Down
1 change: 1 addition & 0 deletions tests/ui-toml/result_large_err/clippy.toml
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
large-error-threshold = 512
large-error-ignored = ["result_large_err::IgnoredError", "result_large_err::IgnoredErrorEnum"]
20 changes: 20 additions & 0 deletions tests/ui-toml/result_large_err/result_large_err.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@compile-flags: --crate-name result_large_err
#![warn(clippy::result_large_err)]
#![allow(clippy::large_enum_variant)]

fn f() -> Result<(), [u8; 511]> {
todo!()
Expand All @@ -7,4 +9,22 @@ fn f2() -> Result<(), [u8; 512]> {
//~^ ERROR: the `Err`-variant returned from this function is very large
todo!()
}

struct IgnoredError {
inner: [u8; 512],
}

fn f3() -> Result<(), IgnoredError> {
todo!()
}

enum IgnoredErrorEnum {
V1,
V2 { inner: [u8; 512] },
}

fn f4() -> Result<(), IgnoredErrorEnum> {
todo!()
}

fn main() {}
2 changes: 1 addition & 1 deletion tests/ui-toml/result_large_err/result_large_err.stderr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error: the `Err`-variant returned from this function is very large
--> tests/ui-toml/result_large_err/result_large_err.rs:6:12
--> tests/ui-toml/result_large_err/result_large_err.rs:8:12
|
LL | fn f2() -> Result<(), [u8; 512]> {
| ^^^^^^^^^^^^^^^^^^^^^ the `Err`-variant is at least 512 bytes
Expand Down
3 changes: 3 additions & 0 deletions tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
excessive-nesting-threshold
future-size-threshold
ignore-interior-mutability
large-error-ignored
large-error-threshold
lint-commented-code
literal-representation-threshold
Expand Down Expand Up @@ -144,6 +145,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
excessive-nesting-threshold
future-size-threshold
ignore-interior-mutability
large-error-ignored
large-error-threshold
lint-commented-code
literal-representation-threshold
Expand Down Expand Up @@ -239,6 +241,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
excessive-nesting-threshold
future-size-threshold
ignore-interior-mutability
large-error-ignored
large-error-threshold
lint-commented-code
literal-representation-threshold
Expand Down
Loading