Skip to content

Commit 7019104

Browse files
Avoid unnecessary String allocations in MinifyingSugg arithmetic ops (#17057)
## Summary In `clippy_lints/src/loops/manual_memcpy.rs`, the four `Add`/`Sub` trait impls on `MinifyingSugg` used the pattern: ```rust match (self.to_string().as_str(), rhs.to_string().as_str()) { ("0", _) => rhs.clone(), (_, "0") => self.clone(), ... } ``` Every call therefore allocated two `String`s purely so they could be matched against the literal `"0"`. The allocations were discarded immediately afterwards. This PR: - Adds an inline `is_zero()` helper that pattern-matches `Sugg::NonParen("0")` without allocating. In this lint's data flow `Sugg::NonParen` is the only variant that can carry the textual value `"0"` (see `sugg::ZERO` and the literal path in `get_offset`), so the check is equivalent to the original `to_string() == "0"`. - Rewrites the four `Add`/`Sub` impls to use `is_zero()` for the zero-side fast paths. - Keeps `self.to_string() == rhs.to_string()` for the `a - a = 0` collapse inside `Sub`, but only as the final branch — it now only runs when both operands are confirmed non-zero, so the common case is fully allocation-free. changelog: none
2 parents b29177d + 7c1c1b0 commit 7019104

1 file changed

Lines changed: 26 additions & 16 deletions

File tree

clippy_lints/src/loops/manual_memcpy.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ impl<'a> MinifyingSugg<'a> {
230230
fn into_sugg(self) -> Sugg<'a> {
231231
self.0
232232
}
233+
234+
fn is_zero(&self) -> bool {
235+
matches!(&self.0, Sugg::NonParen(s) | Sugg::MaybeParen(s) if s == "0")
236+
}
233237
}
234238

235239
impl<'a> From<Sugg<'a>> for MinifyingSugg<'a> {
@@ -241,9 +245,9 @@ impl<'a> From<Sugg<'a>> for MinifyingSugg<'a> {
241245
impl std::ops::Add for &MinifyingSugg<'static> {
242246
type Output = MinifyingSugg<'static>;
243247
fn add(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> {
244-
match (self.to_string().as_str(), rhs.to_string().as_str()) {
245-
("0", _) => rhs.clone(),
246-
(_, "0") => self.clone(),
248+
match (self.is_zero(), rhs.is_zero()) {
249+
(true, _) => rhs.clone(),
250+
(_, true) => self.clone(),
247251
(_, _) => (&self.0 + &rhs.0).into(),
248252
}
249253
}
@@ -252,21 +256,24 @@ impl std::ops::Add for &MinifyingSugg<'static> {
252256
impl std::ops::Sub for &MinifyingSugg<'static> {
253257
type Output = MinifyingSugg<'static>;
254258
fn sub(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> {
255-
match (self.to_string().as_str(), rhs.to_string().as_str()) {
256-
(_, "0") => self.clone(),
257-
("0", _) => (-rhs.0.clone()).into(),
258-
(x, y) if x == y => sugg::ZERO.into(),
259-
(_, _) => (&self.0 - &rhs.0).into(),
259+
if rhs.is_zero() {
260+
self.clone()
261+
} else if self.is_zero() {
262+
(-rhs.0.clone()).into()
263+
} else if self.to_string() == rhs.to_string() {
264+
sugg::ZERO.into()
265+
} else {
266+
(&self.0 - &rhs.0).into()
260267
}
261268
}
262269
}
263270

264271
impl std::ops::Add<&MinifyingSugg<'static>> for MinifyingSugg<'static> {
265272
type Output = MinifyingSugg<'static>;
266273
fn add(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> {
267-
match (self.to_string().as_str(), rhs.to_string().as_str()) {
268-
("0", _) => rhs.clone(),
269-
(_, "0") => self,
274+
match (self.is_zero(), rhs.is_zero()) {
275+
(true, _) => rhs.clone(),
276+
(_, true) => self,
270277
(_, _) => (self.0 + &rhs.0).into(),
271278
}
272279
}
@@ -275,11 +282,14 @@ impl std::ops::Add<&MinifyingSugg<'static>> for MinifyingSugg<'static> {
275282
impl std::ops::Sub<&MinifyingSugg<'static>> for MinifyingSugg<'static> {
276283
type Output = MinifyingSugg<'static>;
277284
fn sub(self, rhs: &MinifyingSugg<'static>) -> MinifyingSugg<'static> {
278-
match (self.to_string().as_str(), rhs.to_string().as_str()) {
279-
(_, "0") => self,
280-
("0", _) => (-rhs.0.clone()).into(),
281-
(x, y) if x == y => sugg::ZERO.into(),
282-
(_, _) => (self.0 - &rhs.0).into(),
285+
if rhs.is_zero() {
286+
self
287+
} else if self.is_zero() {
288+
(-rhs.0.clone()).into()
289+
} else if self.to_string() == rhs.to_string() {
290+
sugg::ZERO.into()
291+
} else {
292+
(self.0 - &rhs.0).into()
283293
}
284294
}
285295
}

0 commit comments

Comments
 (0)