Auto merge of #12624 - J-ZhengLi:issue12586, r=xFrednet

fix [`large_stack_arrays`] linting in `vec` macro

fixes: #12586

this PR also adds a wrapper function `matching_root_macro_call` to `clippy_utils::macros`, considering how often that same pattern appears in the codebase.

(I'm always very indecisive towards naming, so, if anyone have better idea of how that function should be named, feel free to suggest it)

---

changelog: fix [`large_stack_arrays`] linting in `vec` macro; add `matching_root_macro_call` to clippy_utils
This commit is contained in:
bors 2024-04-27 09:30:20 +00:00
commit c6bf9548d5
11 changed files with 194 additions and 48 deletions

View file

@ -9,6 +9,7 @@ use proc_macro::token_stream::IntoIter;
use proc_macro::Delimiter::{self, Brace, Parenthesis};
use proc_macro::Spacing::{self, Alone, Joint};
use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree as TT};
use syn::spanned::Spanned;
type Result<T> = core::result::Result<T, TokenStream>;
@ -124,6 +125,22 @@ fn write_with_span(s: Span, mut input: IntoIter, out: &mut TokenStream) -> Resul
Ok(())
}
/// Takes an array repeat expression such as `[0_u32; 2]`, and return the tokens with 10 times the
/// original size, which turns to `[0_u32; 20]`.
#[proc_macro]
pub fn make_it_big(input: TokenStream) -> TokenStream {
let mut expr_repeat = syn::parse_macro_input!(input as syn::ExprRepeat);
let len_span = expr_repeat.len.span();
if let syn::Expr::Lit(expr_lit) = &mut *expr_repeat.len {
if let syn::Lit::Int(lit_int) = &expr_lit.lit {
let orig_val = lit_int.base10_parse::<usize>().expect("not a valid length parameter");
let new_val = orig_val.saturating_mul(10);
expr_lit.lit = syn::parse_quote_spanned!( len_span => #new_val);
}
}
quote::quote!(#expr_repeat).into()
}
/// Within the item this attribute is attached to, an `inline!` macro is available which expands the
/// contained tokens as though they came from a macro expansion.
///

View file

@ -1,6 +1,9 @@
//@aux-build:proc_macros.rs
#![warn(clippy::large_stack_arrays)]
#![allow(clippy::large_enum_variant)]
extern crate proc_macros;
#[derive(Clone, Copy)]
struct S {
pub data: [u64; 32],
@ -55,3 +58,48 @@ fn main() {
[(); 20_000_000],
);
}
#[allow(clippy::useless_vec)]
fn issue_12586() {
macro_rules! dummy {
($n:expr) => {
$n
};
// Weird rule to test help messages.
($a:expr => $b:expr) => {
[$a, $b, $a, $b]
//~^ ERROR: allocating a local array larger than 512000 bytes
};
($id:ident; $n:literal) => {
dummy!(::std::vec![$id;$n])
};
($($id:expr),+ $(,)?) => {
::std::vec![$($id),*]
}
}
macro_rules! create_then_move {
($id:ident; $n:literal) => {{
let _x_ = [$id; $n];
//~^ ERROR: allocating a local array larger than 512000 bytes
_x_
}};
}
let x = [0u32; 50_000];
let y = vec![x, x, x, x, x];
let y = vec![dummy![x, x, x, x, x]];
let y = vec![dummy![[x, x, x, x, x]]];
let y = dummy![x, x, x, x, x];
let y = [x, x, dummy!(x), x, x];
//~^ ERROR: allocating a local array larger than 512000 bytes
let y = dummy![x => x];
let y = dummy![x;5];
let y = dummy!(vec![dummy![x, x, x, x, x]]);
let y = dummy![[x, x, x, x, x]];
//~^ ERROR: allocating a local array larger than 512000 bytes
let y = proc_macros::make_it_big!([x; 1]);
//~^ ERROR: allocating a local array larger than 512000 bytes
let y = vec![proc_macros::make_it_big!([x; 10])];
let y = vec![create_then_move![x; 5]; 5];
}

View file

@ -1,5 +1,5 @@
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:29:14
--> tests/ui/large_stack_arrays.rs:32:14
|
LL | let _x = [build(); 3];
| ^^^^^^^^^^^^
@ -9,7 +9,7 @@ LL | let _x = [build(); 3];
= help: to override `-D warnings` add `#[allow(clippy::large_stack_arrays)]`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:32:14
--> tests/ui/large_stack_arrays.rs:35:14
|
LL | let _y = [build(), build(), build()];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -17,7 +17,7 @@ LL | let _y = [build(), build(), build()];
= help: consider allocating on the heap with `vec![build(), build(), build()].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:38:9
--> tests/ui/large_stack_arrays.rs:41:9
|
LL | [0u32; 20_000_000],
| ^^^^^^^^^^^^^^^^^^
@ -25,7 +25,7 @@ LL | [0u32; 20_000_000],
= help: consider allocating on the heap with `vec![0u32; 20_000_000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:40:9
--> tests/ui/large_stack_arrays.rs:43:9
|
LL | [S { data: [0; 32] }; 5000],
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -33,7 +33,7 @@ LL | [S { data: [0; 32] }; 5000],
= help: consider allocating on the heap with `vec![S { data: [0; 32] }; 5000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:42:9
--> tests/ui/large_stack_arrays.rs:45:9
|
LL | [Some(""); 20_000_000],
| ^^^^^^^^^^^^^^^^^^^^^^
@ -41,7 +41,7 @@ LL | [Some(""); 20_000_000],
= help: consider allocating on the heap with `vec![Some(""); 20_000_000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:44:9
--> tests/ui/large_stack_arrays.rs:47:9
|
LL | [E::T(0); 5000],
| ^^^^^^^^^^^^^^^
@ -49,12 +49,56 @@ LL | [E::T(0); 5000],
= help: consider allocating on the heap with `vec![E::T(0); 5000].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:46:9
--> tests/ui/large_stack_arrays.rs:49:9
|
LL | [0u8; usize::MAX],
| ^^^^^^^^^^^^^^^^^
|
= help: consider allocating on the heap with `vec![0u8; usize::MAX].into_boxed_slice()`
error: aborting due to 7 previous errors
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:93:13
|
LL | let y = [x, x, dummy!(x), x, x];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider allocating on the heap with `vec![x, x, dummy!(x), x, x].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:70:13
|
LL | [$a, $b, $a, $b]
| ^^^^^^^^^^^^^^^^
...
LL | let y = dummy![x => x];
| -------------- in this macro invocation
|
= note: this error originates in the macro `dummy` (in Nightly builds, run with -Z macro-backtrace for more info)
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:98:20
|
LL | let y = dummy![[x, x, x, x, x]];
| ^^^^^^^^^^^^^^^
|
= help: consider allocating on the heap with `vec![x, x, x, x, x].into_boxed_slice()`
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:101:39
|
LL | let y = proc_macros::make_it_big!([x; 1]);
| ^^^^^^
error: allocating a local array larger than 512000 bytes
--> tests/ui/large_stack_arrays.rs:82:23
|
LL | let _x_ = [$id; $n];
| ^^^^^^^^^
...
LL | let y = vec![create_then_move![x; 5]; 5];
| ----------------------- in this macro invocation
|
= note: this error originates in the macro `create_then_move` (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 12 previous errors