Skip to content

Propose to exchange ranges only when it is safe to do so #14432

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

Merged
merged 2 commits into from
Jul 16, 2025

Conversation

samueltardieu
Copy link
Member

@samueltardieu samueltardieu commented Mar 18, 2025

To avoid false positives, the range_plus_one and range_minus_one lints will restrict themselves to situations where the iterator types can be easily switched from exclusive to inclusive or vice-versa. This includes situations where the range is used as an iterator, or is used for indexing.

On the other hand, assignments of the range to variables, including automatically typed ones or wildcards, will no longer trigger the lint. However, the cases where such an assignment would benefit from the lint are probably rare.

In a second commit, the range_plus_one and range_minus_one logic are unified, in order to properly emit parentheses around the suggestion when needed.

Fix #3307
Fix #9908

changelog: [range_plus_one, range_minus_one]: restrict lint to cases where it is safe to switch the range type

Edit: as a consequence, this led to the removal of three #[expect(clippy::range_plus_one)] in the Clippy sources to avoid those false positives.

@rustbot
Copy link
Collaborator

rustbot commented Mar 18, 2025

r? @llogiq

rustbot has assigned @llogiq.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Mar 18, 2025
@samueltardieu
Copy link
Member Author

This could also be extended to situations where the ranges are used as an argument to a function/method call which accepts an impl or dyn trait implemented by all kind of ranges:

  • Letting this as a future enhancement removes current false positives.
  • Doing it in this PR limits the number of places where the lint triggered before but won't trigger now.

@samueltardieu
Copy link
Member Author

Rebased on master

@samueltardieu
Copy link
Member Author

Putting to draft, I want to double-check the lintcheck, it looks like we get some false negatives there.
@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Mar 31, 2025
@samueltardieu samueltardieu marked this pull request as draft March 31, 2025 14:43
@samueltardieu samueltardieu force-pushed the push-vzpslusykwsk branch 2 times, most recently from db80969 to f532213 Compare March 31, 2025 16:40
@samueltardieu samueltardieu marked this pull request as ready for review March 31, 2025 16:40
@samueltardieu
Copy link
Member Author

Much better. I added checking if the range to be modified is a method or function call argument, and if the target range would be suitable as well.

@rustbot review

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Mar 31, 2025
@samueltardieu
Copy link
Member Author

r? clippy

@samueltardieu
Copy link
Member Author

samueltardieu commented Apr 15, 2025

I added a second commit to fix an issue with parentheses lacking from some suggestions identified in a comment made tonight in #9908.

@samueltardieu
Copy link
Member Author

r? clippy

@rustbot rustbot assigned Jarcho and unassigned blyxyas May 16, 2025
@rustbot

This comment has been minimized.

@samueltardieu
Copy link
Member Author

Rebased

Copy link
Contributor

@Jarcho Jarcho left a comment

Choose a reason for hiding this comment

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

Thank you for fixing this as it's quite annoying currently.

Comment on lines 423 to 467
if let ExprKind::Index(_, index, _) = parent_expr.kind
&& index.hir_id == expr.hir_id
{
return true;
}

false
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to check if Index<RangeType> is implemented for the indexed type.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, and I checked this for Index or IndexMut, depending of what we need.

let expr_ty = inputs[input_idx];
// Check that the `expr` type is present only one, otherwise modifying just one of them it might be
// risky if they are referenced using the same generic type for example.
if inputs.iter().enumerate().all(|(n, ty)| n == input_idx || *ty != expr_ty)
Copy link
Contributor

Choose a reason for hiding this comment

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

This will need a TypeVisitor over all other input parameters. Foo<T> and such needs to be detected.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done with ty.walk(), I don't think we need a visitor, if the range type doesn't appear within the generic arguments it doesn't matter if it is present, for example in a struct field of another argument, as they will not be used together (since we check that the range type is not referenced per-se but through constraints).

Copy link
Contributor

Choose a reason for hiding this comment

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

TypeVisitor actually visits the same things as Ty::walk does, but walk is the better thing here and I totally forgotten it existed.

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels May 21, 2025
@samueltardieu samueltardieu requested a review from Jarcho May 23, 2025 11:11
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels May 23, 2025
@samueltardieu samueltardieu force-pushed the push-vzpslusykwsk branch 4 times, most recently from 0a28296 to 4c23383 Compare May 26, 2025 12:07
@samueltardieu
Copy link
Member Author

Ping @Jarcho

To limit false positives, the `range_plus_one` and `range_minus_one` lints
will restrict themselves to situations where the iterator types can be easily
switched from exclusive to inclusive or vice-versa. This includes situations
where the range is used as an iterator, or is used for indexing. Also,
when the range is used as a function or method call argument and the
parameter type is generic over traits implemented by both kind of
ranges, the lint will trigger.

On the other hand, assignments of the range to variables, including
automatically typed ones or wildcards, will no longer trigger the lint.
However, the cases where such an assignment would benefit from the lint
are probably rare.

This fix doesn't prevent false positives from happening. A more complete
fix would check if the obligations can be satisfied by the new proposed
range type.
Those lints share the detection logic structure, but differed, probably
because of an oversight, in lint emission: only one of them would take
care of emitting parentheses around the suggestion if required.

Factor the code into one function which checks for the right condition
and emits the lint in an identical way.
@samueltardieu
Copy link
Member Author

Rebased since GenericArg::unpack() was renamed to GenericArg::kind() in rustc.

Copy link
Contributor

@Jarcho Jarcho left a comment

Choose a reason for hiding this comment

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

Thank you.

@Jarcho Jarcho added this pull request to the merge queue Jul 16, 2025
Merged via the queue into rust-lang:master with commit e113e66 Jul 16, 2025
11 checks passed
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jul 16, 2025
@samueltardieu samueltardieu deleted the push-vzpslusykwsk branch July 16, 2025 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants