Skip to content

Commit 5368335

Browse files
committed
overhaul LimitStack
- Move it and its helper function `parse_attrs` together to the end of the file, because it's surprising to see front-and-center a struct that's only really used in one place (`cognitive_complexity`). - Avoid panic path in `LimitStack::limit` - Replace `assert` with `debug_assert` to avoid panics in release builds
1 parent acc0a78 commit 5368335

File tree

1 file changed

+46
-42
lines changed

1 file changed

+46
-42
lines changed

clippy_utils/src/attrs.rs

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,34 +12,6 @@ use rustc_session::Session;
1212
use rustc_span::{Span, Symbol};
1313
use std::str::FromStr;
1414

15-
pub struct LimitStack {
16-
stack: Vec<u64>,
17-
}
18-
19-
impl Drop for LimitStack {
20-
fn drop(&mut self) {
21-
assert_eq!(self.stack.len(), 1);
22-
}
23-
}
24-
25-
impl LimitStack {
26-
#[must_use]
27-
pub fn new(limit: u64) -> Self {
28-
Self { stack: vec![limit] }
29-
}
30-
pub fn limit(&self) -> u64 {
31-
*self.stack.last().expect("there should always be a value in the stack")
32-
}
33-
pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
34-
let stack = &mut self.stack;
35-
parse_attrs(sess, attrs, name, |val| stack.push(val));
36-
}
37-
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
38-
let stack = &mut self.stack;
39-
parse_attrs(sess, attrs, name, |val| assert_eq!(stack.pop(), Some(val)));
40-
}
41-
}
42-
4315
pub fn get_attr<'a, A: AttributeExt + 'a>(
4416
sess: &'a Session,
4517
attrs: &'a [A],
@@ -87,20 +59,6 @@ pub fn get_attr<'a, A: AttributeExt + 'a>(
8759
})
8860
}
8961

90-
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name: Symbol, mut f: F) {
91-
for attr in get_attr(sess, attrs, name) {
92-
let Some(value) = attr.value_str() else {
93-
sess.dcx().span_err(attr.span(), "bad clippy attribute");
94-
continue;
95-
};
96-
let Ok(value) = u64::from_str(value.as_str()) else {
97-
sess.dcx().span_err(attr.span(), "not a number");
98-
continue;
99-
};
100-
f(value);
101-
}
102-
}
103-
10462
pub fn get_unique_attr<'a, A: AttributeExt>(sess: &'a Session, attrs: &'a [A], name: Symbol) -> Option<&'a A> {
10563
let mut unique_attr: Option<&A> = None;
10664
for attr in get_attr(sess, attrs, name) {
@@ -165,3 +123,49 @@ pub fn span_contains_cfg(cx: &LateContext<'_>, s: Span) -> bool {
165123
false
166124
})
167125
}
126+
pub struct LimitStack {
127+
default: u64,
128+
stack: Vec<u64>,
129+
}
130+
131+
impl Drop for LimitStack {
132+
fn drop(&mut self) {
133+
debug_assert_eq!(self.stack, Vec::<u64>::new()); // avoid `.is_empty()`, for a nicer error message
134+
}
135+
}
136+
137+
impl LimitStack {
138+
#[must_use]
139+
/// Initialize the stack starting with a default value, which usually comes from configuration
140+
pub fn new(limit: u64) -> Self {
141+
Self {
142+
default: limit,
143+
stack: vec![],
144+
}
145+
}
146+
pub fn limit(&self) -> u64 {
147+
self.stack.last().copied().unwrap_or(self.default)
148+
}
149+
pub fn push_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
150+
let stack = &mut self.stack;
151+
parse_attrs(sess, attrs, name, |val| stack.push(val));
152+
}
153+
pub fn pop_attrs(&mut self, sess: &Session, attrs: &[impl AttributeExt], name: Symbol) {
154+
let stack = &mut self.stack;
155+
parse_attrs(sess, attrs, name, |val| debug_assert_eq!(stack.pop(), Some(val)));
156+
}
157+
}
158+
159+
fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[impl AttributeExt], name: Symbol, mut f: F) {
160+
for attr in get_attr(sess, attrs, name) {
161+
let Some(value) = attr.value_str() else {
162+
sess.dcx().span_err(attr.span(), "bad clippy attribute");
163+
continue;
164+
};
165+
let Ok(value) = u64::from_str(value.as_str()) else {
166+
sess.dcx().span_err(attr.span(), "not a number");
167+
continue;
168+
};
169+
f(value);
170+
}
171+
}

0 commit comments

Comments
 (0)