about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-03-11 15:43:11 +0100
committerGitHub <noreply@github.com>2023-03-11 15:43:11 +0100
commitfbc121fdfd30daad5b99bae1aac4d6bd4d42ba02 (patch)
tree20a69adee2d22412e2e043ff363156dde11ef4f5
parente350fe4e608b653da47e8012d13ef701613e717b (diff)
parenta90abd64fbb0764007d93d60823161f05f564259 (diff)
downloadrust-fbc121fdfd30daad5b99bae1aac4d6bd4d42ba02.tar.gz
rust-fbc121fdfd30daad5b99bae1aac4d6bd4d42ba02.zip
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 :shrug:

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();
```
-rw-r--r--compiler/rustc_lint/src/unused.rs8
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/alloc/src/boxed.rs1
-rw-r--r--library/alloc/src/tests.rs24
-rw-r--r--tests/ui/issues/issue-3029.rs2
-rw-r--r--tests/ui/iterators/into-iter-on-arrays-lint.fixed2
-rw-r--r--tests/ui/iterators/into-iter-on-arrays-lint.rs2
-rw-r--r--tests/ui/lint/unused/unused-allocation.rs7
-rw-r--r--tests/ui/lint/unused/unused-allocation.stderr20
-rw-r--r--tests/ui/self/arbitrary_self_types_trait.rs5
-rw-r--r--tests/ui/structs-enums/align-struct.rs26
11 files changed, 59 insertions, 39 deletions
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index c43162f6325..2ba365e298f 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1349,9 +1349,8 @@ declare_lint! {
     /// ### Example
     ///
     /// ```rust
-    /// #![feature(box_syntax)]
     /// fn main() {
-    ///     let a = (box [1, 2, 3]).len();
+    ///     let a = Box::new([1, 2, 3]).len();
     /// }
     /// ```
     ///
@@ -1373,6 +1372,11 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
     fn check_expr(&mut self, cx: &LateContext<'_>, e: &hir::Expr<'_>) {
         match e.kind {
             hir::ExprKind::Box(_) => {}
+            hir::ExprKind::Call(path_expr, [_])
+                if let hir::ExprKind::Path(qpath) = &path_expr.kind
+                && let Some(did) = cx.qpath_res(qpath, path_expr.hir_id).opt_def_id()
+                && cx.tcx.is_diagnostic_item(sym::box_new, did)
+                => {}
             _ => return,
         }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4e626fd9f30..bf27bd6c5ad 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -429,6 +429,7 @@ symbols! {
         borrowck_graphviz_format,
         borrowck_graphviz_postflow,
         box_free,
+        box_new,
         box_patterns,
         box_syntax,
         bpf_target_feature,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 44a37899007..241b11c3f5f 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -214,6 +214,7 @@ impl<T> Box<T> {
     #[inline(always)]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
+    #[rustc_diagnostic_item = "box_new"]
     pub fn new(x: T) -> Self {
         #[rustc_box]
         Box::new(x)
diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs
index 299ed156a5d..b1d3a9fa8ac 100644
--- a/library/alloc/src/tests.rs
+++ b/library/alloc/src/tests.rs
@@ -4,7 +4,6 @@ use core::any::Any;
 use core::clone::Clone;
 use core::convert::TryInto;
 use core::ops::Deref;
-use core::result::Result::{Err, Ok};
 
 use std::boxed::Box;
 
@@ -15,7 +14,7 @@ fn test_owned_clone() {
     assert!(a == b);
 }
 
-#[derive(PartialEq, Eq)]
+#[derive(Debug, PartialEq, Eq)]
 struct Test;
 
 #[test]
@@ -23,24 +22,17 @@ fn any_move() {
     let a = Box::new(8) as Box<dyn Any>;
     let b = Box::new(Test) as Box<dyn Any>;
 
-    match a.downcast::<i32>() {
-        Ok(a) => {
-            assert!(a == Box::new(8));
-        }
-        Err(..) => panic!(),
-    }
-    match b.downcast::<Test>() {
-        Ok(a) => {
-            assert!(a == Box::new(Test));
-        }
-        Err(..) => panic!(),
-    }
+    let a: Box<i32> = a.downcast::<i32>().unwrap();
+    assert_eq!(*a, 8);
+
+    let b: Box<Test> = b.downcast::<Test>().unwrap();
+    assert_eq!(*b, Test);
 
     let a = Box::new(8) as Box<dyn Any>;
     let b = Box::new(Test) as Box<dyn Any>;
 
-    assert!(a.downcast::<Box<Test>>().is_err());
-    assert!(b.downcast::<Box<i32>>().is_err());
+    assert!(a.downcast::<Box<i32>>().is_err());
+    assert!(b.downcast::<Box<Test>>().is_err());
 }
 
 #[test]
diff --git a/tests/ui/issues/issue-3029.rs b/tests/ui/issues/issue-3029.rs
index a5d30960a4c..43c8a0a23fb 100644
--- a/tests/ui/issues/issue-3029.rs
+++ b/tests/ui/issues/issue-3029.rs
@@ -2,9 +2,7 @@
 // error-pattern:so long
 // ignore-emscripten no processes
 
-#![allow(unused_allocation)]
 #![allow(unreachable_code)]
-#![allow(unused_variables)]
 
 fn main() {
     let mut x = Vec::new();
diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.fixed b/tests/ui/iterators/into-iter-on-arrays-lint.fixed
index 6e02a7024b9..5b91aaf9ea5 100644
--- a/tests/ui/iterators/into-iter-on-arrays-lint.fixed
+++ b/tests/ui/iterators/into-iter-on-arrays-lint.fixed
@@ -2,7 +2,7 @@
 // run-rustfix
 // rustfix-only-machine-applicable
 
-#[allow(unused_must_use)]
+#[allow(unused_must_use, unused_allocation)]
 fn main() {
     let small = [1, 2];
     let big = [0u8; 33];
diff --git a/tests/ui/iterators/into-iter-on-arrays-lint.rs b/tests/ui/iterators/into-iter-on-arrays-lint.rs
index 582d5cadd06..25b0cef73d7 100644
--- a/tests/ui/iterators/into-iter-on-arrays-lint.rs
+++ b/tests/ui/iterators/into-iter-on-arrays-lint.rs
@@ -2,7 +2,7 @@
 // run-rustfix
 // rustfix-only-machine-applicable
 
-#[allow(unused_must_use)]
+#[allow(unused_must_use, unused_allocation)]
 fn main() {
     let small = [1, 2];
     let big = [0u8; 33];
diff --git a/tests/ui/lint/unused/unused-allocation.rs b/tests/ui/lint/unused/unused-allocation.rs
new file mode 100644
index 00000000000..c1a6f5ceaf1
--- /dev/null
+++ b/tests/ui/lint/unused/unused-allocation.rs
@@ -0,0 +1,7 @@
+#![feature(rustc_attrs, stmt_expr_attributes)]
+#![deny(unused_allocation)]
+
+fn main() {
+    _ = (#[rustc_box] Box::new([1])).len(); //~ error: unnecessary allocation, use `&` instead
+    _ = Box::new([1]).len(); //~ error: unnecessary allocation, use `&` instead
+}
diff --git a/tests/ui/lint/unused/unused-allocation.stderr b/tests/ui/lint/unused/unused-allocation.stderr
new file mode 100644
index 00000000000..c9ccfbd30e5
--- /dev/null
+++ b/tests/ui/lint/unused/unused-allocation.stderr
@@ -0,0 +1,20 @@
+error: unnecessary allocation, use `&` instead
+  --> $DIR/unused-allocation.rs:5:9
+   |
+LL |     _ = (#[rustc_box] Box::new([1])).len();
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-allocation.rs:2:9
+   |
+LL | #![deny(unused_allocation)]
+   |         ^^^^^^^^^^^^^^^^^
+
+error: unnecessary allocation, use `&` instead
+  --> $DIR/unused-allocation.rs:6:9
+   |
+LL |     _ = Box::new([1]).len();
+   |         ^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/self/arbitrary_self_types_trait.rs b/tests/ui/self/arbitrary_self_types_trait.rs
index 973c7cae85a..c4651ec7177 100644
--- a/tests/ui/self/arbitrary_self_types_trait.rs
+++ b/tests/ui/self/arbitrary_self_types_trait.rs
@@ -1,4 +1,5 @@
 // run-pass
+#![allow(unused_allocation)]
 
 use std::rc::Rc;
 
@@ -13,7 +14,7 @@ impl Trait for Vec<i32> {
 }
 
 fn main() {
-    let v = vec![1,2,3];
+    let v = vec![1, 2, 3];
 
-    assert_eq!(&[1,2,3], Box::new(Rc::new(v)).trait_method());
+    assert_eq!(&[1, 2, 3], Box::new(Rc::new(v)).trait_method());
 }
diff --git a/tests/ui/structs-enums/align-struct.rs b/tests/ui/structs-enums/align-struct.rs
index f5418e754b2..54092542f98 100644
--- a/tests/ui/structs-enums/align-struct.rs
+++ b/tests/ui/structs-enums/align-struct.rs
@@ -1,5 +1,5 @@
 // run-pass
-#![allow(dead_code)]
+#![allow(dead_code, unused_allocation)]
 
 use std::mem;
 
@@ -20,7 +20,6 @@ struct AlignMany(i32);
 
 // Raising alignment may not alter size.
 #[repr(align(8))]
-#[allow(dead_code)]
 struct Align8Many {
     a: i32,
     b: i32,
@@ -29,9 +28,8 @@ struct Align8Many {
 }
 
 enum Enum {
-    #[allow(dead_code)]
     A(i32),
-    B(Align16)
+    B(Align16),
 }
 
 // Nested alignment - use `#[repr(C)]` to suppress field reordering for sizeof test
@@ -73,7 +71,7 @@ struct AlignLarge {
 
 union UnionContainsAlign {
     a: Align16,
-    b: f32
+    b: f32,
 }
 
 impl Align16 {
@@ -158,7 +156,7 @@ pub fn main() {
     // Note that the size of Nested may change if struct field re-ordering is enabled
     assert_eq!(mem::align_of::<Nested>(), 16);
     assert_eq!(mem::size_of::<Nested>(), 48);
-    let a = Nested{ a: 1, b: 2, c: Align16(3), d: 4};
+    let a = Nested { a: 1, b: 2, c: Align16(3), d: 4 };
     assert_eq!(mem::align_of_val(&a), 16);
     assert_eq!(mem::align_of_val(&a.b), 4);
     assert_eq!(mem::align_of_val(&a.c), 16);
@@ -179,8 +177,8 @@ pub fn main() {
             assert_eq!(a.0, 15);
             assert_eq!(mem::align_of_val(a), 16);
             assert_eq!(mem::size_of_val(a), 16);
-        },
-        _ => ()
+        }
+        _ => (),
     }
     assert!(is_aligned_to(&e, 16));
 
@@ -197,8 +195,8 @@ pub fn main() {
     }
 
     // arrays of aligned elements should also be aligned
-    assert_eq!(mem::align_of::<[Align16;2]>(), 16);
-    assert_eq!(mem::size_of::<[Align16;2]>(), 32);
+    assert_eq!(mem::align_of::<[Align16; 2]>(), 16);
+    assert_eq!(mem::size_of::<[Align16; 2]>(), 32);
 
     let a = [Align16(0), Align16(1)];
     assert_eq!(mem::align_of_val(&a[0]), 16);
@@ -209,7 +207,7 @@ pub fn main() {
     assert_eq!(mem::align_of_val(Box::new(Align16(0)).as_ref()), 16);
 
     // check heap array is aligned
-    let a = vec!(Align16(0), Align16(1));
+    let a = vec![Align16(0), Align16(1)];
     assert_eq!(mem::align_of_val(&a[0]), 16);
     assert_eq!(mem::align_of_val(&a[1]), 16);
 
@@ -224,16 +222,14 @@ pub fn main() {
 
     assert_eq!(mem::align_of::<AlignContainsPacked4C>(), 16);
     assert_eq!(mem::size_of::<AlignContainsPacked4C>(), 32);
-    let a = AlignContainsPacked4C { a: Packed4C{ a: 1, b: 2 }, b: 3 };
+    let a = AlignContainsPacked4C { a: Packed4C { a: 1, b: 2 }, b: 3 };
     assert_eq!(mem::align_of_val(&a), 16);
     assert_eq!(mem::align_of_val(&a.a), 4);
     assert_eq!(mem::align_of_val(&a.b), mem::align_of::<u64>());
     assert_eq!(mem::size_of_val(&a), 32);
     assert!(is_aligned_to(&a, 16));
 
-    let mut large = Box::new(AlignLarge {
-        stuff: [0; 0x10000],
-    });
+    let mut large = Box::new(AlignLarge { stuff: [0; 0x10000] });
     large.stuff[0] = 132;
     *large.stuff.last_mut().unwrap() = 102;
     assert_eq!(large.stuff[0], 132);