chore: Bump Rust to 1.89 (#35788)

Piotr Osiewicz and Julia Ryan created

Release Notes:

- N/A

---------

Co-authored-by: Julia Ryan <juliaryan3.14@gmail.com>

Change summary

Dockerfile-collab                            |  2 
crates/agent2/src/templates.rs               |  4 ++
crates/agent2/src/tools/glob.rs              |  4 ++
crates/fs/src/fake_git_repo.rs               |  4 +-
crates/git/src/repository.rs                 |  8 ++--
crates/gpui/src/keymap/context.rs            | 30 +++++++++++----------
crates/gpui/src/platform/windows/wrapper.rs  | 24 ----------------
crates/terminal_view/src/terminal_element.rs |  2 
flake.lock                                   | 18 ++++++------
rust-toolchain.toml                          |  2 
10 files changed, 43 insertions(+), 55 deletions(-)

Detailed changes

Dockerfile-collab 🔗

@@ -1,6 +1,6 @@
 # syntax = docker/dockerfile:1.2
 
-FROM rust:1.88-bookworm as builder
+FROM rust:1.89-bookworm as builder
 WORKDIR app
 COPY . .
 

crates/agent2/src/templates.rs 🔗

@@ -33,6 +33,10 @@ pub trait Template: Sized {
     }
 }
 
+#[expect(
+    dead_code,
+    reason = "Marked as unused by Rust 1.89 and left as is as of 07 Aug 2025 to let AI team address it."
+)]
 #[derive(Serialize)]
 pub struct GlobTemplate {
     pub project_roots: String,

crates/agent2/src/tools/glob.rs 🔗

@@ -19,6 +19,10 @@ struct GlobInput {
     glob: SharedString,
 }
 
+#[expect(
+    dead_code,
+    reason = "Marked as unused by Rust 1.89 and left as is as of 07 Aug 2025 to let AI team address it."
+)]
 struct GlobTool {
     project: Entity<Project>,
     templates: Arc<Templates>,

crates/fs/src/fake_git_repo.rs 🔗

@@ -402,11 +402,11 @@ impl GitRepository for FakeGitRepository {
         &self,
         _paths: Vec<RepoPath>,
         _env: Arc<HashMap<String, String>>,
-    ) -> BoxFuture<Result<()>> {
+    ) -> BoxFuture<'_, Result<()>> {
         unimplemented!()
     }
 
-    fn stash_pop(&self, _env: Arc<HashMap<String, String>>) -> BoxFuture<Result<()>> {
+    fn stash_pop(&self, _env: Arc<HashMap<String, String>>) -> BoxFuture<'_, Result<()>> {
         unimplemented!()
     }
 

crates/git/src/repository.rs 🔗

@@ -399,9 +399,9 @@ pub trait GitRepository: Send + Sync {
         &self,
         paths: Vec<RepoPath>,
         env: Arc<HashMap<String, String>>,
-    ) -> BoxFuture<Result<()>>;
+    ) -> BoxFuture<'_, Result<()>>;
 
-    fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<Result<()>>;
+    fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<'_, Result<()>>;
 
     fn push(
         &self,
@@ -1203,7 +1203,7 @@ impl GitRepository for RealGitRepository {
         &self,
         paths: Vec<RepoPath>,
         env: Arc<HashMap<String, String>>,
-    ) -> BoxFuture<Result<()>> {
+    ) -> BoxFuture<'_, Result<()>> {
         let working_directory = self.working_directory();
         self.executor
             .spawn(async move {
@@ -1227,7 +1227,7 @@ impl GitRepository for RealGitRepository {
             .boxed()
     }
 
-    fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<Result<()>> {
+    fn stash_pop(&self, env: Arc<HashMap<String, String>>) -> BoxFuture<'_, Result<()>> {
         let working_directory = self.working_directory();
         self.executor
             .spawn(async move {

crates/gpui/src/keymap/context.rs 🔗

@@ -461,6 +461,8 @@ fn skip_whitespace(source: &str) -> &str {
 
 #[cfg(test)]
 mod tests {
+    use core::slice;
+
     use super::*;
     use crate as gpui;
     use KeyBindingContextPredicate::*;
@@ -674,11 +676,11 @@ mod tests {
         assert!(predicate.eval(&contexts));
 
         assert!(!predicate.eval(&[]));
-        assert!(!predicate.eval(&[child_context.clone()]));
+        assert!(!predicate.eval(slice::from_ref(&child_context)));
         assert!(!predicate.eval(&[parent_context]));
 
         let zany_predicate = KeyBindingContextPredicate::parse("child > child").unwrap();
-        assert!(!zany_predicate.eval(&[child_context.clone()]));
+        assert!(!zany_predicate.eval(slice::from_ref(&child_context)));
         assert!(zany_predicate.eval(&[child_context.clone(), child_context.clone()]));
     }
 
@@ -690,13 +692,13 @@ mod tests {
         let parent_context = KeyContext::try_from("parent").unwrap();
         let child_context = KeyContext::try_from("child").unwrap();
 
-        assert!(not_predicate.eval(&[workspace_context.clone()]));
-        assert!(!not_predicate.eval(&[editor_context.clone()]));
+        assert!(not_predicate.eval(slice::from_ref(&workspace_context)));
+        assert!(!not_predicate.eval(slice::from_ref(&editor_context)));
         assert!(!not_predicate.eval(&[editor_context.clone(), workspace_context.clone()]));
         assert!(!not_predicate.eval(&[workspace_context.clone(), editor_context.clone()]));
 
         let complex_not = KeyBindingContextPredicate::parse("!editor && workspace").unwrap();
-        assert!(complex_not.eval(&[workspace_context.clone()]));
+        assert!(complex_not.eval(slice::from_ref(&workspace_context)));
         assert!(!complex_not.eval(&[editor_context.clone(), workspace_context.clone()]));
 
         let not_mode_predicate = KeyBindingContextPredicate::parse("!(mode == full)").unwrap();
@@ -709,18 +711,18 @@ mod tests {
         assert!(not_mode_predicate.eval(&[other_mode_context]));
 
         let not_descendant = KeyBindingContextPredicate::parse("!(parent > child)").unwrap();
-        assert!(not_descendant.eval(&[parent_context.clone()]));
-        assert!(not_descendant.eval(&[child_context.clone()]));
+        assert!(not_descendant.eval(slice::from_ref(&parent_context)));
+        assert!(not_descendant.eval(slice::from_ref(&child_context)));
         assert!(!not_descendant.eval(&[parent_context.clone(), child_context.clone()]));
 
         let not_descendant = KeyBindingContextPredicate::parse("parent > !child").unwrap();
-        assert!(!not_descendant.eval(&[parent_context.clone()]));
-        assert!(!not_descendant.eval(&[child_context.clone()]));
+        assert!(!not_descendant.eval(slice::from_ref(&parent_context)));
+        assert!(!not_descendant.eval(slice::from_ref(&child_context)));
         assert!(!not_descendant.eval(&[parent_context.clone(), child_context.clone()]));
 
         let double_not = KeyBindingContextPredicate::parse("!!editor").unwrap();
-        assert!(double_not.eval(&[editor_context.clone()]));
-        assert!(!double_not.eval(&[workspace_context.clone()]));
+        assert!(double_not.eval(slice::from_ref(&editor_context)));
+        assert!(!double_not.eval(slice::from_ref(&workspace_context)));
 
         // Test complex descendant cases
         let workspace_context = KeyContext::try_from("Workspace").unwrap();
@@ -754,9 +756,9 @@ mod tests {
 
         // !Workspace - shouldn't match when Workspace is in the context
         let not_workspace = KeyBindingContextPredicate::parse("!Workspace").unwrap();
-        assert!(!not_workspace.eval(&[workspace_context.clone()]));
-        assert!(not_workspace.eval(&[pane_context.clone()]));
-        assert!(not_workspace.eval(&[editor_context.clone()]));
+        assert!(!not_workspace.eval(slice::from_ref(&workspace_context)));
+        assert!(not_workspace.eval(slice::from_ref(&pane_context)));
+        assert!(not_workspace.eval(slice::from_ref(&editor_context)));
         assert!(!not_workspace.eval(&workspace_pane_editor));
     }
 }

crates/gpui/src/platform/windows/wrapper.rs 🔗

@@ -1,28 +1,6 @@
 use std::ops::Deref;
 
-use windows::Win32::{Foundation::HANDLE, UI::WindowsAndMessaging::HCURSOR};
-
-#[derive(Debug, Clone, Copy)]
-pub(crate) struct SafeHandle {
-    raw: HANDLE,
-}
-
-unsafe impl Send for SafeHandle {}
-unsafe impl Sync for SafeHandle {}
-
-impl From<HANDLE> for SafeHandle {
-    fn from(value: HANDLE) -> Self {
-        SafeHandle { raw: value }
-    }
-}
-
-impl Deref for SafeHandle {
-    type Target = HANDLE;
-
-    fn deref(&self) -> &Self::Target {
-        &self.raw
-    }
-}
+use windows::Win32::UI::WindowsAndMessaging::HCURSOR;
 
 #[derive(Debug, Clone, Copy)]
 pub(crate) struct SafeCursor {

crates/terminal_view/src/terminal_element.rs 🔗

@@ -136,7 +136,7 @@ impl BatchedTextRun {
             .shape_line(
                 self.text.clone().into(),
                 self.font_size.to_pixels(window.rem_size()),
-                &[self.style.clone()],
+                std::slice::from_ref(&self.style),
                 Some(dimensions.cell_width),
             )
             .paint(pos, dimensions.line_height, window, cx);

flake.lock 🔗

@@ -2,11 +2,11 @@
   "nodes": {
     "crane": {
       "locked": {
-        "lastModified": 1750266157,
-        "narHash": "sha256-tL42YoNg9y30u7zAqtoGDNdTyXTi8EALDeCB13FtbQA=",
+        "lastModified": 1754269165,
+        "narHash": "sha256-0tcS8FHd4QjbCVoxN9jI+PjHgA4vc/IjkUSp+N3zy0U=",
         "owner": "ipetkov",
         "repo": "crane",
-        "rev": "e37c943371b73ed87faf33f7583860f81f1d5a48",
+        "rev": "444e81206df3f7d92780680e45858e31d2f07a08",
         "type": "github"
       },
       "original": {
@@ -33,10 +33,10 @@
     "nixpkgs": {
       "locked": {
         "lastModified": 315532800,
-        "narHash": "sha256-j+zO+IHQ7VwEam0pjPExdbLT2rVioyVS3iq4bLO3GEc=",
-        "rev": "61c0f513911459945e2cb8bf333dc849f1b976ff",
+        "narHash": "sha256-5VYevX3GccubYeccRGAXvCPA1ktrGmIX1IFC0icX07g=",
+        "rev": "a683adc19ff5228af548c6539dbc3440509bfed3",
         "type": "tarball",
-        "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre821324.61c0f5139114/nixexprs.tar.xz"
+        "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre840248.a683adc19ff5/nixexprs.tar.xz"
       },
       "original": {
         "type": "tarball",
@@ -58,11 +58,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1750964660,
-        "narHash": "sha256-YQ6EyFetjH1uy5JhdhRdPe6cuNXlYpMAQePFfZj4W7M=",
+        "lastModified": 1754575663,
+        "narHash": "sha256-afOx8AG0KYtw7mlt6s6ahBBy7eEHZwws3iCRoiuRQS4=",
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "04f0fcfb1a50c63529805a798b4b5c21610ff390",
+        "rev": "6db0fb0e9cec2e9729dc52bf4898e6c135bb8a0f",
         "type": "github"
       },
       "original": {

rust-toolchain.toml 🔗

@@ -1,5 +1,5 @@
 [toolchain]
-channel = "1.88"
+channel = "1.89"
 profile = "minimal"
 components = [ "rustfmt", "clippy" ]
 targets = [