add support for std::alloc::Global, add more tests
This commit is contained in:
parent
79325604da
commit
67bb503f26
@ -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 {
|
||||
|
@ -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"];
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user