Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

typeck: note other end-point when checking range pats #67287

Merged
merged 1 commit into from
Dec 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 21 additions & 10 deletions src/librustc_typeck/check/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,21 +353,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_range(
&self,
span: Span,
begin: &'tcx hir::Expr<'tcx>,
end: &'tcx hir::Expr<'tcx>,
lhs: &'tcx hir::Expr<'tcx>,
rhs: &'tcx hir::Expr<'tcx>,
expected: Ty<'tcx>,
discrim_span: Option<Span>,
) -> Option<Ty<'tcx>> {
let lhs_ty = self.check_expr(begin);
let rhs_ty = self.check_expr(end);
let lhs_ty = self.check_expr(lhs);
let rhs_ty = self.check_expr(rhs);

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

if lhs_fail || rhs_fail {
self.emit_err_pat_range(span, begin.span, end.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
self.emit_err_pat_range(span, lhs.span, rhs.span, lhs_fail, rhs_fail, lhs_ty, rhs_ty);
return None;
}

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

// Subtyping doesn't matter here, as the value is some kind of scalar.
self.demand_eqtype_pat(span, expected, lhs_ty, discrim_span);
self.demand_eqtype_pat(span, expected, rhs_ty, discrim_span);
let demand_eqtype = |x_span, y_span, x_ty, y_ty| {
self.demand_eqtype_pat_diag(x_span, expected, x_ty, discrim_span).map(|mut err| {
self.endpoint_has_type(&mut err, y_span, y_ty);
err.emit();
});
};
demand_eqtype(lhs.span, rhs.span, lhs_ty, rhs_ty);
demand_eqtype(rhs.span, lhs.span, rhs_ty, lhs_ty);

Some(common_type)
}

fn endpoint_has_type(&self, err: &mut DiagnosticBuilder<'_>, span: Span, ty: Ty<'_>) {
if !ty.references_error() {
err.span_label(span, &format!("this is of type `{}`", ty));
}
}

fn emit_err_pat_range(
&self,
span: Span,
Expand Down Expand Up @@ -408,9 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let msg = |ty| format!("this is of type `{}` but it should be `char` or numeric", ty);
let mut one_side_err = |first_span, first_ty, second_span, second_ty: Ty<'_>| {
err.span_label(first_span, &msg(first_ty));
if !second_ty.references_error() {
err.span_label(second_span, &format!("this is of type `{}`", second_ty));
}
self.endpoint_has_type(&mut err, second_span, second_ty);
};
if lhs_fail && rhs_fail {
err.span_label(begin_span, &msg(lhs_ty));
Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/error-codes/E0308-4.stderr
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
error[E0308]: mismatched types
--> $DIR/E0308-4.rs:4:9
--> $DIR/E0308-4.rs:4:15
|
LL | match x {
| - this match expression has type `u8`
LL | 0u8..=3i8 => (),
| ^^^^^^^^^ expected `u8`, found `i8`
| --- ^^^ expected `u8`, found `i8`
| |
| this is of type `u8`

error: aborting due to previous error

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
LL | [_, 99.., _] => {},
| ^^^^ expected struct `std::ops::Range`, found integer
| ^^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
LL | [_, 99..] => {},
| ^^^^ expected struct `std::ops::Range`, found integer
| ^^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ fn main() {
//~^ ERROR `..X` range patterns are not supported
//~| ERROR mismatched types
//~| ERROR mismatched types
//~| ERROR mismatched types
_ => {},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ LL | [..9, 99..100, _] => {},
| ^^^ help: try using the minimum value for the type: `MIN..9`

error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:10
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:12
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
LL | [..9, 99..100, _] => {},
| ^^^ expected struct `std::ops::Range`, found integer
| ^ expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`
Expand All @@ -21,11 +21,26 @@ error[E0308]: mismatched types
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
LL | [..9, 99..100, _] => {},
| ^^^^^^^ expected struct `std::ops::Range`, found integer
| ^^ --- this is of type `{integer}`
| |
| expected struct `std::ops::Range`, found integer
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`

error[E0308]: mismatched types
--> $DIR/exclusive_range_pattern_syntax_collision3.rs:5:19
|
LL | match [5..4, 99..105, 43..44] {
| ----------------------- this match expression has type `std::ops::Range<{integer}>`
LL | [..9, 99..100, _] => {},
| -- ^^^ expected struct `std::ops::Range`, found integer
| |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand what's happening here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first error above is for 99 and the other one is for 100. They now occur twice because the spans are different and so there's no de-duplication. The type error happens because 99..105 is at type Range<{integer}> whereas 99..100 is a range pattern at type {integer}.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my version I tried changing "this match expression has" to "this match expression requires" in an attempt to clarify these errors

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to change that, but that can be in a different PR than this (e.g. yours).

Copy link
Contributor

@estebank estebank Dec 14, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem I have with this wording is "expected struct std::ops::Range, found integer", but now I see that the thing being matched is [5..4, 99..105, 43..44] and not [5, 99, 43], which accounts for the weirdness.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, and that part hasn't changed as you can see from the diff. :)

| this is of type `{integer}`
|
= note: expected struct `std::ops::Range<{integer}>`
found type `{integer}`

error: aborting due to 3 previous errors
error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
4 changes: 3 additions & 1 deletion src/test/ui/match/match-range-fail.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ error[E0308]: mismatched types
--> $DIR/match-range-fail.rs:18:9
|
LL | 'c' ..= 100 => { }
| ^^^^^^^^^^^ expected integer, found `char`
| ^^^ --- this is of type `{integer}`
| |
| expected integer, found `char`

error: aborting due to 4 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/parser/pat-tuple-5.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ error[E0308]: mismatched types
LL | match (0, 1) {
| ------ this match expression has type `({integer}, {integer})`
LL | (PAT ..) => {}
| ^^^^^^ expected tuple, found `u8`
| ^^^ expected tuple, found `u8`
|
= note: expected tuple `({integer}, {integer})`
found type `u8`
Expand Down
48 changes: 30 additions & 18 deletions src/test/ui/parser/recover-range-pats.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -417,13 +417,17 @@ error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:21:12
|
LL | if let .0..Y = 0 {}
| ^^^^^ expected integer, found floating-point number
| ^^ - this is of type `u8`
| |
| expected integer, found floating-point number

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:23:12
--> $DIR/recover-range-pats.rs:23:16
|
LL | if let X.. .0 = 0 {}
| ^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| this is of type `u8`

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

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:36:12
--> $DIR/recover-range-pats.rs:36:16
|
LL | if let X..=.0 = 0 {}
| ^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| this is of type `u8`

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

error[E0308]: mismatched types
--> $DIR/recover-range-pats.rs:52:12
--> $DIR/recover-range-pats.rs:52:17
|
LL | if let X... .0 = 0 {}
| ^^^^^^^ expected integer, found floating-point number
| - ^^ expected integer, found floating-point number
| |
| this is of type `u8`

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

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

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

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

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

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

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

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

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

error: aborting due to 85 previous errors

Expand Down