chore: upgrade to Rust 1.89 (#2465)
Codex created this PR from the following prompt: > upgrade this entire repo to Rust 1.89. Note that this requires updating codex-rs/rust-toolchain.toml as well as the workflows in .github/. Make sure that things are "clippy clean" as this change will likely uncover new Clippy errors. `just fmt` and `cargo clippy --tests` are sufficient to check for correctness Note this modifies a lot of lines because it folds nested `if` statements using `&&`. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2465). * #2467 * __->__ #2465
This commit is contained in:
@@ -33,10 +33,10 @@ impl ApprovalModalView<'_> {
|
||||
|
||||
/// Advance to next request if the current one is finished.
|
||||
fn maybe_advance(&mut self) {
|
||||
if self.current.is_complete() {
|
||||
if let Some(req) = self.queue.pop() {
|
||||
self.current = UserApprovalWidget::new(req, self.app_event_tx.clone());
|
||||
}
|
||||
if self.current.is_complete()
|
||||
&& let Some(req) = self.queue.pop()
|
||||
{
|
||||
self.current = UserApprovalWidget::new(req, self.app_event_tx.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1575,53 +1575,53 @@ mod tests {
|
||||
}
|
||||
14 => {
|
||||
// Try inserting inside an existing element (should clamp to boundary)
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned() {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
let ins = rand_grapheme(&mut rng);
|
||||
ta.insert_str_at(pos, &ins);
|
||||
}
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned()
|
||||
&& let Some(start) = ta.text().find(&payload)
|
||||
{
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
let ins = rand_grapheme(&mut rng);
|
||||
ta.insert_str_at(pos, &ins);
|
||||
}
|
||||
}
|
||||
}
|
||||
15 => {
|
||||
// Replace a range that intersects an element -> whole element should be replaced
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned() {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
// Create an intersecting range [start-δ, end-δ2)
|
||||
let mut s = start.saturating_sub(rng.random_range(0..=2));
|
||||
let mut e = (end + rng.random_range(0..=2)).min(ta.text().len());
|
||||
// Align to char boundaries to satisfy String::replace_range contract
|
||||
let txt = ta.text();
|
||||
while s > 0 && !txt.is_char_boundary(s) {
|
||||
s -= 1;
|
||||
}
|
||||
while e < txt.len() && !txt.is_char_boundary(e) {
|
||||
e += 1;
|
||||
}
|
||||
if s < e {
|
||||
// Small replacement text
|
||||
let mut srep = String::new();
|
||||
for _ in 0..rng.random_range(0..=2) {
|
||||
srep.push_str(&rand_grapheme(&mut rng));
|
||||
}
|
||||
ta.replace_range(s..e, &srep);
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned()
|
||||
&& let Some(start) = ta.text().find(&payload)
|
||||
{
|
||||
let end = start + payload.len();
|
||||
// Create an intersecting range [start-δ, end-δ2)
|
||||
let mut s = start.saturating_sub(rng.random_range(0..=2));
|
||||
let mut e = (end + rng.random_range(0..=2)).min(ta.text().len());
|
||||
// Align to char boundaries to satisfy String::replace_range contract
|
||||
let txt = ta.text();
|
||||
while s > 0 && !txt.is_char_boundary(s) {
|
||||
s -= 1;
|
||||
}
|
||||
while e < txt.len() && !txt.is_char_boundary(e) {
|
||||
e += 1;
|
||||
}
|
||||
if s < e {
|
||||
// Small replacement text
|
||||
let mut srep = String::new();
|
||||
for _ in 0..rng.random_range(0..=2) {
|
||||
srep.push_str(&rand_grapheme(&mut rng));
|
||||
}
|
||||
ta.replace_range(s..e, &srep);
|
||||
}
|
||||
}
|
||||
}
|
||||
16 => {
|
||||
// Try setting the cursor to a position inside an element; it should clamp out
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned() {
|
||||
if let Some(start) = ta.text().find(&payload) {
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
ta.set_cursor(pos);
|
||||
}
|
||||
if let Some(payload) = elem_texts.choose(&mut rng).cloned()
|
||||
&& let Some(start) = ta.text().find(&payload)
|
||||
{
|
||||
let end = start + payload.len();
|
||||
if end - start > 2 {
|
||||
let pos = rng.random_range(start + 1..end - 1);
|
||||
ta.set_cursor(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,18 +339,18 @@ async fn binary_size_transcript_matches_ideal_fixture() {
|
||||
}
|
||||
}
|
||||
"app_event" => {
|
||||
if let Some(variant) = v.get("variant").and_then(|s| s.as_str()) {
|
||||
if variant == "CommitTick" {
|
||||
chat.on_commit_tick();
|
||||
while let Ok(app_ev) = rx.try_recv() {
|
||||
if let AppEvent::InsertHistory(lines) = app_ev {
|
||||
transcript.push_str(&lines_to_single_string(&lines));
|
||||
crate::insert_history::insert_history_lines_to_writer(
|
||||
&mut terminal,
|
||||
&mut ansi,
|
||||
lines,
|
||||
);
|
||||
}
|
||||
if let Some(variant) = v.get("variant").and_then(|s| s.as_str())
|
||||
&& variant == "CommitTick"
|
||||
{
|
||||
chat.on_commit_tick();
|
||||
while let Ok(app_ev) = rx.try_recv() {
|
||||
if let AppEvent::InsertHistory(lines) = app_ev {
|
||||
transcript.push_str(&lines_to_single_string(&lines));
|
||||
crate::insert_history::insert_history_lines_to_writer(
|
||||
&mut terminal,
|
||||
&mut ansi,
|
||||
lines,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,10 +264,10 @@ where
|
||||
#[allow(clippy::print_stderr)]
|
||||
fn drop(&mut self) {
|
||||
// Attempt to restore the cursor state
|
||||
if self.hidden_cursor {
|
||||
if let Err(err) = self.show_cursor() {
|
||||
eprintln!("Failed to show the cursor: {err}");
|
||||
}
|
||||
if self.hidden_cursor
|
||||
&& let Err(err) = self.show_cursor()
|
||||
{
|
||||
eprintln!("Failed to show the cursor: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -309,7 +309,7 @@ where
|
||||
}
|
||||
|
||||
/// Get a Frame object which provides a consistent view into the terminal state for rendering.
|
||||
pub fn get_frame(&mut self) -> Frame {
|
||||
pub fn get_frame(&mut self) -> Frame<'_> {
|
||||
let count = self.frame_count;
|
||||
Frame {
|
||||
cursor_position: None,
|
||||
|
||||
@@ -33,10 +33,10 @@ where
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(home_dir) = std::env::var_os("HOME").map(PathBuf::from) {
|
||||
if let Ok(rel) = path.strip_prefix(&home_dir) {
|
||||
return Some(rel.to_path_buf());
|
||||
}
|
||||
if let Some(home_dir) = std::env::var_os("HOME").map(PathBuf::from)
|
||||
&& let Ok(rel) = path.strip_prefix(&home_dir)
|
||||
{
|
||||
return Some(rel.to_path_buf());
|
||||
}
|
||||
|
||||
None
|
||||
|
||||
@@ -94,13 +94,13 @@ impl FileSearchManager {
|
||||
|
||||
// If there is an in-flight search that is definitely obsolete,
|
||||
// cancel it now.
|
||||
if let Some(active_search) = &st.active_search {
|
||||
if !query.starts_with(&active_search.query) {
|
||||
active_search
|
||||
.cancellation_token
|
||||
.store(true, Ordering::Relaxed);
|
||||
st.active_search = None;
|
||||
}
|
||||
if let Some(active_search) = &st.active_search
|
||||
&& !query.starts_with(&active_search.query)
|
||||
{
|
||||
active_search
|
||||
.cancellation_token
|
||||
.store(true, Ordering::Relaxed);
|
||||
st.active_search = None;
|
||||
}
|
||||
|
||||
// Schedule a search to run after debounce.
|
||||
@@ -187,10 +187,10 @@ impl FileSearchManager {
|
||||
{
|
||||
#[expect(clippy::unwrap_used)]
|
||||
let mut st = search_state.lock().unwrap();
|
||||
if let Some(active_search) = &st.active_search {
|
||||
if Arc::ptr_eq(&active_search.cancellation_token, &cancellation_token) {
|
||||
st.active_search = None;
|
||||
}
|
||||
if let Some(active_search) = &st.active_search
|
||||
&& Arc::ptr_eq(&active_search.cancellation_token, &cancellation_token)
|
||||
{
|
||||
st.active_search = None;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -541,33 +541,33 @@ pub(crate) fn new_status_output(
|
||||
|
||||
// 👤 Account (only if ChatGPT tokens exist), shown under the first block
|
||||
let auth_file = get_auth_file(&config.codex_home);
|
||||
if let Ok(auth) = try_read_auth_json(&auth_file) {
|
||||
if let Some(tokens) = auth.tokens.clone() {
|
||||
lines.push(Line::from(vec!["👤 ".into(), "Account".bold()]));
|
||||
lines.push(Line::from(" • Signed in with ChatGPT"));
|
||||
if let Ok(auth) = try_read_auth_json(&auth_file)
|
||||
&& let Some(tokens) = auth.tokens.clone()
|
||||
{
|
||||
lines.push(Line::from(vec!["👤 ".into(), "Account".bold()]));
|
||||
lines.push(Line::from(" • Signed in with ChatGPT"));
|
||||
|
||||
let info = tokens.id_token;
|
||||
if let Some(email) = &info.email {
|
||||
lines.push(Line::from(vec![" • Login: ".into(), email.clone().into()]));
|
||||
}
|
||||
|
||||
match auth.openai_api_key.as_deref() {
|
||||
Some(key) if !key.is_empty() => {
|
||||
lines.push(Line::from(
|
||||
" • Using API key. Run codex login to use ChatGPT plan",
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
let plan_text = info
|
||||
.get_chatgpt_plan_type()
|
||||
.map(|s| title_case(&s))
|
||||
.unwrap_or_else(|| "Unknown".to_string());
|
||||
lines.push(Line::from(vec![" • Plan: ".into(), plan_text.into()]));
|
||||
}
|
||||
}
|
||||
|
||||
lines.push(Line::from(""));
|
||||
let info = tokens.id_token;
|
||||
if let Some(email) = &info.email {
|
||||
lines.push(Line::from(vec![" • Login: ".into(), email.clone().into()]));
|
||||
}
|
||||
|
||||
match auth.openai_api_key.as_deref() {
|
||||
Some(key) if !key.is_empty() => {
|
||||
lines.push(Line::from(
|
||||
" • Using API key. Run codex login to use ChatGPT plan",
|
||||
));
|
||||
}
|
||||
_ => {
|
||||
let plan_text = info
|
||||
.get_chatgpt_plan_type()
|
||||
.map(|s| title_case(&s))
|
||||
.unwrap_or_else(|| "Unknown".to_string());
|
||||
lines.push(Line::from(vec![" • Plan: ".into(), plan_text.into()]));
|
||||
}
|
||||
}
|
||||
|
||||
lines.push(Line::from(""));
|
||||
}
|
||||
|
||||
// 🧠 Model
|
||||
@@ -612,10 +612,10 @@ pub(crate) fn new_status_output(
|
||||
" • Input: ".into(),
|
||||
usage.non_cached_input().to_string().into(),
|
||||
];
|
||||
if let Some(cached) = usage.cached_input_tokens {
|
||||
if cached > 0 {
|
||||
input_line_spans.push(format!(" (+ {cached} cached)").into());
|
||||
}
|
||||
if let Some(cached) = usage.cached_input_tokens
|
||||
&& cached > 0
|
||||
{
|
||||
input_line_spans.push(format!(" (+ {cached} cached)").into());
|
||||
}
|
||||
lines.push(Line::from(input_line_spans));
|
||||
// Output: <output>
|
||||
@@ -688,16 +688,15 @@ pub(crate) fn new_mcp_tools_output(
|
||||
]));
|
||||
}
|
||||
|
||||
if let Some(env) = cfg.env.as_ref() {
|
||||
if !env.is_empty() {
|
||||
let mut env_pairs: Vec<String> =
|
||||
env.iter().map(|(k, v)| format!("{k}={v}")).collect();
|
||||
env_pairs.sort();
|
||||
lines.push(Line::from(vec![
|
||||
" • Env: ".into(),
|
||||
env_pairs.join(" ").into(),
|
||||
]));
|
||||
}
|
||||
if let Some(env) = cfg.env.as_ref()
|
||||
&& !env.is_empty()
|
||||
{
|
||||
let mut env_pairs: Vec<String> = env.iter().map(|(k, v)| format!("{k}={v}")).collect();
|
||||
env_pairs.sort();
|
||||
lines.push(Line::from(vec![
|
||||
" • Env: ".into(),
|
||||
env_pairs.join(" ").into(),
|
||||
]));
|
||||
}
|
||||
|
||||
if names.is_empty() {
|
||||
|
||||
@@ -123,20 +123,20 @@ impl AuthModeWidget {
|
||||
|
||||
// If the user is already authenticated but the method differs from their
|
||||
// preferred auth method, show a brief explanation.
|
||||
if let LoginStatus::AuthMode(current) = self.login_status {
|
||||
if current != self.preferred_auth_method {
|
||||
let to_label = |mode: AuthMode| match mode {
|
||||
AuthMode::ApiKey => "API key",
|
||||
AuthMode::ChatGPT => "ChatGPT",
|
||||
};
|
||||
let msg = format!(
|
||||
" You’re currently using {} while your preferred method is {}.",
|
||||
to_label(current),
|
||||
to_label(self.preferred_auth_method)
|
||||
);
|
||||
lines.push(Line::from(msg).style(Style::default()));
|
||||
lines.push(Line::from(""));
|
||||
}
|
||||
if let LoginStatus::AuthMode(current) = self.login_status
|
||||
&& current != self.preferred_auth_method
|
||||
{
|
||||
let to_label = |mode: AuthMode| match mode {
|
||||
AuthMode::ApiKey => "API key",
|
||||
AuthMode::ChatGPT => "ChatGPT",
|
||||
};
|
||||
let msg = format!(
|
||||
" You’re currently using {} while your preferred method is {}.",
|
||||
to_label(current),
|
||||
to_label(self.preferred_auth_method)
|
||||
);
|
||||
lines.push(Line::from(msg).style(Style::default()));
|
||||
lines.push(Line::from(""));
|
||||
}
|
||||
|
||||
let create_mode_item = |idx: usize,
|
||||
@@ -222,15 +222,15 @@ impl AuthModeWidget {
|
||||
spans.extend(shimmer_spans("Finish signing in via your browser"));
|
||||
let mut lines = vec![Line::from(spans), Line::from("")];
|
||||
|
||||
if let SignInState::ChatGptContinueInBrowser(state) = &self.sign_in_state {
|
||||
if !state.auth_url.is_empty() {
|
||||
lines.push(Line::from(" If the link doesn't open automatically, open the following link to authenticate:"));
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(" "),
|
||||
state.auth_url.as_str().cyan().underlined(),
|
||||
]));
|
||||
lines.push(Line::from(""));
|
||||
}
|
||||
if let SignInState::ChatGptContinueInBrowser(state) = &self.sign_in_state
|
||||
&& !state.auth_url.is_empty()
|
||||
{
|
||||
lines.push(Line::from(" If the link doesn't open automatically, open the following link to authenticate:"));
|
||||
lines.push(Line::from(vec![
|
||||
Span::raw(" "),
|
||||
state.auth_url.as_str().cyan().underlined(),
|
||||
]));
|
||||
lines.push(Line::from(""));
|
||||
}
|
||||
|
||||
lines.push(
|
||||
|
||||
@@ -96,26 +96,26 @@ impl StreamController {
|
||||
/// Begin a stream, flushing previously completed lines from any other
|
||||
/// active stream to maintain ordering.
|
||||
pub(crate) fn begin(&mut self, kind: StreamKind, sink: &impl HistorySink) {
|
||||
if let Some(current) = self.current_stream {
|
||||
if current != kind {
|
||||
// Synchronously flush completed lines from previous stream.
|
||||
let cfg = self.config.clone();
|
||||
let prev_state = self.state_mut(current);
|
||||
let newly_completed = prev_state.collector.commit_complete_lines(&cfg);
|
||||
if !newly_completed.is_empty() {
|
||||
prev_state.enqueue(newly_completed);
|
||||
}
|
||||
let step = prev_state.drain_all();
|
||||
if !step.history.is_empty() {
|
||||
let mut lines: Lines = Vec::new();
|
||||
self.emit_header_if_needed(current, &mut lines);
|
||||
lines.extend(step.history);
|
||||
// Ensure at most one trailing blank after the flushed block.
|
||||
Self::ensure_single_trailing_blank(&mut lines);
|
||||
sink.insert_history(lines);
|
||||
}
|
||||
self.current_stream = None;
|
||||
if let Some(current) = self.current_stream
|
||||
&& current != kind
|
||||
{
|
||||
// Synchronously flush completed lines from previous stream.
|
||||
let cfg = self.config.clone();
|
||||
let prev_state = self.state_mut(current);
|
||||
let newly_completed = prev_state.collector.commit_complete_lines(&cfg);
|
||||
if !newly_completed.is_empty() {
|
||||
prev_state.enqueue(newly_completed);
|
||||
}
|
||||
let step = prev_state.drain_all();
|
||||
if !step.history.is_empty() {
|
||||
let mut lines: Lines = Vec::new();
|
||||
self.emit_header_if_needed(current, &mut lines);
|
||||
lines.extend(step.history);
|
||||
// Ensure at most one trailing blank after the flushed block.
|
||||
Self::ensure_single_trailing_blank(&mut lines);
|
||||
sink.insert_history(lines);
|
||||
}
|
||||
self.current_stream = None;
|
||||
}
|
||||
|
||||
if self.current_stream != Some(kind) {
|
||||
|
||||
@@ -53,12 +53,12 @@ pub(crate) fn format_json_compact(text: &str) -> Option<String> {
|
||||
}
|
||||
' ' | '\t' if !in_string => {
|
||||
// Add a space after : and , but only when not in a string
|
||||
if let Some(&next_ch) = chars.peek() {
|
||||
if let Some(last_ch) = result.chars().last() {
|
||||
if (last_ch == ':' || last_ch == ',') && !matches!(next_ch, '}' | ']') {
|
||||
result.push(' ');
|
||||
}
|
||||
}
|
||||
if let Some(&next_ch) = chars.peek()
|
||||
&& let Some(last_ch) = result.chars().last()
|
||||
&& (last_ch == ':' || last_ch == ',')
|
||||
&& !matches!(next_ch, '}' | ']')
|
||||
{
|
||||
result.push(' ');
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
||||
Reference in New Issue
Block a user