about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacherr <jwc2002@outlook.com>2023-11-08 21:10:27 +0000
committerJacherr <jwc2002@outlook.com>2023-11-08 21:10:27 +0000
commit67bb503f26ad5d695229153995bd2ab296e590cb (patch)
tree2b127bb9bf92cd46c83787c3feceab58ef96e664
parent79325604da4b0000b7bd6c6fb6553f108a5983d7 (diff)
downloadrust-67bb503f26ad5d695229153995bd2ab296e590cb.tar.gz
rust-67bb503f26ad5d695229153995bd2ab296e590cb.zip
add support for std::alloc::Global, add more tests
-rw-r--r--clippy_lints/src/types/vec_box.rs18
-rw-r--r--clippy_utils/src/paths.rs1
-rw-r--r--tests/ui/vec_box_sized.fixed41
-rw-r--r--tests/ui/vec_box_sized.rs41
-rw-r--r--tests/ui/vec_box_sized.stderr32
5 files changed, 92 insertions, 41 deletions
diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs
index 887439560d1..43f72f1031d 100644
--- a/clippy_lints/src/types/vec_box.rs
+++ b/clippy_lints/src/types/vec_box.rs
@@ -1,5 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::last_path_segment;
+use clippy_utils::{last_path_segment, match_def_path};
+use clippy_utils::paths::ALLOCATOR_GLOBAL;
 use clippy_utils::source::snippet;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
@@ -41,10 +42,19 @@ pub(super) fn check(
             && let Ok(ty_ty_size) = cx.layout_of(ty_ty).map(|l| l.size.bytes())
             && ty_ty_size < box_size_threshold
             // https://github.com/rust-lang/rust-clippy/issues/7114
-            // this code also does not consider that Global can be explicitly
-            // defined (yet) as in Vec<_, Global> so a very slight false negative edge case
             && match (vec_alloc_ty, boxed_alloc_ty) {
                 (None, None) => true,
+                // this is in the event that we have something like
+                // Vec<_, Global>, in which case is equivalent to
+                // Vec<_>
+                (None, Some(GenericArg::Type(inner))) | (Some(GenericArg::Type(inner)), None) => {
+                    if let TyKind::Path(path) = inner.kind
+                        && let Some(did) = cx.qpath_res(&path, inner.hir_id).opt_def_id() {
+                        match_def_path(cx, did, &ALLOCATOR_GLOBAL)
+                    } else {
+                        true
+                    }
+                },
                 (Some(GenericArg::Type(l)), Some(GenericArg::Type(r))) =>
                     hir_ty_to_ty(cx.tcx, l) == hir_ty_to_ty(cx.tcx, r),
                 _ => false
@@ -57,7 +67,7 @@ pub(super) fn check(
                 "`Vec<T>` is already on the heap, the boxing is unnecessary",
                 "try",
                 format!("Vec<{}>", snippet(cx, boxed_ty.span, "..")),
-                Applicability::MachineApplicable,
+                Applicability::Unspecified,
             );
             true
         } else {
diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs
index 5bca554378e..bde8eb892e9 100644
--- a/clippy_utils/src/paths.rs
+++ b/clippy_utils/src/paths.rs
@@ -99,3 +99,4 @@ pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
 pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
 #[expect(clippy::invalid_paths)] // not sure why it thinks this, it works so
 pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
+pub const ALLOCATOR_GLOBAL: [&str; 3] = ["alloc", "alloc", "Global"];
\ No newline at end of file
diff --git a/tests/ui/vec_box_sized.fixed b/tests/ui/vec_box_sized.fixed
index 67067de91cc..0be891a92bc 100644
--- a/tests/ui/vec_box_sized.fixed
+++ b/tests/ui/vec_box_sized.fixed
@@ -1,13 +1,26 @@
 #![allow(dead_code)]
 #![feature(allocator_api)]
 
+use std::alloc::{Layout, AllocError, Allocator};
+use std::ptr::NonNull;
+
 struct SizedStruct(i32);
 struct UnsizedStruct([i32]);
 struct BigStruct([i32; 10000]);
 
+struct DummyAllocator;
+unsafe impl Allocator for DummyAllocator {
+    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+        todo!()
+    }
+    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+        todo!()
+    }
+}
+
 /// The following should trigger the lint
 mod should_trigger {
-    use super::SizedStruct;
+    use super::{SizedStruct, DummyAllocator};
     const C: Vec<i32> = Vec::new();
     static S: Vec<i32> = Vec::new();
 
@@ -17,13 +30,21 @@ mod should_trigger {
 
     struct A(Vec<SizedStruct>);
     struct B(Vec<Vec<u32>>);
+
+    fn allocator_global_defined_vec() -> Vec<i32> {
+        Vec::new()
+    }
+    fn allocator_global_defined_box() -> Vec<i32> {
+        Vec::new()
+    }
+    fn allocator_match() -> Vec<i32> {
+        Vec::new_in(DummyAllocator)
+    }
 }
 
 /// The following should not trigger the lint
 mod should_not_trigger {
-    use super::{BigStruct, UnsizedStruct};
-    use std::alloc::{Layout, AllocError, Allocator};
-    use std::ptr::NonNull;
+    use super::{BigStruct, UnsizedStruct, DummyAllocator};
 
     struct C(Vec<Box<UnsizedStruct>>);
     struct D(Vec<Box<BigStruct>>);
@@ -37,18 +58,8 @@ mod should_not_trigger {
         inner: Vec<Box<T>>,
     }
 
-    struct DummyAllocator;
-    unsafe impl Allocator for DummyAllocator {
-        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
-            todo!()
-        }
-        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
-            todo!()
-        }
-    }
-
     fn allocator_mismatch() -> Vec<Box<i32, DummyAllocator>> {
-        vec![]
+        Vec::new()
     }
 }
 
diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs
index 2b5c2c99945..9314195b103 100644
--- a/tests/ui/vec_box_sized.rs
+++ b/tests/ui/vec_box_sized.rs
@@ -1,13 +1,26 @@
 #![allow(dead_code)]
 #![feature(allocator_api)]
 
+use std::alloc::{Layout, AllocError, Allocator};
+use std::ptr::NonNull;
+
 struct SizedStruct(i32);
 struct UnsizedStruct([i32]);
 struct BigStruct([i32; 10000]);
 
+struct DummyAllocator;
+unsafe impl Allocator for DummyAllocator {
+    fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+        todo!()
+    }
+    unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+        todo!()
+    }
+}
+
 /// The following should trigger the lint
 mod should_trigger {
-    use super::SizedStruct;
+    use super::{SizedStruct, DummyAllocator};
     const C: Vec<Box<i32>> = Vec::new();
     static S: Vec<Box<i32>> = Vec::new();
 
@@ -17,13 +30,21 @@ mod should_trigger {
 
     struct A(Vec<Box<SizedStruct>>);
     struct B(Vec<Vec<Box<(u32)>>>);
+
+    fn allocator_global_defined_vec() -> Vec<Box<i32>, std::alloc::Global> {
+        Vec::new()
+    }
+    fn allocator_global_defined_box() -> Vec<Box<i32, std::alloc::Global>> {
+        Vec::new()
+    }
+    fn allocator_match() -> Vec<Box<i32, DummyAllocator>, DummyAllocator> {
+        Vec::new_in(DummyAllocator)
+    }
 }
 
 /// The following should not trigger the lint
 mod should_not_trigger {
-    use super::{BigStruct, UnsizedStruct};
-    use std::alloc::{Layout, AllocError, Allocator};
-    use std::ptr::NonNull;
+    use super::{BigStruct, UnsizedStruct, DummyAllocator};
 
     struct C(Vec<Box<UnsizedStruct>>);
     struct D(Vec<Box<BigStruct>>);
@@ -37,18 +58,8 @@ mod should_not_trigger {
         inner: Vec<Box<T>>,
     }
 
-    struct DummyAllocator;
-    unsafe impl Allocator for DummyAllocator {
-        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
-            todo!()
-        }
-        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
-            todo!()
-        }
-    }
-
     fn allocator_mismatch() -> Vec<Box<i32, DummyAllocator>> {
-        vec![]
+        Vec::new()
     }
 }
 
diff --git a/tests/ui/vec_box_sized.stderr b/tests/ui/vec_box_sized.stderr
index 0e68aa57dcb..2fa5679650b 100644
--- a/tests/ui/vec_box_sized.stderr
+++ b/tests/ui/vec_box_sized.stderr
@@ -1,5 +1,5 @@
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:11:14
+  --> $DIR/vec_box_sized.rs:24:14
    |
 LL |     const C: Vec<Box<i32>> = Vec::new();
    |              ^^^^^^^^^^^^^ help: try: `Vec<i32>`
@@ -8,34 +8,52 @@ LL |     const C: Vec<Box<i32>> = Vec::new();
    = help: to override `-D warnings` add `#[allow(clippy::vec_box)]`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:12:15
+  --> $DIR/vec_box_sized.rs:25:15
    |
 LL |     static S: Vec<Box<i32>> = Vec::new();
    |               ^^^^^^^^^^^^^ help: try: `Vec<i32>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:15:21
+  --> $DIR/vec_box_sized.rs:28:21
    |
 LL |         sized_type: Vec<Box<SizedStruct>>,
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:18:14
+  --> $DIR/vec_box_sized.rs:31:14
    |
 LL |     struct A(Vec<Box<SizedStruct>>);
    |              ^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<SizedStruct>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:19:18
+  --> $DIR/vec_box_sized.rs:32:18
    |
 LL |     struct B(Vec<Vec<Box<(u32)>>>);
    |                  ^^^^^^^^^^^^^^^ help: try: `Vec<u32>`
 
 error: `Vec<T>` is already on the heap, the boxing is unnecessary
-  --> $DIR/vec_box_sized.rs:63:23
+  --> $DIR/vec_box_sized.rs:34:42
+   |
+LL |     fn allocator_global_defined_vec() -> Vec<Box<i32>, std::alloc::Global> {
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:37:42
+   |
+LL |     fn allocator_global_defined_box() -> Vec<Box<i32, std::alloc::Global>> {
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:40:29
+   |
+LL |     fn allocator_match() -> Vec<Box<i32, DummyAllocator>, DummyAllocator> {
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Vec<i32>`
+
+error: `Vec<T>` is already on the heap, the boxing is unnecessary
+  --> $DIR/vec_box_sized.rs:74:23
    |
 LL |         pub fn f() -> Vec<Box<S>> {
    |                       ^^^^^^^^^^^ help: try: `Vec<S>`
 
-error: aborting due to 6 previous errors
+error: aborting due to 9 previous errors