Skip to content

Commit 4903be8

Browse files
committed
internal: switch FileId to be a Salsa struct
1 parent c68c8a8 commit 4903be8

File tree

11 files changed

+80
-50
lines changed

11 files changed

+80
-50
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/cfg/src/tests.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) {
1616
let tt = syntax_node_to_token_tree(
1717
tt.syntax(),
1818
DummyTestSpanMap,
19-
DUMMY,
19+
*DUMMY,
2020
DocCommentDesugarMode::ProcMacro,
2121
);
2222
let cfg = CfgExpr::parse(&tt);
@@ -29,7 +29,7 @@ fn check_dnf(input: &str, expect: Expect) {
2929
let tt = syntax_node_to_token_tree(
3030
tt.syntax(),
3131
DummyTestSpanMap,
32-
DUMMY,
32+
*DUMMY,
3333
DocCommentDesugarMode::ProcMacro,
3434
);
3535
let cfg = CfgExpr::parse(&tt);
@@ -43,7 +43,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) {
4343
let tt = syntax_node_to_token_tree(
4444
tt.syntax(),
4545
DummyTestSpanMap,
46-
DUMMY,
46+
*DUMMY,
4747
DocCommentDesugarMode::ProcMacro,
4848
);
4949
let cfg = CfgExpr::parse(&tt);
@@ -59,7 +59,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) {
5959
let tt = syntax_node_to_token_tree(
6060
tt.syntax(),
6161
DummyTestSpanMap,
62-
DUMMY,
62+
*DUMMY,
6363
DocCommentDesugarMode::ProcMacro,
6464
);
6565
let cfg = CfgExpr::parse(&tt);

crates/hir-expand/src/builtin/quote.rs

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ impl_to_to_tokentrees! {
222222

223223
#[cfg(test)]
224224
mod tests {
225+
use std::sync::LazyLock;
226+
225227
use crate::tt;
226228
use ::tt::IdentIsRaw;
227229
use expect_test::expect;
@@ -231,7 +233,7 @@ mod tests {
231233

232234
use super::quote;
233235

234-
const DUMMY: tt::Span = tt::Span {
236+
static DUMMY: LazyLock<tt::Span> = LazyLock::new(|| tt::Span {
235237
range: TextRange::empty(TextSize::new(0)),
236238
anchor: SpanAnchor {
237239
file_id: span::EditionedFileId::new(
@@ -241,39 +243,43 @@ mod tests {
241243
ast_id: ROOT_ERASED_FILE_AST_ID,
242244
},
243245
ctx: SyntaxContext::root(Edition::CURRENT),
244-
};
246+
});
245247

246248
#[test]
247249
fn test_quote_delimiters() {
248-
assert_eq!(quote!(DUMMY =>{}).to_string(), "{}");
249-
assert_eq!(quote!(DUMMY =>()).to_string(), "()");
250-
assert_eq!(quote!(DUMMY =>[]).to_string(), "[]");
250+
let dummy = *DUMMY;
251+
assert_eq!(quote!(dummy =>{}).to_string(), "{}");
252+
assert_eq!(quote!(dummy =>()).to_string(), "()");
253+
assert_eq!(quote!(dummy =>[]).to_string(), "[]");
251254
}
252255

253256
#[test]
254257
fn test_quote_idents() {
255-
assert_eq!(quote!(DUMMY =>32).to_string(), "32");
256-
assert_eq!(quote!(DUMMY =>struct).to_string(), "struct");
258+
let dummy = *DUMMY;
259+
assert_eq!(quote!(dummy =>32).to_string(), "32");
260+
assert_eq!(quote!(dummy =>struct).to_string(), "struct");
257261
}
258262

259263
#[test]
260264
fn test_quote_hash_simple_literal() {
261265
let a = 20;
262-
assert_eq!(quote!(DUMMY =>#a).to_string(), "20");
266+
let dummy = *DUMMY;
267+
assert_eq!(quote!(dummy =>#a).to_string(), "20");
263268
let s: String = "hello".into();
264-
assert_eq!(quote!(DUMMY =>#s).to_string(), "\"hello\"");
269+
assert_eq!(quote!(dummy =>#s).to_string(), "\"hello\"");
265270
}
266271

267272
fn mk_ident(name: &str) -> crate::tt::Ident {
268273
let (is_raw, s) = IdentIsRaw::split_from_symbol(name);
269-
crate::tt::Ident { sym: Symbol::intern(s), span: DUMMY, is_raw }
274+
crate::tt::Ident { sym: Symbol::intern(s), span: *DUMMY, is_raw }
270275
}
271276

272277
#[test]
273278
fn test_quote_hash_token_tree() {
274279
let a = mk_ident("hello");
280+
let dummy = *DUMMY;
275281

276-
let quoted = quote!(DUMMY =>#a);
282+
let quoted = quote!(dummy =>#a);
277283
assert_eq!(quoted.to_string(), "hello");
278284
let t = format!("{quoted:#?}");
279285
expect![[r#"
@@ -286,7 +292,8 @@ mod tests {
286292
fn test_quote_simple_derive_copy() {
287293
let name = mk_ident("Foo");
288294

289-
let quoted = quote! {DUMMY =>
295+
let dummy = *DUMMY;
296+
let quoted = quote! {dummy =>
290297
impl Clone for #name {
291298
fn clone(&self) -> Self {
292299
Self {}
@@ -304,19 +311,20 @@ mod tests {
304311
// name: String,
305312
// id: u32,
306313
// }
314+
let dummy = *DUMMY;
307315
let struct_name = mk_ident("Foo");
308316
let fields = [mk_ident("name"), mk_ident("id")];
309-
let fields = fields.iter().map(|it| quote!(DUMMY =>#it: self.#it.clone(), ));
317+
let fields = fields.iter().map(|it| quote!(dummy =>#it: self.#it.clone(), ));
310318

311319
let mut builder = tt::TopSubtreeBuilder::new(crate::tt::Delimiter {
312320
kind: crate::tt::DelimiterKind::Brace,
313-
open: DUMMY,
314-
close: DUMMY,
321+
open: dummy,
322+
close: dummy,
315323
});
316324
fields.for_each(|field| builder.extend_with_tt(field.view().as_token_trees()));
317325
let list = builder.build();
318326

319-
let quoted = quote! {DUMMY =>
327+
let quoted = quote! {dummy =>
320328
impl Clone for #struct_name {
321329
fn clone(&self) -> Self {
322330
Self #list

crates/mbe/src/benchmark.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ fn benchmark_expand_macro_rules() {
5252
invocations
5353
.into_iter()
5454
.map(|(id, tt)| {
55-
let res = rules[&id].expand(&tt, |_| (), DUMMY, Edition::CURRENT);
55+
let res = rules[&id].expand(&tt, |_| (), *DUMMY, Edition::CURRENT);
5656
assert!(res.err.is_none());
5757
res.value.0.0.len()
5858
})
@@ -82,7 +82,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::TopSubtree<Span>> {
8282
let def_tt = syntax_node_to_token_tree(
8383
rule.token_tree().unwrap().syntax(),
8484
DummyTestSpanMap,
85-
DUMMY,
85+
*DUMMY,
8686
DocCommentDesugarMode::Mbe,
8787
);
8888
(id, def_tt)
@@ -114,16 +114,16 @@ fn invocation_fixtures(
114114
let mut try_cnt = 0;
115115
loop {
116116
let mut builder = tt::TopSubtreeBuilder::new(tt::Delimiter {
117-
open: DUMMY,
118-
close: DUMMY,
117+
open: *DUMMY,
118+
close: *DUMMY,
119119
kind: tt::DelimiterKind::Invisible,
120120
});
121121
for op in rule.lhs.iter() {
122122
collect_from_op(op, &mut builder, &mut seed);
123123
}
124124
let subtree = builder.build();
125125

126-
if it.expand(&subtree, |_| (), DUMMY, Edition::CURRENT).err.is_none() {
126+
if it.expand(&subtree, |_| (), *DUMMY, Edition::CURRENT).err.is_none() {
127127
res.push((name.clone(), subtree));
128128
break;
129129
}
@@ -227,25 +227,25 @@ fn invocation_fixtures(
227227
}
228228
fn make_ident(ident: &str) -> tt::Leaf<Span> {
229229
tt::Leaf::Ident(tt::Ident {
230-
span: DUMMY,
230+
span: *DUMMY,
231231
sym: Symbol::intern(ident),
232232
is_raw: tt::IdentIsRaw::No,
233233
})
234234
}
235235
fn make_punct(char: char) -> tt::Leaf<Span> {
236-
tt::Leaf::Punct(tt::Punct { span: DUMMY, char, spacing: tt::Spacing::Alone })
236+
tt::Leaf::Punct(tt::Punct { span: *DUMMY, char, spacing: tt::Spacing::Alone })
237237
}
238238
fn make_literal(lit: &str) -> tt::Leaf<Span> {
239239
tt::Leaf::Literal(tt::Literal {
240-
span: DUMMY,
240+
span: *DUMMY,
241241
symbol: Symbol::intern(lit),
242242
kind: tt::LitKind::Str,
243243
suffix: None,
244244
})
245245
}
246246
fn make_subtree(kind: tt::DelimiterKind, builder: &mut tt::TopSubtreeBuilder<Span>) {
247-
builder.open(kind, DUMMY);
248-
builder.close(DUMMY);
247+
builder.open(kind, *DUMMY);
248+
builder.close(*DUMMY);
249249
}
250250
}
251251
}

crates/rust-analyzer/src/target_spec.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ mod tests {
280280
let tt = syntax_node_to_token_tree(
281281
tt.syntax(),
282282
&DummyTestSpanMap,
283-
DUMMY,
283+
*DUMMY,
284284
DocCommentDesugarMode::Mbe,
285285
);
286286
CfgExpr::parse(&tt)

crates/span/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ impl EditionedFileId {
158158
self.0
159159
}
160160

161-
pub const fn file_id(self) -> FileId {
161+
pub fn file_id(self) -> FileId {
162162
FileId::from_raw(self.0 & Self::FILE_ID_MASK)
163163
}
164164

165-
pub const fn unpack(self) -> (FileId, Edition) {
165+
pub fn unpack(self) -> (FileId, Edition) {
166166
(self.file_id(), self.edition())
167167
}
168168

crates/syntax-bridge/src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ impl<S: Copy, SM: SpanMapper<S>> SpanMapper<S> for &SM {
4646
/// Dummy things for testing where spans don't matter.
4747
pub mod dummy_test_span_utils {
4848

49+
use std::sync::LazyLock;
50+
4951
use span::{Span, SyntaxContext};
5052

5153
use super::*;
5254

53-
pub const DUMMY: Span = Span {
55+
pub static DUMMY: LazyLock<Span> = LazyLock::new(|| Span {
5456
range: TextRange::empty(TextSize::new(0)),
5557
anchor: span::SpanAnchor {
5658
file_id: span::EditionedFileId::new(
@@ -60,7 +62,7 @@ pub mod dummy_test_span_utils {
6062
ast_id: span::ROOT_ERASED_FILE_AST_ID,
6163
},
6264
ctx: SyntaxContext::root(Edition::CURRENT),
63-
};
65+
});
6466

6567
pub struct DummyTestSpanMap;
6668

crates/syntax-bridge/src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn check_punct_spacing(fixture: &str) {
1515
let subtree = syntax_node_to_token_tree(
1616
source_file.syntax(),
1717
DummyTestSpanMap,
18-
DUMMY,
18+
*DUMMY,
1919
DocCommentDesugarMode::Mbe,
2020
);
2121
let mut annotations: FxHashMap<_, _> = extract_annotations(fixture)

crates/vfs/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ fst = "0.4.7"
1919
indexmap.workspace = true
2020
nohash-hasher.workspace = true
2121
crossbeam-channel.workspace = true
22+
salsa.workspace = true
23+
salsa-macros.workspace = true
2224

2325
paths.workspace = true
2426
stdx.workspace = true

crates/vfs/src/lib.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,22 +62,38 @@ use tracing::{Level, span};
6262
/// Handle to a file in [`Vfs`]
6363
///
6464
/// Most functions in rust-analyzer use this when they need to refer to a file.
65-
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
66-
pub struct FileId(u32);
67-
// pub struct FileId(NonMaxU32);
65+
#[salsa_macros::input]
66+
#[derive(Ord)]
67+
pub struct FileId {
68+
path: VfsPath,
69+
}
70+
71+
impl PartialOrd for FileId {
72+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
73+
self.0.as_u32().partial_cmp(&other.0.as_u32())
74+
}
75+
}
76+
77+
impl fmt::Debug for FileId {
78+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
79+
f.debug_tuple("FileId").field(&self.0.as_u32()).finish()
80+
}
81+
}
6882

6983
impl FileId {
7084
const MAX: u32 = 0x7fff_ffff;
7185

7286
#[inline]
73-
pub const fn from_raw(raw: u32) -> FileId {
87+
pub fn from_raw(raw: u32) -> FileId {
88+
use salsa::plumbing::FromId;
7489
assert!(raw <= Self::MAX);
75-
FileId(raw)
90+
let id = unsafe { salsa::Id::from_u32(raw) };
91+
FileId::from_id(id)
7692
}
7793

7894
#[inline]
7995
pub const fn index(self) -> u32 {
80-
self.0
96+
self.0.as_u32()
8197
}
8298
}
8399

@@ -199,7 +215,7 @@ impl Vfs {
199215
/// This will skip deleted files.
200216
pub fn iter(&self) -> impl Iterator<Item = (FileId, &VfsPath)> + '_ {
201217
(0..self.data.len())
202-
.map(|it| FileId(it as u32))
218+
.map(|it| FileId::from_raw(it as u32))
203219
.filter(move |&file_id| matches!(self.get(file_id), FileState::Exists(_)))
204220
.map(move |file_id| {
205221
let path = self.interner.lookup(file_id);
@@ -235,7 +251,7 @@ impl Vfs {
235251
};
236252

237253
let mut set_data = |change_kind| {
238-
self.data[file_id.0 as usize] = match change_kind {
254+
self.data[file_id.0.as_u32() as usize] = match change_kind {
239255
&Change::Create(_, hash) | &Change::Modify(_, hash) => FileState::Exists(hash),
240256
Change::Delete => FileState::Deleted,
241257
};
@@ -299,7 +315,7 @@ impl Vfs {
299315
/// Does not record a change.
300316
fn alloc_file_id(&mut self, path: VfsPath) -> FileId {
301317
let file_id = self.interner.intern(path);
302-
let idx = file_id.0 as usize;
318+
let idx = file_id.0.as_u32() as usize;
303319
let len = self.data.len().max(idx + 1);
304320
self.data.resize(len, FileState::Deleted);
305321
file_id
@@ -311,14 +327,14 @@ impl Vfs {
311327
///
312328
/// Panics if no file is associated to that id.
313329
fn get(&self, file_id: FileId) -> FileState {
314-
self.data[file_id.0 as usize]
330+
self.data[file_id.0.as_u32() as usize]
315331
}
316332

317333
/// We cannot ignore excluded files, because this will lead to errors when the client
318334
/// requests semantic information for them, so we instead mark them specially.
319335
pub fn insert_excluded_file(&mut self, path: VfsPath) {
320336
let file_id = self.alloc_file_id(path);
321-
self.data[file_id.0 as usize] = FileState::Excluded;
337+
self.data[file_id.0.as_u32() as usize] = FileState::Excluded;
322338
}
323339
}
324340

0 commit comments

Comments
 (0)