Skip to content

Commit 4484597

Browse files
committed
restrict manual_clamp to const case, bring it out of nursery
1 parent 95c62ff commit 4484597

File tree

4 files changed

+570
-260
lines changed

4 files changed

+570
-260
lines changed

clippy_lints/src/manual_clamp.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_config::msrvs::{self, Msrv};
2+
use clippy_utils::consts::{constant, Constant};
23
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
34
use clippy_utils::higher::If;
45
use clippy_utils::sugg::Sugg;
@@ -17,6 +18,7 @@ use rustc_middle::ty::Ty;
1718
use rustc_session::impl_lint_pass;
1819
use rustc_span::symbol::sym;
1920
use rustc_span::Span;
21+
use std::cmp::Ordering;
2022
use std::ops::Deref;
2123

2224
declare_clippy_lint! {
@@ -80,7 +82,7 @@ declare_clippy_lint! {
8082
/// ```
8183
#[clippy::version = "1.66.0"]
8284
pub MANUAL_CLAMP,
83-
nursery,
85+
complexity,
8486
"using a clamp pattern instead of the clamp function"
8587
}
8688
impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]);
@@ -103,6 +105,24 @@ struct ClampSuggestion<'tcx> {
103105
hir_with_ignore_attr: Option<HirId>,
104106
}
105107

108+
impl<'tcx> ClampSuggestion<'tcx> {
109+
/// This function will return true if and only if you can demonstrate at compile time that min
110+
/// is less than max.
111+
fn min_less_than_max(&self, cx: &LateContext<'tcx>) -> bool {
112+
let max_type = cx.typeck_results().expr_ty(self.params.max);
113+
let min_type = cx.typeck_results().expr_ty(self.params.min);
114+
if max_type != min_type {
115+
return false;
116+
}
117+
let max = constant(cx, cx.typeck_results(), self.params.max);
118+
let min = constant(cx, cx.typeck_results(), self.params.min);
119+
let cmp = max
120+
.zip(min)
121+
.and_then(|(max, min)| Constant::partial_cmp(cx.tcx, max_type, &min, &max));
122+
cmp.map(|cmp| cmp != Ordering::Greater).unwrap_or(false)
123+
}
124+
}
125+
106126
#[derive(Debug)]
107127
struct InputMinMax<'tcx> {
108128
input: &'tcx Expr<'tcx>,
@@ -123,7 +143,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
123143
.or_else(|| is_match_pattern(cx, expr))
124144
.or_else(|| is_if_elseif_pattern(cx, expr));
125145
if let Some(suggestion) = suggestion {
126-
emit_suggestion(cx, &suggestion);
146+
if suggestion.min_less_than_max(cx) {
147+
emit_suggestion(cx, &suggestion);
148+
}
127149
}
128150
}
129151
}
@@ -133,7 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
133155
return;
134156
}
135157
for suggestion in is_two_if_pattern(cx, block) {
136-
emit_suggestion(cx, &suggestion);
158+
if suggestion.min_less_than_max(cx) {
159+
emit_suggestion(cx, &suggestion);
160+
}
137161
}
138162
}
139163
extract_msrv_attr!(LateContext);

0 commit comments

Comments
 (0)