1
- use clippy_utils:: diagnostics:: span_lint_and_then;
1
+ use clippy_utils:: { diagnostics:: span_lint_and_then, ty :: approx_ty_size } ;
2
2
use rustc_errors:: Applicability ;
3
3
use rustc_hir:: { def_id:: LocalDefId , FnDecl , FnRetTy , ImplItemKind , Item , ItemKind , Node , TraitItem , TraitItemKind } ;
4
4
use rustc_lint:: { LateContext , LateLintPass } ;
@@ -10,6 +10,9 @@ declare_clippy_lint! {
10
10
///
11
11
/// Checks for a return type containing a `Box<T>` where `T` implements `Sized`
12
12
///
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
+ ///
13
16
/// ### Why is this bad?
14
17
///
15
18
/// It's better to just return `T` in these cases. The caller may not need
@@ -36,14 +39,16 @@ declare_clippy_lint! {
36
39
37
40
pub struct UnnecessaryBoxReturns {
38
41
avoid_breaking_exported_api : bool ,
42
+ maximum_size : u64 ,
39
43
}
40
44
41
45
impl_lint_pass ! ( UnnecessaryBoxReturns => [ UNNECESSARY_BOX_RETURNS ] ) ;
42
46
43
47
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 {
45
49
Self {
46
50
avoid_breaking_exported_api,
51
+ maximum_size,
47
52
}
48
53
}
49
54
@@ -71,8 +76,10 @@ impl UnnecessaryBoxReturns {
71
76
72
77
let boxed_ty = return_ty. boxed_ty ( ) ;
73
78
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 {
76
83
span_lint_and_then (
77
84
cx,
78
85
UNNECESSARY_BOX_RETURNS ,
0 commit comments