Move AstIdMap infra to the span crate

This commit is contained in:
Lukas Wirth 2024-03-01 15:39:44 +01:00
parent 549aae7c07
commit efd76ecff1
14 changed files with 61 additions and 73 deletions

2
Cargo.lock generated
View file

@ -1855,7 +1855,9 @@ dependencies = [
name = "span" name = "span"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"hashbrown",
"la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-hash",
"salsa", "salsa",
"stdx", "stdx",
"syntax", "syntax",

View file

@ -6,7 +6,6 @@ use std::mem;
use base_db::CrateId; use base_db::CrateId;
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
ast_id_map::AstIdMap,
name::{name, AsName, Name}, name::{name, AsName, Name},
ExpandError, InFile, ExpandError, InFile,
}; };
@ -14,6 +13,7 @@ use intern::Interned;
use profile::Count; use profile::Count;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::AstIdMap;
use syntax::{ use syntax::{
ast::{ ast::{
self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName, self, ArrayExprKind, AstChildren, BlockExpr, HasArgList, HasAttrs, HasLoopBody, HasName,

View file

@ -47,18 +47,13 @@ use std::{
use ast::{AstNode, StructKind}; use ast::{AstNode, StructKind};
use base_db::CrateId; use base_db::CrateId;
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
ast_id_map::{AstIdNode, FileAstId},
attrs::RawAttrs,
name::Name,
ExpandTo, HirFileId, InFile,
};
use intern::Interned; use intern::Interned;
use la_arena::{Arena, Idx, IdxRange, RawIdx}; use la_arena::{Arena, Idx, IdxRange, RawIdx};
use profile::Count; use profile::Count;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::SmallVec; use smallvec::SmallVec;
use span::Span; use span::{AstIdNode, FileAstId, Span};
use stdx::never; use stdx::never;
use syntax::{ast, match_ast, SyntaxKind}; use syntax::{ast, match_ast, SyntaxKind};
use triomphe::Arc; use triomphe::Arc;

View file

@ -2,10 +2,9 @@
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use hir_expand::{ use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
ast_id_map::AstIdMap, mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId,
};
use la_arena::Arena; use la_arena::Arena;
use span::AstIdMap;
use syntax::{ use syntax::{
ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString}, ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
AstNode, AstNode,

View file

@ -76,7 +76,6 @@ use base_db::{
CrateId, Edition, CrateId, Edition,
}; };
use hir_expand::{ use hir_expand::{
ast_id_map::{AstIdNode, FileAstId},
builtin_attr_macro::BuiltinAttrExpander, builtin_attr_macro::BuiltinAttrExpander,
builtin_derive_macro::BuiltinDeriveExpander, builtin_derive_macro::BuiltinDeriveExpander,
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander}, builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@ -91,7 +90,7 @@ use hir_expand::{
use item_tree::ExternBlock; use item_tree::ExternBlock;
use la_arena::Idx; use la_arena::Idx;
use nameres::DefMap; use nameres::DefMap;
use span::{FileId, Span}; use span::{AstIdNode, FileAstId, FileId, Span};
use stdx::impl_from; use stdx::impl_from;
use syntax::{ast, AstNode}; use syntax::{ast, AstNode};

View file

@ -2,10 +2,10 @@
use std::cell::OnceCell; use std::cell::OnceCell;
use hir_expand::{ use hir_expand::{
ast_id_map::{AstIdMap, AstIdNode},
span_map::{SpanMap, SpanMapRef}, span_map::{SpanMap, SpanMapRef},
AstId, HirFileId, InFile, AstId, HirFileId, InFile,
}; };
use span::{AstIdMap, AstIdNode};
use syntax::ast; use syntax::ast;
use triomphe::Arc; use triomphe::Arc;

View file

@ -61,13 +61,13 @@ use std::ops::Deref;
use base_db::{CrateId, Edition, FileId}; use base_db::{CrateId, Edition, FileId};
use hir_expand::{ use hir_expand::{
ast_id_map::FileAstId, name::Name, proc_macro::ProcMacroKind, HirFileId, InFile, MacroCallId, name::Name, proc_macro::ProcMacroKind, HirFileId, InFile, MacroCallId, MacroDefId,
MacroDefId,
}; };
use itertools::Itertools; use itertools::Itertools;
use la_arena::Arena; use la_arena::Arena;
use profile::Count; use profile::Count;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::FileAstId;
use stdx::format_to; use stdx::format_to;
use syntax::{ast, SmolStr}; use syntax::{ast, SmolStr};
use triomphe::Arc; use triomphe::Arc;

View file

@ -9,7 +9,6 @@ use base_db::{CrateId, Dependency, Edition, FileId};
use cfg::{CfgExpr, CfgOptions}; use cfg::{CfgExpr, CfgOptions};
use either::Either; use either::Either;
use hir_expand::{ use hir_expand::{
ast_id_map::FileAstId,
attrs::{Attr, AttrId}, attrs::{Attr, AttrId},
builtin_attr_macro::{find_builtin_attr, BuiltinAttrExpander}, builtin_attr_macro::{find_builtin_attr, BuiltinAttrExpander},
builtin_derive_macro::find_builtin_derive, builtin_derive_macro::find_builtin_derive,
@ -23,7 +22,7 @@ use itertools::{izip, Itertools};
use la_arena::Idx; use la_arena::Idx;
use limit::Limit; use limit::Limit;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use span::{ErasedFileAstId, Span, SyntaxContextId}; use span::{ErasedFileAstId, FileAstId, Span, SyntaxContextId};
use stdx::always; use stdx::always;
use syntax::{ast, SmolStr}; use syntax::{ast, SmolStr};
use triomphe::Arc; use triomphe::Arc;

View file

@ -5,7 +5,7 @@ use either::Either;
use limit::Limit; use limit::Limit;
use mbe::{syntax_node_to_token_tree, ValueResult}; use mbe::{syntax_node_to_token_tree, ValueResult};
use rustc_hash::FxHashSet; use rustc_hash::FxHashSet;
use span::{SyntaxContextData, SyntaxContextId}; use span::{AstIdMap, SyntaxContextData, SyntaxContextId};
use syntax::{ use syntax::{
ast::{self, HasAttrs}, ast::{self, HasAttrs},
AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T, AstNode, Parse, SyntaxError, SyntaxNode, SyntaxToken, T,
@ -13,7 +13,6 @@ use syntax::{
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
ast_id_map::AstIdMap,
attrs::collect_attrs, attrs::collect_attrs,
builtin_attr_macro::pseudo_derive_attr_expansion, builtin_attr_macro::pseudo_derive_attr_expansion,
builtin_fn_macro::EagerExpander, builtin_fn_macro::EagerExpander,
@ -58,7 +57,6 @@ pub trait ExpandDatabase: SourceDatabase {
#[salsa::input] #[salsa::input]
fn proc_macros(&self) -> Arc<ProcMacros>; fn proc_macros(&self) -> Arc<ProcMacros>;
#[salsa::invoke(AstIdMap::new)]
fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>; fn ast_id_map(&self, file_id: HirFileId) -> Arc<AstIdMap>;
/// Main public API -- parses a hir file, not caring whether it's a real /// Main public API -- parses a hir file, not caring whether it's a real
@ -253,6 +251,10 @@ pub fn expand_speculative(
Some((node.syntax_node(), token)) Some((node.syntax_node(), token))
} }
fn ast_id_map(db: &dyn ExpandDatabase, file_id: span::HirFileId) -> triomphe::Arc<AstIdMap> {
triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id)))
}
fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode { fn parse_or_expand(db: &dyn ExpandDatabase, file_id: HirFileId) -> SyntaxNode {
match file_id.repr() { match file_id.repr() {
HirFileIdRepr::FileId(file_id) => db.parse(file_id).syntax_node(), HirFileIdRepr::FileId(file_id) => db.parse(file_id).syntax_node(),

View file

@ -2,10 +2,16 @@
use std::iter; use std::iter;
use either::Either; use either::Either;
use span::{FileId, FileRange, HirFileId, HirFileIdRepr, MacroFileId, SyntaxContextId}; use span::{
use syntax::{AstNode, SyntaxNode, SyntaxToken, TextRange, TextSize}; AstIdNode, ErasedFileAstId, FileAstId, FileId, FileRange, HirFileId, HirFileIdRepr,
MacroFileId, SyntaxContextId,
};
use syntax::{AstNode, AstPtr, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange, TextSize};
use crate::{db, map_node_range_up, span_for_offset, MacroFileIdExt}; use crate::{
db::{self, ExpandDatabase},
map_node_range_up, span_for_offset, MacroFileIdExt,
};
/// `InFile<T>` stores a value of `T` inside a particular file/syntax tree. /// `InFile<T>` stores a value of `T` inside a particular file/syntax tree.
/// ///
@ -23,6 +29,31 @@ pub type InFile<T> = InFileWrapper<HirFileId, T>;
pub type InMacroFile<T> = InFileWrapper<MacroFileId, T>; pub type InMacroFile<T> = InFileWrapper<MacroFileId, T>;
pub type InRealFile<T> = InFileWrapper<FileId, T>; pub type InRealFile<T> = InFileWrapper<FileId, T>;
/// `AstId` points to an AST node in any file.
///
/// It is stable across reparses, and can be used as salsa key/value.
pub type AstId<N> = crate::InFile<FileAstId<N>>;
impl<N: AstIdNode> AstId<N> {
pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
}
pub fn to_in_file_node(&self, db: &dyn ExpandDatabase) -> crate::InFile<N> {
crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)))
}
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> AstPtr<N> {
db.ast_id_map(self.file_id).get(self.value)
}
}
pub type ErasedAstId = crate::InFile<ErasedFileAstId>;
impl ErasedAstId {
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> SyntaxNodePtr {
db.ast_id_map(self.file_id).get_erased(self.value)
}
}
impl<FileKind, T> InFileWrapper<FileKind, T> { impl<FileKind, T> InFileWrapper<FileKind, T> {
pub fn new(file_id: FileKind, value: T) -> Self { pub fn new(file_id: FileKind, value: T) -> Self {
Self { file_id, value } Self { file_id, value }

View file

@ -6,7 +6,6 @@
#![warn(rust_2018_idioms, unused_lifetimes)] #![warn(rust_2018_idioms, unused_lifetimes)]
pub mod ast_id_map;
pub mod attrs; pub mod attrs;
pub mod builtin_attr_macro; pub mod builtin_attr_macro;
pub mod builtin_derive_macro; pub mod builtin_derive_macro;
@ -32,7 +31,7 @@ use std::{fmt, hash::Hash};
use base_db::{salsa::impl_intern_value_trivial, CrateId, Edition, FileId}; use base_db::{salsa::impl_intern_value_trivial, CrateId, Edition, FileId};
use either::Either; use either::Either;
use span::{FileRange, HirFileIdRepr, Span, SyntaxContextData, SyntaxContextId}; use span::{ErasedFileAstId, FileRange, HirFileIdRepr, Span, SyntaxContextData, SyntaxContextId};
use syntax::{ use syntax::{
ast::{self, AstNode}, ast::{self, AstNode},
SyntaxNode, SyntaxToken, TextRange, TextSize, SyntaxNode, SyntaxToken, TextRange, TextSize,
@ -49,8 +48,7 @@ use crate::{
span_map::{ExpansionSpanMap, SpanMap}, span_map::{ExpansionSpanMap, SpanMap},
}; };
pub use crate::ast_id_map::{AstId, ErasedAstId, ErasedFileAstId}; pub use crate::files::{AstId, ErasedAstId, InFile, InMacroFile, InRealFile};
pub use crate::files::{InFile, InMacroFile, InRealFile};
pub use mbe::ValueResult; pub use mbe::ValueResult;
pub use span::{HirFileId, MacroCallId, MacroFileId}; pub use span::{HirFileId, MacroCallId, MacroFileId};

View file

@ -12,7 +12,8 @@ authors.workspace = true
[dependencies] [dependencies]
la-arena.workspace = true la-arena.workspace = true
salsa.workspace = true salsa.workspace = true
rustc-hash.workspace = true
hashbrown.workspace = true
# local deps # local deps
vfs.workspace = true vfs.workspace = true

View file

@ -5,8 +5,6 @@
//! item as an ID. That way, id's don't change unless the set of items itself //! item as an ID. That way, id's don't change unless the set of items itself
//! changes. //! changes.
// FIXME: Consider moving this into the span crate
use std::{ use std::{
any::type_name, any::type_name,
fmt, fmt,
@ -15,38 +13,12 @@ use std::{
}; };
use la_arena::{Arena, Idx, RawIdx}; use la_arena::{Arena, Idx, RawIdx};
use profile::Count;
use rustc_hash::FxHasher; use rustc_hash::FxHasher;
use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr}; use syntax::{ast, AstNode, AstPtr, SyntaxNode, SyntaxNodePtr};
use crate::db::ExpandDatabase; /// See crates\hir-expand\src\ast_id_map.rs
/// This is a type erased FileAstId.
pub use span::ErasedFileAstId; pub type ErasedFileAstId = la_arena::Idx<syntax::SyntaxNodePtr>;
/// `AstId` points to an AST node in any file.
///
/// It is stable across reparses, and can be used as salsa key/value.
pub type AstId<N> = crate::InFile<FileAstId<N>>;
impl<N: AstIdNode> AstId<N> {
pub fn to_node(&self, db: &dyn ExpandDatabase) -> N {
self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
}
pub fn to_in_file_node(&self, db: &dyn ExpandDatabase) -> crate::InFile<N> {
crate::InFile::new(self.file_id, self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id)))
}
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> AstPtr<N> {
db.ast_id_map(self.file_id).get(self.value)
}
}
pub type ErasedAstId = crate::InFile<ErasedFileAstId>;
impl ErasedAstId {
pub fn to_ptr(&self, db: &dyn ExpandDatabase) -> SyntaxNodePtr {
db.ast_id_map(self.file_id).get_erased(self.value)
}
}
/// `AstId` points to an AST node in a specific file. /// `AstId` points to an AST node in a specific file.
pub struct FileAstId<N: AstIdNode> { pub struct FileAstId<N: AstIdNode> {
@ -138,7 +110,6 @@ pub struct AstIdMap {
arena: Arena<SyntaxNodePtr>, arena: Arena<SyntaxNodePtr>,
/// Reverse: map ptr to id. /// Reverse: map ptr to id.
map: hashbrown::HashMap<Idx<SyntaxNodePtr>, (), ()>, map: hashbrown::HashMap<Idx<SyntaxNodePtr>, (), ()>,
_c: Count<Self>,
} }
impl fmt::Debug for AstIdMap { impl fmt::Debug for AstIdMap {
@ -155,14 +126,7 @@ impl PartialEq for AstIdMap {
impl Eq for AstIdMap {} impl Eq for AstIdMap {}
impl AstIdMap { impl AstIdMap {
pub(crate) fn new( pub fn from_source(node: &SyntaxNode) -> AstIdMap {
db: &dyn ExpandDatabase,
file_id: span::HirFileId,
) -> triomphe::Arc<AstIdMap> {
triomphe::Arc::new(AstIdMap::from_source(&db.parse_or_expand(file_id)))
}
fn from_source(node: &SyntaxNode) -> AstIdMap {
assert!(node.parent().is_none()); assert!(node.parent().is_none());
let mut res = AstIdMap::default(); let mut res = AstIdMap::default();

View file

@ -3,10 +3,12 @@ use std::fmt::{self, Write};
use salsa::InternId; use salsa::InternId;
mod ast_id;
mod hygiene; mod hygiene;
mod map; mod map;
pub use self::{ pub use self::{
ast_id::{AstIdMap, AstIdNode, ErasedFileAstId, FileAstId},
hygiene::{SyntaxContextData, SyntaxContextId, Transparency}, hygiene::{SyntaxContextData, SyntaxContextId, Transparency},
map::{RealSpanMap, SpanMap}, map::{RealSpanMap, SpanMap},
}; };
@ -26,10 +28,6 @@ pub struct FileRange {
pub range: TextRange, pub range: TextRange,
} }
/// See crates\hir-expand\src\ast_id_map.rs
/// This is a type erased FileAstId.
pub type ErasedFileAstId = la_arena::Idx<syntax::SyntaxNodePtr>;
// The first index is always the root node's AstId // The first index is always the root node's AstId
/// The root ast id always points to the encompassing file, using this in spans is discouraged as /// 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 /// any range relative to it will be effectively absolute, ruining the entire point of anchored