Skip to content

Add manual_min_max lint#16890

Open
Souradip121 wants to merge 5 commits intorust-lang:masterfrom
Souradip121:lint-manual-min-max
Open

Add manual_min_max lint#16890
Souradip121 wants to merge 5 commits intorust-lang:masterfrom
Souradip121:lint-manual-min-max

Conversation

@Souradip121
Copy link
Copy Markdown
Contributor

@Souradip121 Souradip121 commented Apr 19, 2026

Adds the manual_min_max lint (complexity, warn-by-default).

Detects manual if-else implementations of Ord::min and Ord::max and
suggests using those methods directly.

Closes #16884

What the lint catches

// Before
let _ = if a > b { b } else { a };
let _ = if a < b { a } else { b };
let _ = if a > b { a } else { b };

// After
let _ = a.min(b);
let _ = a.min(b);
let _ = a.max(b);

All eight variants are covered: both strict (>, <) and non-strict
(>=, <=) comparisons, and both orderings of the then/else branches.
Compound expressions are correctly parenthesized:

// Before
let _ = if a + 1 < b { a + 1 } else { b };

// After
let _ = (a + 1).min(b);

Conservative conditions (no false positives)

The lint is skipped when:

  • The expression is inside a macro expansion
  • The expression is in a const context (Ord::min/Ord::max are not yet const-stable)
  • Either operand has side effects (function calls, etc.) — handled implicitly by eq_expr_value which uses SpanlessEq::deny_side_effects
  • The type does not implement Ord — this excludes f32/f64, which only implement PartialOrd and whose min/max methods have different NaN semantics

Why not extend manual_clamp?

manual_clamp uses MaybeIncorrect applicability (clamp can panic) and
requires const-evaluatable bounds. These two-way patterns never panic and
have no such constraint, so MachineApplicable is appropriate. A separate
lint keeps the two concerns independent.

changelog: [manual_min_max]: new lint to detect manual implementations of Ord::min and Ord::max using if-else expressions.

@rustbot rustbot added needs-fcp PRs that add, remove, or rename lints and need an FCP S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Apr 19, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 19, 2026

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

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: 7 candidates
  • 7 candidates expanded to 7 candidates
  • Random selection from Jarcho, dswij, llogiq, samueltardieu

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 19, 2026

Lintcheck changes for 26a71c2

Lint Added Removed Changed
clippy::manual_min_max 1 0 0

This comment will be updated if you push new changes

Comment thread tests/ui/manual_min_max.fixed Outdated
let b: i32 = 7;

// op=< → min
let _ = a.min(b);
Copy link
Copy Markdown

@ronnodas ronnodas Apr 20, 2026

Choose a reason for hiding this comment

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

I think this should be b.min(a) since in the equality case the result of if a < b { a } else { b } is b. Of course this doesn't matter for i32s so maybe it makes sense to add tests with types that have fields that are ignored by Ord? Note that in case of ties Ord::min returns the first argument and Ord::max returns the second.

View changes since the review

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@ronnodas can you check now, just made another commit.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I haven't looked at the code at all, just the tests, but I believe the max cases are flipped now, a.max(b) returns b if a.cmp(b) == Ordering::Equal. The PR description above should also be updated (the second example in the "What the lint catches section") for posterity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-fcp PRs that add, remove, or rename lints and need an FCP S-waiting-on-review Status: Awaiting review from the assignee but also interested parties

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Manual clamp variant for min and max

4 participants