Skip to content

Commit aeed34c

Browse files
author
navh
committed
use span_lint_and_then
1 parent 870749d commit aeed34c

File tree

3 files changed

+190
-41
lines changed

3 files changed

+190
-41
lines changed

clippy_lints/src/casts/cast_possible_truncation.rs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use clippy_utils::consts::{constant, Constant};
2-
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
2+
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
33
use clippy_utils::expr_or_init;
4-
use clippy_utils::source::snippet_with_applicability;
4+
use clippy_utils::source::snippet;
55
use clippy_utils::ty::{get_discriminant_value, is_isize_or_usize};
66
use rustc_ast::ast;
77
use rustc_attr::IntType;
8-
use rustc_errors::Applicability;
8+
use rustc_errors::{Applicability, SuggestionStyle};
99
use rustc_hir::def::{DefKind, Res};
1010
use rustc_hir::{BinOpKind, Expr, ExprKind};
1111
use rustc_lint::LateContext;
@@ -161,18 +161,19 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>,
161161
_ => return,
162162
};
163163

164-
let mut applicability = Applicability::HasPlaceholders;
165-
166-
let snippet = snippet_with_applicability(cx, expr.span, "x", &mut applicability);
164+
let snippet = snippet(cx, expr.span, "x");
167165
let name_of_cast_from = snippet.split(" as").next().unwrap_or("x");
168-
169-
span_lint_and_sugg(
170-
cx,
171-
CAST_POSSIBLE_TRUNCATION,
172-
expr.span,
173-
&msg,
174-
"avoid silent truncation by using",
175-
format!("{cast_to}::try_from({name_of_cast_from}).expect(\"truncation should be impossible because...\")"),
176-
applicability,
177-
);
166+
let suggestion = format!("{cast_to}::try_from({name_of_cast_from})");
167+
168+
span_lint_and_then(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg, |diag| {
169+
diag.help("if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...");
170+
diag.span_suggestion_with_style(
171+
expr.span,
172+
"... or use `try_from` and handle the error accordingly",
173+
suggestion,
174+
Applicability::Unspecified,
175+
// always show the suggestion in a separate line
176+
SuggestionStyle::ShowAlways,
177+
);
178+
});
178179
}

tests/ui/cast.stderr

Lines changed: 111 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,26 @@ error: casting `f32` to `i32` may truncate the value
4040
--> $DIR/cast.rs:24:5
4141
|
4242
LL | 1f32 as i32;
43-
| ^^^^^^^^^^^ help: avoid silent truncation by using: `i32::try_from(1f32).expect("truncation should be impossible because...")`
43+
| ^^^^^^^^^^^
4444
|
45+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
4546
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
47+
help: ... or use `try_from` and handle the error accordingly
48+
|
49+
LL | i32::try_from(1f32);
50+
| ~~~~~~~~~~~~~~~~~~~
4651

4752
error: casting `f32` to `u32` may truncate the value
4853
--> $DIR/cast.rs:25:5
4954
|
5055
LL | 1f32 as u32;
51-
| ^^^^^^^^^^^ help: avoid silent truncation by using: `u32::try_from(1f32).expect("truncation should be impossible because...")`
56+
| ^^^^^^^^^^^
57+
|
58+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
59+
help: ... or use `try_from` and handle the error accordingly
60+
|
61+
LL | u32::try_from(1f32);
62+
| ~~~~~~~~~~~~~~~~~~~
5263

5364
error: casting `f32` to `u32` may lose the sign of the value
5465
--> $DIR/cast.rs:25:5
@@ -62,31 +73,61 @@ error: casting `f64` to `f32` may truncate the value
6273
--> $DIR/cast.rs:26:5
6374
|
6475
LL | 1f64 as f32;
65-
| ^^^^^^^^^^^ help: avoid silent truncation by using: `f32::try_from(1f64).expect("truncation should be impossible because...")`
76+
| ^^^^^^^^^^^
77+
|
78+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
79+
help: ... or use `try_from` and handle the error accordingly
80+
|
81+
LL | f32::try_from(1f64);
82+
| ~~~~~~~~~~~~~~~~~~~
6683

6784
error: casting `i32` to `i8` may truncate the value
6885
--> $DIR/cast.rs:27:5
6986
|
7087
LL | 1i32 as i8;
71-
| ^^^^^^^^^^ help: avoid silent truncation by using: `i8::try_from(1i32).expect("truncation should be impossible because...")`
88+
| ^^^^^^^^^^
89+
|
90+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
91+
help: ... or use `try_from` and handle the error accordingly
92+
|
93+
LL | i8::try_from(1i32);
94+
| ~~~~~~~~~~~~~~~~~~
7295

7396
error: casting `i32` to `u8` may truncate the value
7497
--> $DIR/cast.rs:28:5
7598
|
7699
LL | 1i32 as u8;
77-
| ^^^^^^^^^^ help: avoid silent truncation by using: `u8::try_from(1i32).expect("truncation should be impossible because...")`
100+
| ^^^^^^^^^^
101+
|
102+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
103+
help: ... or use `try_from` and handle the error accordingly
104+
|
105+
LL | u8::try_from(1i32);
106+
| ~~~~~~~~~~~~~~~~~~
78107

79108
error: casting `f64` to `isize` may truncate the value
80109
--> $DIR/cast.rs:29:5
81110
|
82111
LL | 1f64 as isize;
83-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `isize::try_from(1f64).expect("truncation should be impossible because...")`
112+
| ^^^^^^^^^^^^^
113+
|
114+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
115+
help: ... or use `try_from` and handle the error accordingly
116+
|
117+
LL | isize::try_from(1f64);
118+
| ~~~~~~~~~~~~~~~~~~~~~
84119

85120
error: casting `f64` to `usize` may truncate the value
86121
--> $DIR/cast.rs:30:5
87122
|
88123
LL | 1f64 as usize;
89-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `usize::try_from(1f64).expect("truncation should be impossible because...")`
124+
| ^^^^^^^^^^^^^
125+
|
126+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
127+
help: ... or use `try_from` and handle the error accordingly
128+
|
129+
LL | usize::try_from(1f64);
130+
| ~~~~~~~~~~~~~~~~~~~~~
90131

91132
error: casting `f64` to `usize` may lose the sign of the value
92133
--> $DIR/cast.rs:30:5
@@ -142,19 +183,37 @@ error: casting `i64` to `i8` may truncate the value
142183
--> $DIR/cast.rs:108:5
143184
|
144185
LL | (-99999999999i64).min(1) as i8; // should be linted because signed
145-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: avoid silent truncation by using: `i8::try_from((-99999999999i64).min(1)).expect("truncation should be impossible because...")`
186+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
187+
|
188+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
189+
help: ... or use `try_from` and handle the error accordingly
190+
|
191+
LL | i8::try_from((-99999999999i64).min(1)); // should be linted because signed
192+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
146193

147194
error: casting `u64` to `u8` may truncate the value
148195
--> $DIR/cast.rs:120:5
149196
|
150197
LL | 999999u64.clamp(0, 256) as u8; // should still be linted
151-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: avoid silent truncation by using: `u8::try_from(999999u64.clamp(0, 256)).expect("truncation should be impossible because...")`
198+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
199+
|
200+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
201+
help: ... or use `try_from` and handle the error accordingly
202+
|
203+
LL | u8::try_from(999999u64.clamp(0, 256)); // should still be linted
204+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
152205

153206
error: casting `main::E2` to `u8` may truncate the value
154207
--> $DIR/cast.rs:141:21
155208
|
156209
LL | let _ = self as u8;
157-
| ^^^^^^^^^^ help: avoid silent truncation by using: `u8::try_from(self).expect("truncation should be impossible because...")`
210+
| ^^^^^^^^^^
211+
|
212+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
213+
help: ... or use `try_from` and handle the error accordingly
214+
|
215+
LL | let _ = u8::try_from(self);
216+
| ~~~~~~~~~~~~~~~~~~
158217

159218
error: casting `main::E2::B` to `u8` will truncate the value
160219
--> $DIR/cast.rs:142:21
@@ -168,7 +227,13 @@ error: casting `main::E5` to `i8` may truncate the value
168227
--> $DIR/cast.rs:178:21
169228
|
170229
LL | let _ = self as i8;
171-
| ^^^^^^^^^^ help: avoid silent truncation by using: `i8::try_from(self).expect("truncation should be impossible because...")`
230+
| ^^^^^^^^^^
231+
|
232+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
233+
help: ... or use `try_from` and handle the error accordingly
234+
|
235+
LL | let _ = i8::try_from(self);
236+
| ~~~~~~~~~~~~~~~~~~
172237

173238
error: casting `main::E5::A` to `i8` will truncate the value
174239
--> $DIR/cast.rs:179:21
@@ -180,31 +245,61 @@ error: casting `main::E6` to `i16` may truncate the value
180245
--> $DIR/cast.rs:193:21
181246
|
182247
LL | let _ = self as i16;
183-
| ^^^^^^^^^^^ help: avoid silent truncation by using: `i16::try_from(self).expect("truncation should be impossible because...")`
248+
| ^^^^^^^^^^^
249+
|
250+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
251+
help: ... or use `try_from` and handle the error accordingly
252+
|
253+
LL | let _ = i16::try_from(self);
254+
| ~~~~~~~~~~~~~~~~~~~
184255

185256
error: casting `main::E7` to `usize` may truncate the value on targets with 32-bit wide pointers
186257
--> $DIR/cast.rs:208:21
187258
|
188259
LL | let _ = self as usize;
189-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `usize::try_from(self).expect("truncation should be impossible because...")`
260+
| ^^^^^^^^^^^^^
261+
|
262+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
263+
help: ... or use `try_from` and handle the error accordingly
264+
|
265+
LL | let _ = usize::try_from(self);
266+
| ~~~~~~~~~~~~~~~~~~~~~
190267

191268
error: casting `main::E10` to `u16` may truncate the value
192269
--> $DIR/cast.rs:249:21
193270
|
194271
LL | let _ = self as u16;
195-
| ^^^^^^^^^^^ help: avoid silent truncation by using: `u16::try_from(self).expect("truncation should be impossible because...")`
272+
| ^^^^^^^^^^^
273+
|
274+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
275+
help: ... or use `try_from` and handle the error accordingly
276+
|
277+
LL | let _ = u16::try_from(self);
278+
| ~~~~~~~~~~~~~~~~~~~
196279

197280
error: casting `u32` to `u8` may truncate the value
198281
--> $DIR/cast.rs:257:13
199282
|
200283
LL | let c = (q >> 16) as u8;
201-
| ^^^^^^^^^^^^^^^ help: avoid silent truncation by using: `u8::try_from((q >> 16)).expect("truncation should be impossible because...")`
284+
| ^^^^^^^^^^^^^^^
285+
|
286+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
287+
help: ... or use `try_from` and handle the error accordingly
288+
|
289+
LL | let c = u8::try_from((q >> 16));
290+
| ~~~~~~~~~~~~~~~~~~~~~~~
202291

203292
error: casting `u32` to `u8` may truncate the value
204293
--> $DIR/cast.rs:260:13
205294
|
206295
LL | let c = (q / 1000) as u8;
207-
| ^^^^^^^^^^^^^^^^ help: avoid silent truncation by using: `u8::try_from((q / 1000)).expect("truncation should be impossible because...")`
296+
| ^^^^^^^^^^^^^^^^
297+
|
298+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
299+
help: ... or use `try_from` and handle the error accordingly
300+
|
301+
LL | let c = u8::try_from((q / 1000));
302+
| ~~~~~~~~~~~~~~~~~~~~~~~~
208303

209304
error: aborting due to 33 previous errors
210305

tests/ui/cast_size.stderr

Lines changed: 62 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,14 @@ error: casting `isize` to `i8` may truncate the value
22
--> $DIR/cast_size.rs:12:5
33
|
44
LL | 1isize as i8;
5-
| ^^^^^^^^^^^^ help: avoid silent truncation by using: `i8::try_from(1isize).expect("truncation should be impossible because...")`
5+
| ^^^^^^^^^^^^
66
|
7+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
78
= note: `-D clippy::cast-possible-truncation` implied by `-D warnings`
9+
help: ... or use `try_from` and handle the error accordingly
10+
|
11+
LL | i8::try_from(1isize);
12+
| ~~~~~~~~~~~~~~~~~~~~
813

914
error: casting `isize` to `f64` causes a loss of precision on targets with 64-bit wide pointers (`isize` is 64 bits wide, but `f64`'s mantissa is only 52 bits wide)
1015
--> $DIR/cast_size.rs:15:5
@@ -36,25 +41,49 @@ error: casting `isize` to `i32` may truncate the value on targets with 64-bit wi
3641
--> $DIR/cast_size.rs:19:5
3742
|
3843
LL | 1isize as i32;
39-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `i32::try_from(1isize).expect("truncation should be impossible because...")`
44+
| ^^^^^^^^^^^^^
45+
|
46+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
47+
help: ... or use `try_from` and handle the error accordingly
48+
|
49+
LL | i32::try_from(1isize);
50+
| ~~~~~~~~~~~~~~~~~~~~~
4051

4152
error: casting `isize` to `u32` may truncate the value on targets with 64-bit wide pointers
4253
--> $DIR/cast_size.rs:20:5
4354
|
4455
LL | 1isize as u32;
45-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `u32::try_from(1isize).expect("truncation should be impossible because...")`
56+
| ^^^^^^^^^^^^^
57+
|
58+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
59+
help: ... or use `try_from` and handle the error accordingly
60+
|
61+
LL | u32::try_from(1isize);
62+
| ~~~~~~~~~~~~~~~~~~~~~
4663

4764
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
4865
--> $DIR/cast_size.rs:21:5
4966
|
5067
LL | 1usize as u32;
51-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `u32::try_from(1usize).expect("truncation should be impossible because...")`
68+
| ^^^^^^^^^^^^^
69+
|
70+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
71+
help: ... or use `try_from` and handle the error accordingly
72+
|
73+
LL | u32::try_from(1usize);
74+
| ~~~~~~~~~~~~~~~~~~~~~
5275

5376
error: casting `usize` to `i32` may truncate the value on targets with 64-bit wide pointers
5477
--> $DIR/cast_size.rs:22:5
5578
|
5679
LL | 1usize as i32;
57-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `i32::try_from(1usize).expect("truncation should be impossible because...")`
80+
| ^^^^^^^^^^^^^
81+
|
82+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
83+
help: ... or use `try_from` and handle the error accordingly
84+
|
85+
LL | i32::try_from(1usize);
86+
| ~~~~~~~~~~~~~~~~~~~~~
5887

5988
error: casting `usize` to `i32` may wrap around the value on targets with 32-bit wide pointers
6089
--> $DIR/cast_size.rs:22:5
@@ -68,19 +97,37 @@ error: casting `i64` to `isize` may truncate the value on targets with 32-bit wi
6897
--> $DIR/cast_size.rs:24:5
6998
|
7099
LL | 1i64 as isize;
71-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `isize::try_from(1i64).expect("truncation should be impossible because...")`
100+
| ^^^^^^^^^^^^^
101+
|
102+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
103+
help: ... or use `try_from` and handle the error accordingly
104+
|
105+
LL | isize::try_from(1i64);
106+
| ~~~~~~~~~~~~~~~~~~~~~
72107

73108
error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers
74109
--> $DIR/cast_size.rs:25:5
75110
|
76111
LL | 1i64 as usize;
77-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `usize::try_from(1i64).expect("truncation should be impossible because...")`
112+
| ^^^^^^^^^^^^^
113+
|
114+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
115+
help: ... or use `try_from` and handle the error accordingly
116+
|
117+
LL | usize::try_from(1i64);
118+
| ~~~~~~~~~~~~~~~~~~~~~
78119

79120
error: casting `u64` to `isize` may truncate the value on targets with 32-bit wide pointers
80121
--> $DIR/cast_size.rs:26:5
81122
|
82123
LL | 1u64 as isize;
83-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `isize::try_from(1u64).expect("truncation should be impossible because...")`
124+
| ^^^^^^^^^^^^^
125+
|
126+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
127+
help: ... or use `try_from` and handle the error accordingly
128+
|
129+
LL | isize::try_from(1u64);
130+
| ~~~~~~~~~~~~~~~~~~~~~
84131

85132
error: casting `u64` to `isize` may wrap around the value on targets with 64-bit wide pointers
86133
--> $DIR/cast_size.rs:26:5
@@ -92,7 +139,13 @@ error: casting `u64` to `usize` may truncate the value on targets with 32-bit wi
92139
--> $DIR/cast_size.rs:27:5
93140
|
94141
LL | 1u64 as usize;
95-
| ^^^^^^^^^^^^^ help: avoid silent truncation by using: `usize::try_from(1u64).expect("truncation should be impossible because...")`
142+
| ^^^^^^^^^^^^^
143+
|
144+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_precision_loss)]` ...
145+
help: ... or use `try_from` and handle the error accordingly
146+
|
147+
LL | usize::try_from(1u64);
148+
| ~~~~~~~~~~~~~~~~~~~~~
96149

97150
error: casting `u32` to `isize` may wrap around the value on targets with 32-bit wide pointers
98151
--> $DIR/cast_size.rs:28:5

0 commit comments

Comments
 (0)