@@ -31,6 +31,7 @@ use rustc::ty;
31
31
use std:: cmp:: Ordering ;
32
32
use std:: fmt;
33
33
use std:: iter:: { FromIterator , IntoIterator , repeat} ;
34
+ use std:: mem;
34
35
35
36
use rustc:: hir;
36
37
use rustc:: hir:: { Pat , PatKind } ;
@@ -214,19 +215,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
214
215
// Finally, check if the whole match expression is exhaustive.
215
216
// Check for empty enum, because is_useful only works on inhabited types.
216
217
let pat_ty = cx. tcx . node_id_to_type ( scrut. id ) ;
217
- if inlined_arms. is_empty ( ) {
218
- if !pat_ty. is_empty ( cx. tcx ) {
219
- // We know the type is inhabited, so this must be wrong
220
- let mut err = struct_span_err ! ( cx. tcx. sess, ex. span, E0002 ,
221
- "non-exhaustive patterns: type {} is non-empty" ,
222
- pat_ty) ;
223
- span_help ! ( & mut err, ex. span,
224
- "Please ensure that all possible cases are being handled; \
225
- possibly adding wildcards or more match arms.") ;
226
- err. emit ( ) ;
227
- }
228
- // If the type *is* empty, it's vacuously exhaustive
229
- return ;
218
+ if inlined_arms. is_empty ( ) && pat_ty. is_empty ( cx. tcx ) {
219
+ return
230
220
}
231
221
232
222
let matrix: Matrix = inlined_arms
@@ -235,12 +225,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
235
225
. flat_map ( |arm| & arm. 0 )
236
226
. map ( |pat| vec ! [ wrap_pat( cx, & pat) ] )
237
227
. collect ( ) ;
238
- let match_span = Span {
239
- lo : ex. span . lo ,
240
- hi : scrut. span . hi ,
241
- expn_id : ex. span . expn_id
242
- } ;
243
- check_exhaustive ( cx, match_span, & matrix, source) ;
228
+ check_exhaustive ( cx, ex. span , & matrix, source) ;
244
229
} ,
245
230
_ => ( )
246
231
}
@@ -316,7 +301,10 @@ fn check_arms(cx: &MatchCheckCtxt,
316
301
let & ( ref first_arm_pats, _) = & arms[ 0 ] ;
317
302
let first_pat = & first_arm_pats[ 0 ] ;
318
303
let span = first_pat. span ;
319
- span_err ! ( cx. tcx. sess, span, E0162 , "irrefutable if-let pattern" ) ;
304
+ struct_span_err ! (
305
+ cx. tcx. sess, span, E0162 , "irrefutable if-let pattern" )
306
+ . span_label ( span, & "this pattern always applies" )
307
+ . emit ( ) ;
320
308
printed_if_let_err = true ;
321
309
}
322
310
} ,
@@ -326,7 +314,10 @@ fn check_arms(cx: &MatchCheckCtxt,
326
314
let & ( ref first_arm_pats, _) = & arms[ 0 ] ;
327
315
let first_pat = & first_arm_pats[ 0 ] ;
328
316
let span = first_pat. span ;
329
- span_err ! ( cx. tcx. sess, span, E0165 , "irrefutable while-let pattern" ) ;
317
+ struct_span_err ! (
318
+ cx. tcx. sess, span, E0165 , "irrefutable while-let pattern" )
319
+ . span_label ( span, & "this pattern always applies" )
320
+ . emit ( ) ;
330
321
} ,
331
322
332
323
hir:: MatchSource :: ForLoopDesugar => {
@@ -338,17 +329,17 @@ fn check_arms(cx: &MatchCheckCtxt,
338
329
} ,
339
330
340
331
hir:: MatchSource :: Normal => {
341
- let mut err = struct_span_err ! ( cx. tcx. sess, pat. span, E0001 ,
342
- "unreachable pattern" ) ;
343
- err . span_label ( pat. span , & format ! ( "this is an unreachable pattern" ) ) ;
332
+ let mut diag = struct_span_err ! ( cx. tcx. sess, pat. span, E0001 ,
333
+ "unreachable pattern" ) ;
334
+ diag . span_label ( pat. span , & "this pattern cannot be reached" ) ;
344
335
// if we had a catchall pattern, hint at that
345
336
for row in & seen. 0 {
346
337
if pat_is_catchall ( & cx. tcx . def_map . borrow ( ) , row[ 0 ] . 0 ) {
347
- span_note ! ( err , row[ 0 ] . 0 . span,
348
- "this pattern matches any value" ) ;
338
+ diag . span_label ( row[ 0 ] . 0 . span ,
339
+ & "this pattern matches any value" ) ;
349
340
}
350
341
}
351
- err . emit ( ) ;
342
+ diag . emit ( ) ;
352
343
} ,
353
344
354
345
hir:: MatchSource :: TryDesugar => {
@@ -407,10 +398,18 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
407
398
} ,
408
399
_ => bug ! ( ) ,
409
400
} ;
410
- span_err ! ( cx. tcx. sess, sp, E0297 ,
411
- "refutable pattern in `for` loop binding: \
412
- `{}` not covered",
413
- pat_to_string( witness) ) ;
401
+ let pat = matrix. 0 [ 0 ] [ 0 ] . 0 ;
402
+ let span = match pat. node {
403
+ hir:: PatKind :: TupleStruct ( _, ref subpats, _) => subpats. get ( 0 ) ,
404
+ _ => None
405
+ } . unwrap_or_else ( || {
406
+ span_bug ! ( pat. span, "bad for-loop desugaring {:?}" , pat) ;
407
+ } ) . span ;
408
+ struct_span_err ! ( cx. tcx. sess, span, E0297 ,
409
+ "refutable pattern in `for` loop binding" )
410
+ . span_label ( span, & format ! ( "`{}` not covered" ,
411
+ pat_to_string( witness) ) )
412
+ . emit ( ) ;
414
413
} ,
415
414
_ => {
416
415
let pattern_strings: Vec < _ > = witnesses. iter ( ) . map ( |w| {
@@ -429,15 +428,10 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
429
428
format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
430
429
}
431
430
} ;
432
-
433
- let label_text = match pattern_strings. len ( ) {
434
- 1 => format ! ( "pattern {} not covered" , joined_patterns) ,
435
- _ => format ! ( "patterns {} not covered" , joined_patterns)
436
- } ;
437
431
struct_span_err ! ( cx. tcx. sess, sp, E0004 ,
438
- "non-exhaustive patterns: {} not covered" ,
439
- joined_patterns
440
- ) . span_label ( sp , & label_text ) . emit ( ) ;
432
+ "non-exhaustive patterns" )
433
+ . span_label ( sp , & format ! ( "{} not covered" , joined_patterns) )
434
+ . emit ( ) ;
441
435
} ,
442
436
}
443
437
}
@@ -520,8 +514,11 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
520
514
}
521
515
} else {
522
516
self . failed = true ;
523
- span_err ! ( self . tcx. sess, pat. span, E0158 ,
524
- "statics cannot be referenced in patterns" ) ;
517
+ struct_span_err ! (
518
+ self . tcx. sess, pat. span, E0158 ,
519
+ "unresolvable constant in pattern" )
520
+ . span_label ( pat. span , & "unresolvable constant here" )
521
+ . emit ( ) ;
525
522
pat
526
523
}
527
524
}
@@ -1075,11 +1072,11 @@ fn check_irrefutable(cx: &MatchCheckCtxt, pat: &Pat, is_fn_arg: bool) {
1075
1072
} ;
1076
1073
1077
1074
is_refutable ( cx, pat, |uncovered_pat| {
1078
- span_err ! ( cx. tcx. sess, pat. span, E0005 ,
1079
- "refutable pattern in {}: `{}` not covered" ,
1080
- origin ,
1081
- pat_to_string( uncovered_pat) ,
1082
- ) ;
1075
+ struct_span_err ! ( cx. tcx. sess, pat. span, E0005 ,
1076
+ "refutable pattern in {}" , origin )
1077
+ . span_label ( pat . span , & format ! (
1078
+ "`{}` not covered here" , pat_to_string( uncovered_pat) ) )
1079
+ . emit ( ) ;
1083
1080
} ) ;
1084
1081
}
1085
1082
@@ -1111,16 +1108,20 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
1111
1108
// check legality of moving out of the enum
1112
1109
1113
1110
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
1114
- if sub. map_or ( false , |p| pat_contains_bindings ( & p) ) {
1115
- span_err ! ( cx. tcx. sess, p. span, E0007 , "cannot bind by-move with sub-bindings" ) ;
1111
+ let mut diag = if sub. map_or ( false , |p| pat_contains_bindings ( & p) ) {
1112
+ struct_span_err ! ( cx. tcx. sess, p. span, E0007 , "cannot bind by-move with sub-bindings" )
1116
1113
} else if has_guard {
1117
- span_err ! ( cx. tcx. sess, p. span, E0008 , "cannot bind by-move into a pattern guard" ) ;
1114
+ struct_span_err ! ( cx. tcx. sess, p. span, E0008 , "cannot bind by-move into a pattern guard" )
1118
1115
} else if by_ref_span. is_some ( ) {
1119
- let mut err = struct_span_err ! ( cx. tcx. sess, p. span, E0009 ,
1120
- "cannot bind by-move and by-ref in the same pattern" ) ;
1121
- span_note ! ( & mut err, by_ref_span. unwrap( ) , "by-ref binding occurs here" ) ;
1122
- err. emit ( ) ;
1123
- }
1116
+ let mut diag = struct_span_err ! ( cx. tcx. sess, p. span, E0009 ,
1117
+ "cannot bind by-move and by-ref in the same pattern" ) ;
1118
+ diag. span_label ( by_ref_span. unwrap ( ) , & "by-ref binding occurs here" ) ;
1119
+ diag
1120
+ } else {
1121
+ return
1122
+ } ;
1123
+ diag. span_label ( p. span , & "invalid by-move binding here" ) ;
1124
+ diag. emit ( ) ;
1124
1125
} ;
1125
1126
1126
1127
for pat in pats {
@@ -1171,8 +1172,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
1171
1172
_: LoanCause ) {
1172
1173
match kind {
1173
1174
MutBorrow => {
1174
- span_err ! ( self . cx. tcx. sess, span, E0301 ,
1175
- "cannot mutably borrow in a pattern guard" )
1175
+ struct_span_err ! ( self . cx. tcx. sess, span, E0301 ,
1176
+ "cannot mutably borrow in a pattern guard" )
1177
+ . span_label ( span, & "bad mutable borrow here" )
1178
+ . emit ( ) ;
1176
1179
}
1177
1180
ImmBorrow | UniqueImmBorrow => { }
1178
1181
}
@@ -1181,7 +1184,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
1181
1184
fn mutate ( & mut self , _: NodeId , span : Span , _: cmt , mode : MutateMode ) {
1182
1185
match mode {
1183
1186
MutateMode :: JustWrite | MutateMode :: WriteAndRead => {
1184
- span_err ! ( self . cx. tcx. sess, span, E0302 , "cannot assign in a pattern guard" )
1187
+ struct_span_err ! (
1188
+ self . cx. tcx. sess, span, E0302 , "cannot assign in a pattern guard" )
1189
+ . span_label ( span, & "bad assignment here" )
1190
+ . emit ( ) ;
1185
1191
}
1186
1192
MutateMode :: Init => { }
1187
1193
}
@@ -1192,28 +1198,32 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
1192
1198
/// because of the way rvalues are handled in the borrow check. (See issue
1193
1199
/// #14587.)
1194
1200
fn check_legality_of_bindings_in_at_patterns ( cx : & MatchCheckCtxt , pat : & Pat ) {
1195
- AtBindingPatternVisitor { cx : cx, bindings_allowed : true } . visit_pat ( pat) ;
1201
+ AtBindingPatternVisitor { cx : cx, containing_binding : None } . visit_pat ( pat) ;
1196
1202
}
1197
1203
1198
1204
struct AtBindingPatternVisitor < ' a , ' b : ' a , ' tcx : ' b > {
1199
1205
cx : & ' a MatchCheckCtxt < ' b , ' tcx > ,
1200
- bindings_allowed : bool
1206
+ containing_binding : Option < Span > ,
1201
1207
}
1202
1208
1203
1209
impl < ' a , ' b , ' tcx , ' v > Visitor < ' v > for AtBindingPatternVisitor < ' a , ' b , ' tcx > {
1204
1210
fn visit_pat ( & mut self , pat : & Pat ) {
1205
1211
match pat. node {
1206
1212
PatKind :: Binding ( _, _, ref subpat) => {
1207
- if !self . bindings_allowed {
1208
- span_err ! ( self . cx. tcx. sess, pat. span, E0303 ,
1209
- "pattern bindings are not allowed after an `@`" ) ;
1213
+ if let Some ( containing_binding) = self . containing_binding {
1214
+ struct_span_err ! (
1215
+ self . cx. tcx. sess, pat. span, E0303 ,
1216
+ "nested pattern bindings are invalid" )
1217
+ . span_label ( pat. span , & "invalid nested binding here" )
1218
+ . span_label ( containing_binding, & "within this binding" )
1219
+ . emit ( ) ;
1210
1220
}
1211
1221
1212
1222
if subpat. is_some ( ) {
1213
- let bindings_were_allowed = self . bindings_allowed ;
1214
- self . bindings_allowed = false ;
1223
+ let containing_binding = mem :: replace (
1224
+ & mut self . containing_binding , Some ( pat . span ) ) ;
1215
1225
intravisit:: walk_pat ( self , pat) ;
1216
- self . bindings_allowed = bindings_were_allowed ;
1226
+ self . containing_binding = containing_binding ;
1217
1227
}
1218
1228
}
1219
1229
_ => intravisit:: walk_pat ( self , pat) ,
0 commit comments