Skip to content

Commit 1613c54

Browse files
committed
Add usize cast to clippy::manual_bits suggestion
1 parent 190f0de commit 1613c54

File tree

4 files changed

+129
-59
lines changed

4 files changed

+129
-59
lines changed

clippy_lints/src/manual_bits.rs

+41-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
2-
use clippy_utils::source::snippet_opt;
3-
use clippy_utils::{meets_msrv, msrvs};
2+
use clippy_utils::source::snippet_with_applicability;
3+
use clippy_utils::{get_parent_expr, meets_msrv, msrvs};
44
use rustc_ast::ast::LitKind;
55
use rustc_errors::Applicability;
66
use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath};
@@ -59,16 +59,19 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits {
5959
if matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_));
6060
if let ExprKind::Lit(lit) = &other_expr.kind;
6161
if let LitKind::Int(8, _) = lit.node;
62-
6362
then {
63+
let mut app = Applicability::MachineApplicable;
64+
let ty_snip = snippet_with_applicability(cx, real_ty.span, "..", &mut app);
65+
let sugg = create_sugg(cx, expr, format!("{ty_snip}::BITS"));
66+
6467
span_lint_and_sugg(
6568
cx,
6669
MANUAL_BITS,
6770
expr.span,
6871
"usage of `mem::size_of::<T>()` to obtain the size of `T` in bits",
6972
"consider using",
70-
format!("{}::BITS", snippet_opt(cx, real_ty.span).unwrap()),
71-
Applicability::MachineApplicable,
73+
sugg,
74+
app,
7275
);
7376
}
7477
}
@@ -108,3 +111,36 @@ fn get_size_of_ty<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<
108111
}
109112
}
110113
}
114+
115+
fn create_sugg(cx: &LateContext<'_>, expr: &Expr<'_>, base_sugg: String) -> String {
116+
if let Some(parent_expr) = get_parent_expr(cx, expr) {
117+
if is_ty_conversion(parent_expr) {
118+
return base_sugg;
119+
}
120+
121+
// These expressions have precedence over casts, the suggestion therefore
122+
// needs to be wrapped into parentheses
123+
match parent_expr.kind {
124+
ExprKind::Unary(..) | ExprKind::AddrOf(..) | ExprKind::MethodCall(..) => {
125+
return format!("({base_sugg} as usize)");
126+
},
127+
_ => {},
128+
}
129+
}
130+
131+
format!("{base_sugg} as usize")
132+
}
133+
134+
fn is_ty_conversion(expr: &Expr<'_>) -> bool {
135+
if let ExprKind::Cast(..) = expr.kind {
136+
true
137+
} else if let ExprKind::MethodCall(path, [_], _) = expr.kind
138+
&& path.ident.name == sym!(try_into)
139+
{
140+
// This is only called for `usize` which implements `TryInto`. Therefore,
141+
// we don't have to check here if `self` implements the `TryInto` trait.
142+
true
143+
} else {
144+
false
145+
}
146+
}

tests/ui/manual_bits.fixed

+33-28
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,33 @@
66
use std::mem::{size_of, size_of_val};
77

88
fn main() {
9-
i8::BITS;
10-
i16::BITS;
11-
i32::BITS;
12-
i64::BITS;
13-
i128::BITS;
14-
isize::BITS;
15-
16-
u8::BITS;
17-
u16::BITS;
18-
u32::BITS;
19-
u64::BITS;
20-
u128::BITS;
21-
usize::BITS;
22-
23-
i8::BITS;
24-
i16::BITS;
25-
i32::BITS;
26-
i64::BITS;
27-
i128::BITS;
28-
isize::BITS;
29-
30-
u8::BITS;
31-
u16::BITS;
32-
u32::BITS;
33-
u64::BITS;
34-
u128::BITS;
35-
usize::BITS;
9+
i8::BITS as usize;
10+
i16::BITS as usize;
11+
i32::BITS as usize;
12+
i64::BITS as usize;
13+
i128::BITS as usize;
14+
isize::BITS as usize;
15+
16+
u8::BITS as usize;
17+
u16::BITS as usize;
18+
u32::BITS as usize;
19+
u64::BITS as usize;
20+
u128::BITS as usize;
21+
usize::BITS as usize;
22+
23+
i8::BITS as usize;
24+
i16::BITS as usize;
25+
i32::BITS as usize;
26+
i64::BITS as usize;
27+
i128::BITS as usize;
28+
isize::BITS as usize;
29+
30+
u8::BITS as usize;
31+
u16::BITS as usize;
32+
u32::BITS as usize;
33+
u64::BITS as usize;
34+
u128::BITS as usize;
35+
usize::BITS as usize;
3636

3737
size_of::<usize>() * 4;
3838
4 * size_of::<usize>();
@@ -42,7 +42,12 @@ fn main() {
4242
size_of_val(&0u32) * 8;
4343

4444
type Word = u32;
45-
Word::BITS;
45+
Word::BITS as usize;
4646
type Bool = bool;
4747
size_of::<Bool>() * 8;
48+
49+
let _: u32 = u128::BITS as u32;
50+
let _: u32 = u128::BITS.try_into().unwrap();
51+
let _ = (u128::BITS as usize).pow(5);
52+
let _ = &(u128::BITS as usize);
4853
}

tests/ui/manual_bits.rs

+5
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,9 @@ fn main() {
4545
size_of::<Word>() * 8;
4646
type Bool = bool;
4747
size_of::<Bool>() * 8;
48+
49+
let _: u32 = (size_of::<u128>() * 8) as u32;
50+
let _: u32 = (size_of::<u128>() * 8).try_into().unwrap();
51+
let _ = (size_of::<u128>() * 8).pow(5);
52+
let _ = &(size_of::<u128>() * 8);
4853
}

tests/ui/manual_bits.stderr

+50-26
Original file line numberDiff line numberDiff line change
@@ -2,153 +2,177 @@ error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
22
--> $DIR/manual_bits.rs:9:5
33
|
44
LL | size_of::<i8>() * 8;
5-
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS`
5+
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize`
66
|
77
= note: `-D clippy::manual-bits` implied by `-D warnings`
88

99
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
1010
--> $DIR/manual_bits.rs:10:5
1111
|
1212
LL | size_of::<i16>() * 8;
13-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS`
13+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize`
1414

1515
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
1616
--> $DIR/manual_bits.rs:11:5
1717
|
1818
LL | size_of::<i32>() * 8;
19-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS`
19+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize`
2020

2121
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
2222
--> $DIR/manual_bits.rs:12:5
2323
|
2424
LL | size_of::<i64>() * 8;
25-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS`
25+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize`
2626

2727
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
2828
--> $DIR/manual_bits.rs:13:5
2929
|
3030
LL | size_of::<i128>() * 8;
31-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS`
31+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize`
3232

3333
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
3434
--> $DIR/manual_bits.rs:14:5
3535
|
3636
LL | size_of::<isize>() * 8;
37-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS`
37+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize`
3838

3939
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
4040
--> $DIR/manual_bits.rs:16:5
4141
|
4242
LL | size_of::<u8>() * 8;
43-
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS`
43+
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize`
4444

4545
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
4646
--> $DIR/manual_bits.rs:17:5
4747
|
4848
LL | size_of::<u16>() * 8;
49-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS`
49+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize`
5050

5151
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
5252
--> $DIR/manual_bits.rs:18:5
5353
|
5454
LL | size_of::<u32>() * 8;
55-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS`
55+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize`
5656

5757
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
5858
--> $DIR/manual_bits.rs:19:5
5959
|
6060
LL | size_of::<u64>() * 8;
61-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS`
61+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize`
6262

6363
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
6464
--> $DIR/manual_bits.rs:20:5
6565
|
6666
LL | size_of::<u128>() * 8;
67-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
67+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize`
6868

6969
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
7070
--> $DIR/manual_bits.rs:21:5
7171
|
7272
LL | size_of::<usize>() * 8;
73-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS`
73+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize`
7474

7575
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
7676
--> $DIR/manual_bits.rs:23:5
7777
|
7878
LL | 8 * size_of::<i8>();
79-
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS`
79+
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `i8::BITS as usize`
8080

8181
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
8282
--> $DIR/manual_bits.rs:24:5
8383
|
8484
LL | 8 * size_of::<i16>();
85-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS`
85+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i16::BITS as usize`
8686

8787
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
8888
--> $DIR/manual_bits.rs:25:5
8989
|
9090
LL | 8 * size_of::<i32>();
91-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS`
91+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i32::BITS as usize`
9292

9393
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
9494
--> $DIR/manual_bits.rs:26:5
9595
|
9696
LL | 8 * size_of::<i64>();
97-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS`
97+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `i64::BITS as usize`
9898

9999
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
100100
--> $DIR/manual_bits.rs:27:5
101101
|
102102
LL | 8 * size_of::<i128>();
103-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS`
103+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `i128::BITS as usize`
104104

105105
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
106106
--> $DIR/manual_bits.rs:28:5
107107
|
108108
LL | 8 * size_of::<isize>();
109-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS`
109+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `isize::BITS as usize`
110110

111111
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
112112
--> $DIR/manual_bits.rs:30:5
113113
|
114114
LL | 8 * size_of::<u8>();
115-
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS`
115+
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `u8::BITS as usize`
116116

117117
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
118118
--> $DIR/manual_bits.rs:31:5
119119
|
120120
LL | 8 * size_of::<u16>();
121-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS`
121+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u16::BITS as usize`
122122

123123
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
124124
--> $DIR/manual_bits.rs:32:5
125125
|
126126
LL | 8 * size_of::<u32>();
127-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS`
127+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u32::BITS as usize`
128128

129129
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
130130
--> $DIR/manual_bits.rs:33:5
131131
|
132132
LL | 8 * size_of::<u64>();
133-
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS`
133+
| ^^^^^^^^^^^^^^^^^^^^ help: consider using: `u64::BITS as usize`
134134

135135
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
136136
--> $DIR/manual_bits.rs:34:5
137137
|
138138
LL | 8 * size_of::<u128>();
139-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
139+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS as usize`
140140

141141
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
142142
--> $DIR/manual_bits.rs:35:5
143143
|
144144
LL | 8 * size_of::<usize>();
145-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS`
145+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `usize::BITS as usize`
146146

147147
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
148148
--> $DIR/manual_bits.rs:45:5
149149
|
150150
LL | size_of::<Word>() * 8;
151-
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS`
151+
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `Word::BITS as usize`
152152

153-
error: aborting due to 25 previous errors
153+
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
154+
--> $DIR/manual_bits.rs:49:18
155+
|
156+
LL | let _: u32 = (size_of::<u128>() * 8) as u32;
157+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
158+
159+
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
160+
--> $DIR/manual_bits.rs:50:18
161+
|
162+
LL | let _: u32 = (size_of::<u128>() * 8).try_into().unwrap();
163+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `u128::BITS`
164+
165+
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
166+
--> $DIR/manual_bits.rs:51:13
167+
|
168+
LL | let _ = (size_of::<u128>() * 8).pow(5);
169+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)`
170+
171+
error: usage of `mem::size_of::<T>()` to obtain the size of `T` in bits
172+
--> $DIR/manual_bits.rs:52:14
173+
|
174+
LL | let _ = &(size_of::<u128>() * 8);
175+
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(u128::BITS as usize)`
176+
177+
error: aborting due to 29 previous errors
154178

0 commit comments

Comments
 (0)