Upgrade the Rust toolchain to 1.99.1 (#61205)

## What changed

- Update the workspace, Bazel toolchain and lockfile, CI and release workflows, and Windows setup script from Rust `1.95.0` to `1.99.1`.
- Adapt Rust code to the updated toolchain and Clippy lints, including `try_update` for atomics, `as_chunks` for fixed-size slices, and targeted allowances for generated tonic services.
- Refresh the halfwidth sound mark rendering snapshot to use literal characters in debug output.

GitOrigin-RevId: 5852029f687436dc814c2bca68141ee1f4a67d49
This commit is contained in:
ioanbudea-OAI
2026-11-12 23:51:52 +00:00
committed by copyberry
parent 1f175fa3c4
commit caf0d30005
45 changed files with 193 additions and 196 deletions
-1
View File
@@ -565,7 +565,6 @@ fn signing_key_from_private_key_pkcs8_base64(private_key_pkcs8_base64: &str) ->
#[cfg(test)]
mod tests {
use base64::Engine as _;
use ed25519_dalek::Signature;
use ed25519_dalek::Verifier as _;
use jsonwebtoken::EncodingKey;
+3 -3
View File
@@ -1289,7 +1289,7 @@ impl MessageProcessor {
.clients_revoke(params)
.await
.map(|response| Some(response.into())),
ClientRequest::ConfigRequirementsRead { params: _, .. } => self
ClientRequest::ConfigRequirementsRead { .. } => self
.config_processor
.config_requirements_read()
.await
@@ -1358,7 +1358,7 @@ impl MessageProcessor {
.model_provider_config_write(params)
.await
.map(|r| Some(r.into())),
ClientRequest::ModelProviderCapabilitiesRead { params: _, .. } => self
ClientRequest::ModelProviderCapabilitiesRead { .. } => self
.config_processor
.model_provider_capabilities_read()
.await
@@ -1820,7 +1820,7 @@ impl MessageProcessor {
ClientRequest::ThreadTimelineList { params, .. } => {
self.thread_processor.thread_timeline_list(params).await
}
ClientRequest::ThreadRealtimeListVoices { params: _, .. } => {
ClientRequest::ThreadRealtimeListVoices { .. } => {
self.turn_processor.thread_realtime_list_voices().await
}
ClientRequest::ReviewStart { params, .. } => {
@@ -1,3 +1,5 @@
#![allow(clippy::double_must_use)] // Emitted by async_trait in the generated tonic service.
#[cfg(codex_bazel)]
pub use code_mode_proto::codex::code_mode::v1::*;
@@ -153,7 +153,7 @@ impl SessionRuntime {
fn allocate_cell_id(&self) -> Result<CellId, Error> {
self.inner
.next_cell_id
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |next_cell_id| {
.try_update(Ordering::Relaxed, Ordering::Relaxed, |next_cell_id| {
next_cell_id.checked_add(1)
})
.map(|cell_id| CellId::new(cell_id.to_string()))
@@ -42,13 +42,14 @@ pub(super) async fn emit_update(
submit_id: &str,
tx_event: &Sender<Event>,
update: McpStartupUpdateEvent,
) -> Result<(), async_channel::SendError<Event>> {
) -> Result<(), Box<async_channel::SendError<Event>>> {
tx_event
.send(Event {
id: submit_id.to_string(),
msg: EventMsg::McpStartupUpdate(update),
})
.await
.map_err(Box::new)
}
pub(super) fn mcp_startup_failure_reason(
@@ -20,6 +20,7 @@ use super::ThreadConfigSource;
use super::UserThreadConfig;
use proto::thread_config_loader_client::ThreadConfigLoaderClient;
#[allow(clippy::double_must_use)] // Emitted by async_trait in the generated tonic service.
#[path = "proto/codex.thread_config.v1.rs"]
mod proto;
+7 -4
View File
@@ -276,10 +276,13 @@ pub enum ExecPolicyUpdateError {
JoinBlockingTask { source: tokio::task::JoinError },
#[error("failed to update in-memory rules: {source}")]
AddRule {
#[from]
source: ExecPolicyRuleError,
},
AddRule { source: ExecPolicyRuleError },
}
impl From<ExecPolicyRuleError> for ExecPolicyUpdateError {
fn from(source: ExecPolicyRuleError) -> Self {
Self::AddRule { source }
}
}
pub(crate) struct ExecPolicyManager {
+3 -3
View File
@@ -367,14 +367,14 @@ impl RealtimeStreamedItem {
if self.buffered_text.is_empty() {
return None;
}
let text = self.buffered_text.drain(..).collect::<String>();
let text = std::mem::take(&mut self.buffered_text);
let text = format!("{prefix}{text}");
self.sent_bytes += text.len();
return Some(text);
}
let head = self.buffered_text.drain(..).collect::<String>();
let tail = self.tail_text.drain(..).collect::<String>();
let head = std::mem::take(&mut self.buffered_text);
let tail = std::mem::take(&mut self.tail_text);
let text = format!("{prefix}{head}{HANDOFF_STREAM_TRUNCATION_MARKER}{tail}");
self.sent_bytes += text.len();
Some(text)
@@ -398,7 +398,7 @@ impl ExecutedToolCalls {
fn reserve_direct_call(&self) -> Option<DirectCallPermit> {
let recording = Arc::downgrade(&self.lock_state().as_ref()?.recording);
self.pending_direct_calls
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |pending| {
.try_update(Ordering::Relaxed, Ordering::Relaxed, |pending| {
(pending < MAX_PENDING_EXECUTED_TOOL_CALLS).then_some(pending + 1)
})
.ok()?;
@@ -565,7 +565,7 @@ impl Respond for CodexAppsJsonRpcResponder {
.as_ref()
.is_some_and(|remaining| {
remaining
.fetch_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
.try_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
remaining.checked_sub(1)
})
.is_ok()
+2 -1
View File
@@ -4008,7 +4008,8 @@ async fn astra_async_compaction_keeps_work_added_after_its_snapshot(
)
.await?;
assert_eq!(compaction_events.len(), if over_budget { 4 } else { 2 });
for pair in compaction_events.chunks_exact(2) {
const EVENTS_PER_COMPACTION: usize = 2;
for pair in compaction_events.as_chunks::<EVENTS_PER_COMPACTION>().0 {
assert_eq!((pair[0].0, pair[1].0), ("started", "completed"));
assert_eq!(pair[0].1, pair[1].1);
}
+1 -1
View File
@@ -688,7 +688,7 @@ async fn sandbox_denied_exec_command_returns_original_output() -> Result<()> {
"printf {sentinel:?} >&2; printf {content:?} > {path:?}",
sentinel = format!("{sentinel}\n"),
content = "sandbox denied",
path = &target_path
path = target_path
);
let args = json!({
"cmd": command,
+1 -1
View File
@@ -32,7 +32,7 @@ impl Gauge {
pub fn decrement(&self) {
let _ = self
.value
.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |value| {
.try_update(Ordering::Relaxed, Ordering::Relaxed, |value| {
Some(value.saturating_sub(1))
});
}
@@ -273,7 +273,7 @@ impl EnvironmentInfo {
if let Some(path) = std::env::var_os(name)
.filter(|path| !path.is_empty())
.filter(|path| cfg!(unix) || std::path::Path::new(path).is_absolute())
.and_then(&normalize_temp_path)
.and_then(normalize_temp_path)
&& !temporary_directories.contains(&path)
{
temporary_directories.push(path);
+2 -4
View File
@@ -2459,10 +2459,8 @@ fn decode_utf16(
return Err(PromptDecodeError::InvalidUtf16 { encoding });
}
let units: Vec<u16> = input
.chunks_exact(2)
.map(|chunk| decode_unit([chunk[0], chunk[1]]))
.collect();
let (units, _) = input.as_chunks();
let units: Vec<_> = units.iter().copied().map(decode_unit).collect();
String::from_utf16(&units).map_err(|_| PromptDecodeError::InvalidUtf16 { encoding })
}
+2 -2
View File
@@ -302,10 +302,10 @@ async fn read_bounded_text(
let mut stream = file_system
.read_file_stream(path)
.await
.map_err(&read_error)?;
.map_err(read_error)?;
let mut contents = Vec::new();
while let Some(chunk) = stream.next().await {
let chunk = chunk.map_err(&read_error)?;
let chunk = chunk.map_err(read_error)?;
if contents.len().saturating_add(chunk.len()) > MAX_SKILL_RESOURCE_CONTENT_BYTES {
return Err(SkillProviderError::new(format!(
"executor skill resource {resource} exceeds {MAX_SKILL_RESOURCE_CONTENT_BYTES} bytes"
+2 -3
View File
@@ -222,7 +222,8 @@ fn mcp_server_toml_table(
if let Some(env) = server_config.get("env").and_then(JsonValue::as_object) {
append_env_config(&mut table, env)?;
}
} else if let Some(url) = server_config.get("url").and_then(json_string) {
} else {
let url = server_config.get("url").and_then(json_string)?;
if !matches!(
transport_type,
None | Some("http") | Some("streamable_http")
@@ -236,8 +237,6 @@ fn mcp_server_toml_table(
if let Some(headers) = server_config.get("headers").and_then(JsonValue::as_object) {
append_header_config(&mut table, headers)?;
}
} else {
return None;
}
Some(table)
+1 -1
View File
@@ -1,3 +1,3 @@
[toolchain]
channel = "1.95.0"
channel = "1.99.1"
components = ["clippy", "rustfmt", "rust-src"]
+3 -3
View File
@@ -2026,7 +2026,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() {
assert!(
!output.status.success(),
"command to write {} should fail under seatbelt",
&config_toml.display()
config_toml.display()
);
assert_seatbelt_denied(&output.stderr, &config_toml);
@@ -2070,7 +2070,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() {
assert!(
!output.status.success(),
"command to write {} should fail under seatbelt",
&pre_commit_hook.display()
pre_commit_hook.display()
);
assert_seatbelt_denied(&output.stderr, &pre_commit_hook);
@@ -2114,7 +2114,7 @@ fn create_seatbelt_args_with_read_only_git_and_codex_subpaths() {
assert!(
output.status.success(),
"command to write {} should succeed under seatbelt",
&allowed_file.display()
allowed_file.display()
);
assert_eq!(
"this is allowed\n",
+1 -1
View File
@@ -179,7 +179,7 @@ if (-not (Ensure-Command 'cargo')) {
Write-Host "==> Configuring Rust toolchain per rust-toolchain.toml" -ForegroundColor Cyan
# Pin to the workspace toolchain and install components
$toolchain = '1.95.0'
$toolchain = '1.99.1'
& rustup toolchain install $toolchain --profile minimal | Out-Host
& rustup default $toolchain | Out-Host
& rustup component add clippy rustfmt rust-src --toolchain $toolchain | Out-Host
+2 -5
View File
@@ -88,11 +88,8 @@ pub fn try_parse_word_only_commands_sequence(tree: &Tree, src: &str) -> Option<V
let mut commands = Vec::new();
for node in command_nodes {
if let Some(words) = parse_plain_command_from_node(node, src) {
commands.push(words);
} else {
return None;
}
let words = parse_plain_command_from_node(node, src)?;
commands.push(words);
}
Some(commands)
}
@@ -2825,7 +2825,8 @@ async fn older_external_server_starts_without_unsupported_dynamic_tools_or_histo
let starts = recorded_params(&requests, "thread/start");
assert_eq!(starts.len(), 6);
for attempts in starts.chunks_exact(3) {
const ATTEMPTS_PER_START: usize = 3;
for attempts in starts.as_chunks::<ATTEMPTS_PER_START>().0 {
assert_eq!(attempts[0]["dynamicTools"][0]["type"], "namespace");
assert_eq!(attempts[0]["historyMode"], "paginated");
assert_eq!(attempts[1]["dynamicTools"], serde_json::Value::Null);
@@ -52,7 +52,7 @@ impl AsyncQuestions {
let mut spacer_after_input = 0;
let progress_height;
let footer_lines;
let notes_height;
let mut notes_height = 0;
if has_options {
let min_options_height = remaining.min(1);
@@ -71,7 +71,6 @@ impl AsyncQuestions {
spacer_after_question = u16::from(remaining > 0);
remaining -= spacer_after_question;
options_height += remaining.min(full_options_height.saturating_sub(options_height));
notes_height = 0;
} else {
// Freeform answers take their preferred input height before hints and progress.
let preferred_notes = self
@@ -1119,7 +1119,7 @@ impl ListSelectionView {
None
}
.or_else(|| self.footer_note.clone());
let mut lines = note.map(&wrap).unwrap_or_default();
let mut lines = note.map(wrap).unwrap_or_default();
if self.reserve_result_rows && show_selected_description {
let height = self
.items
@@ -22,12 +22,12 @@ Buffer {
[
Line::from_iter([
Span::from("ab").bold(),
Span::from("カ\u{ff9e}").cyan(),
Span::from("ガ").cyan(),
Span::from("…").cyan(),
]),
Line::from_iter([
Span::from("xy").bold(),
Span::from("ハ\u{ff9f}").magenta(),
Span::from("パ").magenta(),
Span::from("…").magenta(),
]),
]
+4 -2
View File
@@ -149,8 +149,10 @@ fn render_navigation_hints(area: Rect, buf: &mut Buffer, keymap: &PagerKeymap) {
("jump_top", &keymap.jump_top),
("jump_bottom", &keymap.jump_bottom),
];
let hints = actions
.chunks_exact(2)
const ACTIONS_PER_HINT: usize = 2;
let (action_groups, _) = actions.as_chunks::<ACTIONS_PER_HINT>();
let hints = action_groups
.iter()
.zip(["to scroll", "to page", "to jump"])
.map(|(actions, description)| {
(
+2 -1
View File
@@ -216,7 +216,8 @@ struct Palette {
impl Palette {
fn from_rgba(rgba: &[u8]) -> Self {
let mut used = [false; PALETTE_COLOR_COUNT];
for pixel in rgba.chunks_exact(4) {
const RGBA_CHANNELS: usize = 4;
for pixel in rgba.as_chunks::<RGBA_CHANNELS>().0 {
if pixel[3] < TRANSPARENT_ALPHA_THRESHOLD {
continue;
}
@@ -262,10 +262,8 @@ fn render_windows_opaque_fallback(path_bytes: &[u8]) -> Option<String> {
if !path_bytes.len().is_multiple_of(2) {
return None;
}
let path_wide = path_bytes
.chunks_exact(2)
.map(|bytes| u16::from_le_bytes([bytes[0], bytes[1]]))
.collect::<Vec<_>>();
let (units, _) = path_bytes.as_chunks();
let path_wide: Vec<_> = units.iter().copied().map(u16::from_le_bytes).collect();
// Windows absolute paths either have a rooted drive prefix (`C:\\`) or a
// rooted namespace/UNC prefix (`\\server`, `\\.\\`, or `\\?\\`).
+4 -7
View File
@@ -586,10 +586,8 @@ impl PathUri {
let decoded_path = {
use std::os::windows::ffi::OsStringExt;
path_bytes.len().is_multiple_of(2).then(|| {
let path_wide = path_bytes
.chunks_exact(2)
.map(|bytes| u16::from_le_bytes([bytes[0], bytes[1]]))
.collect::<Vec<_>>();
let (units, _) = path_bytes.as_chunks();
let path_wide: Vec<_> = units.iter().copied().map(u16::from_le_bytes).collect();
std::path::PathBuf::from(std::ffi::OsString::from_wide(&path_wide))
})
};
@@ -818,9 +816,8 @@ fn infer_opaque_path_convention(path_bytes: &[u8]) -> Option<PathConvention> {
return None;
}
let mut path_wide = path_bytes
.chunks_exact(2)
.map(|bytes| u16::from_le_bytes([bytes[0], bytes[1]]));
let (units, _) = path_bytes.as_chunks();
let mut path_wide = units.iter().copied().map(u16::from_le_bytes);
let first = path_wide.next()?;
let second = path_wide.next()?;
let has_drive = u8::try_from(first).is_ok_and(|drive| drive.is_ascii_alphabetic())
@@ -92,7 +92,7 @@ where
.iter()
.map(|spec| longest_suffix_prefix_len(pending, spec.open))
.max()
.map_or(0, std::convert::identity)
.unwrap_or(0)
}
fn push_visible_prefix(out: &mut StreamTextChunk<ExtractedInlineTag<T>>, pending: &str) {
@@ -16,12 +16,8 @@ fn microphone_selection_excludes_playback_channels() {
plugged_in[3] = 0.7;
let mut unplugged = plugged_in;
unplugged[0] = 0.0;
let interleaved = [plugged_in, unplugged].concat();
let captured: Vec<_> = interleaved
.chunks_exact(/*chunk_size*/ 16)
.map(|frame| source.sample(frame))
.collect();
assert_eq!(captured, vec![0.25, 0.0]);
let captured = [source.sample(&plugged_in), source.sample(&unplugged)];
assert_eq!(captured, [0.25, 0.0]);
}
#[test]
+2 -2
View File
@@ -67,8 +67,8 @@ impl PlaybackWriter {
at: Instant::now(),
generation: self.epoch,
};
for (sample, bytes) in frame.samples.iter_mut().zip(bytes.chunks_exact(4)) {
*sample = f32::from_le_bytes(bytes.try_into().map_err(|_| "invalid speaker buffer")?);
for (sample, bytes) in frame.samples.iter_mut().zip(bytes.as_chunks().0) {
*sample = f32::from_le_bytes(*bytes);
if !sample.is_finite() {
return Err("invalid speaker sample");
}
+3 -1
View File
@@ -444,7 +444,9 @@ fn sha256_digest_arg(flag_name: &str, value: &str) -> anyhow::Result<[u8; 32]> {
}
let mut digest = [0u8; 32];
for (index, pair) in trimmed.as_bytes().chunks_exact(2).enumerate() {
const HEX_DIGITS_PER_BYTE: usize = 2;
let (pairs, _) = trimmed.as_bytes().as_chunks::<HEX_DIGITS_PER_BYTE>();
for (index, pair) in pairs.iter().enumerate() {
let high = hex_nibble(flag_name, pair[0])?;
let low = hex_nibble(flag_name, pair[1])?;
digest[index] = (high << 4) | low;