mirror of
https://github.com/openai/codex.git
synced 2026-11-13 21:30:47 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "1.95.0"
|
||||
channel = "1.99.1"
|
||||
components = ["clippy", "rustfmt", "rust-src"]
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-2
@@ -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(),
|
||||
]),
|
||||
]
|
||||
|
||||
@@ -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)| {
|
||||
(
|
||||
|
||||
@@ -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 `\\?\\`).
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user