Skip to content

Commit 819e02a

Browse files
committed
Add size-parameter to unecessary_box_returns
Fixes #10641
1 parent 0049816 commit 819e02a

File tree

5 files changed

+28
-4
lines changed

5 files changed

+28
-4
lines changed

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,9 +950,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
950950
store.register_late_pass(|_| Box::new(allow_attributes::AllowAttribute));
951951
store.register_late_pass(move |_| Box::new(manual_main_separator_str::ManualMainSeparatorStr::new(msrv())));
952952
store.register_late_pass(|_| Box::new(unnecessary_struct_initialization::UnnecessaryStruct));
953+
let unnecessary_box_size = conf.unnecessary_box_size;
953954
store.register_late_pass(move |_| {
954955
Box::new(unnecessary_box_returns::UnnecessaryBoxReturns::new(
955956
avoid_breaking_exported_api,
957+
unnecessary_box_size,
956958
))
957959
});
958960
store.register_late_pass(|_| Box::new(lines_filter_map_ok::LinesFilterMapOk));

clippy_lints/src/unnecessary_box_returns.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use clippy_utils::diagnostics::span_lint_and_then;
1+
use clippy_utils::{diagnostics::span_lint_and_then, ty::approx_ty_size};
22
use rustc_errors::Applicability;
33
use rustc_hir::{def_id::LocalDefId, FnDecl, FnRetTy, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind};
44
use rustc_lint::{LateContext, LateLintPass};
@@ -10,6 +10,9 @@ declare_clippy_lint! {
1010
///
1111
/// Checks for a return type containing a `Box<T>` where `T` implements `Sized`
1212
///
13+
/// The lint ignores `Box<T>` where `T` is larger than `unnecessary_box_size`,
14+
/// as returning a large `T` directly may be detrimental to performance.
15+
///
1316
/// ### Why is this bad?
1417
///
1518
/// It's better to just return `T` in these cases. The caller may not need
@@ -36,14 +39,16 @@ declare_clippy_lint! {
3639

3740
pub struct UnnecessaryBoxReturns {
3841
avoid_breaking_exported_api: bool,
42+
maximum_size: u64,
3943
}
4044

4145
impl_lint_pass!(UnnecessaryBoxReturns => [UNNECESSARY_BOX_RETURNS]);
4246

4347
impl UnnecessaryBoxReturns {
44-
pub fn new(avoid_breaking_exported_api: bool) -> Self {
48+
pub fn new(avoid_breaking_exported_api: bool, maximum_size: u64) -> Self {
4549
Self {
4650
avoid_breaking_exported_api,
51+
maximum_size,
4752
}
4853
}
4954

@@ -71,8 +76,10 @@ impl UnnecessaryBoxReturns {
7176

7277
let boxed_ty = return_ty.boxed_ty();
7378

74-
// it's sometimes useful to return Box<T> if T is unsized, so don't lint those
75-
if boxed_ty.is_sized(cx.tcx, cx.param_env) {
79+
// It's sometimes useful to return Box<T> if T is unsized, so don't lint those.
80+
// Also, don't lint if we know that T is very large, in which case returning
81+
// a Box<T> may be beneficial.
82+
if boxed_ty.is_sized(cx.tcx, cx.param_env) && approx_ty_size(cx, boxed_ty) <= self.maximum_size {
7683
span_lint_and_then(
7784
cx,
7885
UNNECESSARY_BOX_RETURNS,

clippy_lints/src/utils/conf.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,10 @@ define_Conf! {
463463
///
464464
/// The maximum byte size a `Future` can have, before it triggers the `clippy::large_futures` lint
465465
(future_size_threshold: u64 = 16 * 1024),
466+
/// Lint: UNNECESSARY_BOX_RETURNS,
467+
///
468+
/// The byte size a `T` in `Box<T>` can have, below which it triggers the `clippy::unnecessary_box` lint
469+
(unnecessary_box_size: u64 = 128),
466470
}
467471

468472
/// Search for the configuration file.

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown fie
4646
too-many-lines-threshold
4747
trivial-copy-size-limit
4848
type-complexity-threshold
49+
unnecessary-box-size
4950
unreadable-literal-lint-fractions
5051
upper-case-acronyms-aggressive
5152
vec-box-size-threshold

tests/ui/unnecessary_box_returns.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,16 @@ fn string() -> String {
5454
String::from("Hello, world")
5555
}
5656

57+
struct Huge([u8; 500]);
58+
struct HasHuge(Box<Huge>);
59+
60+
impl HasHuge {
61+
// don't lint: The size of `Huge` is very large
62+
fn into_huge(self) -> Box<Huge> {
63+
self.0
64+
}
65+
}
66+
5767
fn main() {
5868
// don't lint: this is a closure
5969
let a = || -> Box<usize> { Box::new(5) };

0 commit comments

Comments
 (0)