diff --git a/codex-rs/Cargo.toml b/codex-rs/Cargo.toml index 1ec4191e..7e0d5620 100644 --- a/codex-rs/Cargo.toml +++ b/codex-rs/Cargo.toml @@ -174,6 +174,8 @@ needless_option_as_deref = "deny" needless_question_mark = "deny" needless_update = "deny" redundant_clone = "deny" +redundant_closure = "deny" +redundant_closure_for_method_calls = "deny" redundant_static_lifetimes = "deny" trivially_copy_pass_by_ref = "deny" uninlined_format_args = "deny" diff --git a/codex-rs/apply-patch/src/lib.rs b/codex-rs/apply-patch/src/lib.rs index 5bda31c4..189c1a07 100644 --- a/codex-rs/apply-patch/src/lib.rs +++ b/codex-rs/apply-patch/src/lib.rs @@ -648,21 +648,18 @@ fn derive_new_contents_from_chunks( } }; - let mut original_lines: Vec = original_contents - .split('\n') - .map(|s| s.to_string()) - .collect(); + let mut original_lines: Vec = original_contents.split('\n').map(String::from).collect(); // Drop the trailing empty element that results from the final newline so // that line counts match the behaviour of standard `diff`. - if original_lines.last().is_some_and(|s| s.is_empty()) { + if original_lines.last().is_some_and(String::is_empty) { original_lines.pop(); } let replacements = compute_replacements(&original_lines, path, chunks)?; let new_lines = apply_replacements(original_lines, &replacements); let mut new_lines = new_lines; - if !new_lines.last().is_some_and(|s| s.is_empty()) { + if !new_lines.last().is_some_and(String::is_empty) { new_lines.push(String::new()); } let new_contents = new_lines.join("\n"); @@ -706,7 +703,7 @@ fn compute_replacements( if chunk.old_lines.is_empty() { // Pure addition (no old lines). We'll add them at the end or just // before the final empty line if one exists. - let insertion_idx = if original_lines.last().is_some_and(|s| s.is_empty()) { + let insertion_idx = if original_lines.last().is_some_and(String::is_empty) { original_lines.len() - 1 } else { original_lines.len() @@ -732,11 +729,11 @@ fn compute_replacements( let mut new_slice: &[String] = &chunk.new_lines; - if found.is_none() && pattern.last().is_some_and(|s| s.is_empty()) { + if found.is_none() && pattern.last().is_some_and(String::is_empty) { // Retry without the trailing empty line which represents the final // newline in the file. pattern = &pattern[..pattern.len() - 1]; - if new_slice.last().is_some_and(|s| s.is_empty()) { + if new_slice.last().is_some_and(String::is_empty) { new_slice = &new_slice[..new_slice.len() - 1]; } @@ -848,6 +845,7 @@ mod tests { use super::*; use pretty_assertions::assert_eq; use std::fs; + use std::string::ToString; use tempfile::tempdir; /// Helper to construct a patch with the given body. @@ -856,7 +854,7 @@ mod tests { } fn strs_to_strings(strs: &[&str]) -> Vec { - strs.iter().map(|s| s.to_string()).collect() + strs.iter().map(ToString::to_string).collect() } // Test helpers to reduce repetition when building bash -lc heredoc scripts diff --git a/codex-rs/apply-patch/src/seek_sequence.rs b/codex-rs/apply-patch/src/seek_sequence.rs index 0144580f..b005b08c 100644 --- a/codex-rs/apply-patch/src/seek_sequence.rs +++ b/codex-rs/apply-patch/src/seek_sequence.rs @@ -112,9 +112,10 @@ pub(crate) fn seek_sequence( #[cfg(test)] mod tests { use super::seek_sequence; + use std::string::ToString; fn to_vec(strings: &[&str]) -> Vec { - strings.iter().map(|s| s.to_string()).collect() + strings.iter().map(ToString::to_string).collect() } #[test] diff --git a/codex-rs/arg0/src/lib.rs b/codex-rs/arg0/src/lib.rs index d5df68e5..e70ff2df 100644 --- a/codex-rs/arg0/src/lib.rs +++ b/codex-rs/arg0/src/lib.rs @@ -54,7 +54,7 @@ where let argv1 = args.next().unwrap_or_default(); if argv1 == CODEX_APPLY_PATCH_ARG1 { - let patch_arg = args.next().and_then(|s| s.to_str().map(|s| s.to_owned())); + let patch_arg = args.next().and_then(|s| s.to_str().map(str::to_owned)); let exit_code = match patch_arg { Some(patch_arg) => { let mut stdout = std::io::stdout(); diff --git a/codex-rs/core/src/bash.rs b/codex-rs/core/src/bash.rs index 4bed3a9c..f25b4f7f 100644 --- a/codex-rs/core/src/bash.rs +++ b/codex-rs/core/src/bash.rs @@ -1,3 +1,4 @@ +use tree_sitter::Node; use tree_sitter::Parser; use tree_sitter::Tree; use tree_sitter_bash::LANGUAGE as BASH; @@ -74,7 +75,7 @@ pub fn try_parse_word_only_commands_sequence(tree: &Tree, src: &str) -> Option( if let Some(reasoning_val) = choice.get("delta").and_then(|d| d.get("reasoning")) { let mut maybe_text = reasoning_val .as_str() - .map(|s| s.to_string()) + .map(str::to_string) .filter(|s| !s.is_empty()); if maybe_text.is_none() && reasoning_val.is_object() { diff --git a/codex-rs/core/src/client.rs b/codex-rs/core/src/client.rs index 57848d38..d49bb614 100644 --- a/codex-rs/core/src/client.rs +++ b/codex-rs/core/src/client.rs @@ -4,6 +4,7 @@ use std::sync::OnceLock; use std::time::Duration; use crate::AuthManager; +use crate::auth::CodexAuth; use bytes::Bytes; use codex_protocol::mcp_protocol::AuthMode; use codex_protocol::mcp_protocol::ConversationId; @@ -337,7 +338,7 @@ impl ModelClient { // token. let plan_type = error .plan_type - .or_else(|| auth.as_ref().and_then(|a| a.get_plan_type())); + .or_else(|| auth.as_ref().and_then(CodexAuth::get_plan_type)); let resets_in_seconds = error.resets_in_seconds; return Err(CodexErr::UsageLimitReached(UsageLimitReachedError { plan_type, diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index dfea8919..08b28bde 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -1747,7 +1747,7 @@ async fn run_task( .unwrap_or(i64::MAX); let total_usage_tokens = total_token_usage .as_ref() - .map(|usage| usage.tokens_in_context_window()); + .map(TokenUsage::tokens_in_context_window); let token_limit_reached = total_usage_tokens .map(|tokens| (tokens as i64) >= limit) .unwrap_or(false); diff --git a/codex-rs/core/src/config_edit.rs b/codex-rs/core/src/config_edit.rs index 4b3a5cbd..7b1d75d0 100644 --- a/codex-rs/core/src/config_edit.rs +++ b/codex-rs/core/src/config_edit.rs @@ -136,7 +136,7 @@ async fn persist_overrides_with_behavior( } else { doc.get("profile") .and_then(|i| i.as_str()) - .map(|s| s.to_string()) + .map(str::to_string) }; let mut mutated = false; diff --git a/codex-rs/core/src/custom_prompts.rs b/codex-rs/core/src/custom_prompts.rs index 4974e7c5..357abef5 100644 --- a/codex-rs/core/src/custom_prompts.rs +++ b/codex-rs/core/src/custom_prompts.rs @@ -52,7 +52,7 @@ pub async fn discover_prompts_in_excluding( let Some(name) = path .file_stem() .and_then(|s| s.to_str()) - .map(|s| s.to_string()) + .map(str::to_string) else { continue; }; diff --git a/codex-rs/core/src/git_info.rs b/codex-rs/core/src/git_info.rs index 832b28f1..5c16b72d 100644 --- a/codex-rs/core/src/git_info.rs +++ b/codex-rs/core/src/git_info.rs @@ -200,7 +200,7 @@ async fn get_git_remotes(cwd: &Path) -> Option> { let mut remotes: Vec = String::from_utf8(output.stdout) .ok()? .lines() - .map(|s| s.to_string()) + .map(str::to_string) .collect(); if let Some(pos) = remotes.iter().position(|r| r == "origin") { let origin = remotes.remove(pos); @@ -477,7 +477,7 @@ async fn diff_against_sha(cwd: &Path, sha: &GitSha) -> Option { let untracked: Vec = String::from_utf8(untracked_output.stdout) .ok()? .lines() - .map(|s| s.to_string()) + .map(str::to_string) .filter(|s| !s.is_empty()) .collect(); diff --git a/codex-rs/core/src/is_safe_command.rs b/codex-rs/core/src/is_safe_command.rs index f54e247f..12eb36e0 100644 --- a/codex-rs/core/src/is_safe_command.rs +++ b/codex-rs/core/src/is_safe_command.rs @@ -160,9 +160,10 @@ fn is_valid_sed_n_arg(arg: Option<&str>) -> bool { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; fn vec_str(args: &[&str]) -> Vec { - args.iter().map(|s| s.to_string()).collect() + args.iter().map(ToString::to_string).collect() } #[test] diff --git a/codex-rs/core/src/openai_tools.rs b/codex-rs/core/src/openai_tools.rs index 05b71ce6..48dca796 100644 --- a/codex-rs/core/src/openai_tools.rs +++ b/codex-rs/core/src/openai_tools.rs @@ -400,10 +400,7 @@ fn sanitize_json_schema(value: &mut JsonValue) { } // Normalize/ensure type - let mut ty = map - .get("type") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()); + let mut ty = map.get("type").and_then(|v| v.as_str()).map(str::to_string); // If type is an array (union), pick first supported; else leave to inference if ty.is_none() diff --git a/codex-rs/core/src/parse_command.rs b/codex-rs/core/src/parse_command.rs index 1d2948a4..3c89b61c 100644 --- a/codex-rs/core/src/parse_command.rs +++ b/codex-rs/core/src/parse_command.rs @@ -40,7 +40,7 @@ impl From for codex_protocol::parse_command::ParsedCommand { } fn shlex_join(tokens: &[String]) -> String { - shlex_try_join(tokens.iter().map(|s| s.as_str())) + shlex_try_join(tokens.iter().map(String::as_str)) .unwrap_or_else(|_| "".to_string()) } @@ -72,13 +72,14 @@ pub fn parse_command(command: &[String]) -> Vec { /// Tests are at the top to encourage using TDD + Codex to fix the implementation. mod tests { use super::*; + use std::string::ToString; fn shlex_split_safe(s: &str) -> Vec { - shlex_split(s).unwrap_or_else(|| s.split_whitespace().map(|s| s.to_string()).collect()) + shlex_split(s).unwrap_or_else(|| s.split_whitespace().map(ToString::to_string).collect()) } fn vec_str(args: &[&str]) -> Vec { - args.iter().map(|s| s.to_string()).collect() + args.iter().map(ToString::to_string).collect() } fn assert_parsed(args: &[String], expected: Vec) { @@ -894,7 +895,7 @@ fn simplify_once(commands: &[ParsedCommand]) -> Option> { // echo ... && ...rest => ...rest if let ParsedCommand::Unknown { cmd } = &commands[0] - && shlex_split(cmd).is_some_and(|t| t.first().map(|s| s.as_str()) == Some("echo")) + && shlex_split(cmd).is_some_and(|t| t.first().map(String::as_str) == Some("echo")) { return Some(commands[1..].to_vec()); } @@ -902,7 +903,7 @@ fn simplify_once(commands: &[ParsedCommand]) -> Option> { // cd foo && [any command] => [any command] (keep non-cd when a cd is followed by something) if let Some(idx) = commands.iter().position(|pc| match pc { ParsedCommand::Unknown { cmd } => { - shlex_split(cmd).is_some_and(|t| t.first().map(|s| s.as_str()) == Some("cd")) + shlex_split(cmd).is_some_and(|t| t.first().map(String::as_str) == Some("cd")) } _ => false, }) && commands.len() > idx + 1 @@ -1035,7 +1036,7 @@ fn short_display_path(path: &str) -> String { }); parts .next() - .map(|s| s.to_string()) + .map(str::to_string) .unwrap_or_else(|| trimmed.to_string()) } @@ -1190,8 +1191,8 @@ fn parse_bash_lc_commands(original: &[String]) -> Option> { if had_connectors { let has_pipe = script_tokens.iter().any(|t| t == "|"); let has_sed_n = script_tokens.windows(2).any(|w| { - w.first().map(|s| s.as_str()) == Some("sed") - && w.get(1).map(|s| s.as_str()) == Some("-n") + w.first().map(String::as_str) == Some("sed") + && w.get(1).map(String::as_str) == Some("-n") }); if has_pipe && has_sed_n { ParsedCommand::Read { @@ -1271,7 +1272,7 @@ fn is_small_formatting_command(tokens: &[String]) -> bool { // Keep `sed -n file` (treated as a file read elsewhere); // otherwise consider it a formatting helper in a pipeline. tokens.len() < 4 - || !(tokens[1] == "-n" && is_valid_sed_n_arg(tokens.get(2).map(|s| s.as_str()))) + || !(tokens[1] == "-n" && is_valid_sed_n_arg(tokens.get(2).map(String::as_str))) } _ => false, } @@ -1318,7 +1319,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand { (None, non_flags.first().map(|s| short_display_path(s))) } else { ( - non_flags.first().cloned().map(|s| s.to_string()), + non_flags.first().cloned().map(String::from), non_flags.get(1).map(|s| short_display_path(s)), ) }; @@ -1353,7 +1354,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand { .collect(); // Do not shorten the query: grep patterns may legitimately contain slashes // and should be preserved verbatim. Only paths should be shortened. - let query = non_flags.first().cloned().map(|s| s.to_string()); + let query = non_flags.first().cloned().map(String::from); let path = non_flags.get(1).map(|s| short_display_path(s)); ParsedCommand::Search { cmd: shlex_join(main_cmd), @@ -1363,7 +1364,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand { } Some((head, tail)) if head == "cat" => { // Support both `cat ` and `cat -- ` forms. - let effective_tail: &[String] = if tail.first().map(|s| s.as_str()) == Some("--") { + let effective_tail: &[String] = if tail.first().map(String::as_str) == Some("--") { &tail[1..] } else { tail @@ -1479,7 +1480,7 @@ fn summarize_main_tokens(main_cmd: &[String]) -> ParsedCommand { if head == "sed" && tail.len() >= 3 && tail[0] == "-n" - && is_valid_sed_n_arg(tail.get(1).map(|s| s.as_str())) => + && is_valid_sed_n_arg(tail.get(1).map(String::as_str)) => { if let Some(path) = tail.get(2) { let name = short_display_path(path); diff --git a/codex-rs/core/src/shell.rs b/codex-rs/core/src/shell.rs index 3bfef7e1..ac93d8b1 100644 --- a/codex-rs/core/src/shell.rs +++ b/codex-rs/core/src/shell.rs @@ -73,7 +73,7 @@ impl Shell { return Some(command); } - let joined = shlex::try_join(command.iter().map(|s| s.as_str())).ok(); + let joined = shlex::try_join(command.iter().map(String::as_str)).ok(); return joined.map(|arg| { vec![ ps.exe.clone(), @@ -111,7 +111,7 @@ fn format_shell_invocation_with_rc( rc_path: &str, ) -> Option> { let joined = strip_bash_lc(command) - .or_else(|| shlex::try_join(command.iter().map(|s| s.as_str())).ok())?; + .or_else(|| shlex::try_join(command.iter().map(String::as_str)).ok())?; let rc_command = if std::path::Path::new(rc_path).exists() { format!("source {rc_path} && ({joined})") @@ -224,6 +224,7 @@ pub async fn default_user_shell() -> Shell { mod tests { use super::*; use std::process::Command; + use std::string::ToString; #[tokio::test] async fn test_current_shell_detects_zsh() { @@ -327,7 +328,7 @@ mod tests { }); let actual_cmd = shell - .format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect()); + .format_default_shell_invocation(input.iter().map(ToString::to_string).collect()); let expected_cmd = expected_cmd .iter() .map(|s| s.replace("BASHRC_PATH", bashrc_path.to_str().unwrap())) @@ -371,6 +372,7 @@ mod tests { #[cfg(target_os = "macos")] mod macos_tests { use super::*; + use std::string::ToString; #[tokio::test] async fn test_run_with_profile_escaping_and_execution() { @@ -434,7 +436,7 @@ mod macos_tests { }); let actual_cmd = shell - .format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect()); + .format_default_shell_invocation(input.iter().map(ToString::to_string).collect()); let expected_cmd = expected_cmd .iter() .map(|s| s.replace("ZSHRC_PATH", zshrc_path.to_str().unwrap())) @@ -559,10 +561,10 @@ mod tests_windows { for (shell, input, expected_cmd) in cases { let actual_cmd = shell - .format_default_shell_invocation(input.iter().map(|s| s.to_string()).collect()); + .format_default_shell_invocation(input.iter().map(|s| (*s).to_string()).collect()); assert_eq!( actual_cmd, - Some(expected_cmd.iter().map(|s| s.to_string()).collect()) + Some(expected_cmd.iter().map(|s| (*s).to_string()).collect()) ); } } diff --git a/codex-rs/core/tests/suite/exec.rs b/codex-rs/core/tests/suite/exec.rs index 280917b5..2d1e99b0 100644 --- a/codex-rs/core/tests/suite/exec.rs +++ b/codex-rs/core/tests/suite/exec.rs @@ -1,6 +1,7 @@ #![cfg(target_os = "macos")] use std::collections::HashMap; +use std::string::ToString; use codex_core::exec::ExecParams; use codex_core::exec::ExecToolCallOutput; @@ -29,7 +30,7 @@ async fn run_test_cmd(tmp: TempDir, cmd: Vec<&str>) -> Result String { - try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" ")) + try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" ")) } fn format_file_change(change: &FileChange) -> &'static str { diff --git a/codex-rs/exec/tests/suite/resume.rs b/codex-rs/exec/tests/suite/resume.rs index 5868ed8e..4c4d343e 100644 --- a/codex-rs/exec/tests/suite/resume.rs +++ b/codex-rs/exec/tests/suite/resume.rs @@ -3,6 +3,7 @@ use anyhow::Context; use assert_cmd::prelude::*; use serde_json::Value; use std::process::Command; +use std::string::ToString; use tempfile::TempDir; use uuid::Uuid; use walkdir::WalkDir; @@ -45,7 +46,7 @@ fn find_session_file_containing_marker( && payload.get("type").and_then(|t| t.as_str()) == Some("message") && payload .get("content") - .map(|c| c.to_string()) + .map(ToString::to_string) .unwrap_or_default() .contains(marker) { diff --git a/codex-rs/execpolicy/src/execv_checker.rs b/codex-rs/execpolicy/src/execv_checker.rs index ae61d54c..1c03f591 100644 --- a/codex-rs/execpolicy/src/execv_checker.rs +++ b/codex-rs/execpolicy/src/execv_checker.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ffi::OsString; use std::path::Path; use std::path::PathBuf; @@ -108,7 +109,7 @@ fn ensure_absolute_path(path: &str, cwd: &Option) -> Result { file.absolutize() }; result - .map(|path| path.into_owned()) + .map(Cow::into_owned) .map_err(|error| CannotCanonicalizePath { file: path.to_string(), error: error.kind(), diff --git a/codex-rs/execpolicy/src/main.rs b/codex-rs/execpolicy/src/main.rs index 0a4b1764..68a72c04 100644 --- a/codex-rs/execpolicy/src/main.rs +++ b/codex-rs/execpolicy/src/main.rs @@ -10,6 +10,7 @@ use codex_execpolicy::get_default_policy; use serde::Deserialize; use serde::Serialize; use serde::de; +use starlark::Error as StarlarkError; use std::path::PathBuf; use std::str::FromStr; @@ -71,13 +72,13 @@ fn main() -> Result<()> { } None => get_default_policy(), }; - let policy = policy.map_err(|err| err.into_anyhow())?; + let policy = policy.map_err(StarlarkError::into_anyhow)?; let exec = match args.command { Command::Check { command } => match command.split_first() { Some((first, rest)) => ExecArg { program: first.to_string(), - args: rest.iter().map(|s| s.to_string()).collect(), + args: rest.to_vec(), }, None => { eprintln!("no command provided"); @@ -161,6 +162,6 @@ impl FromStr for ExecArg { type Err = anyhow::Error; fn from_str(s: &str) -> Result { - serde_json::from_str(s).map_err(|e| e.into()) + serde_json::from_str(s).map_err(Into::into) } } diff --git a/codex-rs/execpolicy/src/program.rs b/codex-rs/execpolicy/src/program.rs index fbe0a104..d0cec371 100644 --- a/codex-rs/execpolicy/src/program.rs +++ b/codex-rs/execpolicy/src/program.rs @@ -169,7 +169,7 @@ impl ProgramSpec { let mut options = self .required_options .difference(&matched_opt_names) - .map(|s| s.to_string()) + .map(String::from) .collect::>(); options.sort(); return Err(Error::MissingRequiredOptions { diff --git a/codex-rs/linux-sandbox/tests/suite/landlock.rs b/codex-rs/linux-sandbox/tests/suite/landlock.rs index ea4930fa..6af59ef0 100644 --- a/codex-rs/linux-sandbox/tests/suite/landlock.rs +++ b/codex-rs/linux-sandbox/tests/suite/landlock.rs @@ -38,7 +38,7 @@ async fn run_cmd(cmd: &[&str], writable_roots: &[PathBuf], timeout_ms: u64) { let cwd = std::env::current_dir().expect("cwd should exist"); let sandbox_cwd = cwd.clone(); let params = ExecParams { - command: cmd.iter().map(|elm| elm.to_string()).collect(), + command: cmd.iter().copied().map(str::to_owned).collect(), cwd, timeout_ms: Some(timeout_ms), env: create_env_from_core_vars(), @@ -138,7 +138,7 @@ async fn assert_network_blocked(cmd: &[&str]) { let cwd = std::env::current_dir().expect("cwd should exist"); let sandbox_cwd = cwd.clone(); let params = ExecParams { - command: cmd.iter().map(|s| s.to_string()).collect(), + command: cmd.iter().copied().map(str::to_owned).collect(), cwd, // Give the tool a generous 2-second timeout so even slow DNS timeouts // do not stall the suite. diff --git a/codex-rs/login/src/server.rs b/codex-rs/login/src/server.rs index 7255e468..a1e5e6c3 100644 --- a/codex-rs/login/src/server.rs +++ b/codex-rs/login/src/server.rs @@ -20,6 +20,7 @@ use codex_core::default_client::ORIGINATOR; use codex_core::token_data::TokenData; use codex_core::token_data::parse_id_token; use rand::RngCore; +use serde_json::Value as JsonValue; use tiny_http::Header; use tiny_http::Request; use tiny_http::Response; @@ -496,11 +497,11 @@ fn compose_success_url(port: u16, issuer: &str, id_token: &str, access_token: &s .unwrap_or(""); let completed_onboarding = token_claims .get("completed_platform_onboarding") - .and_then(|v| v.as_bool()) + .and_then(JsonValue::as_bool) .unwrap_or(false); let is_org_owner = token_claims .get("is_org_owner") - .and_then(|v| v.as_bool()) + .and_then(JsonValue::as_bool) .unwrap_or(false); let needs_setup = (!completed_onboarding) && is_org_owner; let plan_type = access_claims diff --git a/codex-rs/mcp-server/src/exec_approval.rs b/codex-rs/mcp-server/src/exec_approval.rs index 1985cc79..119481cd 100644 --- a/codex-rs/mcp-server/src/exec_approval.rs +++ b/codex-rs/mcp-server/src/exec_approval.rs @@ -58,7 +58,7 @@ pub(crate) async fn handle_exec_approval_request( call_id: String, ) { let escaped_command = - shlex::try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" ")); + shlex::try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" ")); let message = format!( "Allow Codex to run `{escaped_command}` in `{cwd}`?", cwd = cwd.to_string_lossy() diff --git a/codex-rs/mcp-server/tests/suite/codex_tool.rs b/codex-rs/mcp-server/tests/suite/codex_tool.rs index 78f758d6..a111539d 100644 --- a/codex-rs/mcp-server/tests/suite/codex_tool.rs +++ b/codex-rs/mcp-server/tests/suite/codex_tool.rs @@ -173,7 +173,7 @@ fn create_expected_elicitation_request( ) -> anyhow::Result { let expected_message = format!( "Allow Codex to run `{}` in `{}`?", - shlex::try_join(command.iter().map(|s| s.as_ref()))?, + shlex::try_join(command.iter().map(std::convert::AsRef::as_ref))?, workdir.to_string_lossy() ); Ok(JSONRPCRequest { diff --git a/codex-rs/ollama/src/client.rs b/codex-rs/ollama/src/client.rs index 45e04861..04b7e9de 100644 --- a/codex-rs/ollama/src/client.rs +++ b/codex-rs/ollama/src/client.rs @@ -117,7 +117,7 @@ impl OllamaClient { .map(|arr| { arr.iter() .filter_map(|v| v.get("name").and_then(|n| n.as_str())) - .map(|s| s.to_string()) + .map(str::to_string) .collect::>() }) .unwrap_or_default(); diff --git a/codex-rs/ollama/src/parser.rs b/codex-rs/ollama/src/parser.rs index b3ed2ca8..c39df668 100644 --- a/codex-rs/ollama/src/parser.rs +++ b/codex-rs/ollama/src/parser.rs @@ -16,8 +16,8 @@ pub(crate) fn pull_events_from_value(value: &JsonValue) -> Vec { .and_then(|d| d.as_str()) .unwrap_or("") .to_string(); - let total = value.get("total").and_then(|t| t.as_u64()); - let completed = value.get("completed").and_then(|t| t.as_u64()); + let total = value.get("total").and_then(JsonValue::as_u64); + let completed = value.get("completed").and_then(JsonValue::as_u64); if total.is_some() || completed.is_some() { events.push(PullEvent::ChunkProgress { digest, diff --git a/codex-rs/protocol-ts/src/lib.rs b/codex-rs/protocol-ts/src/lib.rs index 967d9b1f..3aec3d89 100644 --- a/codex-rs/protocol-ts/src/lib.rs +++ b/codex-rs/protocol-ts/src/lib.rs @@ -134,7 +134,7 @@ fn generate_index_ts(out_dir: &Path) -> Result { } let mut content = - String::with_capacity(HEADER.len() + entries.iter().map(|s| s.len()).sum::()); + String::with_capacity(HEADER.len() + entries.iter().map(String::len).sum::()); content.push_str(HEADER); for line in &entries { content.push_str(line); diff --git a/codex-rs/tui/src/bottom_pane/chat_composer.rs b/codex-rs/tui/src/bottom_pane/chat_composer.rs index d15265c5..65203b51 100644 --- a/codex-rs/tui/src/bottom_pane/chat_composer.rs +++ b/codex-rs/tui/src/bottom_pane/chat_composer.rs @@ -421,7 +421,7 @@ impl ChatComposer { // Capture any needed data from popup before clearing it. let prompt_content = match sel { CommandItem::UserPrompt(idx) => { - popup.prompt_content(idx).map(|s| s.to_string()) + popup.prompt_content(idx).map(str::to_string) } _ => None, }; @@ -550,7 +550,7 @@ impl ChatComposer { let format_label = match Path::new(&sel_path) .extension() .and_then(|e| e.to_str()) - .map(|s| s.to_ascii_lowercase()) + .map(str::to_ascii_lowercase) { Some(ext) if ext == "png" => "PNG", Some(ext) if ext == "jpg" || ext == "jpeg" => "JPEG", @@ -617,7 +617,7 @@ impl ChatComposer { text[safe_cursor..] .chars() .next() - .map(|c| c.is_whitespace()) + .map(char::is_whitespace) .unwrap_or(false) } else { false @@ -645,7 +645,7 @@ impl ChatComposer { let ws_len_right: usize = after_cursor .chars() .take_while(|c| c.is_whitespace()) - .map(|c| c.len_utf8()) + .map(char::len_utf8) .sum(); let start_right = safe_cursor + ws_len_right; let end_right_rel = text[start_right..] diff --git a/codex-rs/tui/src/bottom_pane/command_popup.rs b/codex-rs/tui/src/bottom_pane/command_popup.rs index a492a2e1..a0933f4a 100644 --- a/codex-rs/tui/src/bottom_pane/command_popup.rs +++ b/codex-rs/tui/src/bottom_pane/command_popup.rs @@ -218,6 +218,7 @@ impl WidgetRef for CommandPopup { #[cfg(test)] mod tests { use super::*; + use std::string::ToString; #[test] fn filter_includes_init_when_typing_prefix() { @@ -287,7 +288,7 @@ mod tests { let mut prompt_names: Vec = items .into_iter() .filter_map(|it| match it { - CommandItem::UserPrompt(i) => popup.prompt_name(i).map(|s| s.to_string()), + CommandItem::UserPrompt(i) => popup.prompt_name(i).map(ToString::to_string), _ => None, }) .collect(); diff --git a/codex-rs/tui/src/bottom_pane/mod.rs b/codex-rs/tui/src/bottom_pane/mod.rs index 523043e6..fc9f06c3 100644 --- a/codex-rs/tui/src/bottom_pane/mod.rs +++ b/codex-rs/tui/src/bottom_pane/mod.rs @@ -103,7 +103,7 @@ impl BottomPane { } fn active_view(&self) -> Option<&dyn BottomPaneView> { - self.view_stack.last().map(|view| view.as_ref()) + self.view_stack.last().map(std::convert::AsRef::as_ref) } fn push_view(&mut self, view: Box) { diff --git a/codex-rs/tui/src/bottom_pane/paste_burst.rs b/codex-rs/tui/src/bottom_pane/paste_burst.rs index d507dcae..559744a4 100644 --- a/codex-rs/tui/src/bottom_pane/paste_burst.rs +++ b/codex-rs/tui/src/bottom_pane/paste_burst.rs @@ -183,7 +183,7 @@ impl PasteBurst { let start_byte = retro_start_index(before, retro_chars); let grabbed = before[start_byte..].to_string(); let looks_pastey = - grabbed.chars().any(|c| c.is_whitespace()) || grabbed.chars().count() >= 16; + grabbed.chars().any(char::is_whitespace) || grabbed.chars().count() >= 16; if looks_pastey { // Note: caller is responsible for removing this slice from UI text. self.begin_with_retro_grabbed(grabbed.clone(), now); diff --git a/codex-rs/tui/src/chatwidget.rs b/codex-rs/tui/src/chatwidget.rs index f5b95e53..32375a86 100644 --- a/codex-rs/tui/src/chatwidget.rs +++ b/codex-rs/tui/src/chatwidget.rs @@ -616,7 +616,7 @@ impl ChatWidget { self.flush_answer_stream_with_separator(); // Emit the proposed command into history (like proposed patches) self.add_to_history(history_cell::new_proposed_command(&ev.command)); - let command = shlex::try_join(ev.command.iter().map(|s| s.as_str())) + let command = shlex::try_join(ev.command.iter().map(String::as_str)) .unwrap_or_else(|_| ev.command.join(" ")); self.notify(Notification::ExecApprovalRequested { command }); diff --git a/codex-rs/tui/src/chatwidget/tests.rs b/codex-rs/tui/src/chatwidget/tests.rs index 2837cedc..b983f6f5 100644 --- a/codex-rs/tui/src/chatwidget/tests.rs +++ b/codex-rs/tui/src/chatwidget/tests.rs @@ -1044,7 +1044,10 @@ async fn binary_size_transcript_snapshot() { call_id: e.call_id.clone(), command: e.command, cwd: e.cwd, - parsed_cmd: parsed_cmd.into_iter().map(|c| c.into()).collect(), + parsed_cmd: parsed_cmd + .into_iter() + .map(std::convert::Into::into) + .collect(), }), } } @@ -1121,7 +1124,7 @@ async fn binary_size_transcript_snapshot() { // Trim trailing spaces to match plain text fixture lines.push(s.trim_end().to_string()); } - while lines.last().is_some_and(|l| l.is_empty()) { + while lines.last().is_some_and(std::string::String::is_empty) { lines.pop(); } // Consider content only after the last session banner marker. Skip the transient diff --git a/codex-rs/tui/src/clipboard_paste.rs b/codex-rs/tui/src/clipboard_paste.rs index 82a14045..4945eea3 100644 --- a/codex-rs/tui/src/clipboard_paste.rs +++ b/codex-rs/tui/src/clipboard_paste.rs @@ -198,7 +198,7 @@ pub fn pasted_image_format(path: &Path) -> EncodedImageFormat { match path .extension() .and_then(|e| e.to_str()) - .map(|s| s.to_ascii_lowercase()) + .map(str::to_ascii_lowercase) .as_deref() { Some("png") => EncodedImageFormat::Png, diff --git a/codex-rs/tui/src/diff_render.rs b/codex-rs/tui/src/diff_render.rs index 2787f766..1e0c222b 100644 --- a/codex-rs/tui/src/diff_render.rs +++ b/codex-rs/tui/src/diff_render.rs @@ -1,3 +1,4 @@ +use diffy::Hunk; use ratatui::style::Color; use ratatui::style::Modifier; use ratatui::style::Style; @@ -283,7 +284,7 @@ fn calculate_add_remove_from_diff(diff: &str) -> (usize, usize) { patch .hunks() .iter() - .flat_map(|h| h.lines()) + .flat_map(Hunk::lines) .fold((0, 0), |(a, d), l| match l { diffy::Line::Insert(_) => (a + 1, d), diffy::Line::Delete(_) => (a, d + 1), diff --git a/codex-rs/tui/src/exec_command.rs b/codex-rs/tui/src/exec_command.rs index 93c937e0..5c9a0d03 100644 --- a/codex-rs/tui/src/exec_command.rs +++ b/codex-rs/tui/src/exec_command.rs @@ -5,7 +5,7 @@ use dirs::home_dir; use shlex::try_join; pub(crate) fn escape_command(command: &[String]) -> String { - try_join(command.iter().map(|s| s.as_str())).unwrap_or_else(|_| command.join(" ")) + try_join(command.iter().map(String::as_str)).unwrap_or_else(|_| command.join(" ")) } pub(crate) fn strip_bash_lc_and_escape(command: &[String]) -> String { diff --git a/codex-rs/tui/src/history_cell.rs b/codex-rs/tui/src/history_cell.rs index d4697218..cbb5ad6b 100644 --- a/codex-rs/tui/src/history_cell.rs +++ b/codex-rs/tui/src/history_cell.rs @@ -388,7 +388,7 @@ impl ExecCell { vec![( "Read", itertools::Itertools::intersperse( - names.into_iter().map(|n| n.into()), + names.into_iter().map(Into::into), ", ".dim(), ) .collect(), diff --git a/codex-rs/tui/src/markdown_render.rs b/codex-rs/tui/src/markdown_render.rs index f20bfd75..cac40cff 100644 --- a/codex-rs/tui/src/markdown_render.rs +++ b/codex-rs/tui/src/markdown_render.rs @@ -50,11 +50,7 @@ pub(crate) fn render_markdown_text_with_citations( let mut options = Options::empty(); options.insert(Options::ENABLE_STRIKETHROUGH); let parser = Parser::new_ext(input, options); - let mut w = Writer::new( - parser, - scheme.map(|s| s.to_string()), - Some(cwd.to_path_buf()), - ); + let mut w = Writer::new(parser, scheme.map(str::to_string), Some(cwd.to_path_buf())); w.run(); w.text } @@ -329,7 +325,7 @@ where let is_ordered = self .list_indices .last() - .map(|index| index.is_some()) + .map(Option::is_some) .unwrap_or(false); let width = depth * 4 - 3; let marker = if let Some(last_index) = self.list_indices.last_mut() { diff --git a/codex-rs/tui/src/new_model_popup.rs b/codex-rs/tui/src/new_model_popup.rs index 2106e46c..e2389aad 100644 --- a/codex-rs/tui/src/new_model_popup.rs +++ b/codex-rs/tui/src/new_model_popup.rs @@ -98,7 +98,7 @@ impl WidgetRef for &ModelUpgradePopup { let mut lines: Vec = Vec::new(); if show_animation { let frame = self.animation.current_frame(); - lines.extend(frame.lines().map(|l| l.into())); + lines.extend(frame.lines().map(Into::into)); // Spacer between animation and text content. lines.push("".into()); } diff --git a/codex-rs/tui/src/onboarding/welcome.rs b/codex-rs/tui/src/onboarding/welcome.rs index c62b6402..645c86ba 100644 --- a/codex-rs/tui/src/onboarding/welcome.rs +++ b/codex-rs/tui/src/onboarding/welcome.rs @@ -62,7 +62,7 @@ impl WidgetRef for &WelcomeWidget { let frame = self.animation.current_frame(); // let frame_line_count = frame.lines().count(); // lines.reserve(frame_line_count + 2); - lines.extend(frame.lines().map(|l| l.into())); + lines.extend(frame.lines().map(Into::into)); lines.push("".into()); } lines.push(Line::from(vec![ diff --git a/codex-rs/tui/src/pager_overlay.rs b/codex-rs/tui/src/pager_overlay.rs index e5524b25..271674b3 100644 --- a/codex-rs/tui/src/pager_overlay.rs +++ b/codex-rs/tui/src/pager_overlay.rs @@ -382,7 +382,7 @@ impl TranscriptOverlay { let cell_lines = if Some(idx) == highlight_cell { cell.transcript_lines() .into_iter() - .map(|l| l.reversed()) + .map(Stylize::reversed) .collect() } else { cell.transcript_lines() diff --git a/codex-rs/tui/src/wrapping.rs b/codex-rs/tui/src/wrapping.rs index 1dc4e2e5..bd3c451b 100644 --- a/codex-rs/tui/src/wrapping.rs +++ b/codex-rs/tui/src/wrapping.rs @@ -329,6 +329,7 @@ mod tests { use pretty_assertions::assert_eq; use ratatui::style::Color; use ratatui::style::Stylize; + use std::string::ToString; fn concat_line(line: &Line) -> String { line.spans @@ -543,7 +544,7 @@ mod tests { let lines = [line]; // Force small width to exercise wrapping at spaces. let wrapped = word_wrap_lines_borrowed(&lines, 40); - let joined: String = wrapped.iter().map(|l| l.to_string()).join("\n"); + let joined: String = wrapped.iter().map(ToString::to_string).join("\n"); assert_eq!( joined, r#"Years passed, and Willowmere thrived