@@ -31,6 +31,7 @@ use rustc::ty;
3131use std:: cmp:: Ordering ;
3232use std:: fmt;
3333use std:: iter:: { FromIterator , IntoIterator , repeat} ;
34+ use std:: mem;
3435
3536use rustc:: hir;
3637use rustc:: hir:: { Pat , PatKind } ;
@@ -214,19 +215,8 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
214215 // Finally, check if the whole match expression is exhaustive.
215216 // Check for empty enum, because is_useful only works on inhabited types.
216217 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
230220 }
231221
232222 let matrix: Matrix = inlined_arms
@@ -235,12 +225,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
235225 . flat_map ( |arm| & arm. 0 )
236226 . map ( |pat| vec ! [ wrap_pat( cx, & pat) ] )
237227 . 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) ;
244229 } ,
245230 _ => ( )
246231 }
@@ -316,7 +301,10 @@ fn check_arms(cx: &MatchCheckCtxt,
316301 let & ( ref first_arm_pats, _) = & arms[ 0 ] ;
317302 let first_pat = & first_arm_pats[ 0 ] ;
318303 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 ( ) ;
320308 printed_if_let_err = true ;
321309 }
322310 } ,
@@ -326,7 +314,10 @@ fn check_arms(cx: &MatchCheckCtxt,
326314 let & ( ref first_arm_pats, _) = & arms[ 0 ] ;
327315 let first_pat = & first_arm_pats[ 0 ] ;
328316 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 ( ) ;
330321 } ,
331322
332323 hir:: MatchSource :: ForLoopDesugar => {
@@ -338,17 +329,17 @@ fn check_arms(cx: &MatchCheckCtxt,
338329 } ,
339330
340331 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" ) ;
344335 // if we had a catchall pattern, hint at that
345336 for row in & seen. 0 {
346337 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" ) ;
349340 }
350341 }
351- err . emit ( ) ;
342+ diag . emit ( ) ;
352343 } ,
353344
354345 hir:: MatchSource :: TryDesugar => {
@@ -407,10 +398,18 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
407398 } ,
408399 _ => bug ! ( ) ,
409400 } ;
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 ( ) ;
414413 } ,
415414 _ => {
416415 let pattern_strings: Vec < _ > = witnesses. iter ( ) . map ( |w| {
@@ -429,15 +428,10 @@ fn check_exhaustive<'a, 'tcx>(cx: &MatchCheckCtxt<'a, 'tcx>,
429428 format ! ( "`{}` and {} more" , head. join( "`, `" ) , tail. len( ) )
430429 }
431430 } ;
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- } ;
437431 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 ( ) ;
441435 } ,
442436 }
443437 }
@@ -520,8 +514,11 @@ impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
520514 }
521515 } else {
522516 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 ( ) ;
525522 pat
526523 }
527524 }
@@ -1075,11 +1072,11 @@ fn check_irrefutable(cx: &MatchCheckCtxt, pat: &Pat, is_fn_arg: bool) {
10751072 } ;
10761073
10771074 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 ( ) ;
10831080 } ) ;
10841081}
10851082
@@ -1111,16 +1108,20 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
11111108 // check legality of moving out of the enum
11121109
11131110 // 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" )
11161113 } 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" )
11181115 } 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 ( ) ;
11241125 } ;
11251126
11261127 for pat in pats {
@@ -1171,8 +1172,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
11711172 _: LoanCause ) {
11721173 match kind {
11731174 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 ( ) ;
11761179 }
11771180 ImmBorrow | UniqueImmBorrow => { }
11781181 }
@@ -1181,7 +1184,10 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
11811184 fn mutate ( & mut self , _: NodeId , span : Span , _: cmt , mode : MutateMode ) {
11821185 match mode {
11831186 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 ( ) ;
11851191 }
11861192 MutateMode :: Init => { }
11871193 }
@@ -1192,28 +1198,32 @@ impl<'a, 'gcx, 'tcx> Delegate<'tcx> for MutationChecker<'a, 'gcx> {
11921198/// because of the way rvalues are handled in the borrow check. (See issue
11931199/// #14587.)
11941200fn 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) ;
11961202}
11971203
11981204struct AtBindingPatternVisitor < ' a , ' b : ' a , ' tcx : ' b > {
11991205 cx : & ' a MatchCheckCtxt < ' b , ' tcx > ,
1200- bindings_allowed : bool
1206+ containing_binding : Option < Span > ,
12011207}
12021208
12031209impl < ' a , ' b , ' tcx , ' v > Visitor < ' v > for AtBindingPatternVisitor < ' a , ' b , ' tcx > {
12041210 fn visit_pat ( & mut self , pat : & Pat ) {
12051211 match pat. node {
12061212 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 ( ) ;
12101220 }
12111221
12121222 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 ) ) ;
12151225 intravisit:: walk_pat ( self , pat) ;
1216- self . bindings_allowed = bindings_were_allowed ;
1226+ self . containing_binding = containing_binding ;
12171227 }
12181228 }
12191229 _ => intravisit:: walk_pat ( self , pat) ,
0 commit comments