@@ -147,15 +147,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
147147 ( pattern, pattern_ty)
148148 }
149149
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 {
153152 tcx : self . tcx ,
154153 param_env : self . param_env ,
155- module : module . to_def_id ( ) ,
154+ module : self . tcx . parent_module ( hir_id ) . to_def_id ( ) ,
156155 pattern_arena : & self . pattern_arena ,
157- } ;
158- f ( cx) ;
156+ }
159157 }
160158
161159 fn check_match (
@@ -169,91 +167,88 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
169167 self . check_patterns ( arm. guard . is_some ( ) , & arm. pat ) ;
170168 }
171169
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 ) ;
174171
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 ;
181173
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 ( ) ;
186180
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) ;
189188
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) ;
197195 }
198196
199197 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 ) ;
233199
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 ,
250241 ) ;
251242 }
243+ err. note (
244+ "for more information, visit \
245+ https://doc.rust-lang.org/book/ch18-02-refutability.html",
246+ ) ;
247+ }
252248
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 ( ) ;
257252 }
258253}
259254
0 commit comments