Reduce amount of monomorphizations from FnMut closures (#49453)

Lukas Wirth created

Replaces a bunch of `impl FnMut` parameters with `&mut dyn FnMut` for
functions where this is the sole generic parameter.
Release Notes:

- N/A *or* Added/Fixed/Improved ...

Change summary

crates/agent_ui/src/agent_diff.rs                       |   2 
crates/agent_ui/src/agent_registry_ui.rs                |   2 
crates/agent_ui/src/text_thread_editor.rs               |   2 
crates/askpass/src/askpass.rs                           |  12 
crates/collab_ui/src/channel_view.rs                    |   2 
crates/component_preview/src/component_preview.rs       |   2 
crates/debugger_tools/src/dap_log.rs                    |   2 
crates/debugger_ui/src/stack_trace_view.rs              |   2 
crates/diagnostics/src/buffer_diagnostics.rs            |   2 
crates/diagnostics/src/diagnostics.rs                   |   2 
crates/editor/src/bracket_colorization.rs               |   5 
crates/editor/src/display_map.rs                        |   9 
crates/editor/src/display_map/block_map.rs              |   6 
crates/editor/src/editor.rs                             | 116 +++++-----
crates/editor/src/inlays/inlay_hints.rs                 |   2 
crates/editor/src/items.rs                              |   4 
crates/editor/src/jsx_tag_auto_close.rs                 |   2 
crates/editor/src/movement.rs                           |  48 ++--
crates/editor/src/selections_collection.rs              |  16 
crates/editor/src/semantic_tokens.rs                    |   2 
crates/editor/src/split.rs                              |   2 
crates/extensions_ui/src/extensions_ui.rs               |   2 
crates/git_graph/src/git_graph.rs                       |   2 
crates/git_ui/src/commit_view.rs                        |   2 
crates/git_ui/src/file_diff_view.rs                     |   2 
crates/git_ui/src/file_history_view.rs                  |   2 
crates/git_ui/src/multi_diff_view.rs                    |   2 
crates/git_ui/src/project_diff.rs                       |   2 
crates/git_ui/src/text_diff_view.rs                     |   2 
crates/image_viewer/src/image_viewer.rs                 |   2 
crates/language/src/text_diff.rs                        |  82 +++---
crates/language_tools/src/highlights_tree_view.rs       |  10 
crates/language_tools/src/key_context_view.rs           |   2 
crates/language_tools/src/lsp_log_view.rs               |   2 
crates/language_tools/src/syntax_tree_view.rs           |   8 
crates/markdown_preview/src/markdown_preview_view.rs    |   2 
crates/migrator/src/migrations.rs                       |   2 
crates/migrator/src/migrations/m_2025_10_17/settings.rs |   2 
crates/migrator/src/migrations/m_2025_10_21/settings.rs |   2 
crates/migrator/src/migrations/m_2025_11_25/settings.rs |   2 
crates/migrator/src/migrations/m_2026_02_02/settings.rs |   2 
crates/migrator/src/migrations/m_2026_02_03/settings.rs |   2 
crates/migrator/src/migrations/m_2026_02_04/settings.rs |   2 
crates/multi_buffer/src/multi_buffer.rs                 |   6 
crates/onboarding/src/onboarding.rs                     |   2 
crates/project_panel/src/project_panel.rs               |  17 +
crates/project_panel/src/project_panel_tests.rs         |   2 
crates/remote/src/transport/ssh.rs                      |   2 
crates/repl/src/repl_sessions_ui.rs                     |   2 
crates/search/src/project_search.rs                     |   2 
crates/sqlez/src/domain.rs                              |   2 
crates/sqlez/src/migrations.rs                          |  18 
crates/svg_preview/src/svg_preview_view.rs              |   2 
crates/terminal_view/src/terminal_view.rs               |   2 
crates/vim/src/helix.rs                                 |  82 +++----
crates/vim/src/helix/select.rs                          |   6 
crates/vim/src/indent.rs                                |   8 
crates/vim/src/insert.rs                                |   2 
crates/vim/src/motion.rs                                |  84 ++++---
crates/vim/src/normal.rs                                |  26 +-
crates/vim/src/normal/change.rs                         |   4 
crates/vim/src/normal/convert.rs                        |   8 
crates/vim/src/normal/delete.rs                         |   8 
crates/vim/src/normal/paste.rs                          |   8 
crates/vim/src/normal/scroll.rs                         |   2 
crates/vim/src/normal/substitute.rs                     |   2 
crates/vim/src/normal/toggle_comments.rs                |   8 
crates/vim/src/normal/yank.rs                           |   8 
crates/vim/src/object.rs                                | 111 ++++++---
crates/vim/src/replace.rs                               |   2 
crates/vim/src/rewrap.rs                                |  10 
crates/vim/src/vim.rs                                   |  14 
crates/vim/src/visual.rs                                |  36 +-
crates/workspace/src/item.rs                            |   8 
crates/workspace/src/pane.rs                            |   2 
crates/workspace/src/persistence.rs                     |   4 
crates/workspace/src/shared_screen.rs                   |   2 
crates/workspace/src/theme_preview.rs                   |   2 
crates/workspace/src/welcome.rs                         |   2 
crates/workspace/src/workspace.rs                       |  22 +
80 files changed, 481 insertions(+), 427 deletions(-)

Detailed changes

crates/agent_ui/src/agent_diff.rs 🔗

@@ -470,7 +470,7 @@ impl Item for AgentDiffPane {
         Some(Icon::new(IconName::ZedAssistant).color(Color::Muted))
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/agent_ui/src/agent_registry_ui.rs 🔗

@@ -754,7 +754,7 @@ impl Item for AgentRegistryPage {
         false
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         f(*event)
     }
 }

crates/agent_ui/src/text_thread_editor.rs 🔗

@@ -2712,7 +2712,7 @@ impl Item for TextThreadEditor {
         util::truncate_and_trailoff(&self.title(cx), MAX_TAB_TITLE_LEN).into()
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(item::ItemEvent)) {
         match event {
             EditorEvent::Edited { .. } => {
                 f(item::ItemEvent::Edit);

crates/askpass/src/askpass.rs 🔗

@@ -131,7 +131,7 @@ impl AskPassSession {
                 })
             }
         };
-        let askpass_task = PasswordProxy::new(get_password, executor.clone()).await?;
+        let askpass_task = PasswordProxy::new(Box::new(get_password), executor.clone()).await?;
 
         Ok(Self {
             #[cfg(target_os = "windows")]
@@ -192,10 +192,12 @@ pub struct PasswordProxy {
 
 impl PasswordProxy {
     pub async fn new(
-        mut get_password: impl FnMut(String) -> Task<ControlFlow<(), Result<EncryptedPassword>>>
-        + 'static
-        + Send
-        + Sync,
+        mut get_password: Box<
+            dyn FnMut(String) -> Task<ControlFlow<(), Result<EncryptedPassword>>>
+                + 'static
+                + Send
+                + Sync,
+        >,
         executor: BackgroundExecutor,
     ) -> Result<Self> {
         let temp_dir = tempfile::Builder::new().prefix("zed-askpass").tempdir()?;

crates/collab_ui/src/channel_view.rs 🔗

@@ -553,7 +553,7 @@ impl Item for ChannelView {
         self.editor.read(cx).pixel_position_of_cursor(cx)
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 }

crates/component_preview/src/component_preview.rs 🔗

@@ -757,7 +757,7 @@ impl Item for ComponentPreview {
         })
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         f(*event)
     }
 

crates/debugger_tools/src/dap_log.rs 🔗

@@ -986,7 +986,7 @@ pub fn init(cx: &mut App) {
 impl Item for DapLogView {
     type Event = EditorEvent;
 
-    fn to_item_events(event: &Self::Event, f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/debugger_ui/src/stack_trace_view.rs 🔗

@@ -325,7 +325,7 @@ impl Focusable for StackTraceView {
 impl Item for StackTraceView {
     type Event = EditorEvent;
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/diagnostics/src/buffer_diagnostics.rs 🔗

@@ -866,7 +866,7 @@ impl Item for BufferDiagnosticsEditor {
         Some("Buffer Diagnostics Opened")
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 }

crates/diagnostics/src/diagnostics.rs 🔗

@@ -717,7 +717,7 @@ impl Focusable for ProjectDiagnosticsEditor {
 impl Item for ProjectDiagnosticsEditor {
     type Event = EditorEvent;
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/editor/src/bracket_colorization.rs 🔗

@@ -124,7 +124,10 @@ impl Editor {
         );
 
         if invalidate {
-            self.clear_highlights_with(|key| matches!(key, HighlightKey::ColorizeBracket(_)), cx);
+            self.clear_highlights_with(
+                &mut |key| matches!(key, HighlightKey::ColorizeBracket(_)),
+                cx,
+            );
         }
 
         let editor_background = cx.theme().colors().editor_background;

crates/editor/src/display_map.rs 🔗

@@ -493,7 +493,7 @@ impl DisplayMap {
                 new: WrapRow(0)..snapshot.max_point().row() + WrapRow(1),
             }]);
             self.block_map.deferred_edits.set(edits);
-            self.block_map.retain_blocks_raw(|block| {
+            self.block_map.retain_blocks_raw(&mut |block| {
                 if companion
                     .read(cx)
                     .lhs_custom_block_to_balancing_block
@@ -528,8 +528,9 @@ impl DisplayMap {
                 .wrap_map
                 .update(cx, |wrap_map, cx| wrap_map.sync(snapshot, edits, cx));
 
-            self.block_map
-                .retain_blocks_raw(|block| !matches!(block.placement, BlockPlacement::Replace(_)));
+            self.block_map.retain_blocks_raw(&mut |block| {
+                !matches!(block.placement, BlockPlacement::Replace(_))
+            });
             snapshot
         };
 
@@ -1268,7 +1269,7 @@ impl DisplayMap {
         cleared
     }
 
-    pub fn clear_highlights_with(&mut self, mut f: impl FnMut(&HighlightKey) -> bool) -> bool {
+    pub fn clear_highlights_with(&mut self, f: &mut dyn FnMut(&HighlightKey) -> bool) -> bool {
         let mut cleared = false;
         self.text_highlights.retain(|k, _| {
             let b = !f(k);

crates/editor/src/display_map/block_map.rs 🔗

@@ -736,7 +736,7 @@ impl BlockMap {
     }
 
     // Warning: doesn't sync the block map, use advisedly
-    pub(crate) fn retain_blocks_raw(&mut self, mut pred: impl FnMut(&Arc<CustomBlock>) -> bool) {
+    pub(crate) fn retain_blocks_raw(&mut self, pred: &mut dyn FnMut(&Arc<CustomBlock>) -> bool) {
         let mut ids_to_remove = HashSet::default();
         self.custom_blocks.retain(|block| {
             let keep = pred(block);
@@ -1275,8 +1275,8 @@ impl BlockMap {
                 .row()
         };
         fn determine_spacer(
-            our_wrapper: &mut impl FnMut(Point, Bias) -> WrapRow,
-            companion_wrapper: &mut impl FnMut(Point, Bias) -> WrapRow,
+            our_wrapper: &mut dyn FnMut(Point, Bias) -> WrapRow,
+            companion_wrapper: &mut dyn FnMut(Point, Bias) -> WrapRow,
             our_point: Point,
             their_point: Point,
             delta: i32,

crates/editor/src/editor.rs 🔗

@@ -5317,7 +5317,7 @@ impl Editor {
 
             editor.change_selections(Default::default(), window, cx, |s| {
                 let mut index = 0;
-                s.move_cursors_with(|map, _, _| {
+                s.move_cursors_with(&mut |map, _, _| {
                     let row = rows[index];
                     index += 1;
 
@@ -5398,7 +5398,7 @@ impl Editor {
 
             editor.change_selections(Default::default(), window, cx, |s| {
                 let mut index = 0;
-                s.move_cursors_with(|map, _, _| {
+                s.move_cursors_with(&mut |map, _, _| {
                     let row = rows[index];
                     index += 1;
 
@@ -8526,7 +8526,7 @@ impl Editor {
             let mut suggested_indent = None;
             multibuffer.suggested_indents_callback(
                 cursor_point.row..cursor_point.row + 1,
-                |_, indent| {
+                &mut |_, indent| {
                     suggested_indent = Some(indent);
                     ControlFlow::Break(())
                 },
@@ -10788,7 +10788,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
         self.transact(window, cx, |this, window, cx| {
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         let cursor = movement::right(map, selection.head());
                         selection.end = cursor;
@@ -13114,7 +13114,7 @@ impl Editor {
         self.transact(window, cx, |this, window, cx| {
             let edits = this.change_selections(Default::default(), window, cx, |s| {
                 let mut edits: Vec<(Range<MultiBufferOffset>, String)> = Default::default();
-                s.move_with(|display_map, selection| {
+                s.move_with(&mut |display_map, selection| {
                     if !selection.is_empty() {
                         return;
                     }
@@ -13617,7 +13617,7 @@ impl Editor {
     pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
         self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-            s.move_with(|snapshot, sel| {
+            s.move_with(&mut |snapshot, sel| {
                 if sel.is_empty() {
                     sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()));
                 }
@@ -14058,7 +14058,7 @@ impl Editor {
     pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 let cursor = if selection.is_empty() {
                     movement::left(map, selection.start)
                 } else {
@@ -14072,14 +14072,14 @@ impl Editor {
     pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
+            s.move_heads_with(&mut |map, head, _| (movement::left(map, head), SelectionGoal::None));
         })
     }
 
     pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 let cursor = if selection.is_empty() {
                     movement::right(map, selection.end)
                 } else {
@@ -14093,7 +14093,9 @@ impl Editor {
     pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
+            s.move_heads_with(&mut |map, head, _| {
+                (movement::right(map, head), SelectionGoal::None)
+            });
         });
     }
 
@@ -14114,7 +14116,7 @@ impl Editor {
         let first_selection = self.selections.first_anchor();
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14155,7 +14157,7 @@ impl Editor {
         let text_layout_details = &self.text_layout_details(window, cx);
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14192,7 +14194,7 @@ impl Editor {
         let text_layout_details = &self.text_layout_details(window, cx);
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14218,7 +14220,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         let text_layout_details = &self.text_layout_details(window, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
             })
         })
@@ -14233,7 +14235,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         let text_layout_details = &self.text_layout_details(window, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
             })
         })
@@ -14254,7 +14256,7 @@ impl Editor {
         let text_layout_details = &self.text_layout_details(window, cx);
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
             })
         })
@@ -14300,7 +14302,7 @@ impl Editor {
         let text_layout_details = &self.text_layout_details(window, cx);
 
         self.change_selections(effects, window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14321,7 +14323,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         let text_layout_details = &self.text_layout_details(window, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::up(map, head, goal, false, text_layout_details)
             })
         })
@@ -14342,7 +14344,7 @@ impl Editor {
         let first_selection = self.selections.first_anchor();
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14378,7 +14380,7 @@ impl Editor {
         let text_layout_details = &self.text_layout_details(window, cx);
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
             })
         })
@@ -14423,7 +14425,7 @@ impl Editor {
 
         let text_layout_details = &self.text_layout_details(window, cx);
         self.change_selections(effects, window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if !selection.is_empty() {
                     selection.goal = SelectionGoal::None;
                 }
@@ -14444,7 +14446,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         let text_layout_details = &self.text_layout_details(window, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, goal| {
+            s.move_heads_with(&mut |map, head, goal| {
                 movement::down(map, head, goal, false, text_layout_details)
             })
         });
@@ -14534,7 +14536,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (
                     movement::previous_word_start(map, head),
                     SelectionGoal::None,
@@ -14551,7 +14553,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (
                     movement::previous_subword_start(map, head),
                     SelectionGoal::None,
@@ -14568,7 +14570,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::previous_word_start(map, head),
                     SelectionGoal::None,
@@ -14585,7 +14587,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::previous_subword_start(map, head),
                     SelectionGoal::None,
@@ -14604,7 +14606,7 @@ impl Editor {
         self.transact(window, cx, |this, window, cx| {
             this.select_autoclose_pair(window, cx);
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         let mut cursor = if action.ignore_newlines {
                             movement::previous_word_start(map, selection.head())
@@ -14635,7 +14637,7 @@ impl Editor {
         self.transact(window, cx, |this, window, cx| {
             this.select_autoclose_pair(window, cx);
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         let mut cursor = if action.ignore_newlines {
                             movement::previous_subword_start(map, selection.head())
@@ -14664,7 +14666,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (movement::next_word_end(map, head), SelectionGoal::None)
             });
         })
@@ -14678,7 +14680,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (movement::next_subword_end(map, head), SelectionGoal::None)
             });
         })
@@ -14692,7 +14694,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (movement::next_word_end(map, head), SelectionGoal::None)
             });
         })
@@ -14706,7 +14708,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (movement::next_subword_end(map, head), SelectionGoal::None)
             });
         })
@@ -14721,7 +14723,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
         self.transact(window, cx, |this, window, cx| {
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         let mut cursor = if action.ignore_newlines {
                             movement::next_word_end(map, selection.head())
@@ -14751,7 +14753,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
         self.transact(window, cx, |this, window, cx| {
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         let mut cursor = if action.ignore_newlines {
                             movement::next_subword_end(map, selection.head())
@@ -14780,7 +14782,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (
                     movement::indented_line_beginning(
                         map,
@@ -14802,7 +14804,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::indented_line_beginning(
                         map,
@@ -14825,7 +14827,7 @@ impl Editor {
         self.hide_mouse_cursor(HideMouseCursorOrigin::TypingAction, cx);
         self.transact(window, cx, |this, window, cx| {
             this.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|_, selection| {
+                s.move_with(&mut |_, selection| {
                     selection.reversed = true;
                 });
             });
@@ -14850,7 +14852,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_cursors_with(|map, head, _| {
+            s.move_cursors_with(&mut |map, head, _| {
                 (
                     movement::line_end(map, head, action.stop_at_soft_wraps),
                     SelectionGoal::None,
@@ -14867,7 +14869,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::line_end(map, head, action.stop_at_soft_wraps),
                     SelectionGoal::None,
@@ -14912,7 +14914,7 @@ impl Editor {
             );
             if !action.stop_at_newlines {
                 this.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|_, sel| {
+                    s.move_with(&mut |_, sel| {
                         if sel.is_empty() {
                             sel.end = DisplayPoint::new(sel.end.row() + 1_u32, 0);
                         }
@@ -14937,7 +14939,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::start_of_paragraph(map, selection.head(), 1),
                     SelectionGoal::None,
@@ -14958,7 +14960,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::end_of_paragraph(map, selection.head(), 1),
                     SelectionGoal::None,
@@ -14979,7 +14981,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::start_of_paragraph(map, head, 1),
                     SelectionGoal::None,
@@ -15000,7 +15002,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::end_of_paragraph(map, head, 1),
                     SelectionGoal::None,
@@ -15021,7 +15023,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::start_of_excerpt(
                         map,
@@ -15046,7 +15048,7 @@ impl Editor {
         }
 
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::start_of_excerpt(
                         map,
@@ -15071,7 +15073,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::end_of_excerpt(
                         map,
@@ -15096,7 +15098,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 selection.collapse_to(
                     movement::end_of_excerpt(
                         map,
@@ -15121,7 +15123,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::start_of_excerpt(map, head, workspace::searchable::Direction::Prev),
                     SelectionGoal::None,
@@ -15142,7 +15144,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::start_of_excerpt(map, head, workspace::searchable::Direction::Next),
                     SelectionGoal::None,
@@ -15163,7 +15165,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::end_of_excerpt(map, head, workspace::searchable::Direction::Next),
                     SelectionGoal::None,
@@ -15184,7 +15186,7 @@ impl Editor {
         }
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_heads_with(|map, head, _| {
+            s.move_heads_with(&mut |map, head, _| {
                 (
                     movement::end_of_excerpt(map, head, workspace::searchable::Direction::Prev),
                     SelectionGoal::None,
@@ -16407,7 +16409,7 @@ impl Editor {
                 let snapshot = this.buffer.read(cx).snapshot(cx);
 
                 this.change_selections(Default::default(), window, cx, |s| {
-                    s.move_cursors_with(|display_snapshot, display_point, _| {
+                    s.move_cursors_with(&mut |display_snapshot, display_point, _| {
                         let mut point = display_point.to_point(display_snapshot);
                         point.row += 1;
                         point = snapshot.clip_point(point, Bias::Left);
@@ -17259,7 +17261,7 @@ impl Editor {
     ) {
         self.hide_mouse_cursor(HideMouseCursorOrigin::MovementAction, cx);
         self.change_selections(Default::default(), window, cx, |s| {
-            s.move_offsets_with(|snapshot, selection| {
+            s.move_offsets_with(&mut |snapshot, selection| {
                 let Some(enclosing_bracket_ranges) =
                     snapshot.enclosing_bracket_ranges(selection.start..selection.end)
                 else {
@@ -19762,7 +19764,7 @@ impl Editor {
     pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
         if self.selection_mark_mode {
             self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                s.move_with(|_, sel| {
+                s.move_with(&mut |_, sel| {
                     sel.collapse_to(sel.head(), SelectionGoal::None);
                 });
             })
@@ -19778,7 +19780,7 @@ impl Editor {
         cx: &mut Context<Self>,
     ) {
         self.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-            s.move_with(|_, sel| {
+            s.move_with(&mut |_, sel| {
                 if sel.start != sel.end {
                     sel.reversed = !sel.reversed
                 }
@@ -23855,7 +23857,7 @@ impl Editor {
 
     pub fn clear_highlights_with(
         &mut self,
-        f: impl FnMut(&HighlightKey) -> bool,
+        f: &mut dyn FnMut(&HighlightKey) -> bool,
         cx: &mut Context<Self>,
     ) {
         let cleared = self

crates/editor/src/inlays/inlay_hints.rs 🔗

@@ -227,7 +227,7 @@ impl Editor {
 
         let mut supports = false;
         self.buffer().update(cx, |this, cx| {
-            this.for_each_buffer(|buffer| {
+            this.for_each_buffer(&mut |buffer| {
                 supports |= provider.supports_inlay_hints(buffer, cx);
             });
         });

crates/editor/src/items.rs 🔗

@@ -757,7 +757,7 @@ impl Item for Editor {
     ) {
         self.buffer
             .read(cx)
-            .for_each_buffer(|buffer| f(buffer.entity_id(), buffer.read(cx)));
+            .for_each_buffer(&mut |buffer| f(buffer.entity_id(), buffer.read(cx)));
     }
 
     fn buffer_kind(&self, cx: &App) -> ItemBufferKind {
@@ -1004,7 +1004,7 @@ impl Item for Editor {
         }
     }
 
-    fn to_item_events(event: &EditorEvent, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         match event {
             EditorEvent::Saved | EditorEvent::TitleChanged => {
                 f(ItemEvent::UpdateTab);

crates/editor/src/jsx_tag_auto_close.rs 🔗

@@ -311,7 +311,7 @@ pub(crate) fn refresh_enabled_in_any_buffer(
     editor.jsx_tag_auto_close_enabled_in_any_buffer = {
         let multi_buffer = multi_buffer.read(cx);
         let mut found_enabled = false;
-        multi_buffer.for_each_buffer(|buffer| {
+        multi_buffer.for_each_buffer(&mut |buffer| {
             if found_enabled {
                 return;
             }

crates/editor/src/movement.rs 🔗

@@ -268,7 +268,7 @@ pub fn previous_word_start(map: &DisplaySnapshot, point: DisplayPoint) -> Displa
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
     let mut is_first_iteration = true;
-    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, |left, right| {
+    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, &mut |left, right| {
         // Make alt-left skip punctuation to respect VSCode behaviour. For example: hello.| goes to |hello.
         if is_first_iteration
             && classifier.is_punctuation(right)
@@ -291,7 +291,7 @@ pub fn previous_word_start_or_newline(map: &DisplaySnapshot, point: DisplayPoint
     let raw_point = point.to_point(map);
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
-    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, |left, right| {
+    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, &mut |left, right| {
         (classifier.kind(left) != classifier.kind(right) && !classifier.is_whitespace(right))
             || left == '\n'
             || right == '\n'
@@ -407,7 +407,7 @@ pub fn previous_subword_start(map: &DisplaySnapshot, point: DisplayPoint) -> Dis
     let raw_point = point.to_point(map);
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
-    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, |left, right| {
+    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, &mut |left, right| {
         is_subword_start(left, right, &classifier) || left == '\n'
     })
 }
@@ -422,7 +422,7 @@ pub fn previous_subword_start_or_newline(
     let raw_point = point.to_point(map);
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
-    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, |left, right| {
+    find_preceding_boundary_display_point(map, point, FindRange::MultiLine, &mut |left, right| {
         (is_subword_start(left, right, &classifier)) || left == '\n' || right == '\n'
     })
 }
@@ -441,7 +441,7 @@ pub fn next_word_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPoint
     let raw_point = point.to_point(map);
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
     let mut is_first_iteration = true;
-    find_boundary(map, point, FindRange::MultiLine, |left, right| {
+    find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
         // Make alt-right skip punctuation to respect VSCode behaviour. For example: |.hello goes to .hello|
         if is_first_iteration
             && classifier.is_punctuation(left)
@@ -465,7 +465,7 @@ pub fn next_word_end_or_newline(map: &DisplaySnapshot, point: DisplayPoint) -> D
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
     let mut on_starting_row = true;
-    find_boundary(map, point, FindRange::MultiLine, |left, right| {
+    find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
         if left == '\n' {
             on_starting_row = false;
         }
@@ -483,7 +483,7 @@ pub fn next_subword_end(map: &DisplaySnapshot, point: DisplayPoint) -> DisplayPo
     let raw_point = point.to_point(map);
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
-    find_boundary(map, point, FindRange::MultiLine, |left, right| {
+    find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
         is_subword_end(left, right, &classifier) || right == '\n'
     })
 }
@@ -496,7 +496,7 @@ pub fn next_subword_end_or_newline(map: &DisplaySnapshot, point: DisplayPoint) -
     let classifier = map.buffer_snapshot().char_classifier_at(raw_point);
 
     let mut on_starting_row = true;
-    find_boundary(map, point, FindRange::MultiLine, |left, right| {
+    find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
         if left == '\n' {
             on_starting_row = false;
         }
@@ -655,7 +655,7 @@ pub fn find_preceding_boundary_point(
     buffer_snapshot: &MultiBufferSnapshot,
     from: Point,
     find_range: FindRange,
-    mut is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> Point {
     let mut prev_ch = None;
     let mut offset = from.to_offset(buffer_snapshot);
@@ -685,7 +685,7 @@ pub fn find_preceding_boundary_display_point(
     map: &DisplaySnapshot,
     from: DisplayPoint,
     find_range: FindRange,
-    is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> DisplayPoint {
     let result = find_preceding_boundary_point(
         map.buffer_snapshot(),
@@ -705,7 +705,7 @@ pub fn find_boundary_point(
     map: &DisplaySnapshot,
     from: DisplayPoint,
     find_range: FindRange,
-    mut is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
     return_point_before_boundary: bool,
 ) -> DisplayPoint {
     let mut offset = from.to_offset(map, Bias::Right);
@@ -735,7 +735,7 @@ pub fn find_boundary_point(
 pub fn find_preceding_boundary_trail(
     map: &DisplaySnapshot,
     head: DisplayPoint,
-    mut is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> (Option<DisplayPoint>, DisplayPoint) {
     let mut offset = head.to_offset(map, Bias::Left);
     let mut trail_offset = None;
@@ -783,7 +783,7 @@ pub fn find_preceding_boundary_trail(
 pub fn find_boundary_trail(
     map: &DisplaySnapshot,
     head: DisplayPoint,
-    mut is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> (Option<DisplayPoint>, DisplayPoint) {
     let mut offset = head.to_offset(map, Bias::Right);
     let mut trail_offset = None;
@@ -831,7 +831,7 @@ pub fn find_boundary(
     map: &DisplaySnapshot,
     from: DisplayPoint,
     find_range: FindRange,
-    is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> DisplayPoint {
     find_boundary_point(map, from, find_range, is_boundary, false)
 }
@@ -840,7 +840,7 @@ pub fn find_boundary_exclusive(
     map: &DisplaySnapshot,
     from: DisplayPoint,
     find_range: FindRange,
-    is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> DisplayPoint {
     find_boundary_point(map, from, find_range, is_boundary, true)
 }
@@ -1001,7 +1001,7 @@ mod tests {
         fn assert(
             marked_text: &str,
             cx: &mut gpui::App,
-            is_boundary: impl FnMut(char, char) -> bool,
+            is_boundary: &mut dyn FnMut(char, char) -> bool,
         ) {
             let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
             assert_eq!(
@@ -1015,14 +1015,14 @@ mod tests {
             );
         }
 
-        assert("abcˇdef\ngh\nijˇk", cx, |left, right| {
+        assert("abcˇdef\ngh\nijˇk", cx, &mut |left, right| {
             left == 'c' && right == 'd'
         });
-        assert("abcdef\nˇgh\nijˇk", cx, |left, right| {
+        assert("abcdef\nˇgh\nijˇk", cx, &mut |left, right| {
             left == '\n' && right == 'g'
         });
         let mut line_count = 0;
-        assert("abcdef\nˇgh\nijˇk", cx, |left, _| {
+        assert("abcdef\nˇgh\nijˇk", cx, &mut |left, _| {
             if left == '\n' {
                 line_count += 1;
                 line_count == 2
@@ -1095,7 +1095,7 @@ mod tests {
                 &snapshot,
                 buffer_snapshot.len().to_display_point(&snapshot),
                 FindRange::MultiLine,
-                |left, _| left == 'e',
+                &mut |left, _| left == 'e',
             ),
             snapshot
                 .buffer_snapshot()
@@ -1183,7 +1183,7 @@ mod tests {
         fn assert(
             marked_text: &str,
             cx: &mut gpui::App,
-            is_boundary: impl FnMut(char, char) -> bool,
+            is_boundary: &mut dyn FnMut(char, char) -> bool,
         ) {
             let (snapshot, display_points) = marked_display_snapshot(marked_text, cx);
             assert_eq!(
@@ -1197,14 +1197,14 @@ mod tests {
             );
         }
 
-        assert("abcˇdef\ngh\nijˇk", cx, |left, right| {
+        assert("abcˇdef\ngh\nijˇk", cx, &mut |left, right| {
             left == 'j' && right == 'k'
         });
-        assert("abˇcdef\ngh\nˇijk", cx, |left, right| {
+        assert("abˇcdef\ngh\nˇijk", cx, &mut |left, right| {
             left == '\n' && right == 'i'
         });
         let mut line_count = 0;
-        assert("abcˇdef\ngh\nˇijk", cx, |left, _| {
+        assert("abcˇdef\ngh\nˇijk", cx, &mut |left, _| {
             if left == '\n' {
                 line_count += 1;
                 line_count == 2

crates/editor/src/selections_collection.rs 🔗

@@ -966,7 +966,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 
     pub fn move_with(
         &mut self,
-        mut move_selection: impl FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
+        move_selection: &mut dyn FnMut(&DisplaySnapshot, &mut Selection<DisplayPoint>),
     ) {
         let mut changed = false;
         let display_map = self.display_snapshot();
@@ -990,7 +990,7 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 
     pub fn move_offsets_with(
         &mut self,
-        mut move_selection: impl FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
+        move_selection: &mut dyn FnMut(&MultiBufferSnapshot, &mut Selection<MultiBufferOffset>),
     ) {
         let mut changed = false;
         let display_map = self.display_snapshot();
@@ -1015,13 +1015,13 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 
     pub fn move_heads_with(
         &mut self,
-        mut update_head: impl FnMut(
+        update_head: &mut dyn FnMut(
             &DisplaySnapshot,
             DisplayPoint,
             SelectionGoal,
         ) -> (DisplayPoint, SelectionGoal),
     ) {
-        self.move_with(|map, selection| {
+        self.move_with(&mut |map, selection| {
             let (new_head, new_goal) = update_head(map, selection.head(), selection.goal);
             selection.set_head(new_head, new_goal);
         });
@@ -1029,13 +1029,13 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 
     pub fn move_cursors_with(
         &mut self,
-        mut update_cursor_position: impl FnMut(
+        update_cursor_position: &mut dyn FnMut(
             &DisplaySnapshot,
             DisplayPoint,
             SelectionGoal,
         ) -> (DisplayPoint, SelectionGoal),
     ) {
-        self.move_with(|map, selection| {
+        self.move_with(&mut |map, selection| {
             let (cursor, new_goal) = update_cursor_position(map, selection.head(), selection.goal);
             selection.collapse_to(cursor, new_goal)
         });
@@ -1043,13 +1043,13 @@ impl<'snap, 'a> MutableSelectionsCollection<'snap, 'a> {
 
     pub fn maybe_move_cursors_with(
         &mut self,
-        mut update_cursor_position: impl FnMut(
+        update_cursor_position: &mut dyn FnMut(
             &DisplaySnapshot,
             DisplayPoint,
             SelectionGoal,
         ) -> Option<(DisplayPoint, SelectionGoal)>,
     ) {
-        self.move_cursors_with(|map, point, goal| {
+        self.move_cursors_with(&mut |map, point, goal| {
             update_cursor_position(map, point, goal).unwrap_or((point, goal))
         })
     }

crates/editor/src/semantic_tokens.rs 🔗

@@ -83,7 +83,7 @@ impl Editor {
 
         let mut supports = false;
         self.buffer().update(cx, |this, cx| {
-            this.for_each_buffer(|buffer| {
+            this.for_each_buffer(&mut |buffer| {
                 supports |= provider.supports_semantic_tokens(buffer, cx);
             });
         });

crates/editor/src/split.rs 🔗

@@ -1616,7 +1616,7 @@ impl Item for SplittableEditor {
         self.rhs_editor.read(cx).tab_content(params, window, cx)
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/extensions_ui/src/extensions_ui.rs 🔗

@@ -1883,7 +1883,7 @@ impl Item for ExtensionsPage {
         false
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         f(*event)
     }
 }

crates/git_graph/src/git_graph.rs 🔗

@@ -1816,7 +1816,7 @@ impl Item for GitGraph {
         false
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
         f(*event)
     }
 }

crates/git_ui/src/commit_view.rs 🔗

@@ -958,7 +958,7 @@ impl Item for CommitView {
         }))))
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/git_ui/src/file_diff_view.rs 🔗

@@ -259,7 +259,7 @@ impl Item for FileDiffView {
         Some(format!("{old_path} ↔ {new_path}").into())
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/git_ui/src/file_history_view.rs 🔗

@@ -552,7 +552,7 @@ impl Render for FileHistoryView {
 impl Item for FileHistoryView {
     type Event = ItemEvent;
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
         f(*event)
     }
 

crates/git_ui/src/multi_diff_view.rs 🔗

@@ -281,7 +281,7 @@ impl Item for MultiDiffView {
         self.title()
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/git_ui/src/project_diff.rs 🔗

@@ -861,7 +861,7 @@ impl Item for ProjectDiff {
         Some(Icon::new(IconName::GitBranch).color(Color::Muted))
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/git_ui/src/text_diff_view.rs 🔗

@@ -316,7 +316,7 @@ impl Item for TextDiffView {
         self.path.clone()
     }
 
-    fn to_item_events(event: &EditorEvent, f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &EditorEvent, f: &mut dyn FnMut(ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/image_viewer/src/image_viewer.rs 🔗

@@ -479,7 +479,7 @@ impl EventEmitter<ImageViewEvent> for ImageView {}
 impl Item for ImageView {
     type Event = ImageViewEvent;
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         match event {
             ImageViewEvent::TitleChanged => {
                 f(workspace::item::ItemEvent::UpdateTab);

crates/language/src/text_diff.rs 🔗

@@ -162,7 +162,7 @@ pub fn line_diff(old_text: &str, new_text: &str) -> Vec<(Range<u32>, Range<u32>)
         lines_with_terminator(old_text),
         lines_with_terminator(new_text),
     );
-    diff_internal(&input, |_, _, old_rows, new_rows| {
+    diff_internal(&input, &mut |_, _, old_rows, new_rows| {
         edits.push((old_rows, new_rows));
     });
     edits
@@ -194,7 +194,7 @@ pub fn word_diff_ranges(
     let mut old_ranges: Vec<Range<usize>> = Vec::new();
     let mut new_ranges: Vec<Range<usize>> = Vec::new();
 
-    diff_internal(&input, |old_byte_range, new_byte_range, _, _| {
+    diff_internal(&input, &mut |old_byte_range, new_byte_range, _, _| {
         if !old_byte_range.is_empty() {
             if let Some(last) = old_ranges.last_mut()
                 && last.end >= old_byte_range.start
@@ -227,7 +227,7 @@ pub fn char_diff<'a>(old_text: &'a str, new_text: &'a str) -> Vec<(Range<usize>,
     input.update_before(tokenize_chars(old_text));
     input.update_after(tokenize_chars(new_text));
     let mut edits: Vec<(Range<usize>, &str)> = Vec::new();
-    diff_internal(&input, |old_byte_range, new_byte_range, _, _| {
+    diff_internal(&input, &mut |old_byte_range, new_byte_range, _, _| {
         let replacement = if new_byte_range.is_empty() {
             ""
         } else {
@@ -268,49 +268,49 @@ pub fn text_diff_with_options(
         lines_with_terminator(old_text),
         lines_with_terminator(new_text),
     );
-    diff_internal(
-        &input,
-        |old_byte_range, new_byte_range, old_rows, new_rows| {
-            if should_perform_word_diff_within_hunk(
-                &old_rows,
-                &old_byte_range,
-                &new_rows,
-                &new_byte_range,
-                &options,
-            ) {
-                let old_offset = old_byte_range.start;
-                let new_offset = new_byte_range.start;
-                hunk_input.clear();
-                hunk_input.update_before(tokenize(
-                    &old_text[old_byte_range],
-                    options.language_scope.clone(),
-                ));
-                hunk_input.update_after(tokenize(
-                    &new_text[new_byte_range],
-                    options.language_scope.clone(),
-                ));
-                diff_internal(&hunk_input, |old_byte_range, new_byte_range, _, _| {
-                    let old_byte_range =
-                        old_offset + old_byte_range.start..old_offset + old_byte_range.end;
-                    let new_byte_range =
-                        new_offset + new_byte_range.start..new_offset + new_byte_range.end;
-                    let replacement_text = if new_byte_range.is_empty() {
-                        empty.clone()
-                    } else {
-                        new_text[new_byte_range].into()
-                    };
-                    edits.push((old_byte_range, replacement_text));
-                });
-            } else {
+    diff_internal(&input, &mut |old_byte_range,
+                                new_byte_range,
+                                old_rows,
+                                new_rows| {
+        if should_perform_word_diff_within_hunk(
+            &old_rows,
+            &old_byte_range,
+            &new_rows,
+            &new_byte_range,
+            &options,
+        ) {
+            let old_offset = old_byte_range.start;
+            let new_offset = new_byte_range.start;
+            hunk_input.clear();
+            hunk_input.update_before(tokenize(
+                &old_text[old_byte_range],
+                options.language_scope.clone(),
+            ));
+            hunk_input.update_after(tokenize(
+                &new_text[new_byte_range],
+                options.language_scope.clone(),
+            ));
+            diff_internal(&hunk_input, &mut |old_byte_range, new_byte_range, _, _| {
+                let old_byte_range =
+                    old_offset + old_byte_range.start..old_offset + old_byte_range.end;
+                let new_byte_range =
+                    new_offset + new_byte_range.start..new_offset + new_byte_range.end;
                 let replacement_text = if new_byte_range.is_empty() {
                     empty.clone()
                 } else {
                     new_text[new_byte_range].into()
                 };
                 edits.push((old_byte_range, replacement_text));
-            }
-        },
-    );
+            });
+        } else {
+            let replacement_text = if new_byte_range.is_empty() {
+                empty.clone()
+            } else {
+                new_text[new_byte_range].into()
+            };
+            edits.push((old_byte_range, replacement_text));
+        }
+    });
     edits
 }
 
@@ -343,7 +343,7 @@ fn should_perform_word_diff_within_hunk(
 
 fn diff_internal(
     input: &InternedInput<&str>,
-    mut on_change: impl FnMut(Range<usize>, Range<usize>, Range<u32>, Range<u32>),
+    on_change: &mut dyn FnMut(Range<usize>, Range<usize>, Range<u32>, Range<u32>),
 ) {
     let mut old_offset = 0;
     let mut new_offset = 0;

crates/language_tools/src/highlights_tree_view.rs 🔗

@@ -428,7 +428,7 @@ impl HighlightsTreeView {
         entry_ix: usize,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut f: impl FnMut(&mut Editor, Range<Anchor>, usize, &mut Window, &mut Context<Editor>),
+        f: &mut dyn FnMut(&mut Editor, Range<Anchor>, usize, &mut Window, &mut Context<Editor>),
     ) -> Option<()> {
         let editor_state = self.editor.as_ref()?;
         let entry = self.cached_entries.get(entry_ix)?;
@@ -510,7 +510,7 @@ impl HighlightsTreeView {
                                     entry_ix,
                                     window,
                                     cx,
-                                    |editor, mut range, _, window, cx| {
+                                    &mut |editor, mut range, _, window, cx| {
                                         mem::swap(&mut range.start, &mut range.end);
                                         editor.change_selections(
                                             SelectionEffects::scroll(Autoscroll::newest()),
@@ -533,7 +533,7 @@ impl HighlightsTreeView {
                                         entry_ix,
                                         window,
                                         cx,
-                                        |editor, range, key, _, cx| {
+                                        &mut |editor, range, key, _, cx| {
                                             Self::set_editor_highlights(editor, key, &[range], cx);
                                         },
                                     );
@@ -623,7 +623,7 @@ impl HighlightsTreeView {
                 entry_ix,
                 window,
                 cx,
-                |editor, mut range, _, window, cx| {
+                &mut |editor, mut range, _, window, cx| {
                     mem::swap(&mut range.start, &mut range.end);
                     editor.change_selections(
                         SelectionEffects::scroll(Autoscroll::newest()),
@@ -730,7 +730,7 @@ impl Focusable for HighlightsTreeView {
 impl Item for HighlightsTreeView {
     type Event = ();
 
-    fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
+    fn to_item_events(_: &Self::Event, _: &mut dyn FnMut(workspace::item::ItemEvent)) {}
 
     fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
         "Highlights".into()

crates/language_tools/src/key_context_view.rs 🔗

@@ -143,7 +143,7 @@ impl KeyContextView {
 impl Item for KeyContextView {
     type Event = ();
 
-    fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
+    fn to_item_events(_: &Self::Event, _: &mut dyn FnMut(workspace::item::ItemEvent)) {}
 
     fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
         "Keyboard Context".into()

crates/language_tools/src/lsp_log_view.rs 🔗

@@ -739,7 +739,7 @@ impl Focusable for LspLogView {
 impl Item for LspLogView {
     type Event = EditorEvent;
 
-    fn to_item_events(event: &Self::Event, f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         Editor::to_item_events(event, f)
     }
 

crates/language_tools/src/syntax_tree_view.rs 🔗

@@ -341,7 +341,7 @@ impl SyntaxTreeView {
         descendant_ix: usize,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut f: impl FnMut(&mut Editor, Range<Anchor>, usize, &mut Window, &mut Context<Editor>),
+        f: &mut dyn FnMut(&mut Editor, Range<Anchor>, usize, &mut Window, &mut Context<Editor>),
     ) -> Option<()> {
         let editor_state = self.editor.as_ref()?;
         let buffer_state = editor_state.active_buffer.as_ref()?;
@@ -434,7 +434,7 @@ impl SyntaxTreeView {
                                 descendant_ix,
                                 window,
                                 cx,
-                                |editor, mut range, _, window, cx| {
+                                &mut |editor, mut range, _, window, cx| {
                                     // Put the cursor at the beginning of the node.
                                     mem::swap(&mut range.start, &mut range.end);
 
@@ -458,7 +458,7 @@ impl SyntaxTreeView {
                                     descendant_ix,
                                     window,
                                     cx,
-                                    |editor, range, key, _, cx| {
+                                    &mut |editor, range, key, _, cx| {
                                         Self::set_editor_highlights(editor, key, &[range], cx);
                                     },
                                 );
@@ -573,7 +573,7 @@ impl Focusable for SyntaxTreeView {
 impl Item for SyntaxTreeView {
     type Event = ();
 
-    fn to_item_events(_: &Self::Event, _: impl FnMut(workspace::item::ItemEvent)) {}
+    fn to_item_events(_: &Self::Event, _: &mut dyn FnMut(workspace::item::ItemEvent)) {}
 
     fn tab_content_text(&self, _detail: usize, _cx: &App) -> SharedString {
         "Syntax Tree".into()

crates/markdown_preview/src/markdown_preview_view.rs 🔗

@@ -537,7 +537,7 @@ impl Item for MarkdownPreviewView {
         Some("Markdown Preview Opened")
     }
 
-    fn to_item_events(_event: &Self::Event, _f: impl FnMut(workspace::item::ItemEvent)) {}
+    fn to_item_events(_event: &Self::Event, _f: &mut dyn FnMut(workspace::item::ItemEvent)) {}
 }
 
 impl Render for MarkdownPreviewView {

crates/migrator/src/migrations.rs 🔗

@@ -6,7 +6,7 @@ use settings_content::{PlatformOverrides, ReleaseChannelOverrides};
 /// nested platform, release-channel, and profile override objects.
 pub(crate) fn migrate_settings(
     value: &mut Value,
-    mut migrate_one: impl FnMut(&mut serde_json::Map<String, Value>) -> Result<()>,
+    migrate_one: &mut dyn FnMut(&mut serde_json::Map<String, Value>) -> Result<()>,
 ) -> Result<()> {
     let Some(root_object) = value.as_object_mut() else {
         return Ok(());

crates/migrator/src/migrations/m_2025_10_17/settings.rs 🔗

@@ -4,7 +4,7 @@ use serde_json::Value;
 use crate::migrations::migrate_settings;
 
 pub fn make_file_finder_include_ignored_an_enum(value: &mut Value) -> Result<()> {
-    migrate_settings(value, migrate_one)
+    migrate_settings(value, &mut migrate_one)
 }
 
 fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {

crates/migrator/src/migrations/m_2025_10_21/settings.rs 🔗

@@ -4,7 +4,7 @@ use serde_json::Value;
 use crate::migrations::migrate_settings;
 
 pub fn make_relative_line_numbers_an_enum(value: &mut Value) -> Result<()> {
-    migrate_settings(value, migrate_one)
+    migrate_settings(value, &mut migrate_one)
 }
 
 fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {

crates/migrator/src/migrations/m_2025_11_25/settings.rs 🔗

@@ -4,7 +4,7 @@ use serde_json::Value;
 use crate::migrations::migrate_settings;
 
 pub fn remove_context_server_source(value: &mut Value) -> Result<()> {
-    migrate_settings(value, migrate_one)
+    migrate_settings(value, &mut migrate_one)
 }
 
 fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {

crates/migrator/src/migrations/m_2026_02_02/settings.rs 🔗

@@ -4,7 +4,7 @@ use serde_json::Value;
 use crate::migrations::migrate_settings;
 
 pub fn move_edit_prediction_provider_to_edit_predictions(value: &mut Value) -> Result<()> {
-    migrate_settings(value, migrate_one)
+    migrate_settings(value, &mut migrate_one)
 }
 
 fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {

crates/migrator/src/migrations/m_2026_02_03/settings.rs 🔗

@@ -4,7 +4,7 @@ use serde_json::Value;
 use crate::migrations::migrate_settings;
 
 pub fn migrate_experimental_sweep_mercury(value: &mut Value) -> Result<()> {
-    migrate_settings(value, |obj| {
+    migrate_settings(value, &mut |obj| {
         migrate_one(obj);
         Ok(())
     })

crates/migrator/src/migrations/m_2026_02_04/settings.rs 🔗

@@ -12,7 +12,7 @@ const TOOL_PERMISSIONS_KEY: &str = "tool_permissions";
 const TOOLS_KEY: &str = "tools";
 
 pub fn migrate_tool_permission_defaults(value: &mut Value) -> Result<()> {
-    migrate_settings(value, migrate_one)
+    migrate_settings(value, &mut migrate_one)
 }
 
 fn migrate_one(obj: &mut serde_json::Map<String, Value>) -> Result<()> {

crates/multi_buffer/src/multi_buffer.rs 🔗

@@ -2563,7 +2563,7 @@ impl MultiBuffer {
         language_settings(language.map(|l| l.name()), file, cx)
     }
 
-    pub fn for_each_buffer(&self, mut f: impl FnMut(&Entity<Buffer>)) {
+    pub fn for_each_buffer(&self, f: &mut dyn FnMut(&Entity<Buffer>)) {
         self.buffers.values().for_each(|state| f(&state.buffer))
     }
 
@@ -4978,7 +4978,7 @@ impl MultiBufferSnapshot {
         let mut result = BTreeMap::new();
         self.suggested_indents_callback(
             rows,
-            |row, indent| {
+            &mut |row, indent| {
                 result.insert(row, indent);
                 ControlFlow::Continue(())
             },
@@ -4991,7 +4991,7 @@ impl MultiBufferSnapshot {
     pub fn suggested_indents_callback(
         &self,
         rows: impl IntoIterator<Item = u32>,
-        mut cb: impl FnMut(MultiBufferRow, IndentSize) -> ControlFlow<()>,
+        cb: &mut dyn FnMut(MultiBufferRow, IndentSize) -> ControlFlow<()>,
         cx: &App,
     ) {
         let mut rows_for_excerpt = Vec::new();

crates/onboarding/src/onboarding.rs 🔗

@@ -392,7 +392,7 @@ impl Item for Onboarding {
         })))
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         f(*event)
     }
 }

crates/project_panel/src/project_panel.rs 🔗

@@ -4479,7 +4479,7 @@ impl ProjectPanel {
         range: Range<usize>,
         window: &mut Window,
         cx: &mut Context<ProjectPanel>,
-        mut callback: impl FnMut(
+        callback: &mut dyn FnMut(
             &Entry,
             usize,
             &HashSet<Arc<RelPath>>,
@@ -4517,7 +4517,12 @@ impl ProjectPanel {
         range: Range<usize>,
         window: &mut Window,
         cx: &mut Context<ProjectPanel>,
-        mut callback: impl FnMut(ProjectEntryId, EntryDetails, &mut Window, &mut Context<ProjectPanel>),
+        callback: &mut dyn FnMut(
+            ProjectEntryId,
+            EntryDetails,
+            &mut Window,
+            &mut Context<ProjectPanel>,
+        ),
     ) {
         let mut ix = 0;
         for visible in &self.state.visible_entries {
@@ -5393,7 +5398,7 @@ impl ProjectPanel {
                                 range_start..range_end,
                                 window,
                                 cx,
-                                |entry_id, details, _, _| {
+                                &mut |entry_id, details, _, _| {
                                     new_selections.push(SelectedEntry {
                                         entry_id,
                                         worktree_id: details.worktree_id,
@@ -6372,7 +6377,7 @@ impl Render for ProjectPanel {
                                         range,
                                         window,
                                         cx,
-                                        |id, details, window, cx| {
+                                        &mut |id, details, window, cx| {
                                             items.push(this.render_entry(id, details, window, cx));
                                         },
                                     );
@@ -6394,7 +6399,7 @@ impl Render for ProjectPanel {
                                                 range,
                                                 window,
                                                 cx,
-                                                |entry, _, entries, _, _| {
+                                                &mut |entry, _, entries, _, _| {
                                                     let (depth, _) =
                                                         Self::calculate_depth_and_difference(
                                                             entry, entries,
@@ -6507,7 +6512,7 @@ impl Render for ProjectPanel {
                                             range,
                                             window,
                                             cx,
-                                            |entry, index, entries, _, _| {
+                                            &mut |entry, index, entries, _, _| {
                                                 let (depth, _) =
                                                     Self::calculate_depth_and_difference(
                                                         entry, entries,

crates/project_panel/src/project_panel_tests.rs 🔗

@@ -8829,7 +8829,7 @@ fn visible_entries_as_strings(
     let mut has_editor = false;
 
     panel.update_in(cx, |panel, window, cx| {
-        panel.for_each_visible_entry(range, window, cx, |project_entry, details, _, _| {
+        panel.for_each_visible_entry(range, window, cx, &mut |project_entry, details, _, _| {
             if details.is_editing {
                 assert!(!has_editor, "duplicate editor entry");
                 has_editor = true;

crates/remote/src/transport/ssh.rs 🔗

@@ -1105,7 +1105,7 @@ impl SshSocket {
         let get_password =
             move |_| Task::ready(std::ops::ControlFlow::Continue(Ok(password.clone())));
 
-        let _proxy = askpass::PasswordProxy::new(get_password, executor).await?;
+        let _proxy = askpass::PasswordProxy::new(Box::new(get_password), executor).await?;
         envs.insert("SSH_ASKPASS_REQUIRE".into(), "force".into());
         envs.insert(
             "SSH_ASKPASS".into(),

crates/repl/src/repl_sessions_ui.rs 🔗

@@ -190,7 +190,7 @@ impl Item for ReplSessionsPage {
         false
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(workspace::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(workspace::item::ItemEvent)) {
         f(*event)
     }
 }

crates/search/src/project_search.rs 🔗

@@ -678,7 +678,7 @@ impl Item for ProjectSearchView {
             .update(cx, |editor, cx| editor.navigate(data, window, cx))
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
         match event {
             ViewEvent::UpdateTab => {
                 f(ItemEvent::UpdateBreadcrumbs);

crates/sqlez/src/domain.rs 🔗

@@ -24,7 +24,7 @@ impl<D: Domain> Migrator for D {
         connection.migrate(
             Self::NAME,
             Self::MIGRATIONS,
-            Self::should_allow_migration_change,
+            &mut Self::should_allow_migration_change,
         )
     }
 }

crates/sqlez/src/migrations.rs 🔗

@@ -38,7 +38,7 @@ impl Connection {
         &self,
         domain: &'static str,
         migrations: &[&'static str],
-        mut should_allow_migration_change: impl FnMut(usize, &str, &str) -> bool,
+        should_allow_migration_change: &mut dyn FnMut(usize, &str, &str) -> bool,
     ) -> Result<()> {
         self.with_savepoint("migrating", || {
             // Setup the migrations table unconditionally
@@ -163,7 +163,7 @@ mod test {
                     a TEXT,
                     b TEXT
                 )"}],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
 
@@ -192,7 +192,7 @@ mod test {
                         d TEXT
                     )"},
                 ],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
 
@@ -274,7 +274,7 @@ mod test {
             .migrate(
                 "test",
                 &["DELETE FROM test_table"],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
         assert_eq!(
@@ -296,7 +296,7 @@ mod test {
             .migrate(
                 "test",
                 &["DELETE FROM test_table"],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
         assert_eq!(
@@ -320,7 +320,7 @@ mod test {
                     "CREATE TABLE test (col INTEGER)",
                     "INSERT INTO test (col) VALUES (1)",
                 ],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
 
@@ -333,7 +333,7 @@ mod test {
                 "CREATE TABLE test (color INTEGER )",
                 "INSERT INTO test (color) VALUES (1)",
             ],
-            |_, old, new| {
+            &mut |_, old, new| {
                 assert_eq!(old, "CREATE TABLE test (col INTEGER)");
                 assert_eq!(new, "CREATE TABLE test (color INTEGER)");
                 migration_changed = true;
@@ -353,7 +353,7 @@ mod test {
             .migrate(
                 "first_migration",
                 &["CREATE TABLE table1(a TEXT) STRICT;"],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
 
@@ -375,7 +375,7 @@ mod test {
 
                     ALTER TABLE table2 RENAME TO table1;
                 "}],
-                disallow_migration_change,
+                &mut disallow_migration_change,
             )
             .unwrap();
 

crates/svg_preview/src/svg_preview_view.rs 🔗

@@ -337,5 +337,5 @@ impl Item for SvgPreviewView {
         Some("svg preview: open")
     }
 
-    fn to_item_events(_event: &Self::Event, _f: impl FnMut(workspace::item::ItemEvent)) {}
+    fn to_item_events(_event: &Self::Event, _f: &mut dyn FnMut(workspace::item::ItemEvent)) {}
 }

crates/terminal_view/src/terminal_view.rs 🔗

@@ -1526,7 +1526,7 @@ impl Item for TerminalView {
         }
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
         f(*event)
     }
 }

crates/vim/src/helix.rs 🔗

@@ -135,7 +135,7 @@ impl Vim {
                     return;
                 };
 
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let was_reversed = selection.reversed;
                     let mut current_head = selection.head();
 
@@ -164,7 +164,7 @@ impl Vim {
                                 map.buffer_snapshot().char_classifier_at(head.to_point(map));
                             for _ in 0..times.unwrap_or(1) {
                                 let (_, new_head) =
-                                    movement::find_boundary_trail(map, head, |left, right| {
+                                    movement::find_boundary_trail(map, head, &mut |left, right| {
                                         Self::is_boundary_right(ignore_punctuation)(
                                             left,
                                             right,
@@ -216,7 +216,7 @@ impl Vim {
         &mut self,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut change: impl FnMut(
+        change: &mut dyn FnMut(
             // the start of the cursor
             DisplayPoint,
             &DisplaySnapshot,
@@ -224,7 +224,7 @@ impl Vim {
     ) {
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let cursor_start = if selection.reversed || selection.is_empty() {
                         selection.head()
                     } else {
@@ -245,10 +245,10 @@ impl Vim {
         times: Option<usize>,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut is_boundary: impl FnMut(char, char, &CharClassifier) -> bool,
+        is_boundary: &mut dyn FnMut(char, char, &CharClassifier) -> bool,
     ) {
         let times = times.unwrap_or(1);
-        self.helix_new_selections(window, cx, |cursor, map| {
+        self.helix_new_selections(window, cx, &mut |cursor, map| {
             let mut head = movement::right(map, cursor);
             let mut tail = cursor;
             let classifier = map.buffer_snapshot().char_classifier_at(head.to_point(map));
@@ -257,7 +257,7 @@ impl Vim {
             }
             for _ in 0..times {
                 let (maybe_next_tail, next_head) =
-                    movement::find_boundary_trail(map, head, |left, right| {
+                    movement::find_boundary_trail(map, head, &mut |left, right| {
                         is_boundary(left, right, &classifier)
                     });
 
@@ -279,10 +279,10 @@ impl Vim {
         times: Option<usize>,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut is_boundary: impl FnMut(char, char, &CharClassifier) -> bool,
+        is_boundary: &mut dyn FnMut(char, char, &CharClassifier) -> bool,
     ) {
         let times = times.unwrap_or(1);
-        self.helix_new_selections(window, cx, |cursor, map| {
+        self.helix_new_selections(window, cx, &mut |cursor, map| {
             let mut head = cursor;
             // The original cursor was one character wide,
             // but the search starts from the left side of it,
@@ -294,7 +294,7 @@ impl Vim {
             }
             for _ in 0..times {
                 let (maybe_next_tail, next_head) =
-                    movement::find_preceding_boundary_trail(map, head, |left, right| {
+                    movement::find_preceding_boundary_trail(map, head, &mut |left, right| {
                         is_boundary(left, right, &classifier)
                     });
 
@@ -321,7 +321,7 @@ impl Vim {
         self.update_editor(cx, |_, editor, cx| {
             let text_layout_details = editor.text_layout_details(window, cx);
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let goal = selection.goal;
                     let cursor = if selection.is_empty() || selection.reversed {
                         selection.head()
@@ -371,37 +371,29 @@ impl Vim {
         cx: &mut Context<Self>,
     ) {
         match motion {
-            Motion::NextWordStart { ignore_punctuation } => self.helix_find_range_forward(
-                times,
-                window,
-                cx,
-                Self::is_boundary_right(ignore_punctuation),
-            ),
-            Motion::NextWordEnd { ignore_punctuation } => self.helix_find_range_forward(
-                times,
-                window,
-                cx,
-                Self::is_boundary_left(ignore_punctuation),
-            ),
-            Motion::PreviousWordStart { ignore_punctuation } => self.helix_find_range_backward(
-                times,
-                window,
-                cx,
-                Self::is_boundary_left(ignore_punctuation),
-            ),
-            Motion::PreviousWordEnd { ignore_punctuation } => self.helix_find_range_backward(
-                times,
-                window,
-                cx,
-                Self::is_boundary_right(ignore_punctuation),
-            ),
+            Motion::NextWordStart { ignore_punctuation } => {
+                let mut is_boundary = Self::is_boundary_right(ignore_punctuation);
+                self.helix_find_range_forward(times, window, cx, &mut is_boundary)
+            }
+            Motion::NextWordEnd { ignore_punctuation } => {
+                let mut is_boundary = Self::is_boundary_left(ignore_punctuation);
+                self.helix_find_range_forward(times, window, cx, &mut is_boundary)
+            }
+            Motion::PreviousWordStart { ignore_punctuation } => {
+                let mut is_boundary = Self::is_boundary_left(ignore_punctuation);
+                self.helix_find_range_backward(times, window, cx, &mut is_boundary)
+            }
+            Motion::PreviousWordEnd { ignore_punctuation } => {
+                let mut is_boundary = Self::is_boundary_right(ignore_punctuation);
+                self.helix_find_range_backward(times, window, cx, &mut is_boundary)
+            }
             Motion::EndOfLine { .. } => {
                 // In Helix mode, EndOfLine should position cursor ON the last character,
                 // not after it. We therefore need special handling for it.
                 self.update_editor(cx, |_, editor, cx| {
                     let text_layout_details = editor.text_layout_details(window, cx);
                     editor.change_selections(Default::default(), window, cx, |s| {
-                        s.move_with(|map, selection| {
+                        s.move_with(&mut |map, selection| {
                             let goal = selection.goal;
                             let cursor = if selection.is_empty() || selection.reversed {
                                 selection.head()
@@ -426,7 +418,7 @@ impl Vim {
                 mode,
                 smartcase,
             } => {
-                self.helix_new_selections(window, cx, |cursor, map| {
+                self.helix_new_selections(window, cx, &mut |cursor, map| {
                     let start = cursor;
                     let mut last_boundary = start;
                     for _ in 0..times.unwrap_or(1) {
@@ -434,7 +426,7 @@ impl Vim {
                             map,
                             movement::right(map, last_boundary),
                             mode,
-                            |left, right| {
+                            &mut |left, right| {
                                 let current_char = if before { right } else { left };
                                 motion::is_character_match(char, current_char, smartcase)
                             },
@@ -449,7 +441,7 @@ impl Vim {
                 mode,
                 smartcase,
             } => {
-                self.helix_new_selections(window, cx, |cursor, map| {
+                self.helix_new_selections(window, cx, &mut |cursor, map| {
                     let start = cursor;
                     let mut last_boundary = start;
                     for _ in 0..times.unwrap_or(1) {
@@ -457,7 +449,7 @@ impl Vim {
                             map,
                             last_boundary,
                             mode,
-                            |left, right| {
+                            &mut |left, right| {
                                 let current_char = if after { left } else { right };
                                 motion::is_character_match(char, current_char, smartcase)
                             },
@@ -484,7 +476,7 @@ impl Vim {
             if !has_selection {
                 // If no selection, expand to current character (like 'v' does)
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let head = selection.head();
                         let new_head = movement::saturating_right(map, head);
                         selection.set_tail(head, SelectionGoal::None);
@@ -498,7 +490,7 @@ impl Vim {
                     cx,
                 );
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|_map, selection| {
+                    s.move_with(&mut |_map, selection| {
                         selection.collapse_to(selection.start, SelectionGoal::None);
                     });
                 });
@@ -521,7 +513,7 @@ impl Vim {
         self.start_recording(cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|_map, selection| {
+                s.move_with(&mut |_map, selection| {
                     // In helix normal mode, move cursor to start of selection and collapse
                     if !selection.is_empty() {
                         selection.collapse_to(selection.start, SelectionGoal::None);
@@ -596,7 +588,7 @@ impl Vim {
         self.switch_mode(Mode::Insert, false, window, cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let point = if selection.is_empty() {
                         right(map, selection.head(), 1)
                     } else {
@@ -756,7 +748,7 @@ impl Vim {
             editor.set_clip_at_line_ends(false, cx);
             editor.transact(window, cx, |editor, window, cx| {
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         if selection.start == selection.end {
                             selection.end = movement::right(map, selection.end);
                         }

crates/vim/src/helix/select.rs 🔗

@@ -16,7 +16,7 @@ impl Vim {
         self.stop_recording(cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let Some(range) = object
                         .helix_range(map, selection.clone(), around)
                         .unwrap_or({
@@ -45,7 +45,7 @@ impl Vim {
         self.stop_recording(cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let Ok(Some(range)) = object.helix_next_range(map, selection.clone(), around)
                     else {
                         return;
@@ -69,7 +69,7 @@ impl Vim {
         self.stop_recording(cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let Ok(Some(range)) =
                         object.helix_previous_range(map, selection.clone(), around)
                     else {

crates/vim/src/indent.rs 🔗

@@ -106,7 +106,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut selection_starts: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         selection_starts.insert(selection.id, anchor);
                         motion.expand_selection(
@@ -124,7 +124,7 @@ impl Vim {
                     IndentDirection::Auto => editor.autoindent(&Default::default(), window, cx),
                 }
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = selection_starts.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });
@@ -147,7 +147,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut original_positions: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         original_positions.insert(selection.id, anchor);
                         object.expand_selection(map, selection, around, times);
@@ -159,7 +159,7 @@ impl Vim {
                     IndentDirection::Auto => editor.autoindent(&Default::default(), window, cx),
                 }
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = original_positions.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });

crates/vim/src/insert.rs 🔗

@@ -62,7 +62,7 @@ impl Vim {
                 editor.dismiss_menus_and_popups(false, window, cx);
 
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_cursors_with(|map, mut cursor, _| {
+                    s.move_cursors_with(&mut |map, mut cursor, _| {
                         *cursor.column_mut() = cursor.column().saturating_sub(1);
                         (map.clip_point(cursor, Bias::Left), SelectionGoal::None)
                     });

crates/vim/src/motion.rs 🔗

@@ -1691,18 +1691,19 @@ pub(crate) fn next_word_start(
         .ignore_punctuation(ignore_punctuation);
     for _ in 0..times {
         let mut crossed_newline = false;
-        let new_point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
-            let left_kind = classifier.kind(left);
-            let right_kind = classifier.kind(right);
-            let at_newline = right == '\n';
+        let new_point =
+            movement::find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
+                let left_kind = classifier.kind(left);
+                let right_kind = classifier.kind(right);
+                let at_newline = right == '\n';
 
-            let found = (left_kind != right_kind && right_kind != CharKind::Whitespace)
-                || at_newline && crossed_newline
-                || at_newline && left == '\n'; // Prevents skipping repeated empty lines
+                let found = (left_kind != right_kind && right_kind != CharKind::Whitespace)
+                    || at_newline && crossed_newline
+                    || at_newline && left == '\n'; // Prevents skipping repeated empty lines
 
-            crossed_newline |= at_newline;
-            found
-        });
+                crossed_newline |= at_newline;
+                found
+            });
         if point == new_point {
             break;
         }
@@ -1717,7 +1718,7 @@ fn next_end_impl(
     times: usize,
     allow_cross_newline: bool,
     always_advance: bool,
-    mut is_boundary: impl FnMut(char, char) -> bool,
+    is_boundary: &mut dyn FnMut(char, char) -> bool,
 ) -> DisplayPoint {
     for _ in 0..times {
         let mut need_next_char = false;
@@ -1730,7 +1731,7 @@ fn next_end_impl(
             map,
             new_point,
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 let at_newline = right == '\n';
 
                 if !allow_cross_newline && at_newline {
@@ -1774,7 +1775,7 @@ pub(crate) fn next_word_end(
         times,
         allow_cross_newline,
         always_advance,
-        |left, right| {
+        &mut |left, right| {
             let left_kind = classifier.kind(left);
             let right_kind = classifier.kind(right);
             left_kind != right_kind && left_kind != CharKind::Whitespace
@@ -1800,7 +1801,7 @@ pub(crate) fn next_subword_end(
         times,
         allow_cross_newline,
         true,
-        |left, right| {
+        &mut |left, right| {
             let left_kind = classifier.kind(left);
             let right_kind = classifier.kind(right);
             let is_stopping_punct = |c: char| ".$=\"'{}[]()<>".contains(c);
@@ -1830,7 +1831,7 @@ fn previous_word_start(
             map,
             point,
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 let left_kind = classifier.kind(left);
                 let right_kind = classifier.kind(right);
 
@@ -1867,7 +1868,7 @@ fn previous_word_end(
             &map.buffer_snapshot(),
             point,
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 let left_kind = classifier.kind(left);
                 let right_kind = classifier.kind(right);
                 match (left_kind, right_kind) {
@@ -1914,21 +1915,22 @@ fn next_subword_start(
         .ignore_punctuation(ignore_punctuation);
     for _ in 0..times {
         let mut crossed_newline = false;
-        let new_point = movement::find_boundary(map, point, FindRange::MultiLine, |left, right| {
-            let left_kind = classifier.kind(left);
-            let right_kind = classifier.kind(right);
-            let at_newline = right == '\n';
-            let is_stopping_punct = |c: char| "$=\"'{}[]()<>".contains(c);
-            let found_subword_start = is_subword_start(left, right, ".$_-");
-            let is_word_start = (left_kind != right_kind)
-                && (!right.is_ascii_punctuation() || is_stopping_punct(right));
-            let found = (!right.is_whitespace() && (is_word_start || found_subword_start))
-                || at_newline && crossed_newline
-                || at_newline && left == '\n'; // Prevents skipping repeated empty lines
-
-            crossed_newline |= at_newline;
-            found
-        });
+        let new_point =
+            movement::find_boundary(map, point, FindRange::MultiLine, &mut |left, right| {
+                let left_kind = classifier.kind(left);
+                let right_kind = classifier.kind(right);
+                let at_newline = right == '\n';
+                let is_stopping_punct = |c: char| "$=\"'{}[]()<>".contains(c);
+                let found_subword_start = is_subword_start(left, right, ".$_-");
+                let is_word_start = (left_kind != right_kind)
+                    && (!right.is_ascii_punctuation() || is_stopping_punct(right));
+                let found = (!right.is_whitespace() && (is_word_start || found_subword_start))
+                    || at_newline && crossed_newline
+                    || at_newline && left == '\n'; // Prevents skipping repeated empty lines
+
+                crossed_newline |= at_newline;
+                found
+            });
         if point == new_point {
             break;
         }
@@ -1955,7 +1957,7 @@ fn previous_subword_start(
             map,
             point,
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 let left_kind = classifier.kind(left);
                 let right_kind = classifier.kind(right);
                 let at_newline = right == '\n';
@@ -2004,7 +2006,7 @@ fn previous_subword_end(
             &map.buffer_snapshot(),
             point,
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 let left_kind = classifier.kind(left);
                 let right_kind = classifier.kind(right);
 
@@ -2754,7 +2756,7 @@ fn find_forward(
 
     for _ in 0..times {
         found = false;
-        let new_to = find_boundary(map, to, mode, |_, right| {
+        let new_to = find_boundary(map, to, mode, &mut |_, right| {
             found = is_character_match(target, right, smartcase);
             found
         });
@@ -2792,7 +2794,7 @@ fn find_backward(
     let mut to = from;
 
     for _ in 0..times {
-        let new_to = find_preceding_boundary_display_point(map, to, mode, |_, right| {
+        let new_to = find_preceding_boundary_display_point(map, to, mode, &mut |_, right| {
             is_character_match(target, right, smartcase)
         });
         if to == new_to {
@@ -2844,7 +2846,7 @@ fn sneak(
             map,
             movement::right(map, to),
             FindRange::MultiLine,
-            |left, right| {
+            &mut |left, right| {
                 found = is_character_match(first_target, left, smartcase)
                     && is_character_match(second_target, right, smartcase);
                 found
@@ -2876,12 +2878,16 @@ fn sneak_backward(
 
     for _ in 0..times {
         found = false;
-        let new_to =
-            find_preceding_boundary_display_point(map, to, FindRange::MultiLine, |left, right| {
+        let new_to = find_preceding_boundary_display_point(
+            map,
+            to,
+            FindRange::MultiLine,
+            &mut |left, right| {
                 found = is_character_match(first_target, left, smartcase)
                     && is_character_match(second_target, right, smartcase);
                 found
-            });
+            },
+        );
         if to == new_to {
             break;
         }

crates/vim/src/normal.rs 🔗

@@ -145,7 +145,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
         vim.record_current_action(cx);
         vim.update_editor(cx, |_, editor, cx| {
             editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if selection.is_empty() {
                         selection.end = movement::right(map, selection.end)
                     }
@@ -159,7 +159,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
     Vim::action(editor, cx, |vim, _: &HelixCollapseSelection, window, cx| {
         vim.update_editor(cx, |_, editor, cx| {
             editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     let mut point = selection.head();
                     if !selection.reversed && !selection.is_empty() {
                         point = movement::left(map, selection.head());
@@ -598,7 +598,7 @@ impl Vim {
                 window,
                 cx,
                 |s| {
-                    s.move_cursors_with(|map, cursor, goal| {
+                    s.move_cursors_with(&mut |map, cursor, goal| {
                         motion
                             .move_point(map, cursor, goal, times, &text_layout_details)
                             .unwrap_or((cursor, goal))
@@ -617,7 +617,9 @@ impl Vim {
         self.switch_mode(Mode::Insert, false, window, cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_cursors_with(|map, cursor, _| (right(map, cursor, 1), SelectionGoal::None));
+                s.move_cursors_with(&mut |map, cursor, _| {
+                    (right(map, cursor, 1), SelectionGoal::None)
+                });
             });
         });
     }
@@ -628,7 +630,7 @@ impl Vim {
             let current_mode = self.mode;
             self.update_editor(cx, |_, editor, cx| {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         if current_mode == Mode::VisualLine {
                             let start_of_line = motion::start_of_line(map, false, selection.start);
                             selection.collapse_to(start_of_line, SelectionGoal::None)
@@ -652,7 +654,7 @@ impl Vim {
         self.switch_mode(Mode::Insert, false, window, cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_cursors_with(|map, cursor, _| {
+                s.move_cursors_with(&mut |map, cursor, _| {
                     (
                         first_non_whitespace(map, false, cursor),
                         SelectionGoal::None,
@@ -672,7 +674,7 @@ impl Vim {
         self.switch_mode(Mode::Insert, false, window, cx);
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_cursors_with(|map, cursor, _| {
+                s.move_cursors_with(&mut |map, cursor, _| {
                     (next_line_end(map, cursor, 1), SelectionGoal::None)
                 });
             });
@@ -729,7 +731,7 @@ impl Vim {
                     .collect::<Vec<_>>();
                 editor.edit_with_autoindent(edits, cx);
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_cursors_with(|map, cursor, _| {
+                    s.move_cursors_with(&mut |map, cursor, _| {
                         let previous_line = map.start_of_relative_buffer_row(cursor, -1);
                         let insert_point = motion::end_of_line(map, false, previous_line, 1);
                         (insert_point, SelectionGoal::None)
@@ -770,7 +772,7 @@ impl Vim {
                     })
                     .collect::<Vec<_>>();
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.maybe_move_cursors_with(|map, cursor, goal| {
+                    s.maybe_move_cursors_with(&mut |map, cursor, goal| {
                         Motion::CurrentLine.move_point(
                             map,
                             cursor,
@@ -848,7 +850,7 @@ impl Vim {
                 editor.edit(edits, cx);
 
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|_, selection| {
+                    s.move_with(&mut |_, selection| {
                         if let Some(position) = original_positions.get(&selection.id) {
                             selection.collapse_to(*position, SelectionGoal::None);
                         }
@@ -1025,7 +1027,7 @@ impl Vim {
                 }
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let point = movement::saturating_left(map, selection.head());
                         selection.collapse_to(point, SelectionGoal::None)
                     });
@@ -1061,7 +1063,7 @@ impl Vim {
         mut positions: HashMap<usize, Anchor>,
     ) {
         editor.change_selections(Default::default(), window, cx, |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 if let Some(anchor) = positions.remove(&selection.id) {
                     selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                 }

crates/vim/src/normal/change.rs 🔗

@@ -40,7 +40,7 @@ impl Vim {
                 // We are swapping to insert mode anyway. Just set the line end clipping behavior now
                 editor.set_clip_at_line_ends(false, cx);
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let kind = match motion {
                             Motion::NextWordStart { ignore_punctuation }
                             | Motion::NextSubwordStart { ignore_punctuation } => {
@@ -116,7 +116,7 @@ impl Vim {
             editor.set_clip_at_line_ends(false, cx);
             editor.transact(window, cx, |editor, window, cx| {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         objects_found |= object.expand_selection(map, selection, around, times);
                     });
                 });

crates/vim/src/normal/convert.rs 🔗

@@ -37,7 +37,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut selection_starts: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Left);
                         selection_starts.insert(selection.id, anchor);
                         motion.expand_selection(
@@ -67,7 +67,7 @@ impl Vim {
                     }
                 }
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = selection_starts.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });
@@ -92,7 +92,7 @@ impl Vim {
                 editor.set_clip_at_line_ends(false, cx);
                 let mut original_positions: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         object.expand_selection(map, selection, around, times);
                         original_positions.insert(
                             selection.id,
@@ -118,7 +118,7 @@ impl Vim {
                     }
                 }
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = original_positions.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });

crates/vim/src/normal/delete.rs 🔗

@@ -31,7 +31,7 @@ impl Vim {
                 let mut motion_kind = None;
                 let mut ranges_to_copy = Vec::new();
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let original_head = selection.head();
                         original_columns.insert(selection.id, original_head.column());
                         let kind = motion.expand_selection(
@@ -73,7 +73,7 @@ impl Vim {
                 // Fixup cursor position after the deletion
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let mut cursor = selection.head();
                         if kind.linewise()
                             && let Some(column) = original_columns.get(&selection.id)
@@ -112,7 +112,7 @@ impl Vim {
                 let target_mode = object.target_visual_mode(vim.mode, around);
 
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let cursor_point = selection.head().to_point(map);
                         if target_mode == Mode::VisualLine {
                             column_before_move.insert(selection.id, cursor_point.column);
@@ -174,7 +174,7 @@ impl Vim {
                 // Fixup cursor position after the deletion
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let mut cursor = selection.head();
                         if should_move_to_start.contains(&selection.id) {
                             *cursor.column_mut() = 0;

crates/vim/src/normal/paste.rs 🔗

@@ -249,7 +249,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 editor.set_clip_at_line_ends(false, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         object.expand_selection(map, selection, around, None);
                     });
                 });
@@ -263,7 +263,7 @@ impl Vim {
                 editor.insert(&text, window, cx);
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         selection.start = map.clip_point(selection.start, Bias::Left);
                         selection.end = selection.start
                     })
@@ -287,7 +287,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 editor.set_clip_at_line_ends(false, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         motion.expand_selection(
                             map,
                             selection,
@@ -307,7 +307,7 @@ impl Vim {
                 editor.insert(&text, window, cx);
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         selection.start = map.clip_point(selection.start, Bias::Left);
                         selection.end = selection.start
                     })

crates/vim/src/normal/scroll.rs 🔗

@@ -157,7 +157,7 @@ fn scroll_editor(
         window,
         cx,
         |s| {
-            s.move_with(|map, selection| {
+            s.move_with(&mut |map, selection| {
                 // TODO: Improve the logic and function calls below to be dependent on
                 // the `amount`. If the amount is vertical, we don't care about
                 // columns, while if it's horizontal, we don't care about rows,

crates/vim/src/normal/substitute.rs 🔗

@@ -50,7 +50,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let text_layout_details = editor.text_layout_details(window, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         if selection.start == selection.end {
                             Motion::Right.expand_selection(
                                 map,

crates/vim/src/normal/toggle_comments.rs 🔗

@@ -19,7 +19,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut selection_starts: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         selection_starts.insert(selection.id, anchor);
                         motion.expand_selection(
@@ -33,7 +33,7 @@ impl Vim {
                 });
                 editor.toggle_comments(&Default::default(), window, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = selection_starts.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });
@@ -55,7 +55,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut original_positions: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         original_positions.insert(selection.id, anchor);
                         object.expand_selection(map, selection, around, times);
@@ -63,7 +63,7 @@ impl Vim {
                 });
                 editor.toggle_comments(&Default::default(), window, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = original_positions.remove(&selection.id).unwrap();
                         selection.collapse_to(anchor.to_display_point(map), SelectionGoal::None);
                     });

crates/vim/src/normal/yank.rs 🔗

@@ -29,7 +29,7 @@ impl Vim {
                 let mut original_positions: HashMap<_, _> = Default::default();
                 let mut kind = None;
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let original_position = (selection.head(), selection.goal);
                         kind = motion.expand_selection(
                             map,
@@ -49,7 +49,7 @@ impl Vim {
                 let Some(kind) = kind else { return };
                 vim.yank_selections_content(editor, kind, window, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|_, selection| {
+                    s.move_with(&mut |_, selection| {
                         let (head, goal) = original_positions.remove(&selection.id).unwrap();
                         selection.collapse_to(head, goal);
                     });
@@ -72,7 +72,7 @@ impl Vim {
                 editor.set_clip_at_line_ends(false, cx);
                 let mut start_positions: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         object.expand_selection(map, selection, around, times);
                         let start_position = (selection.start, selection.goal);
                         start_positions.insert(selection.id, start_position);
@@ -84,7 +84,7 @@ impl Vim {
                 };
                 vim.yank_selections_content(editor, kind, window, cx);
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|_, selection| {
+                    s.move_with(&mut |_, selection| {
                         let (head, goal) = start_positions.remove(&selection.id).unwrap();
                         selection.collapse_to(head, goal);
                     });

crates/vim/src/object.rs 🔗

@@ -815,15 +815,17 @@ fn in_word(
         map,
         right(map, relative_to, 1),
         movement::FindRange::SingleLine,
-        |left, right| classifier.kind(left) != classifier.kind(right),
+        &mut |left, right| classifier.kind(left) != classifier.kind(right),
     );
 
-    let mut end =
-        movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
-            classifier.kind(left) != classifier.kind(right)
-        });
+    let mut end = movement::find_boundary(
+        map,
+        relative_to,
+        FindRange::SingleLine,
+        &mut |left, right| classifier.kind(left) != classifier.kind(right),
+    );
 
-    let is_boundary = |left: char, right: char| classifier.kind(left) != classifier.kind(right);
+    let mut is_boundary = |left: char, right: char| classifier.kind(left) != classifier.kind(right);
 
     for _ in 1..times {
         let kind_at_end = map
@@ -834,10 +836,15 @@ fn in_word(
         // Skip whitespace but not punctuation (punctuation is its own word unit).
         let next_end = if kind_at_end == Some(CharKind::Whitespace) {
             let after_whitespace =
-                movement::find_boundary(map, end, FindRange::MultiLine, is_boundary);
-            movement::find_boundary(map, after_whitespace, FindRange::MultiLine, is_boundary)
+                movement::find_boundary(map, end, FindRange::MultiLine, &mut is_boundary);
+            movement::find_boundary(
+                map,
+                after_whitespace,
+                FindRange::MultiLine,
+                &mut is_boundary,
+            )
         } else {
-            movement::find_boundary(map, end, FindRange::MultiLine, is_boundary)
+            movement::find_boundary(map, end, FindRange::MultiLine, &mut is_boundary)
         };
         if next_end == end {
             break;
@@ -873,22 +880,32 @@ fn in_subword(
             map,
             right(map, relative_to, 1),
             movement::FindRange::SingleLine,
-            |left, right| {
+            &mut |left, right| {
                 let is_word_start = classifier.kind(left) != classifier.kind(right);
                 is_word_start || is_subword_start(left, right, "._-")
             },
         )
     } else {
-        movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
-            let is_word_start = classifier.kind(left) != classifier.kind(right);
-            is_word_start || is_subword_start(left, right, "._-")
-        })
+        movement::find_boundary(
+            map,
+            relative_to,
+            FindRange::SingleLine,
+            &mut |left, right| {
+                let is_word_start = classifier.kind(left) != classifier.kind(right);
+                is_word_start || is_subword_start(left, right, "._-")
+            },
+        )
     };
 
-    let end = movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
-        let is_word_end = classifier.kind(left) != classifier.kind(right);
-        is_word_end || is_subword_end(left, right, "._-")
-    });
+    let end = movement::find_boundary(
+        map,
+        relative_to,
+        FindRange::SingleLine,
+        &mut |left, right| {
+            let is_word_end = classifier.kind(left) != classifier.kind(right);
+            is_word_end || is_subword_end(left, right, "._-")
+        },
+    );
 
     Some(start..end)
 }
@@ -1027,7 +1044,7 @@ fn around_subword(
         map,
         right(map, relative_to, 1),
         movement::FindRange::SingleLine,
-        |left, right| {
+        &mut |left, right| {
             let is_separator = |c: char| "._-".contains(c);
             let is_word_start =
                 classifier.kind(left) != classifier.kind(right) && !is_separator(left);
@@ -1035,11 +1052,17 @@ fn around_subword(
         },
     );
 
-    let end = movement::find_boundary(map, relative_to, FindRange::SingleLine, |left, right| {
-        let is_separator = |c: char| "._-".contains(c);
-        let is_word_end = classifier.kind(left) != classifier.kind(right) && !is_separator(right);
-        is_word_end || is_subword_end(left, right, "._-")
-    });
+    let end = movement::find_boundary(
+        map,
+        relative_to,
+        FindRange::SingleLine,
+        &mut |left, right| {
+            let is_separator = |c: char| "._-".contains(c);
+            let is_word_end =
+                classifier.kind(left) != classifier.kind(right) && !is_separator(right);
+            is_word_end || is_subword_end(left, right, "._-")
+        },
+    );
 
     Some(start..end).map(|range| expand_to_include_whitespace(map, range, true))
 }
@@ -1088,31 +1111,37 @@ fn around_next_word(
         map,
         right(map, relative_to, 1),
         FindRange::SingleLine,
-        |left, right| classifier.kind(left) != classifier.kind(right),
+        &mut |left, right| classifier.kind(left) != classifier.kind(right),
     );
 
     let mut word_found = false;
-    let mut end = movement::find_boundary(map, relative_to, FindRange::MultiLine, |left, right| {
-        let left_kind = classifier.kind(left);
-        let right_kind = classifier.kind(right);
+    let mut end = movement::find_boundary(
+        map,
+        relative_to,
+        FindRange::MultiLine,
+        &mut |left, right| {
+            let left_kind = classifier.kind(left);
+            let right_kind = classifier.kind(right);
 
-        let found = (word_found && left_kind != right_kind) || right == '\n' && left == '\n';
+            let found = (word_found && left_kind != right_kind) || right == '\n' && left == '\n';
 
-        if right_kind != CharKind::Whitespace {
-            word_found = true;
-        }
+            if right_kind != CharKind::Whitespace {
+                word_found = true;
+            }
 
-        found
-    });
+            found
+        },
+    );
 
     for _ in 1..times {
-        let next_end = movement::find_boundary(map, end, FindRange::MultiLine, |left, right| {
-            let left_kind = classifier.kind(left);
-            let right_kind = classifier.kind(right);
-
-            let in_word_unit = left_kind != CharKind::Whitespace;
-            (in_word_unit && left_kind != right_kind) || right == '\n' && left == '\n'
-        });
+        let next_end =
+            movement::find_boundary(map, end, FindRange::MultiLine, &mut |left, right| {
+                let left_kind = classifier.kind(left);
+                let right_kind = classifier.kind(right);
+
+                let in_word_unit = left_kind != CharKind::Whitespace;
+                (in_word_unit && left_kind != right_kind) || right == '\n' && left == '\n'
+            });
         if next_end == end {
             break;
         }

crates/vim/src/replace.rs 🔗

@@ -263,7 +263,7 @@ impl Vim {
 
             if let Some(position) = final_cursor_position {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|_map, selection| {
+                    s.move_with(&mut |_map, selection| {
                         selection.collapse_to(position, SelectionGoal::None);
                     });
                 })

crates/vim/src/rewrap.rs 🔗

@@ -29,7 +29,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut Context<Vim>) {
                     cx,
                 );
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         if let Some(anchor) = positions.remove(&selection.id) {
                             let mut point = anchor.to_display_point(map);
                             *point.column_mut() = 0;
@@ -60,7 +60,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut selection_starts: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         selection_starts.insert(selection.id, anchor);
                         motion.expand_selection(
@@ -80,7 +80,7 @@ impl Vim {
                     cx,
                 );
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = selection_starts.remove(&selection.id).unwrap();
                         let mut point = anchor.to_display_point(map);
                         *point.column_mut() = 0;
@@ -104,7 +104,7 @@ impl Vim {
             editor.transact(window, cx, |editor, window, cx| {
                 let mut original_positions: HashMap<_, _> = Default::default();
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = map.display_point_to_anchor(selection.head(), Bias::Right);
                         original_positions.insert(selection.id, anchor);
                         object.expand_selection(map, selection, around, times);
@@ -118,7 +118,7 @@ impl Vim {
                     cx,
                 );
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let anchor = original_positions.remove(&selection.id).unwrap();
                         let mut point = anchor.to_display_point(map);
                         *point.column_mut() = 0;

crates/vim/src/vim.rs 🔗

@@ -1204,7 +1204,7 @@ impl Vim {
         self.update_editor(cx, |vim, editor, cx| {
             if last_mode != Mode::VisualBlock && last_mode.is_visual() && mode == Mode::VisualBlock
             {
-                vim.visual_block_motion(true, editor, window, cx, |_, point, goal| {
+                vim.visual_block_motion(true, editor, window, cx, &mut |_, point, goal| {
                     Some((point, goal))
                 })
             }
@@ -1262,7 +1262,7 @@ impl Vim {
                     vim.extended_pending_selection_id = s.pending_anchor().map(|p| p.id)
                 }
 
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if last_mode.is_visual() && !mode.is_visual() {
                         let mut point = selection.head();
                         if !selection.reversed && !selection.is_empty() {
@@ -1469,7 +1469,7 @@ impl Vim {
                 self.update_editor(cx, |_, editor, cx| {
                     editor.set_clip_at_line_ends(false, cx);
                     editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                        s.move_with(|_, selection| {
+                        s.move_with(&mut |_, selection| {
                             selection.collapse_to(selection.start, selection.goal)
                         })
                     });
@@ -1750,7 +1750,7 @@ impl Vim {
                     editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
                         match original_mode {
                             Some(Mode::VisualLine) => {
-                                s.move_with(|map, selection| {
+                                s.move_with(&mut |map, selection| {
                                     selection.collapse_to(
                                         map.prev_line_boundary(selection.start.to_point(map)).1,
                                         SelectionGoal::None,
@@ -1763,7 +1763,7 @@ impl Vim {
                                 s.select_anchors(vec![first]);
                             }
                             _ => {
-                                s.move_with(|map, selection| {
+                                s.move_with(&mut |map, selection| {
                                     selection.collapse_to(
                                         map.clip_at_line_end(selection.start),
                                         selection.goal,
@@ -1778,7 +1778,7 @@ impl Vim {
             Mode::Normal => {
                 self.update_editor(cx, |_, editor, cx| {
                     editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                        s.move_with(|map, selection| {
+                        s.move_with(&mut |map, selection| {
                             selection
                                 .collapse_to(map.clip_at_line_end(selection.end), selection.goal)
                         })
@@ -1947,7 +1947,7 @@ impl Vim {
                 Mode::HelixNormal | Mode::HelixSelect => {
                     self.update_editor(cx, |_, editor, cx| {
                         editor.change_selections(Default::default(), window, cx, |s| {
-                            s.move_with(|map, selection| {
+                            s.move_with(&mut |map, selection| {
                                 if selection.is_empty() {
                                     selection.end = movement::right(map, selection.start);
                                 }

crates/vim/src/visual.rs 🔗

@@ -228,12 +228,18 @@ impl Vim {
                 )
             {
                 let is_up_or_down = matches!(motion, Motion::Up { .. } | Motion::Down { .. });
-                vim.visual_block_motion(is_up_or_down, editor, window, cx, |map, point, goal| {
-                    motion.move_point(map, point, goal, times, &text_layout_details)
-                })
+                vim.visual_block_motion(
+                    is_up_or_down,
+                    editor,
+                    window,
+                    cx,
+                    &mut |map, point, goal| {
+                        motion.move_point(map, point, goal, times, &text_layout_details)
+                    },
+                )
             } else {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let was_reversed = selection.reversed;
                         let mut current_head = selection.head();
 
@@ -296,7 +302,7 @@ impl Vim {
         editor: &mut Editor,
         window: &mut Window,
         cx: &mut Context<Editor>,
-        mut move_selection: impl FnMut(
+        move_selection: &mut dyn FnMut(
             &DisplaySnapshot,
             DisplayPoint,
             SelectionGoal,
@@ -436,7 +442,7 @@ impl Vim {
 
             self.update_editor(cx, |_, editor, cx| {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let mut mut_selection = selection.clone();
 
                         // all our motions assume that the current character is
@@ -552,7 +558,7 @@ impl Vim {
         self.update_editor(cx, |_, editor, cx| {
             editor.split_selection_into_lines(&Default::default(), window, cx);
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_cursors_with(|map, cursor, _| {
+                s.move_cursors_with(&mut |map, cursor, _| {
                     (next_line_end(map, cursor, 1), SelectionGoal::None)
                 });
             });
@@ -570,7 +576,7 @@ impl Vim {
         self.update_editor(cx, |_, editor, cx| {
             editor.split_selection_into_lines(&Default::default(), window, cx);
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_cursors_with(|map, cursor, _| {
+                s.move_cursors_with(&mut |map, cursor, _| {
                     (
                         first_non_whitespace(map, false, cursor),
                         SelectionGoal::None,
@@ -593,7 +599,7 @@ impl Vim {
     pub fn other_end(&mut self, _: &OtherEnd, window: &mut Window, cx: &mut Context<Self>) {
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|_, selection| {
+                s.move_with(&mut |_, selection| {
                     selection.reversed = !selection.reversed;
                 });
             })
@@ -609,7 +615,7 @@ impl Vim {
         let mode = self.mode;
         self.update_editor(cx, |_, editor, cx| {
             editor.change_selections(Default::default(), window, cx, |s| {
-                s.move_with(|_, selection| {
+                s.move_with(&mut |_, selection| {
                     selection.reversed = !selection.reversed;
                 });
                 if mode == Mode::VisualBlock {
@@ -628,7 +634,7 @@ impl Vim {
 
             editor.transact(window, cx, |editor, window, cx| {
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         if line_mode {
                             let mut position = selection.head();
                             if !selection.reversed {
@@ -665,7 +671,7 @@ impl Vim {
 
                 if line_mode && vim.mode != Mode::VisualBlock {
                     editor.change_selections(Default::default(), window, cx, |s| {
-                        s.move_with(|map, selection| {
+                        s.move_with(&mut |map, selection| {
                             let end = selection.end.to_point(map);
                             let start = selection.start.to_point(map);
                             if end.row < map.buffer_snapshot().max_point().row {
@@ -686,7 +692,7 @@ impl Vim {
                 // Fixup cursor position after the deletion
                 editor.set_clip_at_line_ends(true, cx);
                 editor.change_selections(Default::default(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let mut cursor = selection.head().to_point(map);
 
                         if let Some(column) = original_columns.get(&selection.id) {
@@ -712,7 +718,7 @@ impl Vim {
             // For visual line mode, adjust selections to avoid yanking the next line when on \n
             if line_mode && vim.mode != Mode::VisualBlock {
                 editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                    s.move_with(|map, selection| {
+                    s.move_with(&mut |map, selection| {
                         let start = selection.start.to_point(map);
                         let end = selection.end.to_point(map);
                         if end.column == 0 && end > start {
@@ -735,7 +741,7 @@ impl Vim {
             };
             vim.yank_selections_content(editor, kind, window, cx);
             editor.change_selections(SelectionEffects::no_scroll(), window, cx, |s| {
-                s.move_with(|map, selection| {
+                s.move_with(&mut |map, selection| {
                     if line_mode {
                         selection.start = start_of_line(map, false, selection.start);
                     };

crates/workspace/src/item.rs 🔗

@@ -212,7 +212,7 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
         self.tab_tooltip_text(cx).map(TabTooltipContent::Text)
     }
 
-    fn to_item_events(_event: &Self::Event, _f: impl FnMut(ItemEvent)) {}
+    fn to_item_events(_event: &Self::Event, _f: &mut dyn FnMut(ItemEvent)) {}
 
     fn deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
     fn discarded(&self, _project: Entity<Project>, _window: &mut Window, _cx: &mut Context<Self>) {}
@@ -579,7 +579,7 @@ impl<T: Item> ItemHandle for Entity<T> {
         handler: Box<dyn Fn(ItemEvent, &mut Window, &mut App)>,
     ) -> gpui::Subscription {
         window.subscribe(self, cx, move |_, event, window, cx| {
-            T::to_item_events(event, |item_event| handler(item_event, window, cx));
+            T::to_item_events(event, &mut |item_event| handler(item_event, window, cx));
         })
     }
 
@@ -836,7 +836,7 @@ impl<T: Item> ItemHandle for Entity<T> {
                         workspace.enqueue_item_serialization(item).ok();
                     }
 
-                    T::to_item_events(event, |event| match event {
+                    T::to_item_events(event, &mut |event| match event {
                         ItemEvent::CloseItem => {
                             pane.update(cx, |pane, cx| {
                                 pane.close_item_by_id(
@@ -1545,7 +1545,7 @@ pub mod test {
     impl Item for TestItem {
         type Event = ItemEvent;
 
-        fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+        fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
             f(*event)
         }
 

crates/workspace/src/pane.rs 🔗

@@ -4528,7 +4528,7 @@ impl NavHistory {
     pub fn for_each_entry(
         &self,
         cx: &App,
-        mut f: impl FnMut(&NavigationEntry, (ProjectPath, Option<PathBuf>)),
+        f: &mut dyn FnMut(&NavigationEntry, (ProjectPath, Option<PathBuf>)),
     ) {
         let borrowed_history = self.0.lock();
         borrowed_history

crates/workspace/src/persistence.rs 🔗

@@ -2746,7 +2746,7 @@ mod tests {
                         ON DELETE CASCADE
                     ) STRICT;
                 )],
-                |_, _, _| false,
+                &mut |_, _, _| false,
             )
             .unwrap();
         })
@@ -2795,7 +2795,7 @@ mod tests {
                                 REFERENCES workspaces(workspace_id)
                             ON DELETE CASCADE
                         ) STRICT;)],
-                |_, _, _| false,
+                &mut |_, _, _| false,
             )
         })
         .await

crates/workspace/src/shared_screen.rs 🔗

@@ -133,7 +133,7 @@ impl Item for SharedScreen {
         })))
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(ItemEvent)) {
         match event {
             Event::Close => f(ItemEvent::CloseItem),
         }

crates/workspace/src/theme_preview.rs 🔗

@@ -86,7 +86,7 @@ impl ThemePreview {}
 impl Item for ThemePreview {
     type Event = ();
 
-    fn to_item_events(_: &Self::Event, _: impl FnMut(crate::item::ItemEvent)) {}
+    fn to_item_events(_: &Self::Event, _: &mut dyn FnMut(crate::item::ItemEvent)) {}
 
     fn tab_content_text(&self, _detail: usize, cx: &App) -> SharedString {
         let name = cx.theme().name.clone();

crates/workspace/src/welcome.rs 🔗

@@ -465,7 +465,7 @@ impl Item for WelcomePage {
         false
     }
 
-    fn to_item_events(event: &Self::Event, mut f: impl FnMut(crate::item::ItemEvent)) {
+    fn to_item_events(event: &Self::Event, f: &mut dyn FnMut(crate::item::ItemEvent)) {
         f(*event)
     }
 }

crates/workspace/src/workspace.rs 🔗

@@ -2100,7 +2100,7 @@ impl Workspace {
             let pane = pane.read(cx);
 
             pane.nav_history()
-                .for_each_entry(cx, |entry, (project_path, fs_path)| {
+                .for_each_entry(cx, &mut |entry, (project_path, fs_path)| {
                     if let Some(fs_path) = &fs_path {
                         abs_paths_opened
                             .entry(fs_path.clone())
@@ -2179,7 +2179,13 @@ impl Workspace {
         window: &mut Window,
         cx: &mut Context<Workspace>,
     ) -> Task<Result<()>> {
-        self.navigate_history_impl(pane, mode, window, |history, cx| history.pop(mode, cx), cx)
+        self.navigate_history_impl(
+            pane,
+            mode,
+            window,
+            &mut |history, cx| history.pop(mode, cx),
+            cx,
+        )
     }
 
     fn navigate_tag_history(
@@ -2193,7 +2199,7 @@ impl Workspace {
             pane,
             NavigationMode::Normal,
             window,
-            |history, _cx| history.pop_tag(mode),
+            &mut |history, _cx| history.pop_tag(mode),
             cx,
         )
     }
@@ -2203,7 +2209,7 @@ impl Workspace {
         pane: WeakEntity<Pane>,
         mode: NavigationMode,
         window: &mut Window,
-        mut cb: impl FnMut(&mut NavHistory, &mut App) -> Option<NavigationEntry>,
+        cb: &mut dyn FnMut(&mut NavHistory, &mut App) -> Option<NavigationEntry>,
         cx: &mut Context<Workspace>,
     ) -> Task<Result<()>> {
         let to_load = if let Some(pane) = pane.upgrade() {
@@ -3624,7 +3630,7 @@ impl Workspace {
         window: &mut Window,
         cx: &mut Context<Self>,
     ) -> Option<Entity<T>> {
-        let panel = self.focus_or_unfocus_panel::<T>(window, cx, |_, _, _| true)?;
+        let panel = self.focus_or_unfocus_panel::<T>(window, cx, &mut |_, _, _| true)?;
         panel.to_any().downcast().ok()
     }
 
@@ -3638,7 +3644,7 @@ impl Workspace {
         cx: &mut Context<Self>,
     ) -> bool {
         let mut did_focus_panel = false;
-        self.focus_or_unfocus_panel::<T>(window, cx, |panel, window, cx| {
+        self.focus_or_unfocus_panel::<T>(window, cx, &mut |panel, window, cx| {
             did_focus_panel = !panel.panel_focus_handle(cx).contains_focused(window, cx);
             did_focus_panel
         });
@@ -3687,7 +3693,7 @@ impl Workspace {
         &mut self,
         window: &mut Window,
         cx: &mut Context<Self>,
-        mut should_focus: impl FnMut(&dyn PanelHandle, &mut Window, &mut Context<Dock>) -> bool,
+        should_focus: &mut dyn FnMut(&dyn PanelHandle, &mut Window, &mut Context<Dock>) -> bool,
     ) -> Option<Arc<dyn PanelHandle>> {
         let mut result_panel = None;
         let mut serialize = false;
@@ -12059,7 +12065,7 @@ mod tests {
         // Check navigation history after close
         let has_item = pane.read_with(cx, |pane, cx| {
             let mut has_item = false;
-            pane.nav_history().for_each_entry(cx, |entry, _| {
+            pane.nav_history().for_each_entry(cx, &mut |entry, _| {
                 if entry.item.id() == item1_id {
                     has_item = true;
                 }