@@ -362,66 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
362
362
|| ty. is_char ( )
363
363
|| ty. references_error ( )
364
364
} ;
365
- let lhs_compat = numeric_or_char ( lhs_ty) ;
366
- let rhs_compat = numeric_or_char ( rhs_ty) ;
367
-
368
- if !lhs_compat || !rhs_compat {
369
- let span = if !lhs_compat && !rhs_compat {
370
- span
371
- } else if !lhs_compat {
372
- begin. span
373
- } else {
374
- end. span
375
- } ;
365
+ let lhs_fail = !numeric_or_char ( lhs_ty) ;
366
+ let rhs_fail = !numeric_or_char ( rhs_ty) ;
376
367
377
- let mut err = struct_span_err ! (
378
- self . tcx. sess,
379
- span,
380
- E0029 ,
381
- "only char and numeric types are allowed in range patterns"
368
+ if lhs_fail || rhs_fail {
369
+ self . emit_err_pat_range (
370
+ span, begin. span , end. span , lhs_fail, rhs_fail, lhs_ty, rhs_ty
382
371
) ;
383
- if !lhs_compat && !rhs_compat {
384
- err. span_label (
385
- begin. span ,
386
- & format ! ( "this is of type `{}` but it should be `char` or numeric" , lhs_ty)
387
- ) ;
388
- err. span_label (
389
- end. span ,
390
- & format ! ( "this is of type `{}` but it should be `char` or numeric" , rhs_ty)
391
- ) ;
392
- } else if !lhs_compat {
393
- err. span_label (
394
- begin. span ,
395
- & format ! ( "this is of type `{}` but it should be `char` or numeric" , lhs_ty)
396
- ) ;
397
- if !rhs_ty. references_error ( ) {
398
- err. span_label (
399
- end. span ,
400
- & format ! ( "this is of type `{}`" , rhs_ty)
401
- ) ;
402
- }
403
- } else {
404
- err. span_label (
405
- end. span ,
406
- & format ! ( "this is of type `{}` but it should be `char` or numeric" , rhs_ty)
407
- ) ;
408
- if !lhs_ty. references_error ( ) {
409
- err. span_label (
410
- begin. span ,
411
- & format ! ( "this is of type `{}`" , lhs_ty)
412
- ) ;
413
- }
414
- }
415
- if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
416
- err. note (
417
- "In a match expression, only numbers and characters can be matched \
418
- against a range. This is because the compiler checks that the range \
419
- is non-empty at compile-time, and is unable to evaluate arbitrary \
420
- comparison functions. If you want to capture values of an orderable \
421
- type between two end-points, you can use a guard."
422
- ) ;
423
- }
424
- err. emit ( ) ;
425
372
return None ;
426
373
}
427
374
@@ -435,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
435
382
Some ( common_type)
436
383
}
437
384
385
+ fn emit_err_pat_range (
386
+ & self ,
387
+ span : Span ,
388
+ begin_span : Span ,
389
+ end_span : Span ,
390
+ lhs_fail : bool ,
391
+ rhs_fail : bool ,
392
+ lhs_ty : Ty < ' tcx > ,
393
+ rhs_ty : Ty < ' tcx > ,
394
+ ) {
395
+ let span = if lhs_fail && rhs_fail {
396
+ span
397
+ } else if lhs_fail {
398
+ begin_span
399
+ } else {
400
+ end_span
401
+ } ;
402
+
403
+ let mut err = struct_span_err ! (
404
+ self . tcx. sess,
405
+ span,
406
+ E0029 ,
407
+ "only char and numeric types are allowed in range patterns"
408
+ ) ;
409
+ let msg = |ty| {
410
+ format ! ( "this is of type `{}` but it should be `char` or numeric" , ty)
411
+ } ;
412
+ let mut one_side_err = |first_span, first_ty, second_span, second_ty : Ty < ' _ > | {
413
+ err. span_label ( first_span, & msg ( first_ty) ) ;
414
+ if !second_ty. references_error ( ) {
415
+ err. span_label (
416
+ second_span,
417
+ & format ! ( "this is of type `{}`" , second_ty)
418
+ ) ;
419
+ }
420
+ } ;
421
+ if lhs_fail && rhs_fail {
422
+ err. span_label ( begin_span, & msg ( lhs_ty) ) ;
423
+ err. span_label ( end_span, & msg ( rhs_ty) ) ;
424
+ } else if lhs_fail {
425
+ one_side_err ( begin_span, lhs_ty, end_span, rhs_ty) ;
426
+ } else {
427
+ one_side_err ( end_span, rhs_ty, begin_span, lhs_ty) ;
428
+ }
429
+ if self . tcx . sess . teach ( & err. get_code ( ) . unwrap ( ) ) {
430
+ err. note (
431
+ "In a match expression, only numbers and characters can be matched \
432
+ against a range. This is because the compiler checks that the range \
433
+ is non-empty at compile-time, and is unable to evaluate arbitrary \
434
+ comparison functions. If you want to capture values of an orderable \
435
+ type between two end-points, you can use a guard."
436
+ ) ;
437
+ }
438
+ err. emit ( ) ;
439
+ }
440
+
438
441
fn check_pat_ident (
439
442
& self ,
440
443
pat : & Pat ,
0 commit comments