Skip to content

Commit 20c3562

Browse files
authoredNov 14, 2019
Rollup merge of #66351 - JohnTitor:tweak-range-err-msg, r=Centril
Tweak non-char/numeric in range pattern diagnostic Fixes #66283 r? @estebank
2 parents 2acbd3d + 030fa9a commit 20c3562

File tree

8 files changed

+123
-106
lines changed

8 files changed

+123
-106
lines changed
 

‎src/librustc_typeck/check/pat.rs

+61-29
Original file line numberDiff line numberDiff line change
@@ -362,37 +362,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
362362
|| ty.is_char()
363363
|| ty.references_error()
364364
};
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);
376367

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
382371
);
383-
err.span_label(span, "ranges require char or numeric types");
384-
err.note(&format!("start type: {}", self.ty_to_string(lhs_ty)));
385-
err.note(&format!("end type: {}", self.ty_to_string(rhs_ty)));
386-
if self.tcx.sess.teach(&err.get_code().unwrap()) {
387-
err.note(
388-
"In a match expression, only numbers and characters can be matched \
389-
against a range. This is because the compiler checks that the range \
390-
is non-empty at compile-time, and is unable to evaluate arbitrary \
391-
comparison functions. If you want to capture values of an orderable \
392-
type between two end-points, you can use a guard."
393-
);
394-
}
395-
err.emit();
396372
return None;
397373
}
398374

@@ -406,6 +382,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
406382
Some(common_type)
407383
}
408384

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+
409441
fn check_pat_ident(
410442
&self,
411443
pat: &Pat,

‎src/test/ui/error-codes/E0029-teach.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ error[E0029]: only char and numeric types are allowed in range patterns
22
--> $DIR/E0029-teach.rs:7:9
33
|
44
LL | "hello" ..= "world" => {}
5-
| ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
5+
| -------^^^^^-------
6+
| | |
7+
| | this is of type `&'static str` but it should be `char` or numeric
8+
| this is of type `&'static str` but it should be `char` or numeric
69
|
7-
= note: start type: &'static str
8-
= note: end type: &'static str
910
= note: In a match expression, only numbers and characters can be matched against a range. This is because the compiler checks that the range is non-empty at compile-time, and is unable to evaluate arbitrary comparison functions. If you want to capture values of an orderable type between two end-points, you can use a guard.
1011

1112
error: aborting due to previous error

‎src/test/ui/error-codes/E0029.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ error[E0029]: only char and numeric types are allowed in range patterns
22
--> $DIR/E0029.rs:5:9
33
|
44
LL | "hello" ..= "world" => {}
5-
| ^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
6-
|
7-
= note: start type: &'static str
8-
= note: end type: &'static str
5+
| -------^^^^^-------
6+
| | |
7+
| | this is of type `&'static str` but it should be `char` or numeric
8+
| this is of type `&'static str` but it should be `char` or numeric
99

1010
error: aborting due to previous error
1111

‎src/test/ui/match/match-range-fail.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ fn main() {
33
"bar" ..= "foo" => { }
44
};
55
//~^^ ERROR only char and numeric types are allowed in range
6-
//~| start type: &'static str
7-
//~| end type: &'static str
86

97
match "wow" {
108
10 ..= "what" => ()
119
};
1210
//~^^ ERROR only char and numeric types are allowed in range
13-
//~| start type: {integer}
14-
//~| end type: &'static str
11+
12+
match "wow" {
13+
true ..= "what" => {}
14+
};
15+
//~^^ ERROR only char and numeric types are allowed in range
1516

1617
match 5 {
1718
'c' ..= 100 => { }

‎src/test/ui/match/match-range-fail.stderr

+18-10
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,38 @@ error[E0029]: only char and numeric types are allowed in range patterns
22
--> $DIR/match-range-fail.rs:3:9
33
|
44
LL | "bar" ..= "foo" => { }
5-
| ^^^^^^^^^^^^^^^ ranges require char or numeric types
6-
|
7-
= note: start type: &'static str
8-
= note: end type: &'static str
5+
| -----^^^^^-----
6+
| | |
7+
| | this is of type `&'static str` but it should be `char` or numeric
8+
| this is of type `&'static str` but it should be `char` or numeric
99

1010
error[E0029]: only char and numeric types are allowed in range patterns
11-
--> $DIR/match-range-fail.rs:10:16
11+
--> $DIR/match-range-fail.rs:8:16
1212
|
1313
LL | 10 ..= "what" => ()
14-
| ^^^^^^ ranges require char or numeric types
14+
| -- ^^^^^^ this is of type `&'static str` but it should be `char` or numeric
15+
| |
16+
| this is of type `{integer}`
17+
18+
error[E0029]: only char and numeric types are allowed in range patterns
19+
--> $DIR/match-range-fail.rs:13:9
1520
|
16-
= note: start type: {integer}
17-
= note: end type: &'static str
21+
LL | true ..= "what" => {}
22+
| ----^^^^^------
23+
| | |
24+
| | this is of type `&'static str` but it should be `char` or numeric
25+
| this is of type `bool` but it should be `char` or numeric
1826

1927
error[E0308]: mismatched types
20-
--> $DIR/match-range-fail.rs:17:9
28+
--> $DIR/match-range-fail.rs:18:9
2129
|
2230
LL | 'c' ..= 100 => { }
2331
| ^^^^^^^^^^^ expected integer, found char
2432
|
2533
= note: expected type `{integer}`
2634
found type `char`
2735

28-
error: aborting due to 3 previous errors
36+
error: aborting due to 4 previous errors
2937

3038
Some errors have detailed explanations: E0029, E0308.
3139
For more information about an error, try `rustc --explain E0029`.

‎src/test/ui/parser/recover-range-pats.stderr

+24-48
Original file line numberDiff line numberDiff line change
@@ -401,19 +401,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
401401
--> $DIR/recover-range-pats.rs:19:12
402402
|
403403
LL | if let true..Y = 0 {}
404-
| ^^^^ ranges require char or numeric types
405-
|
406-
= note: start type: bool
407-
= note: end type: u8
404+
| ^^^^ - this is of type `u8`
405+
| |
406+
| this is of type `bool` but it should be `char` or numeric
408407

409408
error[E0029]: only char and numeric types are allowed in range patterns
410409
--> $DIR/recover-range-pats.rs:20:15
411410
|
412411
LL | if let X..true = 0 {}
413-
| ^^^^ ranges require char or numeric types
414-
|
415-
= note: start type: u8
416-
= note: end type: bool
412+
| - ^^^^ this is of type `bool` but it should be `char` or numeric
413+
| |
414+
| this is of type `u8`
417415

418416
error[E0308]: mismatched types
419417
--> $DIR/recover-range-pats.rs:21:12
@@ -437,19 +435,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
437435
--> $DIR/recover-range-pats.rs:32:12
438436
|
439437
LL | if let true..=Y = 0 {}
440-
| ^^^^ ranges require char or numeric types
441-
|
442-
= note: start type: bool
443-
= note: end type: u8
438+
| ^^^^ - this is of type `u8`
439+
| |
440+
| this is of type `bool` but it should be `char` or numeric
444441

445442
error[E0029]: only char and numeric types are allowed in range patterns
446443
--> $DIR/recover-range-pats.rs:33:16
447444
|
448445
LL | if let X..=true = 0 {}
449-
| ^^^^ ranges require char or numeric types
450-
|
451-
= note: start type: u8
452-
= note: end type: bool
446+
| - ^^^^ this is of type `bool` but it should be `char` or numeric
447+
| |
448+
| this is of type `u8`
453449

454450
error[E0308]: mismatched types
455451
--> $DIR/recover-range-pats.rs:34:12
@@ -473,19 +469,17 @@ error[E0029]: only char and numeric types are allowed in range patterns
473469
--> $DIR/recover-range-pats.rs:45:12
474470
|
475471
LL | if let true...Y = 0 {}
476-
| ^^^^ ranges require char or numeric types
477-
|
478-
= note: start type: bool
479-
= note: end type: u8
472+
| ^^^^ - this is of type `u8`
473+
| |
474+
| this is of type `bool` but it should be `char` or numeric
480475

481476
error[E0029]: only char and numeric types are allowed in range patterns
482477
--> $DIR/recover-range-pats.rs:47:16
483478
|
484479
LL | if let X...true = 0 {}
485-
| ^^^^ ranges require char or numeric types
486-
|
487-
= note: start type: u8
488-
= note: end type: bool
480+
| - ^^^^ this is of type `bool` but it should be `char` or numeric
481+
| |
482+
| this is of type `u8`
489483

490484
error[E0308]: mismatched types
491485
--> $DIR/recover-range-pats.rs:49:12
@@ -509,10 +503,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
509503
--> $DIR/recover-range-pats.rs:60:12
510504
|
511505
LL | if let true.. = 0 {}
512-
| ^^^^ ranges require char or numeric types
513-
|
514-
= note: start type: bool
515-
= note: end type: [type error]
506+
| ^^^^ this is of type `bool` but it should be `char` or numeric
516507

517508
error[E0308]: mismatched types
518509
--> $DIR/recover-range-pats.rs:62:12
@@ -527,10 +518,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
527518
--> $DIR/recover-range-pats.rs:70:12
528519
|
529520
LL | if let true..= = 0 {}
530-
| ^^^^ ranges require char or numeric types
531-
|
532-
= note: start type: bool
533-
= note: end type: [type error]
521+
| ^^^^ this is of type `bool` but it should be `char` or numeric
534522

535523
error[E0308]: mismatched types
536524
--> $DIR/recover-range-pats.rs:72:12
@@ -545,10 +533,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
545533
--> $DIR/recover-range-pats.rs:82:12
546534
|
547535
LL | if let true... = 0 {}
548-
| ^^^^ ranges require char or numeric types
549-
|
550-
= note: start type: bool
551-
= note: end type: [type error]
536+
| ^^^^ this is of type `bool` but it should be `char` or numeric
552537

553538
error[E0308]: mismatched types
554539
--> $DIR/recover-range-pats.rs:85:12
@@ -563,10 +548,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
563548
--> $DIR/recover-range-pats.rs:94:14
564549
|
565550
LL | if let ..true = 0 {}
566-
| ^^^^ ranges require char or numeric types
567-
|
568-
= note: start type: [type error]
569-
= note: end type: bool
551+
| ^^^^ this is of type `bool` but it should be `char` or numeric
570552

571553
error[E0308]: mismatched types
572554
--> $DIR/recover-range-pats.rs:96:12
@@ -581,10 +563,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
581563
--> $DIR/recover-range-pats.rs:104:15
582564
|
583565
LL | if let ..=true = 0 {}
584-
| ^^^^ ranges require char or numeric types
585-
|
586-
= note: start type: [type error]
587-
= note: end type: bool
566+
| ^^^^ this is of type `bool` but it should be `char` or numeric
588567

589568
error[E0308]: mismatched types
590569
--> $DIR/recover-range-pats.rs:106:12
@@ -599,10 +578,7 @@ error[E0029]: only char and numeric types are allowed in range patterns
599578
--> $DIR/recover-range-pats.rs:116:15
600579
|
601580
LL | if let ...true = 0 {}
602-
| ^^^^ ranges require char or numeric types
603-
|
604-
= note: start type: [type error]
605-
= note: end type: bool
581+
| ^^^^ this is of type `bool` but it should be `char` or numeric
606582

607583
error[E0308]: mismatched types
608584
--> $DIR/recover-range-pats.rs:119:12

‎src/test/ui/pattern/patkind-litrange-no-expr.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ LL | Arith = 1 + 1,
77
error[E0029]: only char and numeric types are allowed in range patterns
88
--> $DIR/patkind-litrange-no-expr.rs:20:13
99
|
10+
LL | $( $value ..= 42 => Some($name::$variant), )* // PatKind::Range
11+
| -- this is of type `{integer}`
12+
...
1013
LL | Arith = 1 + 1,
11-
| ^^^^^ ranges require char or numeric types
12-
|
13-
= note: start type: {integer}
14-
= note: end type: {integer}
14+
| ^^^^^ this is of type `_` but it should be `char` or numeric
1515

1616
error: aborting due to 2 previous errors
1717

‎src/test/ui/qualified/qualified-path-params.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ error[E0029]: only char and numeric types are allowed in range patterns
88
--> $DIR/qualified-path-params.rs:22:15
99
|
1010
LL | 0 ..= <S as Tr>::A::f::<u8> => {}
11-
| ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types
12-
|
13-
= note: start type: {integer}
14-
= note: end type: fn() {S::f::<u8>}
11+
| - ^^^^^^^^^^^^^^^^^^^^^ this is of type `fn() {S::f::<u8>}` but it should be `char` or numeric
12+
| |
13+
| this is of type `{integer}`
1514

1615
error: aborting due to 2 previous errors
1716

0 commit comments

Comments
 (0)
Please sign in to comment.