Newtype ErasedFileAstId

This commit is contained in:
Lukas Wirth 2024-08-03 19:16:56 +02:00
parent fcb88832de
commit 188c577855
13 changed files with 52 additions and 39 deletions

3
Cargo.lock generated
View file

@ -1268,6 +1268,7 @@ name = "paths"
version = "0.0.0"
dependencies = [
"camino",
"serde",
]
[[package]]
@ -1330,14 +1331,12 @@ dependencies = [
"base-db",
"indexmap",
"intern",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"paths",
"rustc-hash",
"serde",
"serde_json",
"span",
"stdx",
"text-size",
"tracing",
"tt",
]

View file

@ -1,5 +1,5 @@
//! base_db defines basic database traits. The concrete DB is defined by ide.
// FIXME: Rename this crate, base db is non descriptive
mod change;
mod input;

View file

@ -13,13 +13,10 @@ doctest = false
[dependencies]
camino.workspace = true
# Adding this dep sadly puts a lot of rust-analyzer crates after the
# serde-derive crate. Even though we don't activate the derive feature here,
# someone else in the crate graph certainly does!
# serde.workspace = true
serde = { workspace = true, optional = true }
[features]
serde1 = ["camino/serde1"]
serde1 = ["camino/serde1", "dep:serde"]
[lints]
workspace = true

View file

@ -22,12 +22,11 @@ indexmap.workspace = true
paths = { workspace = true, features = ["serde1"] }
tt.workspace = true
stdx.workspace = true
text-size.workspace = true
span.workspace = true
# Ideally this crate would not depend on salsa things, but we need span information here which wraps
# InternIds for the syntax context
span.workspace = true
# only here due to the `Env` newtype :/
base-db.workspace = true
la-arena.workspace = true
intern.workspace = true
[lints]

View file

@ -158,9 +158,7 @@ type ProtocolWrite<W: Write> = for<'o, 'msg> fn(out: &'o mut W, msg: &'msg str)
#[cfg(test)]
mod tests {
use intern::{sym, Symbol};
use la_arena::RawIdx;
use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId};
use text_size::{TextRange, TextSize};
use span::{ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TextSize};
use tt::{Delimiter, DelimiterKind, Ident, Leaf, Literal, Punct, Spacing, Subtree, TokenTree};
use super::*;
@ -171,7 +169,7 @@ mod tests {
span::FileId::from_raw(0xe4e4e),
span::Edition::CURRENT,
),
ast_id: ErasedFileAstId::from_raw(RawIdx::from(0)),
ast_id: ErasedFileAstId::from_raw(0),
};
let token_trees = Box::new([

View file

@ -38,11 +38,9 @@
use std::collections::VecDeque;
use intern::Symbol;
use la_arena::RawIdx;
use rustc_hash::FxHashMap;
use serde::{Deserialize, Serialize};
use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId};
use text_size::TextRange;
use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange};
use crate::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA};
@ -54,7 +52,7 @@ pub fn serialize_span_data_index_map(map: &SpanDataIndexMap) -> Vec<u32> {
.flat_map(|span| {
[
span.anchor.file_id.as_u32(),
span.anchor.ast_id.into_raw().into_u32(),
span.anchor.ast_id.into_raw(),
span.range.start().into(),
span.range.end().into(),
span.ctx.into_u32(),
@ -71,7 +69,7 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
Span {
anchor: SpanAnchor {
file_id: EditionedFileId::from_raw(file_id),
ast_id: ErasedFileAstId::from_raw(RawIdx::from_u32(ast_id)),
ast_id: ErasedFileAstId::from_raw(ast_id),
},
range: TextRange::new(start.into(), end.into()),
ctx: SyntaxContextId::from_u32(e),

View file

@ -479,7 +479,7 @@ mod tests {
range: TextRange::empty(TextSize::new(0)),
anchor: span::SpanAnchor {
file_id: EditionedFileId::current_edition(FileId::from_raw(0)),
ast_id: span::ErasedFileAstId::from_raw(0.into()),
ast_id: span::ErasedFileAstId::from_raw(0),
},
ctx: SyntaxContextId::ROOT,
};
@ -515,7 +515,7 @@ mod tests {
range: TextRange::empty(TextSize::new(0)),
anchor: span::SpanAnchor {
file_id: EditionedFileId::current_edition(FileId::from_raw(0)),
ast_id: span::ErasedFileAstId::from_raw(0.into()),
ast_id: span::ErasedFileAstId::from_raw(0),
},
ctx: SyntaxContextId::ROOT,
};

View file

@ -69,7 +69,7 @@ fn assert_expand_impl(
range: TextRange::new(0.into(), 150.into()),
anchor: SpanAnchor {
file_id: EditionedFileId::current_edition(FileId::from_raw(41)),
ast_id: ErasedFileAstId::from_raw(From::from(1)),
ast_id: ErasedFileAstId::from_raw(1),
},
ctx: SyntaxContextId::ROOT,
};
@ -77,7 +77,7 @@ fn assert_expand_impl(
range: TextRange::new(0.into(), 100.into()),
anchor: SpanAnchor {
file_id: EditionedFileId::current_edition(FileId::from_raw(42)),
ast_id: ErasedFileAstId::from_raw(From::from(2)),
ast_id: ErasedFileAstId::from_raw(2),
},
ctx: SyntaxContextId::ROOT,
};

View file

@ -1084,7 +1084,6 @@ fn resolve_proc_macro() {
let sysroot = project_model::Sysroot::discover(
&AbsPathBuf::assert_utf8(std::env::current_dir().unwrap()),
&Default::default(),
false,
);
let proc_macro_server_path = sysroot.discover_proc_macro_srv().unwrap();
@ -1125,7 +1124,6 @@ edition = "2021"
proc-macro = true
//- /bar/src/lib.rs
extern crate proc_macro;
use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree};
macro_rules! t {
($n:literal) => {

View file

@ -18,7 +18,28 @@ use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr};
/// See crates\hir-expand\src\ast_id_map.rs
/// This is a type erased FileAstId.
pub type ErasedFileAstId = la_arena::Idx<syntax::SyntaxNodePtr>;
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ErasedFileAstId(u32);
impl ErasedFileAstId {
pub const fn into_raw(self) -> u32 {
self.0
}
pub const fn from_raw(u32: u32) -> Self {
Self(u32)
}
}
impl fmt::Display for ErasedFileAstId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl fmt::Debug for ErasedFileAstId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
/// `AstId` points to an AST node in a specific file.
pub struct FileAstId<N: AstIdNode> {
@ -47,7 +68,7 @@ impl<N: AstIdNode> Hash for FileAstId<N> {
impl<N: AstIdNode> fmt::Debug for FileAstId<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "FileAstId::<{}>({})", type_name::<N>(), self.raw.into_raw())
write!(f, "FileAstId::<{}>({})", type_name::<N>(), self.raw)
}
}
@ -176,7 +197,10 @@ impl AstIdMap {
let ptr = ptr.syntax_node_ptr();
let hash = hash_ptr(&ptr);
match self.map.raw_entry().from_hash(hash, |&idx| self.arena[idx] == ptr) {
Some((&raw, &())) => FileAstId { raw, covariant: PhantomData },
Some((&raw, &())) => FileAstId {
raw: ErasedFileAstId(raw.into_raw().into_u32()),
covariant: PhantomData,
},
None => panic!(
"Can't find {:?} in AstIdMap:\n{:?}",
ptr,
@ -186,18 +210,19 @@ impl AstIdMap {
}
pub fn get<N: AstIdNode>(&self, id: FileAstId<N>) -> AstPtr<N> {
AstPtr::try_from_raw(self.arena[id.raw]).unwrap()
AstPtr::try_from_raw(self.arena[Idx::from_raw(RawIdx::from_u32(id.raw.into_raw()))])
.unwrap()
}
pub fn get_erased(&self, id: ErasedFileAstId) -> SyntaxNodePtr {
self.arena[id]
self.arena[Idx::from_raw(RawIdx::from_u32(id.into_raw()))]
}
fn erased_ast_id(&self, item: &SyntaxNode) -> ErasedFileAstId {
let ptr = SyntaxNodePtr::new(item);
let hash = hash_ptr(&ptr);
match self.map.raw_entry().from_hash(hash, |&idx| self.arena[idx] == ptr) {
Some((&idx, &())) => idx,
Some((&idx, &())) => ErasedFileAstId(idx.into_raw().into_u32()),
None => panic!(
"Can't find {:?} in AstIdMap:\n{:?}",
item,
@ -207,7 +232,7 @@ impl AstIdMap {
}
fn alloc(&mut self, item: &SyntaxNode) -> ErasedFileAstId {
self.arena.alloc(SyntaxNodePtr::new(item))
ErasedFileAstId(self.arena.alloc(SyntaxNodePtr::new(item)).into_raw().into_u32())
}
}

View file

@ -21,15 +21,14 @@ pub use vfs::FileId;
/// The root ast id always points to the encompassing file, using this in spans is discouraged as
/// any range relative to it will be effectively absolute, ruining the entire point of anchored
/// relative text ranges.
pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId =
la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(0));
pub const ROOT_ERASED_FILE_AST_ID: ErasedFileAstId = ErasedFileAstId::from_raw(0);
/// FileId used as the span for syntax node fixups. Any Span containing this file id is to be
/// considered fake.
pub const FIXUP_ERASED_FILE_AST_ID_MARKER: ErasedFileAstId =
// we pick the second to last for this in case we every consider making this a NonMaxU32, this
// we pick the second to last for this in case we ever consider making this a NonMaxU32, this
// is required to be stable for the proc-macro-server
la_arena::Idx::from_raw(la_arena::RawIdx::from_u32(!0 - 1));
ErasedFileAstId::from_raw(!0 - 1);
pub type Span = SpanData<SyntaxContextId>;

View file

@ -119,7 +119,7 @@ impl fmt::Display for RealSpanMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "RealSpanMap({:?}):", self.file_id)?;
for span in self.pairs.iter() {
writeln!(f, "{}: {}", u32::from(span.0), span.1.into_raw().into_u32())?;
writeln!(f, "{}: {}", u32::from(span.0), span.1.into_raw())?;
}
Ok(())
}

View file

@ -3,7 +3,7 @@ use std::{iter, mem, str::FromStr, sync};
use base_db::{
CrateDisplayName, CrateGraph, CrateId, CrateName, CrateOrigin, Dependency, Env, FileChange,
FileSet, LangCrateOrigin, SourceRootDatabase, SourceRoot, Version, VfsPath,
FileSet, LangCrateOrigin, SourceRoot, SourceRootDatabase, Version, VfsPath,
};
use cfg::CfgOptions;
use hir_expand::{