Skip to content

Commit 1727363

Browse files
committed
Do not remove cast if it would make the expression type uncertain
1 parent 7d2abed commit 1727363

File tree

4 files changed

+101
-43
lines changed

4 files changed

+101
-43
lines changed

clippy_lints/src/casts/unnecessary_cast.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::numeric_literal::NumericLiteral;
33
use clippy_utils::source::{SpanRangeExt, snippet_opt};
4+
use clippy_utils::ty::expr_type_is_certain;
45
use clippy_utils::visitors::{Visitable, for_each_expr_without_closures};
56
use clippy_utils::{get_parent_expr, is_hir_ty_cfg_dependant, is_ty_alias, path_to_local};
67
use rustc_ast::{LitFloatType, LitIntType, LitKind};
@@ -141,7 +142,10 @@ pub(super) fn check<'tcx>(
141142
}
142143
}
143144

144-
if cast_from.kind() == cast_to.kind() && !expr.span.in_external_macro(cx.sess().source_map()) {
145+
if cast_from.kind() == cast_to.kind()
146+
&& !expr.span.in_external_macro(cx.sess().source_map())
147+
&& expr_type_is_certain(cx, cast_expr)
148+
{
145149
if let Some(id) = path_to_local(cast_expr)
146150
&& !cx.tcx.hir().span(id).eq_ctxt(cast_expr.span)
147151
{

tests/ui/unnecessary_cast.fixed

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
clippy::no_effect,
77
clippy::nonstandard_macro_braces,
88
clippy::unnecessary_operation,
9+
clippy::double_parens,
910
nonstandard_style,
1011
unused
1112
)]
@@ -269,4 +270,24 @@ mod fixable {
269270
{ *x }.pow(2)
270271
//~^ unnecessary_cast
271272
}
273+
274+
fn issue_14366(i: u32) {
275+
// Do not remove the cast if it helps determining the type
276+
let _ = ((1.0 / 8.0) as f64).powf(i as f64);
277+
278+
// But remove useless casts anyway
279+
let _ = ((1.0 / 8.0) as f64).powf(i as f64);
280+
//~^ unnecessary_cast
281+
}
282+
283+
fn ambiguity() {
284+
pub trait T {}
285+
impl T for u32 {}
286+
impl T for String {}
287+
fn f(_: impl T) {}
288+
289+
f((1 + 2) as u32);
290+
f((1 + 2u32));
291+
//~^ unnecessary_cast
292+
}
272293
}

tests/ui/unnecessary_cast.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
clippy::no_effect,
77
clippy::nonstandard_macro_braces,
88
clippy::unnecessary_operation,
9+
clippy::double_parens,
910
nonstandard_style,
1011
unused
1112
)]
@@ -269,4 +270,24 @@ mod fixable {
269270
(*x as usize).pow(2)
270271
//~^ unnecessary_cast
271272
}
273+
274+
fn issue_14366(i: u32) {
275+
// Do not remove the cast if it helps determining the type
276+
let _ = ((1.0 / 8.0) as f64).powf(i as f64);
277+
278+
// But remove useless casts anyway
279+
let _ = (((1.0 / 8.0) as f64) as f64).powf(i as f64);
280+
//~^ unnecessary_cast
281+
}
282+
283+
fn ambiguity() {
284+
pub trait T {}
285+
impl T for u32 {}
286+
impl T for String {}
287+
fn f(_: impl T) {}
288+
289+
f((1 + 2) as u32);
290+
f((1 + 2u32) as u32);
291+
//~^ unnecessary_cast
292+
}
272293
}

tests/ui/unnecessary_cast.stderr

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`)
2-
--> tests/ui/unnecessary_cast.rs:19:5
2+
--> tests/ui/unnecessary_cast.rs:20:5
33
|
44
LL | ptr as *const T
55
| ^^^^^^^^^^^^^^^ help: try: `ptr`
@@ -8,244 +8,256 @@ LL | ptr as *const T
88
= help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]`
99

1010
error: casting integer literal to `i32` is unnecessary
11-
--> tests/ui/unnecessary_cast.rs:55:5
11+
--> tests/ui/unnecessary_cast.rs:56:5
1212
|
1313
LL | 1i32 as i32;
1414
| ^^^^^^^^^^^ help: try: `1_i32`
1515

1616
error: casting float literal to `f32` is unnecessary
17-
--> tests/ui/unnecessary_cast.rs:57:5
17+
--> tests/ui/unnecessary_cast.rs:58:5
1818
|
1919
LL | 1f32 as f32;
2020
| ^^^^^^^^^^^ help: try: `1_f32`
2121

2222
error: casting to the same type is unnecessary (`bool` -> `bool`)
23-
--> tests/ui/unnecessary_cast.rs:59:5
23+
--> tests/ui/unnecessary_cast.rs:60:5
2424
|
2525
LL | false as bool;
2626
| ^^^^^^^^^^^^^ help: try: `false`
2727

2828
error: casting integer literal to `i32` is unnecessary
29-
--> tests/ui/unnecessary_cast.rs:63:5
29+
--> tests/ui/unnecessary_cast.rs:64:5
3030
|
3131
LL | -1_i32 as i32;
3232
| ^^^^^^^^^^^^^ help: try: `-1_i32`
3333

3434
error: casting integer literal to `i32` is unnecessary
35-
--> tests/ui/unnecessary_cast.rs:65:5
35+
--> tests/ui/unnecessary_cast.rs:66:5
3636
|
3737
LL | - 1_i32 as i32;
3838
| ^^^^^^^^^^^^^^ help: try: `- 1_i32`
3939

4040
error: casting float literal to `f32` is unnecessary
41-
--> tests/ui/unnecessary_cast.rs:67:5
41+
--> tests/ui/unnecessary_cast.rs:68:5
4242
|
4343
LL | -1f32 as f32;
4444
| ^^^^^^^^^^^^ help: try: `-1_f32`
4545

4646
error: casting integer literal to `i32` is unnecessary
47-
--> tests/ui/unnecessary_cast.rs:69:5
47+
--> tests/ui/unnecessary_cast.rs:70:5
4848
|
4949
LL | 1_i32 as i32;
5050
| ^^^^^^^^^^^^ help: try: `1_i32`
5151

5252
error: casting float literal to `f32` is unnecessary
53-
--> tests/ui/unnecessary_cast.rs:71:5
53+
--> tests/ui/unnecessary_cast.rs:72:5
5454
|
5555
LL | 1_f32 as f32;
5656
| ^^^^^^^^^^^^ help: try: `1_f32`
5757

5858
error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
59-
--> tests/ui/unnecessary_cast.rs:74:22
59+
--> tests/ui/unnecessary_cast.rs:75:22
6060
|
6161
LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8;
6262
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
6363

6464
error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
65-
--> tests/ui/unnecessary_cast.rs:77:5
65+
--> tests/ui/unnecessary_cast.rs:78:5
6666
|
6767
LL | [1u8, 2].as_ptr() as *const u8;
6868
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()`
6969

7070
error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`)
71-
--> tests/ui/unnecessary_cast.rs:80:5
71+
--> tests/ui/unnecessary_cast.rs:81:5
7272
|
7373
LL | [1u8, 2].as_mut_ptr() as *mut u8;
7474
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()`
7575

7676
error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
77-
--> tests/ui/unnecessary_cast.rs:92:5
77+
--> tests/ui/unnecessary_cast.rs:93:5
7878
|
7979
LL | owo::<u32>([1u32].as_ptr()) as *const u32;
8080
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::<u32>([1u32].as_ptr())`
8181

8282
error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
83-
--> tests/ui/unnecessary_cast.rs:94:5
83+
--> tests/ui/unnecessary_cast.rs:95:5
8484
|
8585
LL | uwu::<u32, u8>([1u32].as_ptr()) as *const u8;
8686
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u8>([1u32].as_ptr())`
8787

8888
error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
89-
--> tests/ui/unnecessary_cast.rs:97:5
89+
--> tests/ui/unnecessary_cast.rs:98:5
9090
|
9191
LL | uwu::<u32, u32>([1u32].as_ptr()) as *const u32;
9292
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u32>([1u32].as_ptr())`
9393

9494
error: casting to the same type is unnecessary (`u32` -> `u32`)
95-
--> tests/ui/unnecessary_cast.rs:133:5
95+
--> tests/ui/unnecessary_cast.rs:134:5
9696
|
9797
LL | aaa() as u32;
9898
| ^^^^^^^^^^^^ help: try: `aaa()`
9999

100100
error: casting to the same type is unnecessary (`u32` -> `u32`)
101-
--> tests/ui/unnecessary_cast.rs:136:5
101+
--> tests/ui/unnecessary_cast.rs:137:5
102102
|
103103
LL | aaa() as u32;
104104
| ^^^^^^^^^^^^ help: try: `aaa()`
105105

106106
error: casting integer literal to `f32` is unnecessary
107-
--> tests/ui/unnecessary_cast.rs:173:9
107+
--> tests/ui/unnecessary_cast.rs:174:9
108108
|
109109
LL | 100 as f32;
110110
| ^^^^^^^^^^ help: try: `100_f32`
111111

112112
error: casting integer literal to `f64` is unnecessary
113-
--> tests/ui/unnecessary_cast.rs:175:9
113+
--> tests/ui/unnecessary_cast.rs:176:9
114114
|
115115
LL | 100 as f64;
116116
| ^^^^^^^^^^ help: try: `100_f64`
117117

118118
error: casting integer literal to `f64` is unnecessary
119-
--> tests/ui/unnecessary_cast.rs:177:9
119+
--> tests/ui/unnecessary_cast.rs:178:9
120120
|
121121
LL | 100_i32 as f64;
122122
| ^^^^^^^^^^^^^^ help: try: `100_f64`
123123

124124
error: casting integer literal to `f32` is unnecessary
125-
--> tests/ui/unnecessary_cast.rs:179:17
125+
--> tests/ui/unnecessary_cast.rs:180:17
126126
|
127127
LL | let _ = -100 as f32;
128128
| ^^^^^^^^^^^ help: try: `-100_f32`
129129

130130
error: casting integer literal to `f64` is unnecessary
131-
--> tests/ui/unnecessary_cast.rs:181:17
131+
--> tests/ui/unnecessary_cast.rs:182:17
132132
|
133133
LL | let _ = -100 as f64;
134134
| ^^^^^^^^^^^ help: try: `-100_f64`
135135

136136
error: casting integer literal to `f64` is unnecessary
137-
--> tests/ui/unnecessary_cast.rs:183:17
137+
--> tests/ui/unnecessary_cast.rs:184:17
138138
|
139139
LL | let _ = -100_i32 as f64;
140140
| ^^^^^^^^^^^^^^^ help: try: `-100_f64`
141141

142142
error: casting float literal to `f32` is unnecessary
143-
--> tests/ui/unnecessary_cast.rs:185:9
143+
--> tests/ui/unnecessary_cast.rs:186:9
144144
|
145145
LL | 100. as f32;
146146
| ^^^^^^^^^^^ help: try: `100_f32`
147147

148148
error: casting float literal to `f64` is unnecessary
149-
--> tests/ui/unnecessary_cast.rs:187:9
149+
--> tests/ui/unnecessary_cast.rs:188:9
150150
|
151151
LL | 100. as f64;
152152
| ^^^^^^^^^^^ help: try: `100_f64`
153153

154154
error: casting integer literal to `u32` is unnecessary
155-
--> tests/ui/unnecessary_cast.rs:200:9
155+
--> tests/ui/unnecessary_cast.rs:201:9
156156
|
157157
LL | 1 as u32;
158158
| ^^^^^^^^ help: try: `1_u32`
159159

160160
error: casting integer literal to `i32` is unnecessary
161-
--> tests/ui/unnecessary_cast.rs:202:9
161+
--> tests/ui/unnecessary_cast.rs:203:9
162162
|
163163
LL | 0x10 as i32;
164164
| ^^^^^^^^^^^ help: try: `0x10_i32`
165165

166166
error: casting integer literal to `usize` is unnecessary
167-
--> tests/ui/unnecessary_cast.rs:204:9
167+
--> tests/ui/unnecessary_cast.rs:205:9
168168
|
169169
LL | 0b10 as usize;
170170
| ^^^^^^^^^^^^^ help: try: `0b10_usize`
171171

172172
error: casting integer literal to `u16` is unnecessary
173-
--> tests/ui/unnecessary_cast.rs:206:9
173+
--> tests/ui/unnecessary_cast.rs:207:9
174174
|
175175
LL | 0o73 as u16;
176176
| ^^^^^^^^^^^ help: try: `0o73_u16`
177177

178178
error: casting integer literal to `u32` is unnecessary
179-
--> tests/ui/unnecessary_cast.rs:208:9
179+
--> tests/ui/unnecessary_cast.rs:209:9
180180
|
181181
LL | 1_000_000_000 as u32;
182182
| ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32`
183183

184184
error: casting float literal to `f64` is unnecessary
185-
--> tests/ui/unnecessary_cast.rs:211:9
185+
--> tests/ui/unnecessary_cast.rs:212:9
186186
|
187187
LL | 1.0 as f64;
188188
| ^^^^^^^^^^ help: try: `1.0_f64`
189189

190190
error: casting float literal to `f32` is unnecessary
191-
--> tests/ui/unnecessary_cast.rs:213:9
191+
--> tests/ui/unnecessary_cast.rs:214:9
192192
|
193193
LL | 0.5 as f32;
194194
| ^^^^^^^^^^ help: try: `0.5_f32`
195195

196196
error: casting integer literal to `i32` is unnecessary
197-
--> tests/ui/unnecessary_cast.rs:218:17
197+
--> tests/ui/unnecessary_cast.rs:219:17
198198
|
199199
LL | let _ = -1 as i32;
200200
| ^^^^^^^^^ help: try: `-1_i32`
201201

202202
error: casting float literal to `f32` is unnecessary
203-
--> tests/ui/unnecessary_cast.rs:220:17
203+
--> tests/ui/unnecessary_cast.rs:221:17
204204
|
205205
LL | let _ = -1.0 as f32;
206206
| ^^^^^^^^^^^ help: try: `-1.0_f32`
207207

208208
error: casting to the same type is unnecessary (`i32` -> `i32`)
209-
--> tests/ui/unnecessary_cast.rs:227:18
209+
--> tests/ui/unnecessary_cast.rs:228:18
210210
|
211211
LL | let _ = &(x as i32);
212212
| ^^^^^^^^^^ help: try: `{ x }`
213213

214214
error: casting integer literal to `i32` is unnecessary
215-
--> tests/ui/unnecessary_cast.rs:234:22
215+
--> tests/ui/unnecessary_cast.rs:235:22
216216
|
217217
LL | let _: i32 = -(1) as i32;
218218
| ^^^^^^^^^^^ help: try: `-1_i32`
219219

220220
error: casting integer literal to `i64` is unnecessary
221-
--> tests/ui/unnecessary_cast.rs:237:22
221+
--> tests/ui/unnecessary_cast.rs:238:22
222222
|
223223
LL | let _: i64 = -(1) as i64;
224224
| ^^^^^^^^^^^ help: try: `-1_i64`
225225

226226
error: casting float literal to `f64` is unnecessary
227-
--> tests/ui/unnecessary_cast.rs:245:22
227+
--> tests/ui/unnecessary_cast.rs:246:22
228228
|
229229
LL | let _: f64 = (-8.0 as f64).exp();
230230
| ^^^^^^^^^^^^^ help: try: `(-8.0_f64)`
231231

232232
error: casting float literal to `f64` is unnecessary
233-
--> tests/ui/unnecessary_cast.rs:248:23
233+
--> tests/ui/unnecessary_cast.rs:249:23
234234
|
235235
LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior
236236
| ^^^^^^^^^^^^ help: try: `8.0_f64`
237237

238238
error: casting to the same type is unnecessary (`f32` -> `f32`)
239-
--> tests/ui/unnecessary_cast.rs:258:20
239+
--> tests/ui/unnecessary_cast.rs:259:20
240240
|
241241
LL | let _num = foo() as f32;
242242
| ^^^^^^^^^^^^ help: try: `foo()`
243243

244244
error: casting to the same type is unnecessary (`usize` -> `usize`)
245-
--> tests/ui/unnecessary_cast.rs:269:9
245+
--> tests/ui/unnecessary_cast.rs:270:9
246246
|
247247
LL | (*x as usize).pow(2)
248248
| ^^^^^^^^^^^^^ help: try: `{ *x }`
249249

250-
error: aborting due to 41 previous errors
250+
error: casting to the same type is unnecessary (`f64` -> `f64`)
251+
--> tests/ui/unnecessary_cast.rs:279:17
252+
|
253+
LL | let _ = (((1.0 / 8.0) as f64) as f64).powf(i as f64);
254+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `((1.0 / 8.0) as f64)`
255+
256+
error: casting to the same type is unnecessary (`u32` -> `u32`)
257+
--> tests/ui/unnecessary_cast.rs:290:11
258+
|
259+
LL | f((1 + 2u32) as u32);
260+
| ^^^^^^^^^^^^^^^^^ help: try: `(1 + 2u32)`
261+
262+
error: aborting due to 43 previous errors
251263

0 commit comments

Comments
 (0)