Fix different kinds values used for `worktree_id` (#17523)

Kirill Bulatov created

Change summary

crates/collab/src/tests/integration_tests.rs       |  8 
crates/copilot/src/copilot.rs                      |  4 
crates/editor/src/editor.rs                        | 15 ++
crates/extension/src/wasm_host/wit/since_v0_1_0.rs |  6 
crates/language/src/buffer.rs                      |  7 
crates/language/src/language.rs                    |  3 
crates/language/src/language_settings.rs           | 14 --
crates/languages/src/yaml.rs                       |  2 
crates/project/src/lsp_store.rs                    |  6 
crates/project/src/project.rs                      |  6 
crates/project/src/project_settings.rs             | 11 -
crates/project/src/task_inventory.rs               | 19 ++-
crates/project/src/terminals.rs                    |  2 
crates/remote_server/src/remote_editing_tests.rs   |  2 
crates/settings/src/settings.rs                    | 35 +++++++
crates/settings/src/settings_store.rs              | 47 ++++++----
crates/workspace/src/item.rs                       |  2 
crates/worktree/src/worktree.rs                    | 74 ++++-----------
18 files changed, 136 insertions(+), 127 deletions(-)

Detailed changes

crates/collab/src/tests/integration_tests.rs 🔗

@@ -3324,7 +3324,7 @@ async fn test_local_settings(
         let store = cx.global::<SettingsStore>();
         assert_eq!(
             store
-                .local_settings(worktree_b.entity_id().as_u64() as _)
+                .local_settings(worktree_b.read(cx).id())
                 .collect::<Vec<_>>(),
             &[
                 (Path::new("").into(), r#"{"tab_size":2}"#.to_string()),
@@ -3343,7 +3343,7 @@ async fn test_local_settings(
         let store = cx.global::<SettingsStore>();
         assert_eq!(
             store
-                .local_settings(worktree_b.entity_id().as_u64() as _)
+                .local_settings(worktree_b.read(cx).id())
                 .collect::<Vec<_>>(),
             &[
                 (Path::new("").into(), r#"{}"#.to_string()),
@@ -3372,7 +3372,7 @@ async fn test_local_settings(
         let store = cx.global::<SettingsStore>();
         assert_eq!(
             store
-                .local_settings(worktree_b.entity_id().as_u64() as _)
+                .local_settings(worktree_b.read(cx).id())
                 .collect::<Vec<_>>(),
             &[
                 (Path::new("a").into(), r#"{"tab_size":8}"#.to_string()),
@@ -3404,7 +3404,7 @@ async fn test_local_settings(
         let store = cx.global::<SettingsStore>();
         assert_eq!(
             store
-                .local_settings(worktree_b.entity_id().as_u64() as _)
+                .local_settings(worktree_b.read(cx).id())
                 .collect::<Vec<_>>(),
             &[(Path::new("a").into(), r#"{"hard_tabs":true}"#.to_string()),]
         )

crates/copilot/src/copilot.rs 🔗

@@ -1250,8 +1250,8 @@ mod tests {
             unimplemented!()
         }
 
-        fn worktree_id(&self) -> usize {
-            0
+        fn worktree_id(&self, _: &AppContext) -> settings::WorktreeId {
+            settings::WorktreeId::from_usize(0)
         }
 
         fn is_private(&self) -> bool {

crates/editor/src/editor.rs 🔗

@@ -116,14 +116,14 @@ use parking_lot::{Mutex, RwLock};
 use project::project_settings::{GitGutterSetting, ProjectSettings};
 use project::{
     CodeAction, Completion, CompletionIntent, FormatTrigger, Item, Location, Project, ProjectPath,
-    ProjectTransaction, TaskSourceKind, WorktreeId,
+    ProjectTransaction, TaskSourceKind,
 };
 use rand::prelude::*;
 use rpc::{proto::*, ErrorExt};
 use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
 use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
 use serde::{Deserialize, Serialize};
-use settings::{update_settings_file, Settings, SettingsStore};
+use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
 use smallvec::SmallVec;
 use snippet::Snippet;
 use std::{
@@ -8742,7 +8742,7 @@ impl Editor {
             let (worktree_id, file) = project
                 .buffer_for_id(runnable.buffer, cx)
                 .and_then(|buffer| buffer.read(cx).file())
-                .map(|file| (WorktreeId::from_usize(file.worktree_id()), file.clone()))
+                .map(|file| (file.worktree_id(cx), file.clone()))
                 .unzip();
 
             (project.task_inventory().clone(), worktree_id, file)
@@ -11421,7 +11421,14 @@ impl Editor {
             .redacted_ranges(search_range, |file| {
                 if let Some(file) = file {
                     file.is_private()
-                        && EditorSettings::get(Some(file.as_ref().into()), cx).redact_private_values
+                        && EditorSettings::get(
+                            Some(SettingsLocation {
+                                worktree_id: file.worktree_id(cx),
+                                path: file.path().as_ref(),
+                            }),
+                            cx,
+                        )
+                        .redact_private_values
                 } else {
                     false
                 }

crates/extension/src/wasm_host/wit/since_v0_1_0.rs 🔗

@@ -1,6 +1,6 @@
 use crate::wasm_host::{wit::ToWasmtimeResult, WasmState};
 use ::http_client::AsyncBody;
-use ::settings::Settings;
+use ::settings::{Settings, WorktreeId};
 use anyhow::{anyhow, bail, Context, Result};
 use async_compression::futures::bufread::GzipDecoder;
 use async_tar::Archive;
@@ -76,7 +76,7 @@ impl HostWorktree for WasmState {
         delegate: Resource<Arc<dyn LspAdapterDelegate>>,
     ) -> wasmtime::Result<u64> {
         let delegate = self.table.get(&delegate)?;
-        Ok(delegate.worktree_id())
+        Ok(delegate.worktree_id().to_proto())
     }
 
     async fn root_path(
@@ -393,7 +393,7 @@ impl ExtensionImports for WasmState {
                 let location = location
                     .as_ref()
                     .map(|location| ::settings::SettingsLocation {
-                        worktree_id: location.worktree_id as usize,
+                        worktree_id: WorktreeId::from_proto(location.worktree_id),
                         path: Path::new(&location.path),
                     });
 

crates/language/src/buffer.rs 🔗

@@ -27,6 +27,7 @@ use gpui::{
 use lsp::LanguageServerId;
 use parking_lot::Mutex;
 use serde_json::Value;
+use settings::WorktreeId;
 use similar::{ChangeTag, TextDiff};
 use smallvec::SmallVec;
 use smol::future::yield_now;
@@ -361,7 +362,7 @@ pub trait File: Send + Sync {
     /// Returns the id of the worktree to which this file belongs.
     ///
     /// This is needed for looking up project-specific settings.
-    fn worktree_id(&self) -> usize;
+    fn worktree_id(&self, cx: &AppContext) -> WorktreeId;
 
     /// Returns whether the file has been deleted.
     fn is_deleted(&self) -> bool;
@@ -4172,8 +4173,8 @@ impl File for TestFile {
         self.path().file_name().unwrap_or(self.root_name.as_ref())
     }
 
-    fn worktree_id(&self) -> usize {
-        0
+    fn worktree_id(&self, _: &AppContext) -> WorktreeId {
+        WorktreeId::from_usize(0)
     }
 
     fn is_deleted(&self) -> bool {

crates/language/src/language.rs 🔗

@@ -38,6 +38,7 @@ use schemars::{
 };
 use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
 use serde_json::Value;
+use settings::WorktreeId;
 use smol::future::FutureExt as _;
 use std::num::NonZeroU32;
 use std::{
@@ -280,7 +281,7 @@ impl CachedLspAdapter {
 pub trait LspAdapterDelegate: Send + Sync {
     fn show_notification(&self, message: &str, cx: &mut AppContext);
     fn http_client(&self) -> Arc<dyn HttpClient>;
-    fn worktree_id(&self) -> u64;
+    fn worktree_id(&self) -> WorktreeId;
     fn worktree_root_path(&self) -> &Path;
     fn update_status(&self, language: LanguageServerName, status: LanguageServerBinaryStatus);
 

crates/language/src/language_settings.rs 🔗

@@ -20,15 +20,6 @@ use settings::{add_references_to_properties, Settings, SettingsLocation, Setting
 use std::{num::NonZeroU32, path::Path, sync::Arc};
 use util::serde::default_true;
 
-impl<'a> From<&'a dyn File> for SettingsLocation<'a> {
-    fn from(val: &'a dyn File) -> Self {
-        SettingsLocation {
-            worktree_id: val.worktree_id(),
-            path: val.path().as_ref(),
-        }
-    }
-}
-
 /// Initializes the language settings.
 pub fn init(cx: &mut AppContext) {
     AllLanguageSettings::register(cx);
@@ -49,7 +40,10 @@ pub fn all_language_settings<'a>(
     file: Option<&Arc<dyn File>>,
     cx: &'a AppContext,
 ) -> &'a AllLanguageSettings {
-    let location = file.map(|f| f.as_ref().into());
+    let location = file.map(|f| SettingsLocation {
+        worktree_id: f.worktree_id(cx),
+        path: f.path().as_ref(),
+    });
     AllLanguageSettings::get(location, cx)
 }
 

crates/languages/src/yaml.rs 🔗

@@ -135,7 +135,7 @@ impl LspAdapter for YamlLspAdapter {
         cx: &mut AsyncAppContext,
     ) -> Result<Value> {
         let location = SettingsLocation {
-            worktree_id: delegate.worktree_id() as usize,
+            worktree_id: delegate.worktree_id(),
             path: delegate.worktree_root_path(),
         };
 

crates/project/src/lsp_store.rs 🔗

@@ -4250,7 +4250,7 @@ impl LspStore {
 
         let project_settings = ProjectSettings::get(
             Some(SettingsLocation {
-                worktree_id: worktree_id.to_proto() as usize,
+                worktree_id,
                 path: Path::new(""),
             }),
             cx,
@@ -6408,8 +6408,8 @@ impl LspAdapterDelegate for ProjectLspAdapterDelegate {
         self.http_client.clone()
     }
 
-    fn worktree_id(&self) -> u64 {
-        self.worktree.id().to_proto()
+    fn worktree_id(&self) -> WorktreeId {
+        self.worktree.id()
     }
 
     fn worktree_root_path(&self) -> &Path {

crates/project/src/project.rs 🔗

@@ -37,7 +37,7 @@ use futures::{
 
 use git::{blame::Blame, repository::GitRepository};
 use gpui::{
-    AnyModel, AppContext, AsyncAppContext, BorrowAppContext, Context, Entity, EventEmitter, Model,
+    AnyModel, AppContext, AsyncAppContext, BorrowAppContext, Context, EventEmitter, Model,
     ModelContext, SharedString, Task, WeakModel, WindowContext,
 };
 use itertools::Itertools;
@@ -1606,7 +1606,7 @@ impl Project {
             self.worktree_store.update(cx, |worktree_store, cx| {
                 for worktree in worktree_store.worktrees() {
                     store
-                        .clear_local_settings(worktree.entity_id().as_u64() as usize, cx)
+                        .clear_local_settings(worktree.read(cx).id(), cx)
                         .log_err();
                 }
             });
@@ -5186,7 +5186,7 @@ impl EventEmitter<Event> for Project {}
 impl<'a> From<&'a ProjectPath> for SettingsLocation<'a> {
     fn from(val: &'a ProjectPath) -> Self {
         SettingsLocation {
-            worktree_id: val.worktree_id.to_usize(),
+            worktree_id: val.worktree_id,
             path: val.path.as_ref(),
         }
     }

crates/project/src/project_settings.rs 🔗

@@ -249,7 +249,7 @@ impl SettingsObserver {
         let store = cx.global::<SettingsStore>();
         for worktree in self.worktree_store.read(cx).worktrees() {
             let worktree_id = worktree.read(cx).id().to_proto();
-            for (path, content) in store.local_settings(worktree.entity_id().as_u64() as usize) {
+            for (path, content) in store.local_settings(worktree.read(cx).id()) {
                 downstream_client
                     .send(proto::UpdateWorktreeSettings {
                         project_id,
@@ -416,17 +416,12 @@ impl SettingsObserver {
         settings_contents: impl IntoIterator<Item = (Arc<Path>, Option<String>)>,
         cx: &mut ModelContext<Self>,
     ) {
-        let worktree_id = worktree.entity_id();
+        let worktree_id = worktree.read(cx).id();
         let remote_worktree_id = worktree.read(cx).id();
         cx.update_global::<SettingsStore, _>(|store, cx| {
             for (directory, file_content) in settings_contents {
                 store
-                    .set_local_settings(
-                        worktree_id.as_u64() as usize,
-                        directory.clone(),
-                        file_content.as_deref(),
-                        cx,
-                    )
+                    .set_local_settings(worktree_id, directory.clone(), file_content.as_deref(), cx)
                     .log_err();
                 if let Some(downstream_client) = &self.downstream_client {
                     downstream_client

crates/project/src/task_inventory.rs 🔗

@@ -579,15 +579,16 @@ impl ContextProvider for BasicContextProvider {
         if !selected_text.trim().is_empty() {
             task_variables.insert(VariableName::SelectedText, selected_text);
         }
-        let worktree_abs_path = buffer
-            .file()
-            .map(|file| WorktreeId::from_usize(file.worktree_id()))
-            .and_then(|worktree_id| {
-                self.project
-                    .read(cx)
-                    .worktree_for_id(worktree_id, cx)
-                    .map(|worktree| worktree.read(cx).abs_path())
-            });
+        let worktree_abs_path =
+            buffer
+                .file()
+                .map(|file| file.worktree_id(cx))
+                .and_then(|worktree_id| {
+                    self.project
+                        .read(cx)
+                        .worktree_for_id(worktree_id, cx)
+                        .map(|worktree| worktree.read(cx).abs_path())
+                });
         if let Some(worktree_path) = worktree_abs_path {
             task_variables.insert(
                 VariableName::WorktreeRoot,

crates/project/src/terminals.rs 🔗

@@ -103,7 +103,7 @@ impl Project {
         if let Some(path) = path.as_ref() {
             if let Some((worktree, _)) = self.find_worktree(path, cx) {
                 settings_location = Some(SettingsLocation {
-                    worktree_id: worktree.read(cx).id().to_usize(),
+                    worktree_id: worktree.read(cx).id(),
                     path,
                 });
             }

crates/remote_server/src/remote_editing_tests.rs 🔗

@@ -242,7 +242,7 @@ async fn test_remote_settings(cx: &mut TestAppContext, server_cx: &mut TestAppCo
         assert_eq!(
             AllLanguageSettings::get(
                 Some(SettingsLocation {
-                    worktree_id: worktree_id.into(),
+                    worktree_id,
                     path: Path::new("src/lib.rs")
                 }),
                 cx

crates/settings/src/settings.rs 🔗

@@ -6,7 +6,7 @@ mod settings_store;
 
 use gpui::AppContext;
 use rust_embed::RustEmbed;
-use std::{borrow::Cow, str};
+use std::{borrow::Cow, fmt, str};
 use util::asset_str;
 
 pub use editable_setting_control::*;
@@ -15,6 +15,39 @@ pub use keymap_file::KeymapFile;
 pub use settings_file::*;
 pub use settings_store::{Settings, SettingsLocation, SettingsSources, SettingsStore};
 
+#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
+pub struct WorktreeId(usize);
+
+impl From<WorktreeId> for usize {
+    fn from(value: WorktreeId) -> Self {
+        value.0
+    }
+}
+
+impl WorktreeId {
+    pub fn from_usize(handle_id: usize) -> Self {
+        Self(handle_id)
+    }
+
+    pub fn from_proto(id: u64) -> Self {
+        Self(id as usize)
+    }
+
+    pub fn to_proto(&self) -> u64 {
+        self.0 as u64
+    }
+
+    pub fn to_usize(&self) -> usize {
+        self.0
+    }
+}
+
+impl fmt::Display for WorktreeId {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        std::fmt::Display::fmt(&self.0, f)
+    }
+}
+
 #[derive(RustEmbed)]
 #[folder = "../../assets"]
 #[include = "settings/*"]

crates/settings/src/settings_store.rs 🔗

@@ -18,7 +18,7 @@ use tree_sitter::Query;
 use tree_sitter_json::language;
 use util::{merge_non_null_json_value_into, RangeExt, ResultExt as _};
 
-use crate::SettingsJsonSchemaParams;
+use crate::{SettingsJsonSchemaParams, WorktreeId};
 
 /// A value that can be defined as a user setting.
 ///
@@ -153,7 +153,7 @@ impl<'a, T: Serialize> SettingsSources<'a, T> {
 
 #[derive(Clone, Copy, Debug)]
 pub struct SettingsLocation<'a> {
-    pub worktree_id: usize,
+    pub worktree_id: WorktreeId,
     pub path: &'a Path,
 }
 
@@ -163,7 +163,7 @@ pub struct SettingsStore {
     raw_default_settings: serde_json::Value,
     raw_user_settings: serde_json::Value,
     raw_extension_settings: serde_json::Value,
-    raw_local_settings: BTreeMap<(usize, Arc<Path>), serde_json::Value>,
+    raw_local_settings: BTreeMap<(WorktreeId, Arc<Path>), serde_json::Value>,
     tab_size_callback: Option<(
         TypeId,
         Box<dyn Fn(&dyn Any) -> Option<usize> + Send + Sync + 'static>,
@@ -179,7 +179,7 @@ impl Global for SettingsStore {}
 #[derive(Debug)]
 struct SettingValue<T> {
     global_value: Option<T>,
-    local_values: Vec<(usize, Arc<Path>, T)>,
+    local_values: Vec<(WorktreeId, Arc<Path>, T)>,
 }
 
 trait AnySettingValue: 'static + Send + Sync {
@@ -193,7 +193,7 @@ trait AnySettingValue: 'static + Send + Sync {
     ) -> Result<Box<dyn Any>>;
     fn value_for_path(&self, path: Option<SettingsLocation>) -> &dyn Any;
     fn set_global_value(&mut self, value: Box<dyn Any>);
-    fn set_local_value(&mut self, root_id: usize, path: Arc<Path>, value: Box<dyn Any>);
+    fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<Path>, value: Box<dyn Any>);
     fn json_schema(
         &self,
         generator: &mut SchemaGenerator,
@@ -519,7 +519,7 @@ impl SettingsStore {
     /// Add or remove a set of local settings via a JSON string.
     pub fn set_local_settings(
         &mut self,
-        root_id: usize,
+        root_id: WorktreeId,
         path: Arc<Path>,
         settings_content: Option<&str>,
         cx: &mut AppContext,
@@ -552,15 +552,24 @@ impl SettingsStore {
     }
 
     /// Add or remove a set of local settings via a JSON string.
-    pub fn clear_local_settings(&mut self, root_id: usize, cx: &mut AppContext) -> Result<()> {
+    pub fn clear_local_settings(&mut self, root_id: WorktreeId, cx: &mut AppContext) -> Result<()> {
         self.raw_local_settings.retain(|k, _| k.0 != root_id);
         self.recompute_values(Some((root_id, "".as_ref())), cx)?;
         Ok(())
     }
 
-    pub fn local_settings(&self, root_id: usize) -> impl '_ + Iterator<Item = (Arc<Path>, String)> {
+    pub fn local_settings(
+        &self,
+        root_id: WorktreeId,
+    ) -> impl '_ + Iterator<Item = (Arc<Path>, String)> {
         self.raw_local_settings
-            .range((root_id, Path::new("").into())..(root_id + 1, Path::new("").into()))
+            .range(
+                (root_id, Path::new("").into())
+                    ..(
+                        WorktreeId::from_usize(root_id.to_usize() + 1),
+                        Path::new("").into(),
+                    ),
+            )
             .map(|((_, path), content)| (path.clone(), serde_json::to_string(content).unwrap()))
     }
 
@@ -673,12 +682,12 @@ impl SettingsStore {
 
     fn recompute_values(
         &mut self,
-        changed_local_path: Option<(usize, &Path)>,
+        changed_local_path: Option<(WorktreeId, &Path)>,
         cx: &mut AppContext,
     ) -> Result<()> {
         // Reload the global and local values for every setting.
         let mut project_settings_stack = Vec::<DeserializedSetting>::new();
-        let mut paths_stack = Vec::<Option<(usize, &Path)>>::new();
+        let mut paths_stack = Vec::<Option<(WorktreeId, &Path)>>::new();
         for setting_value in self.setting_values.values_mut() {
             let default_settings = setting_value.deserialize_setting(&self.raw_default_settings)?;
 
@@ -859,7 +868,7 @@ impl<T: Settings> AnySettingValue for SettingValue<T> {
         self.global_value = Some(*value.downcast().unwrap());
     }
 
-    fn set_local_value(&mut self, root_id: usize, path: Arc<Path>, value: Box<dyn Any>) {
+    fn set_local_value(&mut self, root_id: WorktreeId, path: Arc<Path>, value: Box<dyn Any>) {
         let value = *value.downcast().unwrap();
         match self
             .local_values
@@ -1153,7 +1162,7 @@ mod tests {
 
         store
             .set_local_settings(
-                1,
+                WorktreeId::from_usize(1),
                 Path::new("/root1").into(),
                 Some(r#"{ "user": { "staff": true } }"#),
                 cx,
@@ -1161,7 +1170,7 @@ mod tests {
             .unwrap();
         store
             .set_local_settings(
-                1,
+                WorktreeId::from_usize(1),
                 Path::new("/root1/subdir").into(),
                 Some(r#"{ "user": { "name": "Jane Doe" } }"#),
                 cx,
@@ -1170,7 +1179,7 @@ mod tests {
 
         store
             .set_local_settings(
-                1,
+                WorktreeId::from_usize(1),
                 Path::new("/root2").into(),
                 Some(r#"{ "user": { "age": 42 }, "key2": "b" }"#),
                 cx,
@@ -1179,7 +1188,7 @@ mod tests {
 
         assert_eq!(
             store.get::<UserSettings>(Some(SettingsLocation {
-                worktree_id: 1,
+                worktree_id: WorktreeId::from_usize(1),
                 path: Path::new("/root1/something"),
             })),
             &UserSettings {
@@ -1190,7 +1199,7 @@ mod tests {
         );
         assert_eq!(
             store.get::<UserSettings>(Some(SettingsLocation {
-                worktree_id: 1,
+                worktree_id: WorktreeId::from_usize(1),
                 path: Path::new("/root1/subdir/something")
             })),
             &UserSettings {
@@ -1201,7 +1210,7 @@ mod tests {
         );
         assert_eq!(
             store.get::<UserSettings>(Some(SettingsLocation {
-                worktree_id: 1,
+                worktree_id: WorktreeId::from_usize(1),
                 path: Path::new("/root2/something")
             })),
             &UserSettings {
@@ -1212,7 +1221,7 @@ mod tests {
         );
         assert_eq!(
             store.get::<MultiKeySettings>(Some(SettingsLocation {
-                worktree_id: 1,
+                worktree_id: WorktreeId::from_usize(1),
                 path: Path::new("/root2/something")
             })),
             &MultiKeySettings {

crates/workspace/src/item.rs 🔗

@@ -514,7 +514,7 @@ impl<T: Item> ItemHandle for View<T> {
         if let Some(project_path) = self.project_path(cx) {
             WorkspaceSettings::get(
                 Some(SettingsLocation {
-                    worktree_id: project_path.worktree_id.into(),
+                    worktree_id: project_path.worktree_id,
                     path: &project_path.path,
                 }),
                 cx,

crates/worktree/src/worktree.rs 🔗

@@ -37,6 +37,7 @@ use postage::{
     watch,
 };
 use rpc::proto::{self, AnyProtoClient};
+pub use settings::WorktreeId;
 use settings::{Settings, SettingsLocation, SettingsStore};
 use smallvec::{smallvec, SmallVec};
 use smol::channel::{self, Sender};
@@ -68,15 +69,6 @@ pub const FS_WATCH_LATENCY: Duration = Duration::from_millis(100);
 #[cfg(not(feature = "test-support"))]
 pub const FS_WATCH_LATENCY: Duration = Duration::from_millis(100);
 
-#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
-pub struct WorktreeId(usize);
-
-impl From<WorktreeId> for usize {
-    fn from(value: WorktreeId) -> Self {
-        value.0
-    }
-}
-
 /// A set of local or remote files that are being opened as part of a project.
 /// Responsible for tracking related FS (for local)/collab (for remote) events and corresponding updates.
 /// Stores git repositories data and the diagnostics for the file(s).
@@ -385,24 +377,6 @@ impl Worktree {
         });
 
         cx.new_model(move |cx: &mut ModelContext<Worktree>| {
-            let worktree_id = cx.handle().entity_id().as_u64();
-            let settings_location = Some(SettingsLocation {
-                worktree_id: worktree_id as usize,
-                path: Path::new(EMPTY_PATH),
-            });
-
-            let settings = WorktreeSettings::get(settings_location, cx).clone();
-            cx.observe_global::<SettingsStore>(move |this, cx| {
-                if let Self::Local(this) = this {
-                    let settings = WorktreeSettings::get(settings_location, cx).clone();
-                    if settings != this.settings {
-                        this.settings = settings;
-                        this.restart_background_scanners(cx);
-                    }
-                }
-            })
-            .detach();
-
             let mut snapshot = LocalSnapshot {
                 ignores_by_parent_abs_path: Default::default(),
                 git_repositories: Default::default(),
@@ -428,6 +402,24 @@ impl Worktree {
                 );
             }
 
+            let worktree_id = snapshot.id();
+            let settings_location = Some(SettingsLocation {
+                worktree_id,
+                path: Path::new(EMPTY_PATH),
+            });
+
+            let settings = WorktreeSettings::get(settings_location, cx).clone();
+            cx.observe_global::<SettingsStore>(move |this, cx| {
+                if let Self::Local(this) = this {
+                    let settings = WorktreeSettings::get(settings_location, cx).clone();
+                    if settings != this.settings {
+                        this.settings = settings;
+                        this.restart_background_scanners(cx);
+                    }
+                }
+            })
+            .detach();
+
             let (scan_requests_tx, scan_requests_rx) = channel::unbounded();
             let (path_prefixes_to_scan_tx, path_prefixes_to_scan_rx) = channel::unbounded();
             let mut worktree = LocalWorktree {
@@ -2978,30 +2970,6 @@ async fn build_gitignore(abs_path: &Path, fs: &dyn Fs) -> Result<Gitignore> {
     Ok(builder.build()?)
 }
 
-impl WorktreeId {
-    pub fn from_usize(handle_id: usize) -> Self {
-        Self(handle_id)
-    }
-
-    pub fn from_proto(id: u64) -> Self {
-        Self(id as usize)
-    }
-
-    pub fn to_proto(&self) -> u64 {
-        self.0 as u64
-    }
-
-    pub fn to_usize(&self) -> usize {
-        self.0
-    }
-}
-
-impl fmt::Display for WorktreeId {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
-
 impl Deref for Worktree {
     type Target = Snapshot;
 
@@ -3123,8 +3091,8 @@ impl language::File for File {
             .unwrap_or_else(|| OsStr::new(&self.worktree.read(cx).root_name))
     }
 
-    fn worktree_id(&self) -> usize {
-        self.worktree.entity_id().as_u64() as usize
+    fn worktree_id(&self, cx: &AppContext) -> WorktreeId {
+        self.worktree.read(cx).id()
     }
 
     fn is_deleted(&self) -> bool {