-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Improve diagnostic messages for range patterns. #25743
Conversation
r? @nrc (rust_highfive has picked a reviewer for you, use r? to override) |
☔ The latest upstream changes (presumably #25091) made this pull request unmergeable. Please resolve the merge conflicts. |
I agree there is no need to start a 'note' block here. As far as I know, you can't get a better representation of the int inference var than This PR could do with some tests to make sure the errors don't regress. (Also, needs a rebase) |
@@ -89,30 +89,46 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, | |||
let lhs_ty = fcx.expr_ty(&**begin); | |||
let rhs_ty = fcx.expr_ty(&**end); | |||
|
|||
let lhs_eq_rhs = | |||
let compat = |t| ty::type_is_numeric(t) || ty::type_is_char(t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
numeric_or_char is a better name than compat
I've addressed all your comments and pushed the commit, but I just noticed a failure in the compile-test results.
Don't merge until I've fixed this... |
// 1234 | ||
// Should have 4 spaces: see issue 18946 | ||
line.starts_with("(") | ||
line.starts_with(" ") || line.starts_with("(") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this change was required to support start type:
and end type:
(each with a preceding space).
@nrc: I got it working! By computing a least-upper-bound for the begin and end types of the range and using it as a hint when evaluating and comparing the constants we get inference of the least-complete type from the most-complete one! As a bonus, this also removes the asymmetry whereby This is the output for the example in the PR description:
|
@@ -8,9 +8,17 @@ | |||
// option. This file may not be copied, modified, or distributed | |||
// except according to those terms. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add a comment explaining what is being tested please?
Other than the small nits, this looks good. I wanted to ask around a few more people that unifying the type here is OK (I'm pretty sure it is). I'll try and get this r+'ed tomorrow. |
Ok great, cheers. |
// guarantee that the types are concrete and identical. We need to use the most | ||
// specific type as a type hint. | ||
// For example if we have 0 ... 5usize, we need to infer 0 : usize. | ||
let common_type = infer::common_supertype( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given that we've just unified the two types, computing a common supertype seems harmless but inefficient. If you just want to remove type variables from the type, resolve_type_vars_if_possible
or some similar method seems preferable.
fcx.write_ty(pat.id, lhs_ty); | ||
// Now that we know the types can be unified we find the unified type and use | ||
// it to type the entire expression. | ||
let common_type = fcx.infcx().resolve_type_vars_if_possible(&lhs_ty); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nikomatsakis, this works... there's no need to call it again with rhs_ty
is there?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michaelsproul nope, that looks good to me. (calling it rhs_ty
would yield the same result)
@bors r+ |
📌 Commit 25d0ef3 has been approved by |
Part of #24407. Currently the diagnostics for range patterns are a bit wrong: ```rust fn main() { match 5u32 { 0 ... 10 => (), 'a' ... 10 => (), 10 ... 'z' => (), "what" ... 10 => (), "what" ... "well" => (), 10 ... "what" => () } } ``` ``` range.rs:4:9: 4:19 error: mismatched types in range: expected integral variable, found char [E0211] range.rs:4 'a' ... 10 => (), ^~~~~~~~~~ range.rs:4:9: 4:16 error: only char and numeric types are allowed in range [E0029] range.rs:4 'a' ... 10 => (), ^~~~~~~ range.rs:4:9: 4:19 error: mismatched types: expected `u32`, found `char` (expected u32, found char) [E0308] range.rs:4 'a' ... 10 => (), ^~~~~~~~~~ range.rs:5:9: 5:19 error: mismatched types in range: expected char, found integral variable [E0211] range.rs:5 10 ... 'z' => (), ^~~~~~~~~~ range.rs:5:9: 5:15 error: only char and numeric types are allowed in range [E0029] range.rs:5 10 ... 'z' => (), ^~~~~~ range.rs:6:9: 6:22 error: mismatched types in range: expected integral variable, found &-ptr [E0211] range.rs:6 "what" ... 10 => (), ^~~~~~~~~~~~~ range.rs:6:9: 6:19 error: only char and numeric types are allowed in range [E0029] range.rs:6 "what" ... 10 => (), ^~~~~~~~~~ range.rs:6:9: 6:22 error: mismatched types: expected `u32`, found `&'static str` (expected u32, found &-ptr) [E0308] range.rs:6 "what" ... 10 => (), ^~~~~~~~~~~~~ range.rs:7:9: 7:19 error: only char and numeric types are allowed in range [E0029] range.rs:7 "what" ... "well" => (), ^~~~~~~~~~ range.rs:7:9: 7:26 error: mismatched types: expected `u32`, found `&'static str` (expected u32, found &-ptr) [E0308] range.rs:7 "what" ... "well" => (), ^~~~~~~~~~~~~~~~~ range.rs:8:9: 8:22 error: mismatched types in range: expected &-ptr, found integral variable [E0211] range.rs:8 10 ... "what" => () ^~~~~~~~~~~~~ range.rs:8:9: 8:15 error: only char and numeric types are allowed in range [E0029] range.rs:8 10 ... "what" => () ^~~~~~ error: aborting due to 12 previous errors ``` The problems here are: 1. The type of the end of the range is used to predict the type of the start (only mildly counter intuitive). 2. E0029 is erroneously generated for `char ... num` and `num ... char`. 2. `u32` is mentioned. 3. Errors which are essentially the same are reported multiple times. I've attempted to fix this by checking the requirements in a different order. The output I've achieved for the above example is: ``` /home/michael/Temp/range.rs:4:17: 4:22 error: mismatched types in range: expected char, found integral variable [E0211] /home/michael/Temp/range.rs:4 'a' ... 10 => (), ^~~~~ /home/michael/Temp/range.rs:5:16: 5:22 error: mismatched types in range: expected integral variable, found char [E0211] /home/michael/Temp/range.rs:5 10 ... 'z' => (), ^~~~~~ /home/michael/Temp/range.rs:6:9: 6:19 error: only char and numeric types are allowed in range [E0029] /home/michael/Temp/range.rs:6 "what" ... 10 => (), ^~~~~~~~~~ /home/michael/Temp/range.rs:6:9: 6:19 help: run `rustc --explain E0029` to see a detailed explanation /home/michael/Temp/range.rs:6:9: 6:19 note: Start type: &'static str End type: _ /home/michael/Temp/range.rs:6 "what" ... 10 => (), ^~~~~~~~~~ /home/michael/Temp/range.rs:7:9: 7:26 error: only char and numeric types are allowed in range [E0029] /home/michael/Temp/range.rs:7 "what" ... "well" => (), ^~~~~~~~~~~~~~~~~ /home/michael/Temp/range.rs:7:9: 7:26 help: run `rustc --explain E0029` to see a detailed explanation /home/michael/Temp/range.rs:7:9: 7:26 note: Start type: &'static str End type: &'static str /home/michael/Temp/range.rs:7 "what" ... "well" => (), ^~~~~~~~~~~~~~~~~ /home/michael/Temp/range.rs:8:16: 8:25 error: only char and numeric types are allowed in range [E0029] /home/michael/Temp/range.rs:8 10 ... "what" => () ^~~~~~~~~ /home/michael/Temp/range.rs:8:16: 8:25 help: run `rustc --explain E0029` to see a detailed explanation /home/michael/Temp/range.rs:8:16: 8:25 note: Start type: _ End type: &'static str /home/michael/Temp/range.rs:8 10 ... "what" => () ^~~~~~~~~ error: aborting due to 5 previous errors ``` I think this is already tonnes better, but the `Start type/End type` stuff could be neater. I don't think there's really any need to start a `note:` block but I wanted to get some feedback on this. I'd also appreciate advice on how to print the integer types as something other than `_`.
Part of #24407.
Currently the diagnostics for range patterns are a bit wrong:
The problems here are:
char ... num
andnum ... char
.u32
is mentioned.I've attempted to fix this by checking the requirements in a different order. The output I've achieved for the above example is:
I think this is already tonnes better, but the
Start type/End type
stuff could be neater. I don't think there's really any need to start anote:
block but I wanted to get some feedback on this. I'd also appreciate advice on how to print the integer types as something other than_
.