@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
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 } ;
5
- use rustc_session:: { declare_lint_pass , declare_tool_lint } ;
5
+ use rustc_session:: { declare_tool_lint , impl_lint_pass } ;
6
6
7
7
declare_clippy_lint ! {
8
8
/// ### What it does
@@ -32,48 +32,66 @@ declare_clippy_lint! {
32
32
pedantic,
33
33
"Needlessly returning a Box"
34
34
}
35
- declare_lint_pass ! ( UnnecessaryBoxReturns => [ UNNECESSARY_BOX_RETURNS ] ) ;
36
35
37
- fn check_fn_decl ( cx : & LateContext < ' _ > , decl : & FnDecl < ' _ > , def_id : LocalDefId ) {
38
- let FnRetTy :: Return ( return_ty_hir) = & decl. output else { return } ;
36
+ pub struct UnnecessaryBoxReturns {
37
+ avoid_breaking_exported_api : bool ,
38
+ }
39
39
40
- let return_ty = cx
41
- . tcx
42
- . erase_late_bound_regions ( cx. tcx . fn_sig ( def_id) . skip_binder ( ) )
43
- . output ( ) ;
40
+ impl_lint_pass ! ( UnnecessaryBoxReturns => [ UNNECESSARY_BOX_RETURNS ] ) ;
44
41
45
- if !return_ty. is_box ( ) {
46
- return ;
42
+ impl UnnecessaryBoxReturns {
43
+ pub fn new ( avoid_breaking_exported_api : bool ) -> Self {
44
+ Self {
45
+ avoid_breaking_exported_api,
46
+ }
47
47
}
48
48
49
- let boxed_ty = return_ty. boxed_ty ( ) ;
49
+ fn check_fn_decl ( & mut self , cx : & LateContext < ' _ > , decl : & FnDecl < ' _ > , def_id : LocalDefId ) {
50
+ // we don't want to tell someone to break an exported function if they ask us not to
51
+ if self . avoid_breaking_exported_api && cx. effective_visibilities . is_exported ( def_id) {
52
+ return ;
53
+ }
54
+
55
+ let FnRetTy :: Return ( return_ty_hir) = & decl. output else { return } ;
56
+
57
+ let return_ty = cx
58
+ . tcx
59
+ . erase_late_bound_regions ( cx. tcx . fn_sig ( def_id) . skip_binder ( ) )
60
+ . output ( ) ;
50
61
51
- // it's sometimes useful to return Box<T> if T is unsized, so don't lint those
52
- if boxed_ty. is_sized ( cx. tcx , cx. param_env ) {
53
- span_lint_and_then (
54
- cx,
55
- UNNECESSARY_BOX_RETURNS ,
56
- return_ty_hir. span ,
57
- format ! ( "boxed return of the sized type `{boxed_ty}`" ) . as_str ( ) ,
58
- |diagnostic| {
59
- diagnostic. span_suggestion (
60
- return_ty_hir. span ,
61
- "try" ,
62
- boxed_ty. to_string ( ) ,
63
- // the return value and function callers also needs to
64
- // be changed, so this can't be MachineApplicable
65
- Applicability :: Unspecified ,
66
- ) ;
67
- diagnostic. help ( "changing this also requires a change to the return expressions in this function" ) ;
68
- } ,
69
- ) ;
62
+ if !return_ty. is_box ( ) {
63
+ return ;
64
+ }
65
+
66
+ let boxed_ty = return_ty. boxed_ty ( ) ;
67
+
68
+ // it's sometimes useful to return Box<T> if T is unsized, so don't lint those
69
+ if boxed_ty. is_sized ( cx. tcx , cx. param_env ) {
70
+ span_lint_and_then (
71
+ cx,
72
+ UNNECESSARY_BOX_RETURNS ,
73
+ return_ty_hir. span ,
74
+ format ! ( "boxed return of the sized type `{boxed_ty}`" ) . as_str ( ) ,
75
+ |diagnostic| {
76
+ diagnostic. span_suggestion (
77
+ return_ty_hir. span ,
78
+ "try" ,
79
+ boxed_ty. to_string ( ) ,
80
+ // the return value and function callers also needs to
81
+ // be changed, so this can't be MachineApplicable
82
+ Applicability :: Unspecified ,
83
+ ) ;
84
+ diagnostic. help ( "changing this also requires a change to the return expressions in this function" ) ;
85
+ } ,
86
+ ) ;
87
+ }
70
88
}
71
89
}
72
90
73
91
impl LateLintPass < ' _ > for UnnecessaryBoxReturns {
74
92
fn check_trait_item ( & mut self , cx : & LateContext < ' _ > , item : & TraitItem < ' _ > ) {
75
93
let TraitItemKind :: Fn ( signature, _) = & item. kind else { return } ;
76
- check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
94
+ self . check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
77
95
}
78
96
79
97
fn check_impl_item ( & mut self , cx : & LateContext < ' _ > , item : & rustc_hir:: ImplItem < ' _ > ) {
@@ -86,11 +104,11 @@ impl LateLintPass<'_> for UnnecessaryBoxReturns {
86
104
}
87
105
88
106
let ImplItemKind :: Fn ( signature, ..) = & item. kind else { return } ;
89
- check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
107
+ self . check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
90
108
}
91
109
92
110
fn check_item ( & mut self , cx : & LateContext < ' _ > , item : & Item < ' _ > ) {
93
111
let ItemKind :: Fn ( signature, ..) = & item. kind else { return } ;
94
- check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
112
+ self . check_fn_decl ( cx, signature. decl , item. owner_id . def_id ) ;
95
113
}
96
114
}
0 commit comments