1- use clippy_utils:: diagnostics:: span_lint_and_then;
1+ use clippy_utils:: { diagnostics:: span_lint_and_then, ty :: approx_ty_size } ;
22use rustc_errors:: Applicability ;
33use rustc_hir:: { def_id:: LocalDefId , FnDecl , FnRetTy , ImplItemKind , Item , ItemKind , Node , TraitItem , TraitItemKind } ;
44use 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
3740pub struct UnnecessaryBoxReturns {
3841 avoid_breaking_exported_api : bool ,
42+ maximum_size : u64 ,
3943}
4044
4145impl_lint_pass ! ( UnnecessaryBoxReturns => [ UNNECESSARY_BOX_RETURNS ] ) ;
4246
4347impl 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 ,
0 commit comments