@@ -18,47 +18,89 @@ use rustc_hash::FxHasher;
1818use syntax:: { ast, AstNode , AstPtr , SyntaxNode , SyntaxNodePtr } ;
1919
2020/// `AstId` points to an AST node in a specific file.
21- pub struct FileAstId < N : AstNode > {
21+ pub struct FileAstId < N : AstIdNode > {
2222 raw : ErasedFileAstId ,
2323 covariant : PhantomData < fn ( ) -> N > ,
2424}
2525
26- impl < N : AstNode > Clone for FileAstId < N > {
26+ impl < N : AstIdNode > Clone for FileAstId < N > {
2727 fn clone ( & self ) -> FileAstId < N > {
2828 * self
2929 }
3030}
31- impl < N : AstNode > Copy for FileAstId < N > { }
31+ impl < N : AstIdNode > Copy for FileAstId < N > { }
3232
33- impl < N : AstNode > PartialEq for FileAstId < N > {
33+ impl < N : AstIdNode > PartialEq for FileAstId < N > {
3434 fn eq ( & self , other : & Self ) -> bool {
3535 self . raw == other. raw
3636 }
3737}
38- impl < N : AstNode > Eq for FileAstId < N > { }
39- impl < N : AstNode > Hash for FileAstId < N > {
38+ impl < N : AstIdNode > Eq for FileAstId < N > { }
39+ impl < N : AstIdNode > Hash for FileAstId < N > {
4040 fn hash < H : Hasher > ( & self , hasher : & mut H ) {
4141 self . raw . hash ( hasher) ;
4242 }
4343}
4444
45- impl < N : AstNode > fmt:: Debug for FileAstId < N > {
45+ impl < N : AstIdNode > fmt:: Debug for FileAstId < N > {
4646 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
4747 write ! ( f, "FileAstId::<{}>({})" , type_name:: <N >( ) , self . raw. into_raw( ) )
4848 }
4949}
5050
51- impl < N : AstNode > FileAstId < N > {
51+ impl < N : AstIdNode > FileAstId < N > {
5252 // Can't make this a From implementation because of coherence
53- pub fn upcast < M : AstNode > ( self ) -> FileAstId < M >
53+ pub fn upcast < M : AstIdNode > ( self ) -> FileAstId < M >
5454 where
5555 N : Into < M > ,
5656 {
5757 FileAstId { raw : self . raw , covariant : PhantomData }
5858 }
59+
60+ pub fn erase ( self ) -> ErasedFileAstId {
61+ self . raw
62+ }
5963}
6064
61- type ErasedFileAstId = Idx < SyntaxNodePtr > ;
65+ pub type ErasedFileAstId = Idx < SyntaxNodePtr > ;
66+
67+ pub trait AstIdNode : AstNode { }
68+ macro_rules! register_ast_id_node {
69+ ( impl AstIdNode for $( $ident: ident) ,+ ) => {
70+ $(
71+ impl AstIdNode for ast:: $ident { }
72+ ) +
73+ fn should_alloc_id( kind: syntax:: SyntaxKind ) -> bool {
74+ $(
75+ ast:: $ident:: can_cast( kind)
76+ ) ||+
77+ }
78+ } ;
79+ }
80+ register_ast_id_node ! {
81+ impl AstIdNode for
82+ Item ,
83+ Adt ,
84+ Enum ,
85+ Struct ,
86+ Union ,
87+ Const ,
88+ ExternBlock ,
89+ ExternCrate ,
90+ Fn ,
91+ Impl ,
92+ Macro ,
93+ MacroDef ,
94+ MacroRules ,
95+ MacroCall ,
96+ Module ,
97+ Static ,
98+ Trait ,
99+ TraitAlias ,
100+ TypeAlias ,
101+ Use ,
102+ AssocItem , BlockExpr , Variant , RecordField , TupleField , ConstArg
103+ }
62104
63105/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
64106#[ derive( Default ) ]
@@ -92,14 +134,7 @@ impl AstIdMap {
92134 // change parent's id. This means that, say, adding a new function to a
93135 // trait does not change ids of top-level items, which helps caching.
94136 bdfs ( node, |it| {
95- let kind = it. kind ( ) ;
96- if ast:: Item :: can_cast ( kind)
97- || ast:: BlockExpr :: can_cast ( kind)
98- || ast:: Variant :: can_cast ( kind)
99- || ast:: RecordField :: can_cast ( kind)
100- || ast:: TupleField :: can_cast ( kind)
101- || ast:: ConstArg :: can_cast ( kind)
102- {
137+ if should_alloc_id ( it. kind ( ) ) {
103138 res. alloc ( & it) ;
104139 true
105140 } else {
@@ -120,15 +155,19 @@ impl AstIdMap {
120155 res
121156 }
122157
123- pub fn ast_id < N : AstNode > ( & self , item : & N ) -> FileAstId < N > {
158+ pub fn ast_id < N : AstIdNode > ( & self , item : & N ) -> FileAstId < N > {
124159 let raw = self . erased_ast_id ( item. syntax ( ) ) ;
125160 FileAstId { raw, covariant : PhantomData }
126161 }
127162
128- pub fn get < N : AstNode > ( & self , id : FileAstId < N > ) -> AstPtr < N > {
163+ pub fn get < N : AstIdNode > ( & self , id : FileAstId < N > ) -> AstPtr < N > {
129164 AstPtr :: try_from_raw ( self . arena [ id. raw ] . clone ( ) ) . unwrap ( )
130165 }
131166
167+ pub ( crate ) fn get_raw ( & self , id : ErasedFileAstId ) -> SyntaxNodePtr {
168+ self . arena [ id] . clone ( )
169+ }
170+
132171 fn erased_ast_id ( & self , item : & SyntaxNode ) -> ErasedFileAstId {
133172 let ptr = SyntaxNodePtr :: new ( item) ;
134173 let hash = hash_ptr ( & ptr) ;
0 commit comments