Bump salsa

This commit is contained in:
Lukas Wirth 2025-06-04 13:38:29 +02:00
parent a1f548bce2
commit 8029c731ed
20 changed files with 155 additions and 93 deletions

52
Cargo.lock generated
View file

@ -569,12 +569,6 @@ dependencies = [
"hashbrown 0.15.4",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.5.2"
@ -1020,6 +1014,15 @@ dependencies = [
"triomphe",
]
[[package]]
name = "intrusive-collections"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "189d0897e4cbe8c75efedf3502c18c887b05046e59d28404d4d8e46cbc4d1e86"
dependencies = [
"memoffset",
]
[[package]]
name = "itertools"
version = "0.12.1"
@ -1427,6 +1430,16 @@ dependencies = [
"num-traits",
]
[[package]]
name = "papaya"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92dd0b07c53a0a0c764db2ace8c541dc47320dad97c2200c2a637ab9dd2328f"
dependencies = [
"equivalent",
"seize",
]
[[package]]
name = "parking_lot"
version = "0.12.4"
@ -1955,16 +1968,18 @@ checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
[[package]]
name = "salsa"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8fff508e3d6ef42a32607f7538e17171a877a12015e32036f46e99d00c95781"
checksum = "2e235afdb8e510f38a07138fbe5a0b64691894358a9c0cbd813b1aade110efc9"
dependencies = [
"boxcar",
"crossbeam-queue",
"dashmap",
"crossbeam-utils",
"hashbrown 0.15.4",
"hashlink",
"indexmap",
"intrusive-collections",
"papaya",
"parking_lot",
"portable-atomic",
"rayon",
@ -1978,17 +1993,16 @@ dependencies = [
[[package]]
name = "salsa-macro-rules"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea72b3c06f2ce6350fe3a0eeb7aaaf842d1d8352b706973c19c4f02e298a87c"
checksum = "2edb86a7e9c91f6d30c9ce054312721dbe773a162db27bbfae834d16177b30ce"
[[package]]
name = "salsa-macros"
version = "0.22.0"
version = "0.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ce92025bc160b27814a207cb78d680973af17f863c7f4fc56cf3a535e22f378"
checksum = "d0778d6e209051bc4e75acfe83bcd7848601ec3dbe9c3dbb982829020e9128af"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn",
@ -2025,6 +2039,16 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "seize"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4b8d813387d566f627f3ea1b914c068aac94c40ae27ec43f5f33bde65abefe7"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "semver"
version = "1.0.26"

View file

@ -49,6 +49,8 @@ debug = 2
# ungrammar = { path = "../ungrammar" }
# salsa = { path = "../salsa" }
# salsa-macros = { path = "../salsa/components/salsa-macros" }
# salsa-macro-rules = { path = "../salsa/components/salsa-macro-rules" }
[workspace.dependencies]
# local crates
@ -136,8 +138,8 @@ rayon = "1.10.0"
rowan = "=0.15.15"
# Ideally we'd not enable the macros feature but unfortunately the `tracked` attribute does not work
# on impls without it
salsa = { version = "0.22.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] }
salsa-macros = "0.22.0"
salsa = { version = "0.23.0", default-features = true, features = ["rayon","salsa_unstable", "macros"] }
salsa-macros = "0.23.0"
semver = "1.0.26"
serde = { version = "1.0.219" }
serde_derive = { version = "1.0.219" }

View file

@ -34,7 +34,7 @@ pub type FxIndexSet<T> = indexmap::IndexSet<T, rustc_hash::FxBuildHasher>;
#[macro_export]
macro_rules! impl_intern_key {
($id:ident, $loc:ident) => {
#[salsa_macros::interned(no_lifetime)]
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct $id {
pub loc: $loc,
@ -44,7 +44,7 @@ macro_rules! impl_intern_key {
impl ::std::fmt::Debug for $id {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.debug_tuple(stringify!($id))
.field(&format_args!("{:04x}", self.0.as_u32()))
.field(&format_args!("{:04x}", self.0.index()))
.finish()
}
}
@ -168,7 +168,7 @@ impl Files {
}
}
#[salsa_macros::interned(no_lifetime, debug, constructor=from_span)]
#[salsa_macros::interned(no_lifetime, debug, constructor=from_span, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct EditionedFileId {
pub editioned_file_id: span::EditionedFileId,

View file

@ -29,8 +29,8 @@ pub enum Path {
// This type is being used a lot, make sure it doesn't grow unintentionally.
#[cfg(target_arch = "x86_64")]
const _: () = {
assert!(size_of::<Path>() == 16);
assert!(size_of::<Option<Path>>() == 16);
assert!(size_of::<Path>() == 24);
assert!(size_of::<Option<Path>>() == 24);
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]

View file

@ -149,7 +149,7 @@ pub enum TypeRef {
}
#[cfg(target_arch = "x86_64")]
const _: () = assert!(size_of::<TypeRef>() == 16);
const _: () = assert!(size_of::<TypeRef>() == 24);
pub type TypeRefId = Idx<TypeRef>;

View file

@ -172,7 +172,7 @@ fn no() {}
"ast_id_map_shim",
"parse_shim",
"real_span_map_shim",
"of_",
"EnumVariants::of_",
]
"#]],
expect![[r#"
@ -181,7 +181,7 @@ fn no() {}
"ast_id_map_shim",
"file_item_tree_query",
"real_span_map_shim",
"of_",
"EnumVariants::of_",
]
"#]],
);

View file

@ -145,7 +145,7 @@ pub trait ExpandDatabase: RootQueryDb {
fn syntax_context(&self, file: HirFileId, edition: Edition) -> SyntaxContext;
}
#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext)]
#[salsa_macros::interned(no_lifetime, id = span::SyntaxContext, revisions = usize::MAX)]
pub struct SyntaxContextWrapper {
pub data: SyntaxContext,
}

View file

@ -1056,7 +1056,7 @@ impl ExpandTo {
intern::impl_internable!(ModPath, attrs::AttrInput);
#[salsa_macros::interned(no_lifetime, debug)]
#[salsa_macros::interned(no_lifetime, debug, revisions = usize::MAX)]
#[doc(alias = "MacroFileId")]
pub struct MacroCallId {
pub loc: MacroCallLoc,

View file

@ -236,15 +236,6 @@ pub trait HirDatabase: DefDatabase + std::fmt::Debug {
fn trait_impls_in_deps(&self, krate: Crate) -> Arc<[Arc<TraitImpls>]>;
// Interned IDs for Chalk integration
#[salsa::interned]
fn intern_type_or_const_param_id(
&self,
param_id: TypeOrConstParamId,
) -> InternedTypeOrConstParamId;
#[salsa::interned]
fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
#[salsa::interned]
fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
@ -329,9 +320,31 @@ fn hir_database_is_dyn_compatible() {
fn _assert_dyn_compatible(_: &dyn HirDatabase) {}
}
impl_intern_key!(InternedTypeOrConstParamId, TypeOrConstParamId);
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct InternedTypeOrConstParamId {
pub loc: TypeOrConstParamId,
}
impl ::std::fmt::Debug for InternedTypeOrConstParamId {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.debug_tuple(stringify!(InternedTypeOrConstParamId))
.field(&format_args!("{:04x}", self.0.index()))
.finish()
}
}
impl_intern_key!(InternedLifetimeParamId, LifetimeParamId);
#[salsa_macros::interned(no_lifetime, revisions = usize::MAX)]
#[derive(PartialOrd, Ord)]
pub struct InternedLifetimeParamId {
pub loc: LifetimeParamId,
}
impl ::std::fmt::Debug for InternedLifetimeParamId {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
f.debug_tuple(stringify!(InternedLifetimeParamId))
.field(&format_args!("{:04x}", self.0.index()))
.finish()
}
}
impl_intern_key!(InternedConstParamId, ConstParamId);

View file

@ -1432,10 +1432,10 @@ impl HirDisplay for Ty {
match f.closure_style {
ClosureStyle::Hide => return write!(f, "{TYPE_HINT_TRUNCATION}"),
ClosureStyle::ClosureWithId => {
return write!(f, "{{closure#{:?}}}", id.0.as_u32());
return write!(f, "{{closure#{:?}}}", id.0.index());
}
ClosureStyle::ClosureWithSubst => {
write!(f, "{{closure#{:?}}}", id.0.as_u32())?;
write!(f, "{{closure#{:?}}}", id.0.index())?;
return hir_fmt_generics(f, substs.as_slice(Interner), None, None);
}
_ => (),

View file

@ -13,7 +13,8 @@ use salsa::{
use crate::{
AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId, Interner, OpaqueTyId,
PlaceholderIndex, chalk_db, db::HirDatabase,
PlaceholderIndex, chalk_db,
db::{HirDatabase, InternedLifetimeParamId, InternedTypeOrConstParamId},
};
pub trait ToChalk {
@ -125,30 +126,32 @@ pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeOrConstParamId {
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) });
db.lookup_intern_type_or_const_param_id(interned_id)
let interned_id =
InternedTypeOrConstParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
interned_id.loc(db)
}
pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeOrConstParamId) -> PlaceholderIndex {
let interned_id = db.intern_type_or_const_param_id(id);
let interned_id = InternedTypeOrConstParamId::new(db, id);
PlaceholderIndex {
ui: chalk_ir::UniverseIndex::ROOT,
idx: interned_id.as_id().as_u32() as usize,
idx: interned_id.as_id().index() as usize,
}
}
pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
// SAFETY: We cannot really encapsulate this unfortunately, so just hope this is sound.
let interned_id = FromId::from_id(unsafe { Id::from_u32(idx.idx.try_into().unwrap()) });
db.lookup_intern_lifetime_param_id(interned_id)
let interned_id =
InternedLifetimeParamId::from_id(unsafe { Id::from_index(idx.idx.try_into().unwrap()) });
interned_id.loc(db)
}
pub fn lt_to_placeholder_idx(db: &dyn HirDatabase, id: LifetimeParamId) -> PlaceholderIndex {
let interned_id = db.intern_lifetime_param_id(id);
let interned_id = InternedLifetimeParamId::new(db, id);
PlaceholderIndex {
ui: chalk_ir::UniverseIndex::ROOT,
idx: interned_id.as_id().as_u32() as usize,
idx: interned_id.as_id().index() as usize,
}
}

View file

@ -166,10 +166,10 @@ impl TestDB {
self.events.lock().unwrap().take().unwrap()
}
pub(crate) fn log_executed(&self, f: impl FnOnce()) -> Vec<String> {
pub(crate) fn log_executed(&self, f: impl FnOnce()) -> (Vec<String>, Vec<salsa::Event>) {
let events = self.log(f);
events
.into_iter()
let executed = events
.iter()
.filter_map(|e| match e.kind {
// This is pretty horrible, but `Debug` is the only way to inspect
// QueryDescriptor at the moment.
@ -181,6 +181,7 @@ impl TestDB {
}
_ => None,
})
.collect()
.collect();
(executed, events)
}
}

View file

@ -1,6 +1,7 @@
use base_db::SourceDatabase;
use expect_test::Expect;
use hir_def::{DefWithBodyId, ModuleDefId};
use salsa::EventKind;
use test_fixture::WithFixture;
use crate::{db::HirDatabase, test_db::TestDB};
@ -567,11 +568,11 @@ fn main() {
"ast_id_map_shim",
"parse_shim",
"real_span_map_shim",
"query_with_diagnostics_",
"TraitItems::query_with_diagnostics_",
"body_shim",
"body_with_source_map_shim",
"attrs_shim",
"of_",
"ImplItems::of_",
"infer_shim",
"trait_signature_shim",
"trait_signature_with_source_map_shim",
@ -596,8 +597,8 @@ fn main() {
"struct_signature_with_source_map_shim",
"generic_predicates_shim",
"value_ty_shim",
"firewall_",
"query_",
"VariantFields::firewall_",
"VariantFields::query_",
"lang_item",
"inherent_impls_in_crate_shim",
"impl_signature_shim",
@ -674,11 +675,11 @@ fn main() {
"file_item_tree_query",
"real_span_map_shim",
"crate_local_def_map",
"query_with_diagnostics_",
"TraitItems::query_with_diagnostics_",
"body_with_source_map_shim",
"attrs_shim",
"body_shim",
"of_",
"ImplItems::of_",
"infer_shim",
"attrs_shim",
"trait_signature_with_source_map_shim",
@ -697,7 +698,7 @@ fn main() {
"function_signature_with_source_map_shim",
"expr_scopes_shim",
"struct_signature_with_source_map_shim",
"query_",
"VariantFields::query_",
"inherent_impls_in_crate_shim",
"impl_signature_with_source_map_shim",
"impl_signature_shim",
@ -718,10 +719,23 @@ fn execute_assert_events(
required: &[(&str, usize)],
expect: Expect,
) {
let events = db.log_executed(f);
for (event, count) in required {
let n = events.iter().filter(|it| it.contains(event)).count();
assert_eq!(n, *count, "Expected {event} to be executed {count} times, but only got {n}");
}
expect.assert_debug_eq(&events);
let (executed, events) = db.log_executed(f);
salsa::attach(db, || {
for (event, count) in required {
let n = executed.iter().filter(|it| it.contains(event)).count();
assert_eq!(
n,
*count,
"Expected {event} to be executed {count} times, but only got {n}:\n \
Executed: {executed:#?}\n \
Event log: {events:#?}",
events = events
.iter()
.filter(|event| !matches!(event.kind, EventKind::WillCheckCancellation))
.map(|event| { format!("{:?}", event.kind) })
.collect::<Vec<_>>(),
);
}
expect.assert_debug_eq(&executed);
});
}

View file

@ -1,5 +1,7 @@
//! Assorted functions shared by several assists.
use std::slice;
pub(crate) use gen_trait_fn_body::gen_trait_fn_body;
use hir::{
DisplayTarget, HasAttrs as HirHasAttrs, HirDisplay, InFile, ModuleDef, PathResolution,
@ -912,7 +914,7 @@ fn handle_as_ref_str(
) -> Option<(ReferenceConversionType, bool)> {
let str_type = hir::BuiltinType::str().ty(db);
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, std::slice::from_ref(&str_type))
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&str_type))
.then_some((ReferenceConversionType::AsRefStr, could_deref_to_target(ty, &str_type, db)))
}
@ -924,11 +926,10 @@ fn handle_as_ref_slice(
let type_argument = ty.type_arguments().next()?;
let slice_type = hir::Type::new_slice(type_argument);
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, std::slice::from_ref(&slice_type))
.then_some((
ReferenceConversionType::AsRefSlice,
could_deref_to_target(ty, &slice_type, db),
))
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&slice_type)).then_some((
ReferenceConversionType::AsRefSlice,
could_deref_to_target(ty, &slice_type, db),
))
}
fn handle_dereferenced(
@ -938,7 +939,7 @@ fn handle_dereferenced(
) -> Option<(ReferenceConversionType, bool)> {
let type_argument = ty.type_arguments().next()?;
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, std::slice::from_ref(&type_argument))
ty.impls_trait(db, famous_defs.core_convert_AsRef()?, slice::from_ref(&type_argument))
.then_some((
ReferenceConversionType::Dereferenced,
could_deref_to_target(ty, &type_argument, db),

View file

@ -272,5 +272,5 @@ fn crate_name(db: &RootDatabase, krate: Crate) -> Symbol {
.display_name
.as_deref()
.cloned()
.unwrap_or_else(|| Symbol::integer(salsa::plumbing::AsId::as_id(&krate).as_u32() as usize))
.unwrap_or_else(|| Symbol::integer(salsa::plumbing::AsId::as_id(&krate).index() as usize))
}

View file

@ -79,7 +79,7 @@ impl<'a> dot::Labeller<'a, Crate, Edge<'a>> for DotCrateGraph<'_> {
}
fn node_id(&'a self, n: &Crate) -> Id<'a> {
let id = n.as_id().as_u32();
let id = n.as_id().index();
Id::new(format!("_{id:?}")).unwrap()
}

View file

@ -6,7 +6,7 @@ use std::{
use ide_db::base_db::{
DbPanicContext,
salsa::{self, Cancelled, UnexpectedCycle},
salsa::{self, Cancelled},
};
use lsp_server::{ExtractError, Response, ResponseError};
use serde::{Serialize, de::DeserializeOwned};
@ -350,9 +350,6 @@ where
if let Some(panic_message) = panic_message {
message.push_str(": ");
message.push_str(panic_message);
} else if let Some(cycle) = panic.downcast_ref::<UnexpectedCycle>() {
tracing::error!("{cycle}");
message.push_str(": unexpected cycle");
} else if let Ok(cancelled) = panic.downcast::<Cancelled>() {
tracing::error!("Cancellation propagated out of salsa! This is a bug");
return Err(HandlerCancelledError::Inner(*cancelled));

View file

@ -107,9 +107,10 @@ impl fmt::Debug for ErasedFileAstId {
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
#[repr(u8)]
enum ErasedFileAstIdKind {
/// This needs to not change because it's depended upon by the proc macro server.
Fixup,
Fixup = 0,
// The following are associated with `ErasedHasNameFileAstId`.
Enum,
Struct,
@ -413,9 +414,9 @@ impl ErasedAstIdNextIndexMap {
}
macro_rules! register_enum_ast_id {
(impl AstIdNode for $($ident:ident),+ ) => {
(impl $AstIdNode:ident for $($ident:ident),+ ) => {
$(
impl AstIdNode for ast::$ident {}
impl $AstIdNode for ast::$ident {}
)+
};
}
@ -426,9 +427,9 @@ register_enum_ast_id! {
}
macro_rules! register_has_name_ast_id {
(impl AstIdNode for $($ident:ident = $name_method:ident),+ ) => {
(impl $AstIdNode:ident for $($ident:ident = $name_method:ident),+ ) => {
$(
impl AstIdNode for ast::$ident {}
impl $AstIdNode for ast::$ident {}
)+
fn has_name_ast_id(node: &SyntaxNode, index_map: &mut ErasedAstIdNextIndexMap) -> Option<ErasedFileAstId> {
@ -472,9 +473,9 @@ register_has_name_ast_id! {
}
macro_rules! register_assoc_item_ast_id {
(impl AstIdNode for $($ident:ident = $name_callback:expr),+ ) => {
(impl $AstIdNode:ident for $($ident:ident = $name_callback:expr),+ ) => {
$(
impl AstIdNode for ast::$ident {}
impl $AstIdNode for ast::$ident {}
)+
fn assoc_item_ast_id(

View file

@ -97,6 +97,7 @@ const _: () = {
const LOCATION: salsa::plumbing::Location =
salsa::plumbing::Location { file: file!(), line: line!() };
const DEBUG_NAME: &'static str = "SyntaxContextData";
const REVISIONS: std::num::NonZeroUsize = std::num::NonZeroUsize::MAX;
type Fields<'a> = SyntaxContextData;
type Struct<'a> = SyntaxContext;
}
@ -108,7 +109,9 @@ const _: () = {
static CACHE: zalsa_::IngredientCache<zalsa_struct_::IngredientImpl<SyntaxContext>> =
zalsa_::IngredientCache::new();
CACHE.get_or_create(db.zalsa(), || {
db.zalsa().add_or_lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>()
db.zalsa()
.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>()
.get_or_create()
})
}
}
@ -130,9 +133,12 @@ const _: () = {
type MemoIngredientMap = salsa::plumbing::MemoIngredientSingletonIndex;
fn lookup_or_create_ingredient_index(
aux: &salsa::plumbing::Zalsa,
zalsa: &salsa::plumbing::Zalsa,
) -> salsa::plumbing::IngredientIndices {
aux.add_or_lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>().into()
zalsa
.lookup_jar_by_type::<zalsa_struct_::JarImpl<SyntaxContext>>()
.get_or_create()
.into()
}
#[inline]
@ -326,14 +332,14 @@ impl<'db> SyntaxContext {
None
} else {
// SAFETY: By our invariant, this is either a root (which we verified it's not) or a valid `salsa::Id`.
unsafe { Some(salsa::Id::from_u32(self.0)) }
unsafe { Some(salsa::Id::from_index(self.0)) }
}
}
#[inline]
fn from_salsa_id(id: salsa::Id) -> Self {
// SAFETY: This comes from a Salsa ID.
unsafe { Self::from_u32(id.as_u32()) }
unsafe { Self::from_u32(id.index()) }
}
#[inline]

View file

@ -5,8 +5,8 @@
use std::fmt;
use fst::{IntoStreamer, Streamer};
use nohash_hasher::IntMap;
use rustc_hash::FxHashMap;
use indexmap::IndexMap;
use rustc_hash::{FxBuildHasher, FxHashMap};
use crate::{AnchoredPath, FileId, Vfs, VfsPath};
@ -14,7 +14,7 @@ use crate::{AnchoredPath, FileId, Vfs, VfsPath};
#[derive(Default, Clone, Eq, PartialEq)]
pub struct FileSet {
files: FxHashMap<VfsPath, FileId>,
paths: IntMap<FileId, VfsPath>,
paths: IndexMap<FileId, VfsPath, FxBuildHasher>,
}
impl FileSet {