1
- use rustc_lint:: { LateLintPass , LateContext } ;
2
1
use rustc_ast:: ast:: Attribute ;
3
- use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
4
2
use rustc_errors:: Applicability ;
5
- use rustc_hir:: intravisit:: { FnKind , walk_expr , NestedVisitorMap , Visitor } ;
6
- use rustc_span :: source_map :: Span ;
7
- use rustc_middle :: lint :: in_external_macro ;
3
+ use rustc_hir:: intravisit:: { walk_expr , FnKind , NestedVisitorMap , Visitor } ;
4
+ use rustc_hir :: { Block , Body , Expr , ExprKind , FnDecl , HirId , MatchSource , StmtKind } ;
5
+ use rustc_lint :: { LateContext , LateLintPass } ;
8
6
use rustc_middle:: hir:: map:: Map ;
7
+ use rustc_middle:: lint:: in_external_macro;
9
8
use rustc_middle:: ty:: subst:: GenericArgKind ;
10
- use rustc_hir:: { Block , Body , Expr , ExprKind , FnDecl , HirId , MatchSource , StmtKind } ;
9
+ use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
10
+ use rustc_span:: source_map:: Span ;
11
11
12
12
use crate :: utils:: { fn_def_id, snippet_opt, span_lint_and_sugg, span_lint_and_then} ;
13
13
@@ -46,16 +46,39 @@ enum RetReplacement {
46
46
declare_lint_pass ! ( NeedlessReturn => [ NEEDLESS_RETURN ] ) ;
47
47
48
48
impl < ' tcx > LateLintPass < ' tcx > for NeedlessReturn {
49
- fn check_fn ( & mut self , cx : & LateContext < ' tcx > , kind : FnKind < ' tcx > , _: & ' tcx FnDecl < ' tcx > , body : & ' tcx Body < ' tcx > , _: Span , _: HirId ) {
49
+ fn check_fn (
50
+ & mut self ,
51
+ cx : & LateContext < ' tcx > ,
52
+ kind : FnKind < ' tcx > ,
53
+ _: & ' tcx FnDecl < ' tcx > ,
54
+ body : & ' tcx Body < ' tcx > ,
55
+ _: Span ,
56
+ _: HirId ,
57
+ ) {
50
58
match kind {
51
59
FnKind :: Closure ( _) => {
52
- check_final_expr ( cx, & body. value , Some ( body. value . span ) , RetReplacement :: Empty )
53
- }
60
+ if !last_statement_borrows ( cx, & body. value ) {
61
+ check_final_expr ( cx, & body. value , Some ( body. value . span ) , RetReplacement :: Empty )
62
+ }
63
+ } ,
54
64
FnKind :: ItemFn ( ..) | FnKind :: Method ( ..) => {
55
65
if let ExprKind :: Block ( ref block, _) = body. value . kind {
56
- check_block_return ( cx, block)
66
+ if let Some ( expr) = block. expr {
67
+ if !last_statement_borrows ( cx, expr) {
68
+ check_final_expr ( cx, expr, Some ( expr. span ) , RetReplacement :: Empty ) ;
69
+ }
70
+ } else if let Some ( stmt) = block. stmts . iter ( ) . last ( ) {
71
+ match stmt. kind {
72
+ StmtKind :: Expr ( ref expr) | StmtKind :: Semi ( ref expr) => {
73
+ if !last_statement_borrows ( cx, expr) {
74
+ check_final_expr ( cx, expr, Some ( stmt. span ) , RetReplacement :: Empty ) ;
75
+ }
76
+ } ,
77
+ _ => ( ) ,
78
+ }
79
+ }
57
80
}
58
- }
81
+ } ,
59
82
}
60
83
}
61
84
}
@@ -71,23 +94,16 @@ fn check_block_return(cx: &LateContext<'_>, block: &Block<'_>) {
71
94
match stmt. kind {
72
95
StmtKind :: Expr ( ref expr) | StmtKind :: Semi ( ref expr) => {
73
96
check_final_expr ( cx, expr, Some ( stmt. span ) , RetReplacement :: Empty ) ;
74
- }
97
+ } ,
75
98
_ => ( ) ,
76
99
}
77
100
}
78
101
}
79
102
80
-
81
- fn check_final_expr (
82
- cx : & LateContext < ' _ > ,
83
- expr : & Expr < ' _ > ,
84
- span : Option < Span > ,
85
- replacement : RetReplacement ,
86
- ) {
103
+ fn check_final_expr ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , span : Option < Span > , replacement : RetReplacement ) {
87
104
match expr. kind {
88
105
// simple return is always "bad"
89
106
ExprKind :: Ret ( ref inner) => {
90
-
91
107
// allow `#[cfg(a)] return a; #[cfg(b)] return b;`
92
108
if !expr. attrs . iter ( ) . any ( attr_is_cfg) {
93
109
emit_return_lint (
@@ -97,32 +113,34 @@ fn check_final_expr(
97
113
replacement,
98
114
) ;
99
115
}
100
- }
116
+ } ,
101
117
// a whole block? check it!
102
118
ExprKind :: Block ( ref block, _) => {
103
119
check_block_return ( cx, block) ;
104
- }
120
+ } ,
105
121
// a match expr, check all arms
106
122
// an if/if let expr, check both exprs
107
123
// note, if without else is going to be a type checking error anyways
108
124
// (except for unit type functions) so we don't match it
109
-
110
- ExprKind :: Match ( _, ref arms, source) => {
111
- match source {
112
- MatchSource :: Normal => {
113
- for arm in arms. iter ( ) {
114
- check_final_expr ( cx, & arm. body , Some ( arm. body . span ) , RetReplacement :: Block ) ;
115
- }
116
- }
117
- MatchSource :: IfDesugar { contains_else_clause : true } | MatchSource :: IfLetDesugar { contains_else_clause : true } => {
118
- if let ExprKind :: Block ( ref ifblock, _) = arms[ 0 ] . body . kind {
119
- check_block_return ( cx, ifblock) ;
120
- }
121
- check_final_expr ( cx, arms[ 1 ] . body , None , RetReplacement :: Empty ) ;
125
+ ExprKind :: Match ( _, ref arms, source) => match source {
126
+ MatchSource :: Normal => {
127
+ for arm in arms. iter ( ) {
128
+ check_final_expr ( cx, & arm. body , Some ( arm. body . span ) , RetReplacement :: Block ) ;
122
129
}
123
- _ => ( )
130
+ } ,
131
+ MatchSource :: IfDesugar {
132
+ contains_else_clause : true ,
124
133
}
125
- }
134
+ | MatchSource :: IfLetDesugar {
135
+ contains_else_clause : true ,
136
+ } => {
137
+ if let ExprKind :: Block ( ref ifblock, _) = arms[ 0 ] . body . kind {
138
+ check_block_return ( cx, ifblock) ;
139
+ }
140
+ check_final_expr ( cx, arms[ 1 ] . body , None , RetReplacement :: Empty ) ;
141
+ } ,
142
+ _ => ( ) ,
143
+ } ,
126
144
_ => ( ) ,
127
145
}
128
146
}
@@ -139,7 +157,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa
139
157
diag. span_suggestion ( ret_span, "remove `return`" , snippet, Applicability :: MachineApplicable ) ;
140
158
}
141
159
} )
142
- }
160
+ } ,
143
161
None => match replacement {
144
162
RetReplacement :: Empty => {
145
163
span_lint_and_sugg (
@@ -151,7 +169,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa
151
169
String :: new ( ) ,
152
170
Applicability :: MachineApplicable ,
153
171
) ;
154
- }
172
+ } ,
155
173
RetReplacement :: Block => {
156
174
span_lint_and_sugg (
157
175
cx,
@@ -162,7 +180,7 @@ fn emit_return_lint(cx: &LateContext<'_>, ret_span: Span, inner_span: Option<Spa
162
180
"{}" . to_string ( ) ,
163
181
Applicability :: MachineApplicable ,
164
182
) ;
165
- }
183
+ } ,
166
184
} ,
167
185
}
168
186
}
@@ -204,4 +222,3 @@ impl<'tcx> Visitor<'tcx> for BorrowVisitor<'_, 'tcx> {
204
222
NestedVisitorMap :: None
205
223
}
206
224
}
207
-
0 commit comments