diff --git a/crates/assistant/src/context_store.rs b/crates/assistant/src/context_store.rs index 34d4e5a700bc99..9c2c02c35de3a1 100644 --- a/crates/assistant/src/context_store.rs +++ b/crates/assistant/src/context_store.rs @@ -716,7 +716,7 @@ impl ContextStore { let candidates = metadata .iter() .enumerate() - .map(|(id, metadata)| StringMatchCandidate::new(id, metadata.title.clone())) + .map(|(id, metadata)| StringMatchCandidate::new(id, &metadata.title)) .collect::>(); let matches = fuzzy::match_strings( &candidates, diff --git a/crates/assistant/src/prompt_library.rs b/crates/assistant/src/prompt_library.rs index 578e0c647fa5f7..705f059331741b 100644 --- a/crates/assistant/src/prompt_library.rs +++ b/crates/assistant/src/prompt_library.rs @@ -1439,10 +1439,7 @@ impl PromptStore { .iter() .enumerate() .filter_map(|(ix, metadata)| { - Some(StringMatchCandidate::new( - ix, - metadata.title.as_ref()?.to_string(), - )) + Some(StringMatchCandidate::new(ix, metadata.title.as_ref()?)) }) .collect::>(); let matches = fuzzy::match_strings( diff --git a/crates/assistant/src/slash_command.rs b/crates/assistant/src/slash_command.rs index 9ff4eb094f08cf..9e74729faefb11 100644 --- a/crates/assistant/src/slash_command.rs +++ b/crates/assistant/src/slash_command.rs @@ -78,11 +78,7 @@ impl SlashCommandCompletionProvider { .command_names(cx) .into_iter() .enumerate() - .map(|(ix, def)| StringMatchCandidate { - id: ix, - string: def.to_string(), - char_bag: def.as_ref().into(), - }) + .map(|(ix, def)| StringMatchCandidate::new(ix, &def)) .collect::>(); let command_name = command_name.to_string(); let editor = self.editor.clone(); diff --git a/crates/assistant/src/slash_command/diagnostics_command.rs b/crates/assistant/src/slash_command/diagnostics_command.rs index 3f1e3e5e718fc5..2a10283053d9b0 100644 --- a/crates/assistant/src/slash_command/diagnostics_command.rs +++ b/crates/assistant/src/slash_command/diagnostics_command.rs @@ -218,10 +218,7 @@ impl Options { } fn match_candidates_for_args() -> [StringMatchCandidate; 1] { - [StringMatchCandidate::new( - 0, - INCLUDE_WARNINGS_ARGUMENT.to_string(), - )] + [StringMatchCandidate::new(0, INCLUDE_WARNINGS_ARGUMENT)] } } diff --git a/crates/assistant/src/slash_command/tab_command.rs b/crates/assistant/src/slash_command/tab_command.rs index 1579938c92ee43..b6e38f2e479d57 100644 --- a/crates/assistant/src/slash_command/tab_command.rs +++ b/crates/assistant/src/slash_command/tab_command.rs @@ -249,11 +249,7 @@ fn tab_items_for_queries( .enumerate() .filter_map(|(id, (full_path, ..))| { let path_string = full_path.as_deref()?.to_string_lossy().to_string(); - Some(fuzzy::StringMatchCandidate { - id, - char_bag: path_string.as_str().into(), - string: path_string, - }) + Some(fuzzy::StringMatchCandidate::new(id, &path_string)) }) .collect::>(); let mut processed_matches = HashSet::default(); diff --git a/crates/collab_ui/src/chat_panel/message_editor.rs b/crates/collab_ui/src/chat_panel/message_editor.rs index 7023a8d07ed76c..c116660ded5d58 100644 --- a/crates/collab_ui/src/chat_panel/message_editor.rs +++ b/crates/collab_ui/src/chat_panel/message_editor.rs @@ -381,11 +381,7 @@ impl MessageEditor { let candidates = names .into_iter() - .map(|user| StringMatchCandidate { - id: 0, - string: user.clone(), - char_bag: user.chars().collect(), - }) + .map(|user| StringMatchCandidate::new(0, &user)) .collect::>(); Some((start_anchor, query, candidates)) @@ -401,11 +397,7 @@ impl MessageEditor { LazyLock::new(|| { let emojis = emojis::iter() .flat_map(|s| s.shortcodes()) - .map(|emoji| StringMatchCandidate { - id: 0, - string: emoji.to_string(), - char_bag: emoji.chars().collect(), - }) + .map(|emoji| StringMatchCandidate::new(0, emoji)) .collect::>(); emojis }); diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 3af4eec893dc5e..2572fa48b741db 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -393,11 +393,8 @@ impl CollabPanel { // Populate the active user. if let Some(user) = user_store.current_user() { self.match_candidates.clear(); - self.match_candidates.push(StringMatchCandidate { - id: 0, - string: user.github_login.clone(), - char_bag: user.github_login.chars().collect(), - }); + self.match_candidates + .push(StringMatchCandidate::new(0, &user.github_login)); let matches = executor.block(match_strings( &self.match_candidates, &query, @@ -436,11 +433,10 @@ impl CollabPanel { self.match_candidates.clear(); self.match_candidates .extend(room.remote_participants().values().map(|participant| { - StringMatchCandidate { - id: participant.user.id as usize, - string: participant.user.github_login.clone(), - char_bag: participant.user.github_login.chars().collect(), - } + StringMatchCandidate::new( + participant.user.id as usize, + &participant.user.github_login, + ) })); let mut matches = executor.block(match_strings( &self.match_candidates, @@ -489,10 +485,8 @@ impl CollabPanel { self.match_candidates.clear(); self.match_candidates .extend(room.pending_participants().iter().enumerate().map( - |(id, participant)| StringMatchCandidate { - id, - string: participant.github_login.clone(), - char_bag: participant.github_login.chars().collect(), + |(id, participant)| { + StringMatchCandidate::new(id, &participant.github_login) }, )); let matches = executor.block(match_strings( @@ -519,17 +513,12 @@ impl CollabPanel { if channel_store.channel_count() > 0 || self.channel_editing_state.is_some() { self.match_candidates.clear(); - self.match_candidates - .extend( - channel_store - .ordered_channels() - .enumerate() - .map(|(ix, (_, channel))| StringMatchCandidate { - id: ix, - string: channel.name.clone().into(), - char_bag: channel.name.chars().collect(), - }), - ); + self.match_candidates.extend( + channel_store + .ordered_channels() + .enumerate() + .map(|(ix, (_, channel))| StringMatchCandidate::new(ix, &channel.name)), + ); let matches = executor.block(match_strings( &self.match_candidates, &query, @@ -600,14 +589,12 @@ impl CollabPanel { let channel_invites = channel_store.channel_invitations(); if !channel_invites.is_empty() { self.match_candidates.clear(); - self.match_candidates - .extend(channel_invites.iter().enumerate().map(|(ix, channel)| { - StringMatchCandidate { - id: ix, - string: channel.name.clone().into(), - char_bag: channel.name.chars().collect(), - } - })); + self.match_candidates.extend( + channel_invites + .iter() + .enumerate() + .map(|(ix, channel)| StringMatchCandidate::new(ix, &channel.name)), + ); let matches = executor.block(match_strings( &self.match_candidates, &query, @@ -637,17 +624,12 @@ impl CollabPanel { let incoming = user_store.incoming_contact_requests(); if !incoming.is_empty() { self.match_candidates.clear(); - self.match_candidates - .extend( - incoming - .iter() - .enumerate() - .map(|(ix, user)| StringMatchCandidate { - id: ix, - string: user.github_login.clone(), - char_bag: user.github_login.chars().collect(), - }), - ); + self.match_candidates.extend( + incoming + .iter() + .enumerate() + .map(|(ix, user)| StringMatchCandidate::new(ix, &user.github_login)), + ); let matches = executor.block(match_strings( &self.match_candidates, &query, @@ -666,17 +648,12 @@ impl CollabPanel { let outgoing = user_store.outgoing_contact_requests(); if !outgoing.is_empty() { self.match_candidates.clear(); - self.match_candidates - .extend( - outgoing - .iter() - .enumerate() - .map(|(ix, user)| StringMatchCandidate { - id: ix, - string: user.github_login.clone(), - char_bag: user.github_login.chars().collect(), - }), - ); + self.match_candidates.extend( + outgoing + .iter() + .enumerate() + .map(|(ix, user)| StringMatchCandidate::new(ix, &user.github_login)), + ); let matches = executor.block(match_strings( &self.match_candidates, &query, @@ -703,17 +680,12 @@ impl CollabPanel { let contacts = user_store.contacts(); if !contacts.is_empty() { self.match_candidates.clear(); - self.match_candidates - .extend( - contacts - .iter() - .enumerate() - .map(|(ix, contact)| StringMatchCandidate { - id: ix, - string: contact.user.github_login.clone(), - char_bag: contact.user.github_login.chars().collect(), - }), - ); + self.match_candidates.extend( + contacts + .iter() + .enumerate() + .map(|(ix, contact)| StringMatchCandidate::new(ix, &contact.user.github_login)), + ); let matches = executor.block(match_strings( &self.match_candidates, diff --git a/crates/collab_ui/src/collab_panel/channel_modal.rs b/crates/collab_ui/src/collab_panel/channel_modal.rs index d0bcf49a0bfff3..3c61c479452c38 100644 --- a/crates/collab_ui/src/collab_panel/channel_modal.rs +++ b/crates/collab_ui/src/collab_panel/channel_modal.rs @@ -272,11 +272,7 @@ impl PickerDelegate for ChannelModalDelegate { self.match_candidates.clear(); self.match_candidates .extend(self.members.iter().enumerate().map(|(id, member)| { - StringMatchCandidate { - id, - string: member.user.github_login.clone(), - char_bag: member.user.github_login.chars().collect(), - } + StringMatchCandidate::new(id, &member.user.github_login) })); let matches = cx.background_executor().block(match_strings( diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 36ca20cd4f270e..5e383c4d07f62e 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -283,11 +283,7 @@ impl PickerDelegate for CommandPaletteDelegate { let candidates = commands .iter() .enumerate() - .map(|(ix, command)| StringMatchCandidate { - id: ix, - string: command.name.to_string(), - char_bag: command.name.chars().collect(), - }) + .map(|(ix, command)| StringMatchCandidate::new(ix, &command.name)) .collect::>(); let matches = if query.is_empty() { candidates diff --git a/crates/editor/src/code_context_menus.rs b/crates/editor/src/code_context_menus.rs index cd473bd69596c5..2c826068462b63 100644 --- a/crates/editor/src/code_context_menus.rs +++ b/crates/editor/src/code_context_menus.rs @@ -163,7 +163,7 @@ impl CompletionsMenu { .map(|(id, completion)| { StringMatchCandidate::new( id, - completion.label.text[completion.label.filter_range.clone()].into(), + &completion.label.text[completion.label.filter_range.clone()], ) }) .collect(); @@ -211,7 +211,7 @@ impl CompletionsMenu { let match_candidates = choices .iter() .enumerate() - .map(|(id, completion)| StringMatchCandidate::new(id, completion.to_string())) + .map(|(id, completion)| StringMatchCandidate::new(id, &completion)) .collect(); let matches = choices .iter() diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 61e4c228c7c9cb..ab8a1893f5449a 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -13293,7 +13293,7 @@ fn snippet_completions( snippet .prefix .iter() - .map(move |prefix| StringMatchCandidate::new(ix, prefix.clone())) + .map(move |prefix| StringMatchCandidate::new(ix, &prefix)) }) .collect::>(); diff --git a/crates/extensions_ui/src/extension_version_selector.rs b/crates/extensions_ui/src/extension_version_selector.rs index 91bc1d72ac524c..bb7ee179a4d0a0 100644 --- a/crates/extensions_ui/src/extension_version_selector.rs +++ b/crates/extensions_ui/src/extension_version_selector.rs @@ -113,13 +113,7 @@ impl PickerDelegate for ExtensionVersionSelectorDelegate { .iter() .enumerate() .map(|(id, extension)| { - let text = format!("v{}", extension.manifest.version); - - StringMatchCandidate { - id, - char_bag: text.as_str().into(), - string: text, - } + StringMatchCandidate::new(id, &format!("v{}", extension.manifest.version)) }) .collect::>(); diff --git a/crates/extensions_ui/src/extensions_ui.rs b/crates/extensions_ui/src/extensions_ui.rs index 3adde9140e3198..248e3117369f45 100644 --- a/crates/extensions_ui/src/extensions_ui.rs +++ b/crates/extensions_ui/src/extensions_ui.rs @@ -328,11 +328,7 @@ impl ExtensionsPage { let match_candidates = dev_extensions .iter() .enumerate() - .map(|(ix, manifest)| StringMatchCandidate { - id: ix, - string: manifest.name.clone(), - char_bag: manifest.name.as_str().into(), - }) + .map(|(ix, manifest)| StringMatchCandidate::new(ix, &manifest.name)) .collect::>(); let matches = match_strings( diff --git a/crates/file_finder/src/open_path_prompt.rs b/crates/file_finder/src/open_path_prompt.rs index 5906f62d71199d..cd4b69f613c3eb 100644 --- a/crates/file_finder/src/open_path_prompt.rs +++ b/crates/file_finder/src/open_path_prompt.rs @@ -131,7 +131,7 @@ impl PickerDelegate for OpenPathDelegate { .iter() .enumerate() .map(|(ix, path)| { - StringMatchCandidate::new(ix, path.to_string_lossy().into()) + StringMatchCandidate::new(ix, &path.to_string_lossy()) }) .collect::>(); diff --git a/crates/fuzzy/src/strings.rs b/crates/fuzzy/src/strings.rs index 1a5fb2b02f8914..fbec4477f2efc3 100644 --- a/crates/fuzzy/src/strings.rs +++ b/crates/fuzzy/src/strings.rs @@ -18,22 +18,12 @@ pub struct StringMatchCandidate { pub char_bag: CharBag, } -impl Match for StringMatch { - fn score(&self) -> f64 { - self.score - } - - fn set_positions(&mut self, positions: Vec) { - self.positions = positions; - } -} - impl StringMatchCandidate { - pub fn new(id: usize, string: String) -> Self { + pub fn new(id: usize, string: &str) -> Self { Self { id, - char_bag: CharBag::from(string.as_str()), - string, + string: string.into(), + char_bag: string.into(), } } } @@ -56,6 +46,16 @@ pub struct StringMatch { pub string: String, } +impl Match for StringMatch { + fn score(&self) -> f64 { + self.score + } + + fn set_positions(&mut self, positions: Vec) { + self.positions = positions; + } +} + impl StringMatch { pub fn ranges(&self) -> impl '_ + Iterator> { let mut positions = self.positions.iter().peekable(); diff --git a/crates/indexed_docs/src/store.rs b/crates/indexed_docs/src/store.rs index 059ee69dcd78a5..fa80bf527f003e 100644 --- a/crates/indexed_docs/src/store.rs +++ b/crates/indexed_docs/src/store.rs @@ -208,7 +208,7 @@ impl IndexedDocsStore { let candidates = items .iter() .enumerate() - .map(|(ix, item_path)| StringMatchCandidate::new(ix, item_path.clone())) + .map(|(ix, item_path)| StringMatchCandidate::new(ix, &item_path)) .collect::>(); let matches = fuzzy::match_strings( diff --git a/crates/language/src/outline.rs b/crates/language/src/outline.rs index cd4e1d7fdbd90b..7f62f221a6af3a 100644 --- a/crates/language/src/outline.rs +++ b/crates/language/src/outline.rs @@ -73,8 +73,8 @@ impl Outline { .map(|range| &item.text[range.start..range.end]) .collect::(); - path_candidates.push(StringMatchCandidate::new(id, path_text.clone())); - candidates.push(StringMatchCandidate::new(id, candidate_text)); + path_candidates.push(StringMatchCandidate::new(id, &path_text)); + candidates.push(StringMatchCandidate::new(id, &candidate_text)); } Self { diff --git a/crates/language_selector/src/language_selector.rs b/crates/language_selector/src/language_selector.rs index 9e90c43a7b3e61..7e935dbdcba4ec 100644 --- a/crates/language_selector/src/language_selector.rs +++ b/crates/language_selector/src/language_selector.rs @@ -112,7 +112,7 @@ impl LanguageSelectorDelegate { .then_some(name) }) .enumerate() - .map(|(candidate_id, name)| StringMatchCandidate::new(candidate_id, name)) + .map(|(candidate_id, name)| StringMatchCandidate::new(candidate_id, &name)) .collect::>(); Self { diff --git a/crates/outline_panel/src/outline_panel.rs b/crates/outline_panel/src/outline_panel.rs index 21c40807b8e7b0..16c229ddd411e3 100644 --- a/crates/outline_panel/src/outline_panel.rs +++ b/crates/outline_panel/src/outline_panel.rs @@ -3296,40 +3296,32 @@ impl OutlinePanel { if let Some(file_name) = self.relative_path(fs_entry, cx).as_deref().map(file_name) { - state.match_candidates.push(StringMatchCandidate { - id, - string: file_name.to_string(), - char_bag: file_name.chars().collect(), - }); + state + .match_candidates + .push(StringMatchCandidate::new(id, &file_name)); } } PanelEntry::FoldedDirs(worktree_id, entries) => { let dir_names = self.dir_names_string(entries, *worktree_id, cx); { - state.match_candidates.push(StringMatchCandidate { - id, - string: dir_names.clone(), - char_bag: dir_names.chars().collect(), - }); + state + .match_candidates + .push(StringMatchCandidate::new(id, &dir_names)); } } PanelEntry::Outline(outline_entry) => match outline_entry { OutlineEntry::Outline(_, _, outline) => { - state.match_candidates.push(StringMatchCandidate { - id, - string: outline.text.clone(), - char_bag: outline.text.chars().collect(), - }); + state + .match_candidates + .push(StringMatchCandidate::new(id, &outline.text)); } OutlineEntry::Excerpt(..) => {} }, PanelEntry::Search(new_search_entry) => { if let Some(search_data) = new_search_entry.render_data.get() { - state.match_candidates.push(StringMatchCandidate { - id, - char_bag: search_data.context_text.chars().collect(), - string: search_data.context_text.clone(), - }); + state + .match_candidates + .push(StringMatchCandidate::new(id, &search_data.context_text)); } } } diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 753980a26e9a23..49beeec478d8fe 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -179,7 +179,7 @@ impl PickerDelegate for ProjectSymbolsDelegate { .map(|(id, symbol)| { StringMatchCandidate::new( id, - symbol.label.text[symbol.label.filter_range.clone()].to_string(), + &symbol.label.text[symbol.label.filter_range.clone()], ) }) .partition(|candidate| { @@ -313,7 +313,7 @@ mod tests { let candidates = fake_symbols .iter() .enumerate() - .map(|(id, symbol)| StringMatchCandidate::new(id, symbol.name.clone())) + .map(|(id, symbol)| StringMatchCandidate::new(id, &symbol.name)) .collect::>(); let matches = if params.query.is_empty() { Vec::new() diff --git a/crates/recent_projects/src/recent_projects.rs b/crates/recent_projects/src/recent_projects.rs index 8deae201ba8aa3..54129b85e8ae52 100644 --- a/crates/recent_projects/src/recent_projects.rs +++ b/crates/recent_projects/src/recent_projects.rs @@ -228,7 +228,7 @@ impl PickerDelegate for RecentProjectsDelegate { .join(""), }; - StringMatchCandidate::new(id, combined_string) + StringMatchCandidate::new(id, &combined_string) }) .collect::>(); self.matches = smol::block_on(fuzzy::match_strings( diff --git a/crates/snippets_ui/src/snippets_ui.rs b/crates/snippets_ui/src/snippets_ui.rs index 223dfb7ce9a7ef..237261e999aa14 100644 --- a/crates/snippets_ui/src/snippets_ui.rs +++ b/crates/snippets_ui/src/snippets_ui.rs @@ -96,7 +96,7 @@ impl ScopeSelectorDelegate { let candidates = candidates .chain(languages) .enumerate() - .map(|(candidate_id, name)| StringMatchCandidate::new(candidate_id, name)) + .map(|(candidate_id, name)| StringMatchCandidate::new(candidate_id, &name)) .collect::>(); Self { diff --git a/crates/storybook/src/stories/picker.rs b/crates/storybook/src/stories/picker.rs index 844617ae35b798..5df6cc23c41997 100644 --- a/crates/storybook/src/stories/picker.rs +++ b/crates/storybook/src/stories/picker.rs @@ -22,11 +22,7 @@ impl Delegate { .iter() .copied() .enumerate() - .map(|(id, string)| StringMatchCandidate { - id, - char_bag: string.into(), - string: string.into(), - }) + .map(|(id, string)| StringMatchCandidate::new(id, string)) .collect(), matches: vec![], selected_ix: 0, diff --git a/crates/tasks_ui/src/modal.rs b/crates/tasks_ui/src/modal.rs index 1e074a65a6bd1f..521115cf5f3567 100644 --- a/crates/tasks_ui/src/modal.rs +++ b/crates/tasks_ui/src/modal.rs @@ -516,7 +516,7 @@ fn string_match_candidates<'a>( .map(|(index, (_, candidate))| StringMatchCandidate { id: index, char_bag: candidate.resolved_label.chars().collect(), - string: candidate.display_label().to_owned(), + string: candidate.display_label().into(), }) .collect() } diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 45e590a36690d4..e69e1d6093695c 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -230,11 +230,7 @@ impl PickerDelegate for ThemeSelectorDelegate { .themes .iter() .enumerate() - .map(|(id, meta)| StringMatchCandidate { - id, - char_bag: meta.name.as_ref().into(), - string: meta.name.to_string(), - }) + .map(|(id, meta)| StringMatchCandidate::new(id, &meta.name)) .collect::>(); cx.spawn(|this, mut cx| async move { diff --git a/crates/toolchain_selector/src/toolchain_selector.rs b/crates/toolchain_selector/src/toolchain_selector.rs index c277e321543e67..2c886bb8c460fb 100644 --- a/crates/toolchain_selector/src/toolchain_selector.rs +++ b/crates/toolchain_selector/src/toolchain_selector.rs @@ -296,7 +296,7 @@ impl PickerDelegate for ToolchainSelectorDelegate { .map(|(candidate_id, toolchain)| { let path = Self::relativize_path(toolchain.path, &worktree_root_path); let string = format!("{}{}", toolchain.name, path); - StringMatchCandidate::new(candidate_id, string) + StringMatchCandidate::new(candidate_id, &string) }) .collect::>(); match_strings( diff --git a/crates/vcs_menu/src/lib.rs b/crates/vcs_menu/src/lib.rs index 9a80c1b4dc48b2..5dc02cc7c22538 100644 --- a/crates/vcs_menu/src/lib.rs +++ b/crates/vcs_menu/src/lib.rs @@ -172,11 +172,7 @@ impl PickerDelegate for BranchListDelegate { branches .into_iter() .enumerate() - .map(|(ix, command)| StringMatchCandidate { - id: ix, - char_bag: command.name.chars().collect(), - string: command.name.into(), - }) + .map(|(ix, command)| StringMatchCandidate::new(ix, &command.name)) .collect::>() }); let Some(candidates) = candidates.log_err() else { diff --git a/crates/welcome/src/base_keymap_picker.rs b/crates/welcome/src/base_keymap_picker.rs index 4e47fa13510672..7690a56151bd50 100644 --- a/crates/welcome/src/base_keymap_picker.rs +++ b/crates/welcome/src/base_keymap_picker.rs @@ -127,11 +127,7 @@ impl PickerDelegate for BaseKeymapSelectorDelegate { let background = cx.background_executor().clone(); let candidates = BaseKeymap::names() .enumerate() - .map(|(id, name)| StringMatchCandidate { - id, - char_bag: name.into(), - string: name.into(), - }) + .map(|(id, name)| StringMatchCandidate::new(id, name)) .collect::>(); cx.spawn(|this, mut cx| async move {