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