@@ -147,15 +147,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
147
147
( pattern, pattern_ty)
148
148
}
149
149
150
- fn check_in_cx ( & self , hir_id : HirId , f : impl FnOnce ( MatchCheckCtxt < ' _ , ' tcx > ) ) {
151
- let module = self . tcx . parent_module ( hir_id) ;
152
- let cx = MatchCheckCtxt {
150
+ fn new_cx ( & self , hir_id : HirId ) -> MatchCheckCtxt < ' _ , ' tcx > {
151
+ MatchCheckCtxt {
153
152
tcx : self . tcx ,
154
153
param_env : self . param_env ,
155
- module : module . to_def_id ( ) ,
154
+ module : self . tcx . parent_module ( hir_id ) . to_def_id ( ) ,
156
155
pattern_arena : & self . pattern_arena ,
157
- } ;
158
- f ( cx) ;
156
+ }
159
157
}
160
158
161
159
fn check_match (
@@ -169,91 +167,88 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
169
167
self . check_patterns ( arm. guard . is_some ( ) , & arm. pat ) ;
170
168
}
171
169
172
- self . check_in_cx ( scrut. hir_id , |ref mut cx| {
173
- let mut have_errors = false ;
170
+ let mut cx = self . new_cx ( scrut. hir_id ) ;
174
171
175
- let inlined_arms: Vec < _ > = arms
176
- . iter ( )
177
- . map ( |hir:: Arm { pat, guard, .. } | {
178
- ( self . lower_pattern ( cx, pat, & mut have_errors) . 0 , pat. hir_id , guard. is_some ( ) )
179
- } )
180
- . collect ( ) ;
172
+ let mut have_errors = false ;
181
173
182
- // Bail out early if inlining failed.
183
- if have_errors {
184
- return ;
185
- }
174
+ let inlined_arms: Vec < _ > = arms
175
+ . iter ( )
176
+ . map ( |hir:: Arm { pat, guard, .. } | {
177
+ ( self . lower_pattern ( & mut cx, pat, & mut have_errors) . 0 , pat. hir_id , guard. is_some ( ) )
178
+ } )
179
+ . collect ( ) ;
186
180
187
- // Fourth, check for unreachable arms.
188
- let matrix = check_arms ( cx, & inlined_arms, source) ;
181
+ // Bail out early if inlining failed.
182
+ if have_errors {
183
+ return ;
184
+ }
185
+
186
+ // Fourth, check for unreachable arms.
187
+ let matrix = check_arms ( & mut cx, & inlined_arms, source) ;
189
188
190
- // Fifth, check if the match is exhaustive.
191
- let scrut_ty = self . tables . node_type ( scrut. hir_id ) ;
192
- // Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
193
- // since an empty matrix can occur when there are arms, if those arms all have guards.
194
- let is_empty_match = inlined_arms. is_empty ( ) ;
195
- check_exhaustive ( cx, scrut_ty, scrut. span , & matrix, scrut. hir_id , is_empty_match) ;
196
- } )
189
+ // Fifth, check if the match is exhaustive.
190
+ let scrut_ty = self . tables . node_type ( scrut. hir_id ) ;
191
+ // Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
192
+ // since an empty matrix can occur when there are arms, if those arms all have guards.
193
+ let is_empty_match = inlined_arms. is_empty ( ) ;
194
+ check_exhaustive ( & mut cx, scrut_ty, scrut. span , & matrix, scrut. hir_id , is_empty_match) ;
197
195
}
198
196
199
197
fn check_irrefutable ( & self , pat : & ' tcx Pat < ' tcx > , origin : & str , sp : Option < Span > ) {
200
- self . check_in_cx ( pat. hir_id , |ref mut cx| {
201
- let ( pattern, pattern_ty) = self . lower_pattern ( cx, pat, & mut false ) ;
202
- let pats: Matrix < ' _ , ' _ > = vec ! [ PatStack :: from_pattern( pattern) ] . into_iter ( ) . collect ( ) ;
203
-
204
- let witnesses = match check_not_useful ( cx, pattern_ty, & pats, pat. hir_id ) {
205
- Ok ( _) => return ,
206
- Err ( err) => err,
207
- } ;
208
-
209
- let joined_patterns = joined_uncovered_patterns ( & witnesses) ;
210
- let mut err = struct_span_err ! (
211
- self . tcx. sess,
212
- pat. span,
213
- E0005 ,
214
- "refutable pattern in {}: {} not covered" ,
215
- origin,
216
- joined_patterns
217
- ) ;
218
- let suggest_if_let = match & pat. kind {
219
- hir:: PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
220
- if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) =>
221
- {
222
- const_not_var ( & mut err, cx. tcx , pat, path) ;
223
- false
224
- }
225
- _ => {
226
- err. span_label (
227
- pat. span ,
228
- pattern_not_covered_label ( & witnesses, & joined_patterns) ,
229
- ) ;
230
- true
231
- }
232
- } ;
198
+ let mut cx = self . new_cx ( pat. hir_id ) ;
233
199
234
- if let ( Some ( span) , true ) = ( sp, suggest_if_let) {
235
- err. note (
236
- "`let` bindings require an \" irrefutable pattern\" , like a `struct` or \
237
- an `enum` with only one variant",
238
- ) ;
239
- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
240
- err. span_suggestion (
241
- span,
242
- "you might want to use `if let` to ignore the variant that isn't matched" ,
243
- format ! ( "if {} {{ /* */ }}" , & snippet[ ..snippet. len( ) - 1 ] ) ,
244
- Applicability :: HasPlaceholders ,
245
- ) ;
246
- }
247
- err. note (
248
- "for more information, visit \
249
- https://doc.rust-lang.org/book/ch18-02-refutability.html",
200
+ let ( pattern, pattern_ty) = self . lower_pattern ( & mut cx, pat, & mut false ) ;
201
+ let pats: Matrix < ' _ , ' _ > = vec ! [ PatStack :: from_pattern( pattern) ] . into_iter ( ) . collect ( ) ;
202
+
203
+ let witnesses = match check_not_useful ( & mut cx, pattern_ty, & pats, pat. hir_id ) {
204
+ Ok ( _) => return ,
205
+ Err ( err) => err,
206
+ } ;
207
+
208
+ let joined_patterns = joined_uncovered_patterns ( & witnesses) ;
209
+ let mut err = struct_span_err ! (
210
+ self . tcx. sess,
211
+ pat. span,
212
+ E0005 ,
213
+ "refutable pattern in {}: {} not covered" ,
214
+ origin,
215
+ joined_patterns
216
+ ) ;
217
+ let suggest_if_let = match & pat. kind {
218
+ hir:: PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
219
+ if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) =>
220
+ {
221
+ const_not_var ( & mut err, cx. tcx , pat, path) ;
222
+ false
223
+ }
224
+ _ => {
225
+ err. span_label ( pat. span , pattern_not_covered_label ( & witnesses, & joined_patterns) ) ;
226
+ true
227
+ }
228
+ } ;
229
+
230
+ if let ( Some ( span) , true ) = ( sp, suggest_if_let) {
231
+ err. note (
232
+ "`let` bindings require an \" irrefutable pattern\" , like a `struct` or \
233
+ an `enum` with only one variant",
234
+ ) ;
235
+ if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
236
+ err. span_suggestion (
237
+ span,
238
+ "you might want to use `if let` to ignore the variant that isn't matched" ,
239
+ format ! ( "if {} {{ /* */ }}" , & snippet[ ..snippet. len( ) - 1 ] ) ,
240
+ Applicability :: HasPlaceholders ,
250
241
) ;
251
242
}
243
+ err. note (
244
+ "for more information, visit \
245
+ https://doc.rust-lang.org/book/ch18-02-refutability.html",
246
+ ) ;
247
+ }
252
248
253
- adt_defined_here ( cx, & mut err, pattern_ty, & witnesses) ;
254
- err. note ( & format ! ( "the matched value is of type `{}`" , pattern_ty) ) ;
255
- err. emit ( ) ;
256
- } ) ;
249
+ adt_defined_here ( & mut cx, & mut err, pattern_ty, & witnesses) ;
250
+ err. note ( & format ! ( "the matched value is of type `{}`" , pattern_ty) ) ;
251
+ err. emit ( ) ;
257
252
}
258
253
}
259
254
0 commit comments