From b022edce934b2fb939f876ccb78c1fb8b5bd6349 Mon Sep 17 00:00:00 2001 From: Wonko Date: Fri, 9 Jan 2026 15:17:06 +0100 Subject: [PATCH 1/2] add test for unstacking cognitive_complexity= attribute --- tests/ui/cognitive_complexity.rs | 25 +++++++++++++++++++++++++ tests/ui/cognitive_complexity.stderr | 18 +++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index 8080c6775e0b..3945028f8271 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -472,3 +472,28 @@ mod issue14422 { return; } } + +#[clippy::cognitive_complexity = "1"] +mod attribute_stacking { + fn bad() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } + + #[clippy::cognitive_complexity = "2"] + fn ok() { + if true { + println!("a"); + } + } + + // should revert to cognitive_complexity = "1" + fn bad_again() { + //~^ cognitive_complexity + if true { + println!("a"); + } + } +} diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 67ef4e5655bd..e5f54a37229d 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -176,5 +176,21 @@ LL | fn bar() { | = help: you could split it up into multiple smaller functions -error: aborting due to 22 previous errors +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:478:8 + | +LL | fn bad() { + | ^^^ + | + = help: you could split it up into multiple smaller functions + +error: the function has a cognitive complexity of (2/1) + --> tests/ui/cognitive_complexity.rs:493:8 + | +LL | fn bad_again() { + | ^^^^^^^^^ + | + = help: you could split it up into multiple smaller functions + +error: aborting due to 24 previous errors From 13b82eb615c68c71baf85ea8dcfbcab51a1dce1a Mon Sep 17 00:00:00 2001 From: Wonko Date: Fri, 9 Jan 2026 13:43:55 +0100 Subject: [PATCH 2/2] Fix LimitStack::pop_attrs in release mode The `LimitStack::pop_attrs` function used to pop from the stack in `debug_assert_eq!` and check the value. The `pop` operation was therefore only executed in debug builds, leading to an unbalanced stack in release builds when attributes were present. This change ensures the `pop` operation is always executed, by moving it out of the debug-only assertion. The assertion is kept for debug builds. changelog: fix unbalanced stack in attributes --- clippy_utils/src/attrs.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 32f6cb4fd5e9..56490cfc8b65 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -159,7 +159,10 @@ impl LimitStack { } pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) { let stack = &mut self.stack; - parse_attrs(sess, attrs, name, |val| debug_assert_eq!(stack.pop(), Some(val))); + parse_attrs(sess, attrs, name, |val| { + let popped = stack.pop(); + debug_assert_eq!(popped, Some(val)); + }); } }