]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/item_tree.rs
Merge #6924
[rust.git] / crates / hir_def / src / item_tree.rs
1 //! A simplified AST that only contains items.
2
3 mod lower;
4
5 use std::{
6     any::type_name,
7     fmt::{self, Debug},
8     hash::{Hash, Hasher},
9     marker::PhantomData,
10     ops::{Index, Range},
11     sync::Arc,
12 };
13
14 use arena::{Arena, Idx, RawId};
15 use ast::{AstNode, AttrsOwner, NameOwner, StructKind};
16 use base_db::CrateId;
17 use either::Either;
18 use hir_expand::{
19     ast_id_map::FileAstId,
20     hygiene::Hygiene,
21     name::{name, AsName, Name},
22     HirFileId, InFile,
23 };
24 use rustc_hash::FxHashMap;
25 use smallvec::SmallVec;
26 use syntax::{ast, match_ast};
27 use test_utils::mark;
28
29 use crate::{
30     attr::{Attrs, RawAttrs},
31     db::DefDatabase,
32     generics::GenericParams,
33     path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
34     type_ref::{Mutability, TypeBound, TypeRef},
35     visibility::RawVisibility,
36 };
37
38 #[derive(Copy, Clone, Eq, PartialEq)]
39 pub struct RawVisibilityId(u32);
40
41 impl RawVisibilityId {
42     pub const PUB: Self = RawVisibilityId(u32::max_value());
43     pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1);
44     pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2);
45 }
46
47 impl fmt::Debug for RawVisibilityId {
48     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49         let mut f = f.debug_tuple("RawVisibilityId");
50         match *self {
51             Self::PUB => f.field(&"pub"),
52             Self::PRIV => f.field(&"pub(self)"),
53             Self::PUB_CRATE => f.field(&"pub(crate)"),
54             _ => f.field(&self.0),
55         };
56         f.finish()
57     }
58 }
59
60 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
61 pub struct GenericParamsId(u32);
62
63 impl GenericParamsId {
64     pub const EMPTY: Self = GenericParamsId(u32::max_value());
65 }
66
67 /// The item tree of a source file.
68 #[derive(Debug, Eq, PartialEq)]
69 pub struct ItemTree {
70     top_level: SmallVec<[ModItem; 1]>,
71     attrs: FxHashMap<AttrOwner, RawAttrs>,
72     inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
73
74     data: Option<Box<ItemTreeData>>,
75 }
76
77 impl ItemTree {
78     pub fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
79         let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
80         let syntax = if let Some(node) = db.parse_or_expand(file_id) {
81             node
82         } else {
83             return Arc::new(Self::empty());
84         };
85
86         let hygiene = Hygiene::new(db.upcast(), file_id);
87         let ctx = lower::Ctx::new(db, hygiene.clone(), file_id);
88         let mut top_attrs = None;
89         let mut item_tree = match_ast! {
90             match syntax {
91                 ast::SourceFile(file) => {
92                     top_attrs = Some(RawAttrs::new(&file, &hygiene));
93                     ctx.lower_module_items(&file)
94                 },
95                 ast::MacroItems(items) => {
96                     ctx.lower_module_items(&items)
97                 },
98                 ast::MacroStmts(stmts) => {
99                     ctx.lower_inner_items(stmts.syntax())
100                 },
101                 // Macros can expand to expressions. We return an empty item tree in this case, but
102                 // still need to collect inner items.
103                 ast::Expr(e) => {
104                     ctx.lower_inner_items(e.syntax())
105                 },
106                 _ => {
107                     panic!("cannot create item tree from {:?}", syntax);
108                 },
109             }
110         };
111
112         if let Some(attrs) = top_attrs {
113             item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
114         }
115         item_tree.shrink_to_fit();
116         Arc::new(item_tree)
117     }
118
119     fn empty() -> Self {
120         Self {
121             top_level: Default::default(),
122             attrs: Default::default(),
123             inner_items: Default::default(),
124             data: Default::default(),
125         }
126     }
127
128     fn shrink_to_fit(&mut self) {
129         if let Some(data) = &mut self.data {
130             let ItemTreeData {
131                 imports,
132                 extern_crates,
133                 functions,
134                 structs,
135                 fields,
136                 unions,
137                 enums,
138                 variants,
139                 consts,
140                 statics,
141                 traits,
142                 impls,
143                 type_aliases,
144                 mods,
145                 macro_calls,
146                 macro_rules,
147                 macro_defs,
148                 exprs,
149                 vis,
150                 generics,
151             } = &mut **data;
152
153             imports.shrink_to_fit();
154             extern_crates.shrink_to_fit();
155             functions.shrink_to_fit();
156             structs.shrink_to_fit();
157             fields.shrink_to_fit();
158             unions.shrink_to_fit();
159             enums.shrink_to_fit();
160             variants.shrink_to_fit();
161             consts.shrink_to_fit();
162             statics.shrink_to_fit();
163             traits.shrink_to_fit();
164             impls.shrink_to_fit();
165             type_aliases.shrink_to_fit();
166             mods.shrink_to_fit();
167             macro_calls.shrink_to_fit();
168             macro_rules.shrink_to_fit();
169             macro_defs.shrink_to_fit();
170             exprs.shrink_to_fit();
171
172             vis.arena.shrink_to_fit();
173             generics.arena.shrink_to_fit();
174         }
175     }
176
177     /// Returns an iterator over all items located at the top level of the `HirFileId` this
178     /// `ItemTree` was created from.
179     pub fn top_level_items(&self) -> &[ModItem] {
180         &self.top_level
181     }
182
183     /// Returns the inner attributes of the source file.
184     pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
185         self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
186     }
187
188     pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
189         self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
190     }
191
192     pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
193         self.raw_attrs(of).clone().filter(db, krate)
194     }
195
196     /// Returns the lowered inner items that `ast` corresponds to.
197     ///
198     /// Most AST items are lowered to a single `ModItem`, but some (eg. `use` items) may be lowered
199     /// to multiple items in the `ItemTree`.
200     pub fn inner_items(&self, ast: FileAstId<ast::Item>) -> &[ModItem] {
201         &self.inner_items[&ast]
202     }
203
204     pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
205         self.inner_items.values().flatten().copied()
206     }
207
208     pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
209         // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty
210         // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with).
211         let root =
212             db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree");
213
214         let id = self[of.value].ast_id();
215         let map = db.ast_id_map(of.file_id);
216         let ptr = map.get(id);
217         ptr.to_node(&root)
218     }
219
220     fn data(&self) -> &ItemTreeData {
221         self.data.as_ref().expect("attempted to access data of empty ItemTree")
222     }
223
224     fn data_mut(&mut self) -> &mut ItemTreeData {
225         self.data.get_or_insert_with(Box::default)
226     }
227 }
228
229 #[derive(Default, Debug, Eq, PartialEq)]
230 struct ItemVisibilities {
231     arena: Arena<RawVisibility>,
232 }
233
234 impl ItemVisibilities {
235     fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
236         match &vis {
237             RawVisibility::Public => RawVisibilityId::PUB,
238             RawVisibility::Module(path) if path.segments.is_empty() => match &path.kind {
239                 PathKind::Super(0) => RawVisibilityId::PRIV,
240                 PathKind::Crate => RawVisibilityId::PUB_CRATE,
241                 _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
242             },
243             _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
244         }
245     }
246 }
247
248 static VIS_PUB: RawVisibility = RawVisibility::Public;
249 static VIS_PRIV: RawVisibility =
250     RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() });
251 static VIS_PUB_CRATE: RawVisibility =
252     RawVisibility::Module(ModPath { kind: PathKind::Crate, segments: Vec::new() });
253
254 #[derive(Default, Debug, Eq, PartialEq)]
255 struct GenericParamsStorage {
256     arena: Arena<GenericParams>,
257 }
258
259 impl GenericParamsStorage {
260     fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
261         if params.types.is_empty()
262             && params.lifetimes.is_empty()
263             && params.where_predicates.is_empty()
264         {
265             return GenericParamsId::EMPTY;
266         }
267
268         GenericParamsId(self.arena.alloc(params).into_raw().into())
269     }
270 }
271
272 static EMPTY_GENERICS: GenericParams =
273     GenericParams { types: Arena::new(), lifetimes: Arena::new(), where_predicates: Vec::new() };
274
275 #[derive(Default, Debug, Eq, PartialEq)]
276 struct ItemTreeData {
277     imports: Arena<Import>,
278     extern_crates: Arena<ExternCrate>,
279     functions: Arena<Function>,
280     structs: Arena<Struct>,
281     fields: Arena<Field>,
282     unions: Arena<Union>,
283     enums: Arena<Enum>,
284     variants: Arena<Variant>,
285     consts: Arena<Const>,
286     statics: Arena<Static>,
287     traits: Arena<Trait>,
288     impls: Arena<Impl>,
289     type_aliases: Arena<TypeAlias>,
290     mods: Arena<Mod>,
291     macro_calls: Arena<MacroCall>,
292     macro_rules: Arena<MacroRules>,
293     macro_defs: Arena<MacroDef>,
294     exprs: Arena<Expr>,
295
296     vis: ItemVisibilities,
297     generics: GenericParamsStorage,
298 }
299
300 #[derive(Debug, Eq, PartialEq, Hash)]
301 pub enum AttrOwner {
302     /// Attributes on an item.
303     ModItem(ModItem),
304     /// Inner attributes of the source file.
305     TopLevel,
306
307     Variant(Idx<Variant>),
308     Field(Idx<Field>),
309 }
310
311 macro_rules! from_attrs {
312     ( $( $var:ident($t:ty) ),+ ) => {
313         $(
314             impl From<$t> for AttrOwner {
315                 fn from(t: $t) -> AttrOwner {
316                     AttrOwner::$var(t)
317                 }
318             }
319         )+
320     };
321 }
322
323 from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>));
324
325 /// Trait implemented by all item nodes in the item tree.
326 pub trait ItemTreeNode: Clone {
327     type Source: AstNode + Into<ast::Item>;
328
329     fn ast_id(&self) -> FileAstId<Self::Source>;
330
331     /// Looks up an instance of `Self` in an item tree.
332     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
333
334     /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
335     fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
336
337     /// Upcasts a `FileItemTreeId` to a generic `ModItem`.
338     fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
339 }
340
341 pub struct FileItemTreeId<N: ItemTreeNode> {
342     index: Idx<N>,
343     _p: PhantomData<N>,
344 }
345
346 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
347     fn clone(&self) -> Self {
348         Self { index: self.index, _p: PhantomData }
349     }
350 }
351 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
352
353 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
354     fn eq(&self, other: &FileItemTreeId<N>) -> bool {
355         self.index == other.index
356     }
357 }
358 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
359
360 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
361     fn hash<H: Hasher>(&self, state: &mut H) {
362         self.index.hash(state)
363     }
364 }
365
366 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
367     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
368         self.index.fmt(f)
369     }
370 }
371
372 pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>;
373
374 macro_rules! mod_items {
375     ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
376         #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
377         pub enum ModItem {
378             $(
379                 $typ(FileItemTreeId<$typ>),
380             )+
381         }
382
383         $(
384             impl From<FileItemTreeId<$typ>> for ModItem {
385                 fn from(id: FileItemTreeId<$typ>) -> ModItem {
386                     ModItem::$typ(id)
387                 }
388             }
389         )+
390
391         $(
392             impl ItemTreeNode for $typ {
393                 type Source = $ast;
394
395                 fn ast_id(&self) -> FileAstId<Self::Source> {
396                     self.ast_id
397                 }
398
399                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
400                     &tree.data().$fld[index]
401                 }
402
403                 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
404                     if let ModItem::$typ(id) = mod_item {
405                         Some(id)
406                     } else {
407                         None
408                     }
409                 }
410
411                 fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
412                     ModItem::$typ(id)
413                 }
414             }
415
416             impl Index<Idx<$typ>> for ItemTree {
417                 type Output = $typ;
418
419                 fn index(&self, index: Idx<$typ>) -> &Self::Output {
420                     &self.data().$fld[index]
421                 }
422             }
423         )+
424     };
425 }
426
427 mod_items! {
428     Import in imports -> ast::Use,
429     ExternCrate in extern_crates -> ast::ExternCrate,
430     Function in functions -> ast::Fn,
431     Struct in structs -> ast::Struct,
432     Union in unions -> ast::Union,
433     Enum in enums -> ast::Enum,
434     Const in consts -> ast::Const,
435     Static in statics -> ast::Static,
436     Trait in traits -> ast::Trait,
437     Impl in impls -> ast::Impl,
438     TypeAlias in type_aliases -> ast::TypeAlias,
439     Mod in mods -> ast::Module,
440     MacroCall in macro_calls -> ast::MacroCall,
441     MacroRules in macro_rules -> ast::MacroRules,
442     MacroDef in macro_defs -> ast::MacroDef,
443 }
444
445 macro_rules! impl_index {
446     ( $($fld:ident: $t:ty),+ $(,)? ) => {
447         $(
448             impl Index<Idx<$t>> for ItemTree {
449                 type Output = $t;
450
451                 fn index(&self, index: Idx<$t>) -> &Self::Output {
452                     &self.data().$fld[index]
453                 }
454             }
455         )+
456     };
457 }
458
459 impl_index!(fields: Field, variants: Variant, exprs: Expr);
460
461 impl Index<RawVisibilityId> for ItemTree {
462     type Output = RawVisibility;
463     fn index(&self, index: RawVisibilityId) -> &Self::Output {
464         match index {
465             RawVisibilityId::PRIV => &VIS_PRIV,
466             RawVisibilityId::PUB => &VIS_PUB,
467             RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE,
468             _ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
469         }
470     }
471 }
472
473 impl Index<GenericParamsId> for ItemTree {
474     type Output = GenericParams;
475
476     fn index(&self, index: GenericParamsId) -> &Self::Output {
477         match index {
478             GenericParamsId::EMPTY => &EMPTY_GENERICS,
479             _ => &self.data().generics.arena[Idx::from_raw(index.0.into())],
480         }
481     }
482 }
483
484 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
485     type Output = N;
486     fn index(&self, id: FileItemTreeId<N>) -> &N {
487         N::lookup(self, id.index)
488     }
489 }
490
491 /// A desugared `use` import.
492 #[derive(Debug, Clone, Eq, PartialEq)]
493 pub struct Import {
494     pub path: ModPath,
495     pub alias: Option<ImportAlias>,
496     pub visibility: RawVisibilityId,
497     pub is_glob: bool,
498     pub is_prelude: bool,
499     /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
500     /// `Import`s can map to the same `use` item.
501     pub ast_id: FileAstId<ast::Use>,
502     /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`.
503     ///
504     /// This can be used to get the `UseTree` this `Import` corresponds to and allows emitting
505     /// precise diagnostics.
506     pub index: usize,
507 }
508
509 #[derive(Debug, Clone, Eq, PartialEq)]
510 pub struct ExternCrate {
511     pub name: Name,
512     pub alias: Option<ImportAlias>,
513     pub visibility: RawVisibilityId,
514     /// Whether this is a `#[macro_use] extern crate ...`.
515     pub is_macro_use: bool,
516     pub ast_id: FileAstId<ast::ExternCrate>,
517 }
518
519 #[derive(Debug, Clone, Eq, PartialEq)]
520 pub struct Function {
521     pub name: Name,
522     pub visibility: RawVisibilityId,
523     pub generic_params: GenericParamsId,
524     pub has_self_param: bool,
525     pub has_body: bool,
526     pub is_unsafe: bool,
527     /// Whether the function is located in an `extern` block (*not* whether it is an
528     /// `extern "abi" fn`).
529     pub is_extern: bool,
530     pub params: Box<[TypeRef]>,
531     pub is_varargs: bool,
532     pub ret_type: TypeRef,
533     pub ast_id: FileAstId<ast::Fn>,
534 }
535
536 #[derive(Debug, Clone, Eq, PartialEq)]
537 pub struct Struct {
538     pub name: Name,
539     pub visibility: RawVisibilityId,
540     pub generic_params: GenericParamsId,
541     pub fields: Fields,
542     pub ast_id: FileAstId<ast::Struct>,
543     pub kind: StructDefKind,
544 }
545
546 #[derive(Debug, Clone, Eq, PartialEq)]
547 pub enum StructDefKind {
548     /// `struct S { ... }` - type namespace only.
549     Record,
550     /// `struct S(...);`
551     Tuple,
552     /// `struct S;`
553     Unit,
554 }
555
556 #[derive(Debug, Clone, Eq, PartialEq)]
557 pub struct Union {
558     pub name: Name,
559     pub visibility: RawVisibilityId,
560     pub generic_params: GenericParamsId,
561     pub fields: Fields,
562     pub ast_id: FileAstId<ast::Union>,
563 }
564
565 #[derive(Debug, Clone, Eq, PartialEq)]
566 pub struct Enum {
567     pub name: Name,
568     pub visibility: RawVisibilityId,
569     pub generic_params: GenericParamsId,
570     pub variants: IdRange<Variant>,
571     pub ast_id: FileAstId<ast::Enum>,
572 }
573
574 #[derive(Debug, Clone, Eq, PartialEq)]
575 pub struct Const {
576     /// const _: () = ();
577     pub name: Option<Name>,
578     pub visibility: RawVisibilityId,
579     pub type_ref: TypeRef,
580     pub ast_id: FileAstId<ast::Const>,
581 }
582
583 #[derive(Debug, Clone, Eq, PartialEq)]
584 pub struct Static {
585     pub name: Name,
586     pub visibility: RawVisibilityId,
587     pub mutable: bool,
588     /// Whether the static is in an `extern` block.
589     pub is_extern: bool,
590     pub type_ref: TypeRef,
591     pub ast_id: FileAstId<ast::Static>,
592 }
593
594 #[derive(Debug, Clone, Eq, PartialEq)]
595 pub struct Trait {
596     pub name: Name,
597     pub visibility: RawVisibilityId,
598     pub generic_params: GenericParamsId,
599     pub auto: bool,
600     pub items: Box<[AssocItem]>,
601     pub ast_id: FileAstId<ast::Trait>,
602 }
603
604 #[derive(Debug, Clone, Eq, PartialEq)]
605 pub struct Impl {
606     pub generic_params: GenericParamsId,
607     pub target_trait: Option<TypeRef>,
608     pub target_type: TypeRef,
609     pub is_negative: bool,
610     pub items: Box<[AssocItem]>,
611     pub ast_id: FileAstId<ast::Impl>,
612 }
613
614 #[derive(Debug, Clone, PartialEq, Eq)]
615 pub struct TypeAlias {
616     pub name: Name,
617     pub visibility: RawVisibilityId,
618     /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
619     pub bounds: Box<[TypeBound]>,
620     pub generic_params: GenericParamsId,
621     pub type_ref: Option<TypeRef>,
622     pub is_extern: bool,
623     pub ast_id: FileAstId<ast::TypeAlias>,
624 }
625
626 #[derive(Debug, Clone, Eq, PartialEq)]
627 pub struct Mod {
628     pub name: Name,
629     pub visibility: RawVisibilityId,
630     pub kind: ModKind,
631     pub ast_id: FileAstId<ast::Module>,
632 }
633
634 #[derive(Debug, Clone, Eq, PartialEq)]
635 pub enum ModKind {
636     /// `mod m { ... }`
637     Inline { items: Box<[ModItem]> },
638
639     /// `mod m;`
640     Outline {},
641 }
642
643 #[derive(Debug, Clone, Eq, PartialEq)]
644 pub struct MacroCall {
645     /// Path to the called macro.
646     pub path: ModPath,
647     pub ast_id: FileAstId<ast::MacroCall>,
648 }
649
650 #[derive(Debug, Clone, Eq, PartialEq)]
651 pub struct MacroRules {
652     /// The name of the declared macro.
653     pub name: Name,
654     pub ast_id: FileAstId<ast::MacroRules>,
655 }
656
657 /// "Macros 2.0" macro definition.
658 #[derive(Debug, Clone, Eq, PartialEq)]
659 pub struct MacroDef {
660     pub name: Name,
661     pub visibility: RawVisibilityId,
662     pub ast_id: FileAstId<ast::MacroDef>,
663 }
664
665 // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
666 // lengths, but we don't do much with them yet.
667 #[derive(Debug, Clone, Eq, PartialEq)]
668 pub struct Expr;
669
670 macro_rules! impl_froms {
671     ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
672         $(
673             impl From<$t> for $e {
674                 fn from(it: $t) -> $e {
675                     $e::$v(it)
676                 }
677             }
678         )*
679     }
680 }
681
682 impl ModItem {
683     pub fn as_assoc_item(&self) -> Option<AssocItem> {
684         match self {
685             ModItem::Import(_)
686             | ModItem::ExternCrate(_)
687             | ModItem::Struct(_)
688             | ModItem::Union(_)
689             | ModItem::Enum(_)
690             | ModItem::Static(_)
691             | ModItem::Trait(_)
692             | ModItem::Impl(_)
693             | ModItem::Mod(_)
694             | ModItem::MacroRules(_)
695             | ModItem::MacroDef(_) => None,
696             ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
697             ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
698             ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
699             ModItem::Function(func) => Some(AssocItem::Function(*func)),
700         }
701     }
702
703     pub fn downcast<N: ItemTreeNode>(self) -> Option<FileItemTreeId<N>> {
704         N::id_from_mod_item(self)
705     }
706
707     pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
708         match self {
709             ModItem::Import(it) => tree[it.index].ast_id().upcast(),
710             ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
711             ModItem::Function(it) => tree[it.index].ast_id().upcast(),
712             ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
713             ModItem::Union(it) => tree[it.index].ast_id().upcast(),
714             ModItem::Enum(it) => tree[it.index].ast_id().upcast(),
715             ModItem::Const(it) => tree[it.index].ast_id().upcast(),
716             ModItem::Static(it) => tree[it.index].ast_id().upcast(),
717             ModItem::Trait(it) => tree[it.index].ast_id().upcast(),
718             ModItem::Impl(it) => tree[it.index].ast_id().upcast(),
719             ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
720             ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
721             ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
722             ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
723             ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
724         }
725     }
726 }
727
728 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
729 pub enum AssocItem {
730     Function(FileItemTreeId<Function>),
731     TypeAlias(FileItemTreeId<TypeAlias>),
732     Const(FileItemTreeId<Const>),
733     MacroCall(FileItemTreeId<MacroCall>),
734 }
735
736 impl_froms!(AssocItem {
737     Function(FileItemTreeId<Function>),
738     TypeAlias(FileItemTreeId<TypeAlias>),
739     Const(FileItemTreeId<Const>),
740     MacroCall(FileItemTreeId<MacroCall>),
741 });
742
743 impl From<AssocItem> for ModItem {
744     fn from(item: AssocItem) -> Self {
745         match item {
746             AssocItem::Function(it) => it.into(),
747             AssocItem::TypeAlias(it) => it.into(),
748             AssocItem::Const(it) => it.into(),
749             AssocItem::MacroCall(it) => it.into(),
750         }
751     }
752 }
753
754 #[derive(Debug, Eq, PartialEq)]
755 pub struct Variant {
756     pub name: Name,
757     pub fields: Fields,
758 }
759
760 pub struct IdRange<T> {
761     range: Range<u32>,
762     _p: PhantomData<T>,
763 }
764
765 impl<T> IdRange<T> {
766     fn new(range: Range<Idx<T>>) -> Self {
767         Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData }
768     }
769 }
770
771 impl<T> Iterator for IdRange<T> {
772     type Item = Idx<T>;
773     fn next(&mut self) -> Option<Self::Item> {
774         self.range.next().map(|raw| Idx::from_raw(raw.into()))
775     }
776 }
777
778 impl<T> fmt::Debug for IdRange<T> {
779     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
780         f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish()
781     }
782 }
783
784 impl<T> Clone for IdRange<T> {
785     fn clone(&self) -> Self {
786         Self { range: self.range.clone(), _p: PhantomData }
787     }
788 }
789
790 impl<T> PartialEq for IdRange<T> {
791     fn eq(&self, other: &Self) -> bool {
792         self.range == other.range
793     }
794 }
795
796 impl<T> Eq for IdRange<T> {}
797
798 #[derive(Debug, Clone, PartialEq, Eq)]
799 pub enum Fields {
800     Record(IdRange<Field>),
801     Tuple(IdRange<Field>),
802     Unit,
803 }
804
805 /// A single field of an enum variant or struct
806 #[derive(Debug, Clone, PartialEq, Eq)]
807 pub struct Field {
808     pub name: Name,
809     pub type_ref: TypeRef,
810     pub visibility: RawVisibilityId,
811 }