Use Duration to improve type safety and unit correctness (#62969)

# Objective

- Prefer using `Duration` instead of integers when dealing with spans of
time. This prevents confusing different units of time and comparing
arbitrary integers with durations.
- Remove `_ms`/`_secs` suffixes from variables which are `Duration`,
since their unit is inside of the type.
- Initialize large integer constants using `Duration`, which has more
descriptive constructors, while maintaining the resulting integer type.

Release Notes:

- N/A or Added/Fixed/Improved ...
This commit is contained in:
tidely authored and GitHub committed 2026-08-21 07:28:05 +00:00
1 parent 7eb7a53cd6
commit 570d9095a7
9 files changed
+43 -46

No files matched your search

+1 -1
View File
@@ -5349,7 +5349,7 @@ mod tests {
::terminal::terminal_settings::AlternateScroll::On,
None,
vec![],
0,
Duration::ZERO,
false,
0,
Some(completion_tx),
+1 -1
View File
@@ -638,7 +638,7 @@ fn truncate_to_visible_width(s: &str, max_visible_len: usize) -> &str {
}
fn format_duration(duration: Duration) -> String {
const MINUTE_IN_MILLIS: f32 = 60. * 1000.;
const MINUTE_IN_MILLIS: f32 = Duration::from_mins(1).as_millis() as f32;
let millis = duration.as_millis() as f32;
if millis < 1000.0 {
+7 -9
View File
@@ -36745,7 +36745,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
use std::sync::atomic::AtomicU32;
use std::time::Duration;
const BASE_TIMEOUT_SECS: u64 = 1;
const BASE_TIMEOUT: Duration = Duration::from_secs(1);
let request_count = Arc::new(AtomicU32::new(0));
let closure_request_count = request_count.clone();
@@ -36760,7 +36760,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings(cx, &|settings: &mut SettingsContent| {
settings.global_lsp_settings = Some(GlobalLspSettingsContent {
request_timeout: Some(BASE_TIMEOUT_SECS),
request_timeout: Some(BASE_TIMEOUT.as_secs()),
max_buffer_line_length: None,
button: Some(true),
notifications: None,
@@ -36795,9 +36795,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
move |params, cx| {
let request_count = request_count.clone();
async move {
cx.background_executor()
.timer(Duration::from_secs(BASE_TIMEOUT_SECS * 2))
.await;
cx.background_executor().timer(BASE_TIMEOUT * 2).await;
let count = request_count.fetch_add(1, atomic::Ordering::Release) + 1;
assert_eq!(
params.text_document.uri,
@@ -36833,7 +36831,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
let fake_server = fake_servers.next().await.unwrap();
cx.executor()
.advance_clock(Duration::from_secs(BASE_TIMEOUT_SECS) + Duration::from_millis(100));
.advance_clock(BASE_TIMEOUT + Duration::from_millis(100));
cx.executor().run_until_parked();
editor
.update(cx, |editor, _window, cx| {
@@ -36850,7 +36848,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
.into_response()
.unwrap();
cx.executor()
.advance_clock(Duration::from_secs(BASE_TIMEOUT_SECS) + Duration::from_millis(100));
.advance_clock(BASE_TIMEOUT + Duration::from_millis(100));
cx.executor().run_until_parked();
editor
.update(cx, |editor, _window, cx| {
@@ -36865,7 +36863,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
SettingsStore::update_global(cx, |store, cx| {
store.update_user_settings(cx, |settings| {
settings.global_lsp_settings = Some(GlobalLspSettingsContent {
request_timeout: Some(BASE_TIMEOUT_SECS * 4),
request_timeout: Some(BASE_TIMEOUT.as_secs() * 4),
max_buffer_line_length: None,
button: Some(true),
notifications: None,
@@ -36880,7 +36878,7 @@ async fn test_inlay_hints_request_timeout(cx: &mut TestAppContext) {
.into_response()
.unwrap();
cx.executor()
.advance_clock(Duration::from_secs(BASE_TIMEOUT_SECS * 4) + Duration::from_millis(100));
.advance_clock(BASE_TIMEOUT * 4 + Duration::from_millis(100));
cx.executor().run_until_parked();
editor
.update(cx, |editor, _window, cx| {
@@ -28,8 +28,8 @@ use workspace::{
};
use zed_actions::OpenPerformanceProfiler;
const NANOS_PER_MS: u128 = 1_000_000;
const VISIBLE_WINDOW_NANOS: u128 = 10 * 1_000_000_000;
const NANOS_PER_MS: u128 = Duration::from_millis(1).as_nanos();
const VISIBLE_WINDOW_NANOS: u128 = Duration::from_secs(10).as_nanos();
const REMOTE_POLL_INTERVAL: Duration = Duration::from_millis(500);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -37,7 +37,7 @@ const OPENAI_AUTHORIZE_URL: &str = "https://auth.openai.com/oauth/authorize";
const CLIENT_ID: &str = "app_EMoamEEZ73f0CkXaXp7hrann";
const CREDENTIALS_KEY: &str = "https://chatgpt.com/backend-api/codex";
const TOKEN_REFRESH_BUFFER_MS: u64 = 5 * 60 * 1000;
const TOKEN_REFRESH_BUFFER_MS: u64 = Duration::from_mins(5).as_millis() as u64;
/// Requests the complete account catalog without Codex CLI version filtering.
///
/// The backend treats this exact version as an ungated sentinel. Other versions
+3 -2
View File
@@ -12,6 +12,7 @@ use std::{
borrow::Cow,
path::{Path, PathBuf},
sync::Arc,
time::Duration,
};
use task::{Shell, ShellBuilder, ShellKind, SpawnInTerminal};
use terminal::{
@@ -251,7 +252,7 @@ impl Project {
settings.alternate_scroll,
settings.max_scroll_history_lines,
settings.path_hyperlink_regexes,
settings.path_hyperlink_timeout_ms,
Duration::from_millis(settings.path_hyperlink_timeout_ms),
is_via_remote,
cx.entity_id().as_u64(),
Some(completion_tx),
@@ -421,7 +422,7 @@ impl Project {
settings.alternate_scroll,
settings.max_scroll_history_lines,
settings.path_hyperlink_regexes,
settings.path_hyperlink_timeout_ms,
Duration::from_millis(settings.path_hyperlink_timeout_ms),
is_via_remote,
cx.entity_id().as_u64(),
None,
+7 -10
View File
@@ -713,9 +713,9 @@ pub(crate) async fn matches_to_multibuffer(
PopulateProjectSearch::Completed
}
const SEARCH_DEBOUNCE_MS: u64 = 100;
const CLICK_THRESHOLD_MS: u128 = 50;
const DOUBLE_CLICK_THRESHOLD_MS: u128 = 300;
const SEARCH_DEBOUNCE: Duration = Duration::from_millis(100);
const CLICK_THRESHOLD: Duration = Duration::from_millis(50);
const DOUBLE_CLICK_THRESHOLD: Duration = Duration::from_millis(300);
const SEARCH_RESULTS_BATCH_SIZE: usize = 256;
const MAX_MATCH_CONTEXT_BYTES: usize = 512;
@@ -894,9 +894,7 @@ impl PickerDelegate for Delegate {
let (signal_done, match_updating_done) = futures::channel::oneshot::channel();
self.in_progress_search =
InProgressSearch::Connected(cx.spawn_in(window, async move |picker, cx| {
cx.background_executor()
.timer(Duration::from_millis(SEARCH_DEBOUNCE_MS))
.await;
cx.background_executor().timer(SEARCH_DEBOUNCE).await;
if cancel_flag.load(std::sync::atomic::Ordering::SeqCst) {
return None;
@@ -934,15 +932,14 @@ impl PickerDelegate for Delegate {
let now = std::time::Instant::now();
let is_click = self
.last_selection_change_time
.map(|t| now.duration_since(t).as_millis() < CLICK_THRESHOLD_MS)
.map(|t| now.duration_since(t) < CLICK_THRESHOLD)
.unwrap_or(false);
if is_click {
let is_double_click = self
.last_click
.map(|(ix, t)| {
ix == self.selected_index
&& now.duration_since(t).as_millis() < DOUBLE_CLICK_THRESHOLD_MS
ix == self.selected_index && now.duration_since(t) < DOUBLE_CLICK_THRESHOLD
})
.unwrap_or(false);
self.last_click = Some((self.selected_index, now));
@@ -1564,7 +1561,7 @@ mod tests {
// Search is debounced; advance past the debounce and let results stream in.
cx.executor()
.advance_clock(std::time::Duration::from_millis(SEARCH_DEBOUNCE_MS + 50));
.advance_clock(SEARCH_DEBOUNCE + Duration::from_millis(50));
cx.run_until_parked();
picker.read_with(cx, |picker, _| {
+8 -7
View File
@@ -49,18 +49,19 @@ impl From<(String, bool, Match)> for HyperlinkMatch {
impl Default for RegexSearches {
fn default() -> Self {
Self::new(Vec::<String>::new(), 0)
Self::new(Vec::<String>::new(), Duration::ZERO)
}
}
impl RegexSearches {
pub(crate) fn new(
path_hyperlink_regexes: impl IntoIterator<Item: AsRef<str>>,
path_hyperlink_timeout_ms: u64,
path_hyperlink_timeout: Duration,
) -> Self {
Self {
url_regex: RegexSearch::new(URL_REGEX).ok(),
path_hyperlink_regexes: Self::path_hyperlink_regexes(path_hyperlink_regexes),
path_hyperlink_timeout: Duration::from_millis(path_hyperlink_timeout_ms),
path_hyperlink_timeout,
}
}
@@ -1322,7 +1323,7 @@ mod tests {
term: &Term<VoidListener>,
point: AlacPoint,
) -> Option<HyperlinkMatch> {
const PATH_HYPERLINK_TIMEOUT_MS: u64 = 1000;
const PATH_HYPERLINK_TIMEOUT: Duration = Duration::from_millis(1000);
thread_local! {
static TEST_REGEX_SEARCHES: RefCell<RegexSearches> =
@@ -1335,7 +1336,7 @@ mod tests {
RegexSearches::new(
&default_terminal_settings.path_hyperlink_regexes,
PATH_HYPERLINK_TIMEOUT_MS
PATH_HYPERLINK_TIMEOUT
)
});
}
@@ -1917,7 +1918,7 @@ mod tests {
r#"[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2} (?<link>(?<path>.+))"#;
const MULTIPLE_SAME_LINE_REGEX: &str =
r#"(?<link>(?<path>🦀 multiple_same_line 🦀) 🚣(?<line>[0-9]+) 🏛(?<column>[0-9]+)):"#;
const PATH_HYPERLINK_TIMEOUT_MS: u64 = 1000;
const PATH_HYPERLINK_TIMEOUT: Duration = Duration::from_millis(1000);
thread_local! {
static TEST_REGEX_SEARCHES: RefCell<RegexSearches> =
@@ -1936,7 +1937,7 @@ mod tests {
.chain(default_terminal_settings.path_hyperlink_regexes
.iter()
.map(AsRef::as_ref)),
PATH_HYPERLINK_TIMEOUT_MS)
PATH_HYPERLINK_TIMEOUT)
});
}
+13 -13
View File
@@ -1011,7 +1011,7 @@ impl TerminalBuilder {
alternate_scroll,
max_scroll_history_lines,
path_hyperlink_regexes: Vec::default(),
path_hyperlink_timeout_ms: 0,
path_hyperlink_timeout: Duration::ZERO,
window_id,
},
child_exited: None,
@@ -1046,7 +1046,7 @@ impl TerminalBuilder {
alternate_scroll: AlternateScroll,
max_scroll_history_lines: Option<usize>,
path_hyperlink_regexes: Vec<String>,
path_hyperlink_timeout_ms: u64,
path_hyperlink_timeout: Duration,
is_remote_terminal: bool,
window_id: u64,
completion_tx: Option<Sender<Option<ExitStatus>>>,
@@ -1271,7 +1271,7 @@ impl TerminalBuilder {
selection_phase: SelectionPhase::Ended,
hyperlink_regex_searches: RegexSearches::new(
&path_hyperlink_regexes,
path_hyperlink_timeout_ms,
path_hyperlink_timeout,
),
vi_mode_enabled: false,
is_remote_terminal,
@@ -1288,7 +1288,7 @@ impl TerminalBuilder {
alternate_scroll,
max_scroll_history_lines,
path_hyperlink_regexes,
path_hyperlink_timeout_ms,
path_hyperlink_timeout,
window_id,
},
child_exited: None,
@@ -1507,7 +1507,7 @@ struct CopyTemplate {
alternate_scroll: AlternateScroll,
max_scroll_history_lines: Option<usize>,
path_hyperlink_regexes: Vec<String>,
path_hyperlink_timeout_ms: u64,
path_hyperlink_timeout: Duration,
window_id: u64,
}
@@ -1545,7 +1545,7 @@ impl TaskStatus {
}
const FIND_HYPERLINK_THROTTLE_PX: Pixels = px(5.0);
const FIND_HYPERLINK_THROTTLE_MS: Duration = Duration::from_millis(100);
const FIND_HYPERLINK_THROTTLE: Duration = Duration::from_millis(100);
/// Minimum pointer movement before a left click begins a selection. This keeps
/// a click that jitters by a pixel or two (such as the window-focusing click)
@@ -2460,7 +2460,7 @@ impl Terminal {
+ (position.y - last_pos.y).abs())
> FIND_HYPERLINK_THROTTLE_PX;
let time_elapsed =
now.duration_since(self.last_mouse_move_time) > FIND_HYPERLINK_THROTTLE_MS;
now.duration_since(self.last_mouse_move_time) > FIND_HYPERLINK_THROTTLE;
distance_moved || time_elapsed
});
@@ -3082,7 +3082,7 @@ impl Terminal {
self.template.alternate_scroll,
self.template.max_scroll_history_lines,
self.template.path_hyperlink_regexes.clone(),
self.template.path_hyperlink_timeout_ms,
self.template.path_hyperlink_timeout,
self.is_remote_terminal,
self.template.window_id,
None,
@@ -3631,7 +3631,7 @@ mod tests {
AlternateScroll::On,
None,
vec![],
0,
Duration::ZERO,
false,
0,
Some(completion_tx),
@@ -3682,7 +3682,7 @@ mod tests {
AlternateScroll::On,
None,
vec![],
0,
Duration::ZERO,
false,
0,
Some(completion_tx),
@@ -4075,7 +4075,7 @@ mod tests {
AlternateScroll::On,
None,
vec![],
0,
Duration::ZERO,
false,
0,
Some(completion_tx),
@@ -4143,7 +4143,7 @@ mod tests {
AlternateScroll::On,
None,
vec![],
0,
Duration::ZERO,
false,
0,
None,
@@ -4209,7 +4209,7 @@ mod tests {
AlternateScroll::On,
None,
Vec::new(),
0,
Duration::ZERO,
false,
0,
Some(completion_tx),