-
Notifications
You must be signed in to change notification settings - Fork 14k
Implement suggestion when array of 1 range used as argument of type Range
#148002
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
base: main
Are you sure you want to change the base?
Conversation
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 seems like a mistake that a new user could reasonably hit if they haven't internalized that item[..x] means Index[Mut] with Range parameter, and think that the ..x syntax must be wrapped in [].
So +1 on adding the diagnostic. Have a few comments on the implementation, see below.
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
Outdated
Show resolved
Hide resolved
623dbfd to
d2b40f7
Compare
|
This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This comment has been minimized.
This comment has been minimized.
|
I used let pattern chain instead of early I edited the tests to include this example: let range = [1..5];
let mut vec = vec![1, 2, 3, 4, 5];
vec.drain(range);And I have a question about this. Should compiler give an error in this case or is it outside of a scope for such suggestion? Right now I also wonder if something like this should be a part of this PR: let range_wrong: Range<usize> = [1..5];
// ^^^^^^^^^^^^ ^^^^^^ array [Range<usize>; 1]
// struct Range<usize> |
|
@rustbot label -S-waiting-on-author +S-waiting-on-review |
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.
Sorry for the delay.
I used let pattern chain instead of early
returns similarly how other functions in this file do this to make it even less verbose.
Thanks, I like it so far!
I answered the rest of your questions in inline comments.
| // Should not produce this suggestion: | ||
|
|
||
| let range = [1..5]; | ||
| let mut vec = vec![1, 2, 3, 4, 5]; | ||
| vec.drain(range); | ||
| //~^ ERROR: the trait bound `[std::ops::Range<{integer}>; 1]: RangeBounds<usize>` is not satisfied [E0277] |
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.
I edited the tests to include this example:
let range = [1..5]; let mut vec = vec![1, 2, 3, 4, 5]; vec.drain(range);And I have a question about this. Should compiler give an error in this case or is it outside of a scope for such suggestion?
I think it's fine to leave this as future work, maybe with the note like this instead:
| // Should not produce this suggestion: | |
| let range = [1..5]; | |
| let mut vec = vec![1, 2, 3, 4, 5]; | |
| vec.drain(range); | |
| //~^ ERROR: the trait bound `[std::ops::Range<{integer}>; 1]: RangeBounds<usize>` is not satisfied [E0277] | |
| // Does not produce this suggestion (but could in the future): | |
| let range = [1..5]; | |
| let mut vec = vec![1, 2, 3, 4, 5]; | |
| vec.drain(range); | |
| //~^ ERROR: the trait bound `[std::ops::Range<{integer}>; 1]: RangeBounds<usize>` is not satisfied [E0277] | |
| // Should not produce this suggestion: |
| @@ -0,0 +1,27 @@ | |||
| fn main() { | |||
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.
I also wonder if something like this should be a part of this PR:
let range_wrong: Range<usize> = [1..5]; // ^^^^^^^^^^^^ ^^^^^^ array [Range<usize>; 1] // struct Range<usize>
I'm fine with it not being so, though maybe you could add it as a test as well?
| && snip.starts_with('[') | ||
| && snip.ends_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.
Right now
suggest_remove_brackets_from_rangeonly works for inline ranges - for that it checks if snippet starts and ends with[,]. It this the right solution?
Well, it does make it considerably easier to construct the suggestion, and there is precedence for it in suggest_block_to_brackets, so I think it's fine.
| && let ty::Adt(adt_def, _) = inner_type.kind() | ||
| && self.tcx.is_range(adt_def.did()) |
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.
I just realized, we already have something that describes whether a type is a valid range: the RangeBounds trait.
So maybe we can use something like this instead:
| && let ty::Adt(adt_def, _) = inner_type.kind() | |
| && self.tcx.is_range(adt_def.did()) | |
| // NOTE: Assumes that arrays do not implement `RangeBounds`. | |
| && let Some(range_bounds) = self.tcx.get_diagnostic_item(sym::RangeBounds) | |
| && self.type_implements_trait(range_bounds, [inner_type], param_env).must_apply_modulo_regions() |
And then we can get rid of the is_range function?
| vec.drain([..]); | ||
| //~^ ERROR: the trait bound `[RangeFull; 1]: RangeBounds<usize>` is not satisfied [E0277] | ||
| //~| SUGGESTION: .. | ||
| } |
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 test that calls a different method than Vec::drain?
And possibly also a test like:
let my_range = 1..3;
vec.drain([my_range]);
Fixes: #147944
Using array of 1 range instead of range itself as argument of
impl RangeBoundsnow additionally produces this suggestion: