@@ -2,14 +2,13 @@ use super::{DocHeaders, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, MISSING_SAFETY_D
2
2
use clippy_utils:: diagnostics:: { span_lint, span_lint_and_note} ;
3
3
use clippy_utils:: macros:: { is_panic, root_macro_call_first_node} ;
4
4
use clippy_utils:: ty:: { get_type_diagnostic_name, implements_trait_with_env, is_type_diagnostic_item} ;
5
- use clippy_utils:: visitors:: Visitable ;
5
+ use clippy_utils:: visitors:: for_each_expr ;
6
6
use clippy_utils:: { fulfill_or_allowed, is_doc_hidden, method_chain_args, return_ty} ;
7
- use rustc_hir:: intravisit:: { self , Visitor } ;
8
- use rustc_hir:: { AnonConst , BodyId , Expr , FnSig , OwnerId , Safety } ;
7
+ use rustc_hir:: { BodyId , FnSig , OwnerId , Safety } ;
9
8
use rustc_lint:: LateContext ;
10
- use rustc_middle:: hir:: nested_filter:: OnlyBodies ;
11
9
use rustc_middle:: ty;
12
10
use rustc_span:: { Span , sym} ;
11
+ use std:: ops:: ControlFlow ;
13
12
14
13
pub fn check (
15
14
cx : & LateContext < ' _ > ,
@@ -51,7 +50,7 @@ pub fn check(
51
50
}
52
51
if !headers. panics
53
52
&& let Some ( body_id) = body_id
54
- && let Some ( panic_span) = FindPanicUnwrap :: find_span ( cx, body_id)
53
+ && let Some ( panic_span) = find_panic ( cx, body_id)
55
54
{
56
55
span_lint_and_note (
57
56
cx,
@@ -96,65 +95,38 @@ pub fn check(
96
95
}
97
96
}
98
97
99
- struct FindPanicUnwrap < ' a , ' tcx > {
100
- cx : & ' a LateContext < ' tcx > ,
101
- panic_span : Option < Span > ,
102
- typeck_results : & ' tcx ty:: TypeckResults < ' tcx > ,
103
- }
104
-
105
- impl < ' a , ' tcx > FindPanicUnwrap < ' a , ' tcx > {
106
- pub fn find_span ( cx : & ' a LateContext < ' tcx > , body_id : BodyId ) -> Option < Span > {
107
- let mut vis = Self {
108
- cx,
109
- panic_span : None ,
110
- typeck_results : cx. tcx . typeck_body ( body_id) ,
111
- } ;
112
- cx. tcx . hir_body ( body_id) . visit ( & mut vis) ;
113
- vis. panic_span
114
- }
115
- }
116
-
117
- impl < ' tcx > Visitor < ' tcx > for FindPanicUnwrap < ' _ , ' tcx > {
118
- type NestedFilter = OnlyBodies ;
119
-
120
- fn visit_expr ( & mut self , expr : & ' tcx Expr < ' _ > ) {
121
- if self . panic_span . is_some ( ) {
122
- return ;
123
- }
124
-
125
- if let Some ( macro_call) = root_macro_call_first_node ( self . cx , expr) {
126
- if ( is_panic ( self . cx , macro_call. def_id )
98
+ fn find_panic ( cx : & LateContext < ' _ > , body_id : BodyId ) -> Option < Span > {
99
+ let mut panic_span = None ;
100
+ let typeck = cx. tcx . typeck_body ( body_id) ;
101
+ for_each_expr ( cx, cx. tcx . hir_body ( body_id) , |expr| {
102
+ if let Some ( macro_call) = root_macro_call_first_node ( cx, expr)
103
+ && ( is_panic ( cx, macro_call. def_id )
127
104
|| matches ! (
128
- self . cx. tcx. get_diagnostic_name( macro_call. def_id) ,
105
+ cx. tcx. get_diagnostic_name( macro_call. def_id) ,
129
106
Some ( sym:: assert_macro | sym:: assert_eq_macro | sym:: assert_ne_macro)
130
107
) )
131
- && !self . cx . tcx . hir_is_inside_const_context ( expr. hir_id )
132
- && !fulfill_or_allowed ( self . cx , MISSING_PANICS_DOC , [ expr. hir_id ] )
133
- {
134
- self . panic_span = Some ( macro_call . span ) ;
135
- }
108
+ && !cx. tcx . hir_is_inside_const_context ( expr. hir_id )
109
+ && !fulfill_or_allowed ( cx, MISSING_PANICS_DOC , [ expr. hir_id ] )
110
+ && panic_span . is_none ( )
111
+ {
112
+ panic_span = Some ( macro_call . span ) ;
136
113
}
137
114
138
115
// check for `unwrap` and `expect` for both `Option` and `Result`
139
- if let Some ( arglists) = method_chain_args ( expr, & [ "unwrap" ] ) . or ( method_chain_args ( expr, & [ "expect" ] ) ) {
140
- let receiver_ty = self . typeck_results . expr_ty ( arglists[ 0 ] . 0 ) . peel_refs ( ) ;
141
- if matches ! (
142
- get_type_diagnostic_name( self . cx, receiver_ty) ,
116
+ if let Some ( arglists) = method_chain_args ( expr, & [ "unwrap" ] ) . or_else ( || method_chain_args ( expr, & [ "expect" ] ) )
117
+ && let receiver_ty = typeck . expr_ty ( arglists[ 0 ] . 0 ) . peel_refs ( )
118
+ && matches ! (
119
+ get_type_diagnostic_name( cx, receiver_ty) ,
143
120
Some ( sym:: Option | sym:: Result )
144
- ) && !fulfill_or_allowed ( self . cx , MISSING_PANICS_DOC , [ expr. hir_id ] )
145
- {
146
- self . panic_span = Some ( expr. span ) ;
147
- }
121
+ )
122
+ && !fulfill_or_allowed ( cx, MISSING_PANICS_DOC , [ expr. hir_id ] )
123
+ && panic_span. is_none ( )
124
+ {
125
+ panic_span = Some ( expr. span ) ;
148
126
}
149
127
150
- // and check sub-expressions
151
- intravisit:: walk_expr ( self , expr) ;
152
- }
153
-
154
- // Panics in const blocks will cause compilation to fail.
155
- fn visit_anon_const ( & mut self , _: & ' tcx AnonConst ) { }
156
-
157
- fn maybe_tcx ( & mut self ) -> Self :: MaybeTyCtxt {
158
- self . cx . tcx
159
- }
128
+ // Visit all nodes to fulfill any `#[expect]`s after the first linted panic
129
+ ControlFlow :: < !> :: Continue ( ( ) )
130
+ } ) ;
131
+ panic_span
160
132
}
0 commit comments