Skip to content

Commit fbc121f

Browse files
authored
Rollup merge of #104363 - WaffleLapkin:bonk_box_new, r=Nilstrieb
Make `unused_allocation` lint against `Box::new` too Previously it only linted against `box` syntax, which likely won't ever be stabilized, which is pretty useless. Even now I'm not sure if it's a meaningful lint, but it's at least something 🤷 This means that code like the following will be linted against: ```rust Box::new([1, 2, 3]).len(); f(&Box::new(1)); // where f : &i32 -> () ``` The lint works by checking if a `Box::new` (or `box`) expression has an a borrow adjustment, meaning that the code that first stores the box in a variable won't be linted against: ```rust let boxed = Box::new([1, 2, 3]); // no lint boxed.len(); ```
2 parents e350fe4 + a90abd6 commit fbc121f

File tree

11 files changed

+59
-39
lines changed

11 files changed

+59
-39
lines changed

compiler/rustc_lint/src/unused.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -1349,9 +1349,8 @@ declare_lint! {
13491349
/// ### Example
13501350
///
13511351
/// ```rust
1352-
/// #![feature(box_syntax)]
13531352
/// fn main() {
1354-
/// let a = (box [1, 2, 3]).len();
1353+
/// let a = Box::new([1, 2, 3]).len();
13551354
/// }
13561355
/// ```
13571356
///
@@ -1373,6 +1372,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
13731372
fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
13741373
match e.kind {
13751374
hir::ExprKind::Box(_) => {}
1375+
hir::ExprKind::Call(path_expr, [_])
1376+
if let hir::ExprKind::Path(qpath) = &path_expr.kind
1377+
&& let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()
1378+
&& cx.tcx.is_diagnostic_item(sym::box_new, did)
1379+
=> {}
13761380
_ => return,
13771381
}
13781382

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ symbols! {
429429
borrowck_graphviz_format,
430430
borrowck_graphviz_postflow,
431431
box_free,
432+
box_new,
432433
box_patterns,
433434
box_syntax,
434435
bpf_target_feature,

library/alloc/src/boxed.rs

+1
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,7 @@ impl<T> Box<T> {
214214
#[inline(always)]
215215
#[stable(feature = "rust1", since = "1.0.0")]
216216
#[must_use]
217+
#[rustc_diagnostic_item = "box_new"]
217218
pub fn new(x: T) -> Self {
218219
#[rustc_box]
219220
Box::new(x)

library/alloc/src/tests.rs

+8-16
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use core::any::Any;
44
use core::clone::Clone;
55
use core::convert::TryInto;
66
use core::ops::Deref;
7-
use core::result::Result::{Err, Ok};
87

98
use std::boxed::Box;
109

@@ -15,32 +14,25 @@ fn test_owned_clone() {
1514
assert!(a == b);
1615
}
1716

18-
#[derive(PartialEq, Eq)]
17+
#[derive(Debug, PartialEq, Eq)]
1918
struct Test;
2019

2120
#[test]
2221
fn any_move() {
2322
let a = Box::new(8) as Box<dyn Any>;
2423
let b = Box::new(Test) as Box<dyn Any>;
2524

26-
match a.downcast::<i32>() {
27-
Ok(a) => {
28-
assert!(a == Box::new(8));
29-
}
30-
Err(..) => panic!(),
31-
}
32-
match b.downcast::<Test>() {
33-
Ok(a) => {
34-
assert!(a == Box::new(Test));
35-
}
36-
Err(..) => panic!(),
37-
}
25+
let a: Box<i32> = a.downcast::<i32>().unwrap();
26+
assert_eq!(*a, 8);
27+
28+
let b: Box<Test> = b.downcast::<Test>().unwrap();
29+
assert_eq!(*b, Test);
3830

3931
let a = Box::new(8) as Box<dyn Any>;
4032
let b = Box::new(Test) as Box<dyn Any>;
4133

42-
assert!(a.downcast::<Box<Test>>().is_err());
43-
assert!(b.downcast::<Box<i32>>().is_err());
34+
assert!(a.downcast::<Box<i32>>().is_err());
35+
assert!(b.downcast::<Box<Test>>().is_err());
4436
}
4537

4638
#[test]

tests/ui/issues/issue-3029.rs

-2
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// error-pattern:so long
33
// ignore-emscripten no processes
44

5-
#![allow(unused_allocation)]
65
#![allow(unreachable_code)]
7-
#![allow(unused_variables)]
86

97
fn main() {
108
let mut x = Vec::new();

tests/ui/iterators/into-iter-on-arrays-lint.fixed

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// run-rustfix
33
// rustfix-only-machine-applicable
44

5-
#[allow(unused_must_use)]
5+
#[allow(unused_must_use, unused_allocation)]
66
fn main() {
77
let small = [1, 2];
88
let big = [0u8; 33];

tests/ui/iterators/into-iter-on-arrays-lint.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// run-rustfix
33
// rustfix-only-machine-applicable
44

5-
#[allow(unused_must_use)]
5+
#[allow(unused_must_use, unused_allocation)]
66
fn main() {
77
let small = [1, 2];
88
let big = [0u8; 33];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#![feature(rustc_attrs, stmt_expr_attributes)]
2+
#![deny(unused_allocation)]
3+
4+
fn main() {
5+
_ = (#[rustc_box] Box::new([1])).len(); //~ error: unnecessary allocation, use `&` instead
6+
_ = Box::new([1]).len(); //~ error: unnecessary allocation, use `&` instead
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error: unnecessary allocation, use `&` instead
2+
--> $DIR/unused-allocation.rs:5:9
3+
|
4+
LL | _ = (#[rustc_box] Box::new([1])).len();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/unused-allocation.rs:2:9
9+
|
10+
LL | #![deny(unused_allocation)]
11+
| ^^^^^^^^^^^^^^^^^
12+
13+
error: unnecessary allocation, use `&` instead
14+
--> $DIR/unused-allocation.rs:6:9
15+
|
16+
LL | _ = Box::new([1]).len();
17+
| ^^^^^^^^^^^^^
18+
19+
error: aborting due to 2 previous errors
20+

tests/ui/self/arbitrary_self_types_trait.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// run-pass
2+
#![allow(unused_allocation)]
23

34
use std::rc::Rc;
45

@@ -13,7 +14,7 @@ impl Trait for Vec<i32> {
1314
}
1415

1516
fn main() {
16-
let v = vec![1,2,3];
17+
let v = vec![1, 2, 3];
1718

18-
assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method());
19+
assert_eq!(&[1, 2, 3], Box::new(Rc::new(v)).trait_method());
1920
}

tests/ui/structs-enums/align-struct.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-pass
2-
#![allow(dead_code)]
2+
#![allow(dead_code, unused_allocation)]
33

44
use std::mem;
55

@@ -20,7 +20,6 @@ struct AlignMany(i32);
2020

2121
// Raising alignment may not alter size.
2222
#[repr(align(8))]
23-
#[allow(dead_code)]
2423
struct Align8Many {
2524
a: i32,
2625
b: i32,
@@ -29,9 +28,8 @@ struct Align8Many {
2928
}
3029

3130
enum Enum {
32-
#[allow(dead_code)]
3331
A(i32),
34-
B(Align16)
32+
B(Align16),
3533
}
3634

3735
// Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
@@ -73,7 +71,7 @@ struct AlignLarge {
7371

7472
union UnionContainsAlign {
7573
a: Align16,
76-
b: f32
74+
b: f32,
7775
}
7876

7977
impl Align16 {
@@ -158,7 +156,7 @@ pub fn main() {
158156
// Note that the size of Nested may change if struct field re-ordering is enabled
159157
assert_eq!(mem::align_of::<Nested>(), 16);
160158
assert_eq!(mem::size_of::<Nested>(), 48);
161-
let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
159+
let a = Nested { a: 1, b: 2, c: Align16(3), d: 4 };
162160
assert_eq!(mem::align_of_val(&a), 16);
163161
assert_eq!(mem::align_of_val(&a.b), 4);
164162
assert_eq!(mem::align_of_val(&a.c), 16);
@@ -179,8 +177,8 @@ pub fn main() {
179177
assert_eq!(a.0, 15);
180178
assert_eq!(mem::align_of_val(a), 16);
181179
assert_eq!(mem::size_of_val(a), 16);
182-
},
183-
_ => ()
180+
}
181+
_ => (),
184182
}
185183
assert!(is_aligned_to(&e, 16));
186184

@@ -197,8 +195,8 @@ pub fn main() {
197195
}
198196

199197
// arrays of aligned elements should also be aligned
200-
assert_eq!(mem::align_of::<[Align16;2]>(), 16);
201-
assert_eq!(mem::size_of::<[Align16;2]>(), 32);
198+
assert_eq!(mem::align_of::<[Align16; 2]>(), 16);
199+
assert_eq!(mem::size_of::<[Align16; 2]>(), 32);
202200

203201
let a = [Align16(0), Align16(1)];
204202
assert_eq!(mem::align_of_val(&a[0]), 16);
@@ -209,7 +207,7 @@ pub fn main() {
209207
assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
210208

211209
// check heap array is aligned
212-
let a = vec!(Align16(0), Align16(1));
210+
let a = vec![Align16(0), Align16(1)];
213211
assert_eq!(mem::align_of_val(&a[0]), 16);
214212
assert_eq!(mem::align_of_val(&a[1]), 16);
215213

@@ -224,16 +222,14 @@ pub fn main() {
224222

225223
assert_eq!(mem::align_of::<AlignContainsPacked4C>(), 16);
226224
assert_eq!(mem::size_of::<AlignContainsPacked4C>(), 32);
227-
let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 };
225+
let a = AlignContainsPacked4C { a: Packed4C { a: 1, b: 2 }, b: 3 };
228226
assert_eq!(mem::align_of_val(&a), 16);
229227
assert_eq!(mem::align_of_val(&a.a), 4);
230228
assert_eq!(mem::align_of_val(&a.b), mem::align_of::<u64>());
231229
assert_eq!(mem::size_of_val(&a), 32);
232230
assert!(is_aligned_to(&a, 16));
233231

234-
let mut large = Box::new(AlignLarge {
235-
stuff: [0; 0x10000],
236-
});
232+
let mut large = Box::new(AlignLarge { stuff: [0; 0x10000] });
237233
large.stuff[0] = 132;
238234
*large.stuff.last_mut().unwrap() = 102;
239235
assert_eq!(large.stuff[0], 132);

0 commit comments

Comments
 (0)