Skip to content

Commit f57c8ae

Browse files
committed
[ty] Fix subtraction overflow bug
PR #21549 introduced a subtle overflow bug that seemed impossible, but can empirically happen. This PR fixes it by saturating to zero. I did try to write a regression test for this, but couldn't manage it. Instead, I'll attach before-and-after screen recordings.
1 parent 03dfbf2 commit f57c8ae

File tree

2 files changed

+20
-1
lines changed

2 files changed

+20
-1
lines changed

crates/ruff_text_size/src/size.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,25 @@ impl TextSize {
106106
pub fn checked_sub(self, rhs: TextSize) -> Option<TextSize> {
107107
self.raw.checked_sub(rhs.raw).map(|raw| TextSize { raw })
108108
}
109+
110+
/// Saturating addition. Returns maximum `TextSize` if overflow occurred.
111+
#[inline]
112+
#[must_use]
113+
pub fn saturating_add(self, rhs: TextSize) -> TextSize {
114+
TextSize {
115+
raw: self.raw.saturating_add(rhs.raw),
116+
}
117+
}
118+
119+
/// Saturating subtraction. Returns minimum `TextSize` if overflow
120+
/// occurred.
121+
#[inline]
122+
#[must_use]
123+
pub fn saturating_sub(self, rhs: TextSize) -> TextSize {
124+
TextSize {
125+
raw: self.raw.saturating_sub(rhs.raw),
126+
}
127+
}
109128
}
110129

111130
impl From<u32> for TextSize {

crates/ty_ide/src/completion.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1341,7 +1341,7 @@ fn is_in_definition_place(
13411341
/// E.g. naming a parameter, type parameter, or `for` <name>).
13421342
fn is_in_variable_binding(parsed: &ParsedModuleRef, offset: TextSize, typed: Option<&str>) -> bool {
13431343
let range = if let Some(typed) = typed {
1344-
let start = offset - typed.text_len();
1344+
let start = offset.saturating_sub(typed.text_len());
13451345
TextRange::new(start, offset)
13461346
} else {
13471347
TextRange::empty(offset)

0 commit comments

Comments
 (0)