1
1
use clippy_config:: msrvs:: { self , Msrv } ;
2
+ use clippy_utils:: consts:: { constant, Constant } ;
2
3
use clippy_utils:: diagnostics:: { span_lint_and_then, span_lint_hir_and_then} ;
3
4
use clippy_utils:: higher:: If ;
4
5
use clippy_utils:: sugg:: Sugg ;
@@ -17,6 +18,7 @@ use rustc_middle::ty::Ty;
17
18
use rustc_session:: impl_lint_pass;
18
19
use rustc_span:: symbol:: sym;
19
20
use rustc_span:: Span ;
21
+ use std:: cmp:: Ordering ;
20
22
use std:: ops:: Deref ;
21
23
22
24
declare_clippy_lint ! {
@@ -80,7 +82,7 @@ declare_clippy_lint! {
80
82
/// ```
81
83
#[ clippy:: version = "1.66.0" ]
82
84
pub MANUAL_CLAMP ,
83
- nursery ,
85
+ complexity ,
84
86
"using a clamp pattern instead of the clamp function"
85
87
}
86
88
impl_lint_pass ! ( ManualClamp => [ MANUAL_CLAMP ] ) ;
@@ -103,6 +105,24 @@ struct ClampSuggestion<'tcx> {
103
105
hir_with_ignore_attr : Option < HirId > ,
104
106
}
105
107
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
+
106
126
#[ derive( Debug ) ]
107
127
struct InputMinMax < ' tcx > {
108
128
input : & ' tcx Expr < ' tcx > ,
@@ -123,7 +143,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
123
143
. or_else ( || is_match_pattern ( cx, expr) )
124
144
. or_else ( || is_if_elseif_pattern ( cx, expr) ) ;
125
145
if let Some ( suggestion) = suggestion {
126
- emit_suggestion ( cx, & suggestion) ;
146
+ if suggestion. min_less_than_max ( cx) {
147
+ emit_suggestion ( cx, & suggestion) ;
148
+ }
127
149
}
128
150
}
129
151
}
@@ -133,7 +155,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
133
155
return ;
134
156
}
135
157
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
+ }
137
161
}
138
162
}
139
163
extract_msrv_attr ! ( LateContext ) ;
0 commit comments