1
1
use super :: _match:: Usefulness :: * ;
2
2
use super :: _match:: WitnessPreference :: * ;
3
3
use super :: _match:: { expand_pattern, is_useful, MatchCheckCtxt , Matrix , PatStack } ;
4
-
5
4
use super :: { PatCtxt , PatKind , PatternError } ;
6
5
6
+ use arena:: TypedArena ;
7
7
use rustc_ast:: ast:: Mutability ;
8
8
use rustc_errors:: { error_code, struct_span_err, Applicability , DiagnosticBuilder } ;
9
9
use rustc_hir as hir;
@@ -17,7 +17,6 @@ use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERN
17
17
use rustc_session:: parse:: feature_err;
18
18
use rustc_session:: Session ;
19
19
use rustc_span:: { sym, Span } ;
20
-
21
20
use std:: slice;
22
21
23
22
crate fn check_match ( tcx : TyCtxt < ' _ > , def_id : DefId ) {
@@ -26,8 +25,12 @@ crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
26
25
Some ( id) => tcx. hir ( ) . body_owned_by ( tcx. hir ( ) . as_local_hir_id ( id) ) ,
27
26
} ;
28
27
29
- let mut visitor =
30
- MatchVisitor { tcx, tables : tcx. body_tables ( body_id) , param_env : tcx. param_env ( def_id) } ;
28
+ let mut visitor = MatchVisitor {
29
+ tcx,
30
+ tables : tcx. body_tables ( body_id) ,
31
+ param_env : tcx. param_env ( def_id) ,
32
+ pattern_arena : TypedArena :: default ( ) ,
33
+ } ;
31
34
visitor. visit_body ( tcx. hir ( ) . body ( body_id) ) ;
32
35
}
33
36
@@ -39,6 +42,7 @@ struct MatchVisitor<'a, 'tcx> {
39
42
tcx : TyCtxt < ' tcx > ,
40
43
tables : & ' a ty:: TypeckTables < ' tcx > ,
41
44
param_env : ty:: ParamEnv < ' tcx > ,
45
+ pattern_arena : TypedArena < super :: Pat < ' tcx > > ,
42
46
}
43
47
44
48
impl < ' tcx > Visitor < ' tcx > for MatchVisitor < ' _ , ' tcx > {
@@ -143,9 +147,13 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
143
147
( pattern, pattern_ty)
144
148
}
145
149
146
- fn check_in_cx ( & self , hir_id : HirId , f : impl FnOnce ( MatchCheckCtxt < ' _ , ' tcx > ) ) {
147
- let module = self . tcx . parent_module ( hir_id) ;
148
- MatchCheckCtxt :: create_and_enter ( self . tcx , self . param_env , module. to_def_id ( ) , |cx| f ( cx) ) ;
150
+ fn new_cx ( & self , hir_id : HirId ) -> MatchCheckCtxt < ' _ , ' tcx > {
151
+ MatchCheckCtxt {
152
+ tcx : self . tcx ,
153
+ param_env : self . param_env ,
154
+ module : self . tcx . parent_module ( hir_id) . to_def_id ( ) ,
155
+ pattern_arena : & self . pattern_arena ,
156
+ }
149
157
}
150
158
151
159
fn check_match (
@@ -159,91 +167,88 @@ impl<'tcx> MatchVisitor<'_, 'tcx> {
159
167
self . check_patterns ( arm. guard . is_some ( ) , & arm. pat ) ;
160
168
}
161
169
162
- self . check_in_cx ( scrut. hir_id , |ref mut cx| {
163
- let mut have_errors = false ;
170
+ let mut cx = self . new_cx ( scrut. hir_id ) ;
164
171
165
- let inlined_arms: Vec < _ > = arms
166
- . iter ( )
167
- . map ( |hir:: Arm { pat, guard, .. } | {
168
- ( self . lower_pattern ( cx, pat, & mut have_errors) . 0 , pat. hir_id , guard. is_some ( ) )
169
- } )
170
- . collect ( ) ;
172
+ let mut have_errors = false ;
171
173
172
- // Bail out early if inlining failed.
173
- if have_errors {
174
- return ;
175
- }
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 ( ) ;
180
+
181
+ // Bail out early if inlining failed.
182
+ if have_errors {
183
+ return ;
184
+ }
176
185
177
- // Fourth, check for unreachable arms.
178
- let matrix = check_arms ( cx, & inlined_arms, source) ;
186
+ // Fourth, check for unreachable arms.
187
+ let matrix = check_arms ( & mut cx, & inlined_arms, source) ;
179
188
180
- // Fifth, check if the match is exhaustive.
181
- let scrut_ty = self . tables . node_type ( scrut. hir_id ) ;
182
- // Note: An empty match isn't the same as an empty matrix for diagnostics purposes,
183
- // since an empty matrix can occur when there are arms, if those arms all have guards.
184
- let is_empty_match = inlined_arms. is_empty ( ) ;
185
- check_exhaustive ( cx, scrut_ty, scrut. span , & matrix, scrut. hir_id , is_empty_match) ;
186
- } )
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) ;
187
195
}
188
196
189
197
fn check_irrefutable ( & self , pat : & ' tcx Pat < ' tcx > , origin : & str , sp : Option < Span > ) {
190
- self . check_in_cx ( pat. hir_id , |ref mut cx| {
191
- let ( pattern, pattern_ty) = self . lower_pattern ( cx, pat, & mut false ) ;
192
- let pats: Matrix < ' _ , ' _ > = vec ! [ PatStack :: from_pattern( pattern) ] . into_iter ( ) . collect ( ) ;
193
-
194
- let witnesses = match check_not_useful ( cx, pattern_ty, & pats, pat. hir_id ) {
195
- Ok ( _) => return ,
196
- Err ( err) => err,
197
- } ;
198
-
199
- let joined_patterns = joined_uncovered_patterns ( & witnesses) ;
200
- let mut err = struct_span_err ! (
201
- self . tcx. sess,
202
- pat. span,
203
- E0005 ,
204
- "refutable pattern in {}: {} not covered" ,
205
- origin,
206
- joined_patterns
207
- ) ;
208
- let suggest_if_let = match & pat. kind {
209
- hir:: PatKind :: Path ( hir:: QPath :: Resolved ( None , path) )
210
- if path. segments . len ( ) == 1 && path. segments [ 0 ] . args . is_none ( ) =>
211
- {
212
- const_not_var ( & mut err, cx. tcx , pat, path) ;
213
- false
214
- }
215
- _ => {
216
- err. span_label (
217
- pat. span ,
218
- pattern_not_covered_label ( & witnesses, & joined_patterns) ,
219
- ) ;
220
- true
221
- }
222
- } ;
198
+ let mut cx = self . new_cx ( pat. hir_id ) ;
223
199
224
- if let ( Some ( span) , true ) = ( sp, suggest_if_let) {
225
- err. note (
226
- "`let` bindings require an \" irrefutable pattern\" , like a `struct` or \
227
- an `enum` with only one variant",
228
- ) ;
229
- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( span) {
230
- err. span_suggestion (
231
- span,
232
- "you might want to use `if let` to ignore the variant that isn't matched" ,
233
- format ! ( "if {} {{ /* */ }}" , & snippet[ ..snippet. len( ) - 1 ] ) ,
234
- Applicability :: HasPlaceholders ,
235
- ) ;
236
- }
237
- err. note (
238
- "for more information, visit \
239
- 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 ,
240
241
) ;
241
242
}
243
+ err. note (
244
+ "for more information, visit \
245
+ https://doc.rust-lang.org/book/ch18-02-refutability.html",
246
+ ) ;
247
+ }
242
248
243
- adt_defined_here ( cx, & mut err, pattern_ty, & witnesses) ;
244
- err. note ( & format ! ( "the matched value is of type `{}`" , pattern_ty) ) ;
245
- err. emit ( ) ;
246
- } ) ;
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 ( ) ;
247
252
}
248
253
}
249
254
0 commit comments