Skip to content

Commit 5488ae7

Browse files
committed
fix: large_stack_frames FP on compiler generated targets
1 parent 7e2d26f commit 5488ae7

File tree

10 files changed

+214
-5
lines changed

10 files changed

+214
-5
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6623,6 +6623,8 @@ Released 2018-09-13
66236623
[`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
66246624
[`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
66256625
[`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code
6626+
[`lint-inside-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inside-tests
6627+
[`lint-macro-generated-functions`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-macro-generated-functions
66266628
[`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
66276629
[`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
66286630
[`max-fn-params-bools`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-fn-params-bools

book/src/lint_configuration.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,26 @@ that would be collapsed.
683683
* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if)
684684

685685

686+
## `lint-inside-tests`
687+
Whether functions inside `#[cfg(test)]` modules or test functions should be checked.
688+
689+
**Default Value:** `false`
690+
691+
---
692+
**Affected lints:**
693+
* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames)
694+
695+
696+
## `lint-macro-generated-functions`
697+
Whether functions generated by macros should be checked.
698+
699+
**Default Value:** `false`
700+
701+
---
702+
**Affected lints:**
703+
* [`large_stack_frames`](https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_frames)
704+
705+
686706
## `literal-representation-threshold`
687707
The lower bound for linting decimal literals
688708

clippy_config/src/conf.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,12 @@ define_Conf! {
672672
/// Use the `check-inconsistent-struct-field-initializers` configuration instead.
673673
#[conf_deprecated("Please use `check-inconsistent-struct-field-initializers` instead", check_inconsistent_struct_field_initializers)]
674674
lint_inconsistent_struct_field_initializers: bool = false,
675+
/// Whether functions inside `#[cfg(test)]` modules or test functions should be checked.
676+
#[lints(large_stack_frames)]
677+
lint_inside_tests: bool = false,
678+
/// Whether functions generated by macros should be checked.
679+
#[lints(large_stack_frames)]
680+
lint_macro_generated_functions: bool = false,
675681
/// The lower bound for linting decimal literals
676682
#[lints(decimal_literal_representation)]
677683
literal_representation_threshold: u64 = 16384,

clippy_lints/src/large_stack_frames.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::{fmt, ops};
22

33
use clippy_config::Conf;
44
use clippy_utils::diagnostics::span_lint_and_then;
5-
use clippy_utils::fn_has_unsatisfiable_preds;
65
use clippy_utils::source::SpanRangeExt;
6+
use clippy_utils::{fn_has_unsatisfiable_preds, is_in_test};
77
use rustc_hir::def_id::LocalDefId;
88
use rustc_hir::intravisit::FnKind;
99
use rustc_hir::{Body, FnDecl};
@@ -83,12 +83,16 @@ declare_clippy_lint! {
8383

8484
pub struct LargeStackFrames {
8585
maximum_allowed_size: u64,
86+
lint_macro_generated_functions: bool,
87+
lint_inside_tests: bool,
8688
}
8789

8890
impl LargeStackFrames {
8991
pub fn new(conf: &'static Conf) -> Self {
9092
Self {
9193
maximum_allowed_size: conf.stack_size_threshold,
94+
lint_macro_generated_functions: conf.lint_macro_generated_functions,
95+
lint_inside_tests: conf.lint_inside_tests,
9296
}
9397
}
9498
}
@@ -170,16 +174,45 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames {
170174
FnKind::Closure => entire_fn_span,
171175
};
172176

177+
// Don't lint inside tests if configured to not do so.
178+
if !self.lint_inside_tests && is_in_test(cx.tcx, cx.tcx.local_def_id_to_hir_id(local_def_id)) {
179+
return;
180+
}
181+
182+
let mut is_from_expansion = false;
183+
if fn_span.from_expansion() {
184+
// Don't lint functions that are generated by special compiling targets, like `--test`.
185+
if fn_span.is_dummy() && fn_span.source_callsite().is_dummy() {
186+
return;
187+
}
188+
189+
// Don't lint functions generated by macros if configured to not do so.
190+
if !self.lint_macro_generated_functions {
191+
return;
192+
}
193+
194+
is_from_expansion = true;
195+
}
196+
173197
span_lint_and_then(
174198
cx,
175199
LARGE_STACK_FRAMES,
176-
fn_span,
177-
format!("this function may allocate {frame_size} on the stack"),
200+
fn_span.source_callsite(),
201+
if is_from_expansion {
202+
"function generated by this macro may allocate a lot of stack space".to_owned()
203+
} else {
204+
format!("this function may allocate {frame_size} on the stack")
205+
},
178206
|diag| {
207+
if is_from_expansion {
208+
diag.note(format!("this function has a stack frame size of {frame_size}"));
209+
}
179210
// Point out the largest individual contribution to this size, because
180211
// it is the most likely to be unintentionally large.
181-
if let Some((local, size)) = sizes_of_locals().max_by_key(|&(_, size)| size) {
182-
let local_span: Span = local.source_info.span;
212+
else if let Some((local, size)) = sizes_of_locals().max_by_key(|&(_, size)| size)
213+
&& let local_span = local.source_info.span
214+
&& !local_span.from_expansion()
215+
{
183216
let size = Space::Used(size); // pluralizes for us
184217
let ty = local.ty;
185218

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
stack-size-threshold = 0
2+
lint-macro-generated-functions = true
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR"
2+
//@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR"
3+
4+
#![warn(clippy::large_stack_frames)]
5+
6+
extern crate serde;
7+
8+
use serde::{Deserialize, Serialize};
9+
10+
struct ArrayDefault<const N: usize>([u8; N]);
11+
12+
macro_rules! mac {
13+
($name:ident) => {
14+
fn foo(x: ArrayDefault<1_000_000>) {
15+
let $name = 1;
16+
println!("macro_name called");
17+
}
18+
};
19+
}
20+
21+
mac!(something);
22+
//~^ large_stack_frames
23+
24+
#[derive(Deserialize, Serialize)]
25+
//~^ large_stack_frames
26+
//~| large_stack_frames
27+
//~| large_stack_frames
28+
//~| large_stack_frames
29+
//~| large_stack_frames
30+
//~| large_stack_frames
31+
//~| large_stack_frames
32+
//~| large_stack_frames
33+
34+
struct S {
35+
a: [u128; 31],
36+
}
37+
38+
fn main() {}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
error: function generated by this macro may allocate a lot of stack space
2+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:21:1
3+
|
4+
LL | mac!(something);
5+
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: this function has a stack frame size of 1000092 bytes
8+
= note: 1000092 bytes is larger than Clippy's configured `stack-size-threshold` of 0
9+
= note: allocating large amounts of stack space can overflow the stack and cause the program to abort
10+
= note: `-D clippy::large-stack-frames` implied by `-D warnings`
11+
= help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]`
12+
13+
error: function generated by this macro may allocate a lot of stack space
14+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
15+
|
16+
LL | #[derive(Deserialize, Serialize)]
17+
| ^^^^^^^^^^^
18+
|
19+
= note: this function has a stack frame size of 57 bytes
20+
= note: 57 bytes is larger than Clippy's configured `stack-size-threshold` of 0
21+
22+
error: function generated by this macro may allocate a lot of stack space
23+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
24+
|
25+
LL | #[derive(Deserialize, Serialize)]
26+
| ^^^^^^^^^^^
27+
|
28+
= note: this function has a stack frame size of 10 bytes
29+
= note: 10 bytes is larger than Clippy's configured `stack-size-threshold` of 0
30+
31+
error: function generated by this macro may allocate a lot of stack space
32+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
33+
|
34+
LL | #[derive(Deserialize, Serialize)]
35+
| ^^^^^^^^^^^
36+
|
37+
= note: this function has a stack frame size of 19 bytes
38+
= note: 19 bytes is larger than Clippy's configured `stack-size-threshold` of 0
39+
40+
error: function generated by this macro may allocate a lot of stack space
41+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
42+
|
43+
LL | #[derive(Deserialize, Serialize)]
44+
| ^^^^^^^^^^^
45+
|
46+
= note: this function has a stack frame size of 35 bytes
47+
= note: 35 bytes is larger than Clippy's configured `stack-size-threshold` of 0
48+
49+
error: function generated by this macro may allocate a lot of stack space
50+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
51+
|
52+
LL | #[derive(Deserialize, Serialize)]
53+
| ^^^^^^^^^^^
54+
|
55+
= note: this function has a stack frame size of 57 bytes
56+
= note: 57 bytes is larger than Clippy's configured `stack-size-threshold` of 0
57+
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
58+
59+
error: function generated by this macro may allocate a lot of stack space
60+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
61+
|
62+
LL | #[derive(Deserialize, Serialize)]
63+
| ^^^^^^^^^^^
64+
|
65+
= note: this function has a stack frame size of 3137 bytes
66+
= note: 3137 bytes is larger than Clippy's configured `stack-size-threshold` of 0
67+
68+
error: function generated by this macro may allocate a lot of stack space
69+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:10
70+
|
71+
LL | #[derive(Deserialize, Serialize)]
72+
| ^^^^^^^^^^^
73+
|
74+
= note: this function has a stack frame size of 4798 bytes
75+
= note: 4798 bytes is larger than Clippy's configured `stack-size-threshold` of 0
76+
77+
error: function generated by this macro may allocate a lot of stack space
78+
--> tests/ui-toml/large_stack_frames_for_macro_generated_fns/large_stack_frames.rs:24:23
79+
|
80+
LL | #[derive(Deserialize, Serialize)]
81+
| ^^^^^^^^^
82+
|
83+
= note: this function has a stack frame size of 170 bytes
84+
= note: 170 bytes is larger than Clippy's configured `stack-size-threshold` of 0
85+
86+
error: aborting due to 9 previous errors
87+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
stack-size-threshold = 0
2+
lint-inside-tests = true
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// This test checks if `clippy::large_stack_frames` is working correctly when encountering functions
2+
// generated by special compiling targets like `--test`.
3+
//@compile-flags: --test
4+
//@check-pass
5+
6+
#![warn(clippy::large_stack_frames)]
7+
8+
#[cfg(test)]
9+
#[allow(clippy::large_stack_frames)]
10+
mod test {
11+
#[test]
12+
fn main_test() {}
13+
}

tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
5050
ignore-interior-mutability
5151
large-error-threshold
5252
lint-commented-code
53+
lint-inside-tests
54+
lint-macro-generated-functions
5355
literal-representation-threshold
5456
matches-for-let-else
5557
max-fn-params-bools
@@ -144,6 +146,8 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
144146
ignore-interior-mutability
145147
large-error-threshold
146148
lint-commented-code
149+
lint-inside-tests
150+
lint-macro-generated-functions
147151
literal-representation-threshold
148152
matches-for-let-else
149153
max-fn-params-bools
@@ -238,6 +242,8 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
238242
ignore-interior-mutability
239243
large-error-threshold
240244
lint-commented-code
245+
lint-inside-tests
246+
lint-macro-generated-functions
241247
literal-representation-threshold
242248
matches-for-let-else
243249
max-fn-params-bools

0 commit comments

Comments
 (0)