-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fix large_stack_frames
FP on compiler generated targets
#15101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,6 +170,11 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { | |
FnKind::Closure => entire_fn_span, | ||
}; | ||
|
||
// Don't lint compiler-generated targets | ||
if fn_span.is_dummy() { | ||
return; | ||
} | ||
|
||
Comment on lines
+173
to
+177
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comparing against the dummy span feels too specific. Why not return from the beginning of the function if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think it is a good idea to ignore macros in this lint There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you produce a realistic test case in which a macro should not be ignored and would get a sensible message? Right now, checking for And if the goal is to lint all functions to ensure that a given stack size is not exceeded, maybe compiler generated functions should be checked after all instead of being silently ignored, and the message fixed. One could also add a configuration option to exclude test methods from the lint, that would be my preferred option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Adding @y21 to the discussion as they are currently working on this lint. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree for adding configuration option for test methods. As for compiler generated functions, I'm not sure whether we should ignore it or not. I doubt if we can give a sensible error message, and even if we can, it would be hard for the user to fix it.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm, I'm a bit torn on this one. When I initially implemented the lint, the idea was to catch functions that allocate so much stack space that they almost certainly always instantly overflow the stack when called, or are seriously at risk for it. So like most other correctness lints, I think it'd still make sense to lint some macro generated code, since you'd probably still want to know about those functions in your program. Here's a real world example where a function is generated by a macro that this lint would catch: https://docs.rs/hex/latest/src/hex/lib.rs.html#206 I am honestly a bit surprised about the linked issue. Surely they don't literally run with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this case, should external macros be filtered or not? For example, in the current test case #[derive(serde::Deserialize, serde::Serialize)]
struct S {
a: [u128; 31],
} will lint, and also this one: proc_macros::external! {
fn foo() {
println!("Hello, world!");
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would personally say it still makes sense to lint external macros. It seems useful to get a warning if there's any function that could accidentally overflow the stack regardless of where it comes from (to the best of its abilities ofc, it will always have some FNs) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. r? @y21 given their ongoing work on this topic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thought a bit more about it and yeah I think I'm fine with this specifically only ignoring dummy spans. I'd ideally like this lint to warn any function regardless of where it comes from, but if there's nowhere where people can put lint level attrs for a test harness' main function, it means they'd need to have a global |
||
span_lint_and_then( | ||
cx, | ||
LARGE_STACK_FRAMES, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
stack-size-threshold = 0 |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add a short comment at the top of the file that this is specifically testing the test harness' compiler-generated |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
//@compile-flags: --test | ||
#![allow(unused)] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this is needed. |
||
#![warn(clippy::large_stack_frames)] | ||
|
||
fn main() { | ||
//~^ large_stack_frames | ||
println!("Hello, world!"); | ||
} | ||
|
||
#[cfg(test)] | ||
#[allow(clippy::large_stack_frames)] | ||
mod test { | ||
#[test] | ||
fn main_test() {} | ||
} |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,16 @@ | ||||
error: this function may allocate 88 bytes on the stack | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might lead to spurious failures when test suite is run on a 32 bit machine since The existing test file already normalizes away differing digits for pointer sizes in the stderr like this:
But, given that this is (I assume) mainly just testing that we don't emit a warning, we can just use |
||||
--> tests/ui-toml/large_stack_frames_for_generated_fn/large_stack_frames.rs:5:4 | ||||
| | ||||
LL | fn main() { | ||||
| ^^^^ | ||||
LL | | ||||
LL | println!("Hello, world!"); | ||||
| ------------------------- this is the largest part, at 48 bytes for type `std::fmt::Arguments<'_>` | ||||
| | ||||
= note: 88 bytes is larger than Clippy's configured `stack-size-threshold` of 0 | ||||
= note: allocating large amounts of stack space can overflow the stack and cause the program to abort | ||||
= note: `-D clippy::large-stack-frames` implied by `-D warnings` | ||||
= help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` | ||||
|
||||
error: aborting due to 1 previous error | ||||
|
Uh oh!
There was an error while loading. Please reload this page.