Skip to content

Commit 92ca7c9

Browse files
committed
Auto merge of rust-lang#11287 - Centri3:rust-lang#11285, r=llogiq
[`cast_lossless`]: Suggest type alias instead of the aliased type Fixes rust-lang#11285 Still an issue with the "from" side, i.e., `I8::from(1) as I64` shows as `i8 to I64`, but this should be ok. Not possible to reliably fix currently anyway. changelog: [`cast_lossless`]: Suggest type alias instead of the aliased type
2 parents 3a14911 + 244d7da commit 92ca7c9

11 files changed

+126
-58
lines changed

clippy_lints/src/casts/cast_lossless.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use clippy_config::msrvs::{self, Msrv};
22
use clippy_utils::diagnostics::span_lint_and_sugg;
33
use clippy_utils::in_constant;
4-
use clippy_utils::source::snippet_opt;
4+
use clippy_utils::source::{snippet_opt, snippet_with_applicability};
55
use clippy_utils::ty::is_isize_or_usize;
66
use rustc_errors::Applicability;
7-
use rustc_hir::{Expr, ExprKind};
7+
use rustc_hir::{Expr, ExprKind, QPath, TyKind};
88
use rustc_lint::LateContext;
99
use rustc_middle::ty::{self, FloatTy, Ty};
1010

@@ -16,6 +16,7 @@ pub(super) fn check(
1616
cast_op: &Expr<'_>,
1717
cast_from: Ty<'_>,
1818
cast_to: Ty<'_>,
19+
cast_to_hir: &rustc_hir::Ty<'_>,
1920
msrv: &Msrv,
2021
) {
2122
if !should_lint(cx, expr, cast_from, cast_to, msrv) {
@@ -24,11 +25,11 @@ pub(super) fn check(
2425

2526
// The suggestion is to use a function call, so if the original expression
2627
// has parens on the outside, they are no longer needed.
27-
let mut applicability = Applicability::MachineApplicable;
28+
let mut app = Applicability::MachineApplicable;
2829
let opt = snippet_opt(cx, cast_op.span.source_callsite());
2930
let sugg = opt.as_ref().map_or_else(
3031
|| {
31-
applicability = Applicability::HasPlaceholders;
32+
app = Applicability::HasPlaceholders;
3233
".."
3334
},
3435
|snip| {
@@ -40,10 +41,27 @@ pub(super) fn check(
4041
},
4142
);
4243

44+
// Display the type alias instead of the aliased type. Fixes #11285
45+
//
46+
// FIXME: Once `lazy_type_alias` is stabilized(?) we should use `rustc_middle` types instead,
47+
// this will allow us to display the right type with `cast_from` as well.
48+
let cast_to_fmt = if let TyKind::Path(QPath::Resolved(None, path)) = cast_to_hir.kind
49+
// It's a bit annoying but the turbofish is optional for types. A type in an `as` cast
50+
// shouldn't have these if they're primitives, which are the only things we deal with.
51+
//
52+
// This could be removed for performance if this check is determined to have a pretty major
53+
// effect.
54+
&& path.segments.iter().all(|segment| segment.args.is_none())
55+
{
56+
snippet_with_applicability(cx, cast_to_hir.span, "..", &mut app)
57+
} else {
58+
cast_to.to_string().into()
59+
};
60+
4361
let message = if cast_from.is_bool() {
44-
format!("casting `{cast_from:}` to `{cast_to:}` is more cleanly stated with `{cast_to:}::from(_)`")
62+
format!("casting `{cast_from}` to `{cast_to_fmt}` is more cleanly stated with `{cast_to_fmt}::from(_)`")
4563
} else {
46-
format!("casting `{cast_from}` to `{cast_to}` may become silently lossy if you later change the type")
64+
format!("casting `{cast_from}` to `{cast_to_fmt}` may become silently lossy if you later change the type")
4765
};
4866

4967
span_lint_and_sugg(
@@ -52,8 +70,8 @@ pub(super) fn check(
5270
expr.span,
5371
&message,
5472
"try",
55-
format!("{cast_to}::from({sugg})"),
56-
applicability,
73+
format!("{cast_to_fmt}::from({sugg})"),
74+
app,
5775
);
5876
}
5977

clippy_lints/src/casts/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -791,7 +791,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
791791
cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
792792
cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
793793
}
794-
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
794+
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, cast_to_hir, &self.msrv);
795795
cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
796796
}
797797

tests/ui/cast_lossless_bool.fixed

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![allow(dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type U8 = u8;
5+
46
fn main() {
57
// Test clippy::cast_lossless with casts to integer types
68
let _ = u8::from(true);
@@ -19,6 +21,8 @@ fn main() {
1921

2022
// Test with an expression wrapped in parens
2123
let _ = u16::from(true | false);
24+
25+
let _ = U8::from(true);
2226
}
2327

2428
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,

tests/ui/cast_lossless_bool.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![allow(dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type U8 = u8;
5+
46
fn main() {
57
// Test clippy::cast_lossless with casts to integer types
68
let _ = true as u8;
@@ -19,6 +21,8 @@ fn main() {
1921

2022
// Test with an expression wrapped in parens
2123
let _ = (true | false) as u16;
24+
25+
let _ = true as U8;
2226
}
2327

2428
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,

tests/ui/cast_lossless_bool.stderr

+21-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
2-
--> tests/ui/cast_lossless_bool.rs:6:13
2+
--> tests/ui/cast_lossless_bool.rs:8:13
33
|
44
LL | let _ = true as u8;
55
| ^^^^^^^^^^ help: try: `u8::from(true)`
@@ -8,82 +8,88 @@ LL | let _ = true as u8;
88
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
99

1010
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
11-
--> tests/ui/cast_lossless_bool.rs:7:13
11+
--> tests/ui/cast_lossless_bool.rs:9:13
1212
|
1313
LL | let _ = true as u16;
1414
| ^^^^^^^^^^^ help: try: `u16::from(true)`
1515

1616
error: casting `bool` to `u32` is more cleanly stated with `u32::from(_)`
17-
--> tests/ui/cast_lossless_bool.rs:8:13
17+
--> tests/ui/cast_lossless_bool.rs:10:13
1818
|
1919
LL | let _ = true as u32;
2020
| ^^^^^^^^^^^ help: try: `u32::from(true)`
2121

2222
error: casting `bool` to `u64` is more cleanly stated with `u64::from(_)`
23-
--> tests/ui/cast_lossless_bool.rs:9:13
23+
--> tests/ui/cast_lossless_bool.rs:11:13
2424
|
2525
LL | let _ = true as u64;
2626
| ^^^^^^^^^^^ help: try: `u64::from(true)`
2727

2828
error: casting `bool` to `u128` is more cleanly stated with `u128::from(_)`
29-
--> tests/ui/cast_lossless_bool.rs:10:13
29+
--> tests/ui/cast_lossless_bool.rs:12:13
3030
|
3131
LL | let _ = true as u128;
3232
| ^^^^^^^^^^^^ help: try: `u128::from(true)`
3333

3434
error: casting `bool` to `usize` is more cleanly stated with `usize::from(_)`
35-
--> tests/ui/cast_lossless_bool.rs:11:13
35+
--> tests/ui/cast_lossless_bool.rs:13:13
3636
|
3737
LL | let _ = true as usize;
3838
| ^^^^^^^^^^^^^ help: try: `usize::from(true)`
3939

4040
error: casting `bool` to `i8` is more cleanly stated with `i8::from(_)`
41-
--> tests/ui/cast_lossless_bool.rs:13:13
41+
--> tests/ui/cast_lossless_bool.rs:15:13
4242
|
4343
LL | let _ = true as i8;
4444
| ^^^^^^^^^^ help: try: `i8::from(true)`
4545

4646
error: casting `bool` to `i16` is more cleanly stated with `i16::from(_)`
47-
--> tests/ui/cast_lossless_bool.rs:14:13
47+
--> tests/ui/cast_lossless_bool.rs:16:13
4848
|
4949
LL | let _ = true as i16;
5050
| ^^^^^^^^^^^ help: try: `i16::from(true)`
5151

5252
error: casting `bool` to `i32` is more cleanly stated with `i32::from(_)`
53-
--> tests/ui/cast_lossless_bool.rs:15:13
53+
--> tests/ui/cast_lossless_bool.rs:17:13
5454
|
5555
LL | let _ = true as i32;
5656
| ^^^^^^^^^^^ help: try: `i32::from(true)`
5757

5858
error: casting `bool` to `i64` is more cleanly stated with `i64::from(_)`
59-
--> tests/ui/cast_lossless_bool.rs:16:13
59+
--> tests/ui/cast_lossless_bool.rs:18:13
6060
|
6161
LL | let _ = true as i64;
6262
| ^^^^^^^^^^^ help: try: `i64::from(true)`
6363

6464
error: casting `bool` to `i128` is more cleanly stated with `i128::from(_)`
65-
--> tests/ui/cast_lossless_bool.rs:17:13
65+
--> tests/ui/cast_lossless_bool.rs:19:13
6666
|
6767
LL | let _ = true as i128;
6868
| ^^^^^^^^^^^^ help: try: `i128::from(true)`
6969

7070
error: casting `bool` to `isize` is more cleanly stated with `isize::from(_)`
71-
--> tests/ui/cast_lossless_bool.rs:18:13
71+
--> tests/ui/cast_lossless_bool.rs:20:13
7272
|
7373
LL | let _ = true as isize;
7474
| ^^^^^^^^^^^^^ help: try: `isize::from(true)`
7575

7676
error: casting `bool` to `u16` is more cleanly stated with `u16::from(_)`
77-
--> tests/ui/cast_lossless_bool.rs:21:13
77+
--> tests/ui/cast_lossless_bool.rs:23:13
7878
|
7979
LL | let _ = (true | false) as u16;
8080
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
8181

82+
error: casting `bool` to `U8` is more cleanly stated with `U8::from(_)`
83+
--> tests/ui/cast_lossless_bool.rs:25:13
84+
|
85+
LL | let _ = true as U8;
86+
| ^^^^^^^^^^ help: try: `U8::from(true)`
87+
8288
error: casting `bool` to `u8` is more cleanly stated with `u8::from(_)`
83-
--> tests/ui/cast_lossless_bool.rs:49:13
89+
--> tests/ui/cast_lossless_bool.rs:53:13
8490
|
8591
LL | let _ = true as u8;
8692
| ^^^^^^^^^^ help: try: `u8::from(true)`
8793

88-
error: aborting due to 14 previous errors
94+
error: aborting due to 15 previous errors
8995

tests/ui/cast_lossless_float.fixed

+5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type F32 = f32;
5+
type F64 = f64;
6+
47
fn main() {
58
// Test clippy::cast_lossless with casts to floating-point types
69
let x0 = 1i8;
710
let _ = f32::from(x0);
811
let _ = f64::from(x0);
12+
let _ = F32::from(x0);
13+
let _ = F64::from(x0);
914
let x1 = 1u8;
1015
let _ = f32::from(x1);
1116
let _ = f64::from(x1);

tests/ui/cast_lossless_float.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type F32 = f32;
5+
type F64 = f64;
6+
47
fn main() {
58
// Test clippy::cast_lossless with casts to floating-point types
69
let x0 = 1i8;
710
let _ = x0 as f32;
811
let _ = x0 as f64;
12+
let _ = x0 as F32;
13+
let _ = x0 as F64;
914
let x1 = 1u8;
1015
let _ = x1 as f32;
1116
let _ = x1 as f64;

tests/ui/cast_lossless_float.stderr

+24-12
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: casting `i8` to `f32` may become silently lossy if you later change the type
2-
--> tests/ui/cast_lossless_float.rs:7:13
2+
--> tests/ui/cast_lossless_float.rs:10:13
33
|
44
LL | let _ = x0 as f32;
55
| ^^^^^^^^^ help: try: `f32::from(x0)`
@@ -8,64 +8,76 @@ LL | let _ = x0 as f32;
88
= help: to override `-D warnings` add `#[allow(clippy::cast_lossless)]`
99

1010
error: casting `i8` to `f64` may become silently lossy if you later change the type
11-
--> tests/ui/cast_lossless_float.rs:8:13
11+
--> tests/ui/cast_lossless_float.rs:11:13
1212
|
1313
LL | let _ = x0 as f64;
1414
| ^^^^^^^^^ help: try: `f64::from(x0)`
1515

16+
error: casting `i8` to `F32` may become silently lossy if you later change the type
17+
--> tests/ui/cast_lossless_float.rs:12:13
18+
|
19+
LL | let _ = x0 as F32;
20+
| ^^^^^^^^^ help: try: `F32::from(x0)`
21+
22+
error: casting `i8` to `F64` may become silently lossy if you later change the type
23+
--> tests/ui/cast_lossless_float.rs:13:13
24+
|
25+
LL | let _ = x0 as F64;
26+
| ^^^^^^^^^ help: try: `F64::from(x0)`
27+
1628
error: casting `u8` to `f32` may become silently lossy if you later change the type
17-
--> tests/ui/cast_lossless_float.rs:10:13
29+
--> tests/ui/cast_lossless_float.rs:15:13
1830
|
1931
LL | let _ = x1 as f32;
2032
| ^^^^^^^^^ help: try: `f32::from(x1)`
2133

2234
error: casting `u8` to `f64` may become silently lossy if you later change the type
23-
--> tests/ui/cast_lossless_float.rs:11:13
35+
--> tests/ui/cast_lossless_float.rs:16:13
2436
|
2537
LL | let _ = x1 as f64;
2638
| ^^^^^^^^^ help: try: `f64::from(x1)`
2739

2840
error: casting `i16` to `f32` may become silently lossy if you later change the type
29-
--> tests/ui/cast_lossless_float.rs:13:13
41+
--> tests/ui/cast_lossless_float.rs:18:13
3042
|
3143
LL | let _ = x2 as f32;
3244
| ^^^^^^^^^ help: try: `f32::from(x2)`
3345

3446
error: casting `i16` to `f64` may become silently lossy if you later change the type
35-
--> tests/ui/cast_lossless_float.rs:14:13
47+
--> tests/ui/cast_lossless_float.rs:19:13
3648
|
3749
LL | let _ = x2 as f64;
3850
| ^^^^^^^^^ help: try: `f64::from(x2)`
3951

4052
error: casting `u16` to `f32` may become silently lossy if you later change the type
41-
--> tests/ui/cast_lossless_float.rs:16:13
53+
--> tests/ui/cast_lossless_float.rs:21:13
4254
|
4355
LL | let _ = x3 as f32;
4456
| ^^^^^^^^^ help: try: `f32::from(x3)`
4557

4658
error: casting `u16` to `f64` may become silently lossy if you later change the type
47-
--> tests/ui/cast_lossless_float.rs:17:13
59+
--> tests/ui/cast_lossless_float.rs:22:13
4860
|
4961
LL | let _ = x3 as f64;
5062
| ^^^^^^^^^ help: try: `f64::from(x3)`
5163

5264
error: casting `i32` to `f64` may become silently lossy if you later change the type
53-
--> tests/ui/cast_lossless_float.rs:19:13
65+
--> tests/ui/cast_lossless_float.rs:24:13
5466
|
5567
LL | let _ = x4 as f64;
5668
| ^^^^^^^^^ help: try: `f64::from(x4)`
5769

5870
error: casting `u32` to `f64` may become silently lossy if you later change the type
59-
--> tests/ui/cast_lossless_float.rs:21:13
71+
--> tests/ui/cast_lossless_float.rs:26:13
6072
|
6173
LL | let _ = x5 as f64;
6274
| ^^^^^^^^^ help: try: `f64::from(x5)`
6375

6476
error: casting `f32` to `f64` may become silently lossy if you later change the type
65-
--> tests/ui/cast_lossless_float.rs:24:13
77+
--> tests/ui/cast_lossless_float.rs:29:13
6678
|
6779
LL | let _ = 1.0f32 as f64;
6880
| ^^^^^^^^^^^^^ help: try: `f64::from(1.0f32)`
6981

70-
error: aborting due to 11 previous errors
82+
error: aborting due to 13 previous errors
7183

tests/ui/cast_lossless_integer.fixed

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type I64 = i64;
5+
46
fn main() {
57
// Test clippy::cast_lossless with casts to integer types
68
let _ = i16::from(1i8);
@@ -24,6 +26,8 @@ fn main() {
2426

2527
// Test with an expression wrapped in parens
2628
let _ = u16::from(1u8 + 1u8);
29+
30+
let _ = I64::from(1i8);
2731
}
2832

2933
// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,

tests/ui/cast_lossless_integer.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#![allow(clippy::no_effect, clippy::unnecessary_operation, dead_code)]
22
#![warn(clippy::cast_lossless)]
33

4+
type I64 = i64;
5+
46
fn main() {
57
// Test clippy::cast_lossless with casts to integer types
68
let _ = 1i8 as i16;
@@ -24,6 +26,8 @@ fn main() {
2426

2527
// Test with an expression wrapped in parens
2628
let _ = (1u8 + 1u8) as u16;
29+
30+
let _ = 1i8 as I64;
2731
}
2832

2933
// The lint would suggest using `f64::from(input)` here but the `XX::from` function is not const,

0 commit comments

Comments
 (0)