Skip to content

Commit 2896a4c

Browse files
Rollup merge of rust-lang#67287 - Centril:mismatch-range-improve-diag, r=estebank
typeck: note other end-point when checking range pats Fixes rust-lang#57389, alternative to rust-lang#67214 that should be less invasive to type checking logic. r? @estebank
2 parents 0db3e03 + 01599fc commit 2896a4c

9 files changed

+81
-38
lines changed

src/librustc_typeck/check/pat.rs

+21-10
Original file line numberDiff line numberDiff line change
@@ -341,21 +341,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
341341
fn check_pat_range(
342342
&self,
343343
span: Span,
344-
begin: &'tcx hir::Expr,
345-
end: &'tcx hir::Expr,
344+
lhs: &'tcx hir::Expr,
345+
rhs: &'tcx hir::Expr,
346346
expected: Ty<'tcx>,
347347
discrim_span: Option<Span>,
348348
) -> Option<Ty<'tcx>> {
349-
let lhs_ty = self.check_expr(begin);
350-
let rhs_ty = self.check_expr(end);
349+
let lhs_ty = self.check_expr(lhs);
350+
let rhs_ty = self.check_expr(rhs);
351351

352352
// Check that both end-points are of numeric or char type.
353353
let numeric_or_char = |ty: Ty<'_>| ty.is_numeric() || ty.is_char() || ty.references_error();
354354
let lhs_fail = !numeric_or_char(lhs_ty);
355355
let rhs_fail = !numeric_or_char(rhs_ty);
356356

357357
if lhs_fail || rhs_fail {
358-
self.emit_err_pat_range(span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
358+
self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
359359
return None;
360360
}
361361

@@ -364,11 +364,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
364364
let common_type = self.resolve_vars_if_possible(&lhs_ty);
365365

366366
// Subtyping doesn't matter here, as the value is some kind of scalar.
367-
self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span);
368-
self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span);
367+
let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
368+
self.demand_eqtype_pat_diag(x_span, expected, x_ty, discrim_span).map(|mut err| {
369+
self.endpoint_has_type(&mut err, y_span, y_ty);
370+
err.emit();
371+
});
372+
};
373+
demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
374+
demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);
375+
369376
Some(common_type)
370377
}
371378

379+
fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
380+
if !ty.references_error() {
381+
err.span_label(span, &format!("this is of type `{}`", ty));
382+
}
383+
}
384+
372385
fn emit_err_pat_range(
373386
&self,
374387
span: Span,
@@ -396,9 +409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
396409
let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
397410
let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
398411
err.span_label(first_span, &msg(first_ty));
399-
if !second_ty.references_error() {
400-
err.span_label(second_span, &format!("this is of type `{}`", second_ty));
401-
}
412+
self.endpoint_has_type(&mut err, second_span, second_ty);
402413
};
403414
if lhs_fail && rhs_fail {
404415
err.span_label(begin_span, &msg(lhs_ty));

src/test/ui/error-codes/E0308-4.stderr

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
error[E0308]: mismatched types
2-
--> $DIR/E0308-4.rs:4:9
2+
--> $DIR/E0308-4.rs:4:15
33
|
44
LL | match x {
55
| - this match expression has type `u8`
66
LL | 0u8..=3i8 => (),
7-
| ^^^^^^^^^ expected `u8`, found `i8`
7+
| --- ^^^ expected `u8`, found `i8`
8+
| |
9+
| this is of type `u8`
810

911
error: aborting due to previous error
1012

src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ error[E0308]: mismatched types
1010
LL | match [5..4, 99..105, 43..44] {
1111
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
1212
LL | [_, 99.., _] => {},
13-
| ^^^^ expected struct `std::ops::Range`, found integer
13+
| ^^ expected struct `std::ops::Range`, found integer
1414
|
1515
= note: expected struct `std::ops::Range<{integer}>`
1616
found type `{integer}`

src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision2.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ error[E0308]: mismatched types
1616
LL | match [5..4, 99..105, 43..44] {
1717
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
1818
LL | [_, 99..] => {},
19-
| ^^^^ expected struct `std::ops::Range`, found integer
19+
| ^^ expected struct `std::ops::Range`, found integer
2020
|
2121
= note: expected struct `std::ops::Range<{integer}>`
2222
found type `{integer}`

src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ fn main() {
66
//~^ ERROR `..X` range patterns are not supported
77
//~| ERROR mismatched types
88
//~| ERROR mismatched types
9+
//~| ERROR mismatched types
910
_ => {},
1011
}
1112
}

src/test/ui/exclusive-range/exclusive_range_pattern_syntax_collision3.stderr

+19-4
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ LL | [..9, 99..100, _] => {},
55
| ^^^ help: try using the minimum value for the type: `MIN..9`
66

77
error[E0308]: mismatched types
8-
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
8+
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
99
|
1010
LL | match [5..4, 99..105, 43..44] {
1111
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
1212
LL | [..9, 99..100, _] => {},
13-
| ^^^ expected struct `std::ops::Range`, found integer
13+
| ^ expected struct `std::ops::Range`, found integer
1414
|
1515
= note: expected struct `std::ops::Range<{integer}>`
1616
found type `{integer}`
@@ -21,11 +21,26 @@ error[E0308]: mismatched types
2121
LL | match [5..4, 99..105, 43..44] {
2222
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
2323
LL | [..9, 99..100, _] => {},
24-
| ^^^^^^^ expected struct `std::ops::Range`, found integer
24+
| ^^ --- this is of type `{integer}`
25+
| |
26+
| expected struct `std::ops::Range`, found integer
27+
|
28+
= note: expected struct `std::ops::Range<{integer}>`
29+
found type `{integer}`
30+
31+
error[E0308]: mismatched types
32+
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
33+
|
34+
LL | match [5..4, 99..105, 43..44] {
35+
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
36+
LL | [..9, 99..100, _] => {},
37+
| -- ^^^ expected struct `std::ops::Range`, found integer
38+
| |
39+
| this is of type `{integer}`
2540
|
2641
= note: expected struct `std::ops::Range<{integer}>`
2742
found type `{integer}`
2843

29-
error: aborting due to 3 previous errors
44+
error: aborting due to 4 previous errors
3045

3146
For more information about this error, try `rustc --explain E0308`.

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ error[E0308]: mismatched types
2828
--> $DIR/match-range-fail.rs:18:9
2929
|
3030
LL | 'c' ..= 100 => { }
31-
| ^^^^^^^^^^^ expected integer, found `char`
31+
| ^^^ --- this is of type `{integer}`
32+
| |
33+
| expected integer, found `char`
3234

3335
error: aborting due to 4 previous errors
3436

src/test/ui/parser/pat-tuple-5.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ error[E0308]: mismatched types
1919
LL | match (0, 1) {
2020
| ------ this match expression has type `({integer}, {integer})`
2121
LL | (PAT ..) => {}
22-
| ^^^^^^ expected tuple, found `u8`
22+
| ^^^ expected tuple, found `u8`
2323
|
2424
= note: expected tuple `({integer}, {integer})`
2525
found type `u8`

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

+30-18
Original file line numberDiff line numberDiff line change
@@ -417,13 +417,17 @@ error[E0308]: mismatched types
417417
--> $DIR/recover-range-pats.rs:21:12
418418
|
419419
LL | if let .0..Y = 0 {}
420-
| ^^^^^ expected integer, found floating-point number
420+
| ^^ - this is of type `u8`
421+
| |
422+
| expected integer, found floating-point number
421423

422424
error[E0308]: mismatched types
423-
--> $DIR/recover-range-pats.rs:23:12
425+
--> $DIR/recover-range-pats.rs:23:16
424426
|
425427
LL | if let X.. .0 = 0 {}
426-
| ^^^^^^ expected integer, found floating-point number
428+
| - ^^ expected integer, found floating-point number
429+
| |
430+
| this is of type `u8`
427431

428432
error[E0029]: only char and numeric types are allowed in range patterns
429433
--> $DIR/recover-range-pats.rs:32:12
@@ -445,13 +449,17 @@ error[E0308]: mismatched types
445449
--> $DIR/recover-range-pats.rs:34:12
446450
|
447451
LL | if let .0..=Y = 0 {}
448-
| ^^^^^^ expected integer, found floating-point number
452+
| ^^ - this is of type `u8`
453+
| |
454+
| expected integer, found floating-point number
449455

450456
error[E0308]: mismatched types
451-
--> $DIR/recover-range-pats.rs:36:12
457+
--> $DIR/recover-range-pats.rs:36:16
452458
|
453459
LL | if let X..=.0 = 0 {}
454-
| ^^^^^^ expected integer, found floating-point number
460+
| - ^^ expected integer, found floating-point number
461+
| |
462+
| this is of type `u8`
455463

456464
error[E0029]: only char and numeric types are allowed in range patterns
457465
--> $DIR/recover-range-pats.rs:45:12
@@ -473,13 +481,17 @@ error[E0308]: mismatched types
473481
--> $DIR/recover-range-pats.rs:49:12
474482
|
475483
LL | if let .0...Y = 0 {}
476-
| ^^^^^^ expected integer, found floating-point number
484+
| ^^ - this is of type `u8`
485+
| |
486+
| expected integer, found floating-point number
477487

478488
error[E0308]: mismatched types
479-
--> $DIR/recover-range-pats.rs:52:12
489+
--> $DIR/recover-range-pats.rs:52:17
480490
|
481491
LL | if let X... .0 = 0 {}
482-
| ^^^^^^^ expected integer, found floating-point number
492+
| - ^^ expected integer, found floating-point number
493+
| |
494+
| this is of type `u8`
483495

484496
error[E0029]: only char and numeric types are allowed in range patterns
485497
--> $DIR/recover-range-pats.rs:60:12
@@ -491,7 +503,7 @@ error[E0308]: mismatched types
491503
--> $DIR/recover-range-pats.rs:62:12
492504
|
493505
LL | if let .0.. = 0 {}
494-
| ^^^^ expected integer, found floating-point number
506+
| ^^ expected integer, found floating-point number
495507

496508
error[E0029]: only char and numeric types are allowed in range patterns
497509
--> $DIR/recover-range-pats.rs:70:12
@@ -503,7 +515,7 @@ error[E0308]: mismatched types
503515
--> $DIR/recover-range-pats.rs:72:12
504516
|
505517
LL | if let .0..= = 0 {}
506-
| ^^^^^ expected integer, found floating-point number
518+
| ^^ expected integer, found floating-point number
507519

508520
error[E0029]: only char and numeric types are allowed in range patterns
509521
--> $DIR/recover-range-pats.rs:82:12
@@ -515,7 +527,7 @@ error[E0308]: mismatched types
515527
--> $DIR/recover-range-pats.rs:85:12
516528
|
517529
LL | if let .0... = 0 {}
518-
| ^^^^^ expected integer, found floating-point number
530+
| ^^ expected integer, found floating-point number
519531

520532
error[E0029]: only char and numeric types are allowed in range patterns
521533
--> $DIR/recover-range-pats.rs:94:14
@@ -524,10 +536,10 @@ LL | if let ..true = 0 {}
524536
| ^^^^ this is of type `bool` but it should be `char` or numeric
525537

526538
error[E0308]: mismatched types
527-
--> $DIR/recover-range-pats.rs:96:12
539+
--> $DIR/recover-range-pats.rs:96:15
528540
|
529541
LL | if let .. .0 = 0 {}
530-
| ^^^^^ expected integer, found floating-point number
542+
| ^^ expected integer, found floating-point number
531543

532544
error[E0029]: only char and numeric types are allowed in range patterns
533545
--> $DIR/recover-range-pats.rs:104:15
@@ -536,10 +548,10 @@ LL | if let ..=true = 0 {}
536548
| ^^^^ this is of type `bool` but it should be `char` or numeric
537549

538550
error[E0308]: mismatched types
539-
--> $DIR/recover-range-pats.rs:106:12
551+
--> $DIR/recover-range-pats.rs:106:15
540552
|
541553
LL | if let ..=.0 = 0 {}
542-
| ^^^^^ expected integer, found floating-point number
554+
| ^^ expected integer, found floating-point number
543555

544556
error[E0029]: only char and numeric types are allowed in range patterns
545557
--> $DIR/recover-range-pats.rs:116:15
@@ -548,10 +560,10 @@ LL | if let ...true = 0 {}
548560
| ^^^^ this is of type `bool` but it should be `char` or numeric
549561

550562
error[E0308]: mismatched types
551-
--> $DIR/recover-range-pats.rs:119:12
563+
--> $DIR/recover-range-pats.rs:119:15
552564
|
553565
LL | if let ....3 = 0 {}
554-
| ^^^^^ expected integer, found floating-point number
566+
| ^^ expected integer, found floating-point number
555567

556568
error: aborting due to 85 previous errors
557569

0 commit comments

Comments
 (0)