]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/item_tree.rs
Use block_def_map in body lowering
[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, SyntaxKind};
28 use test_utils::mark;
29
30 use crate::{
31     attr::{Attrs, RawAttrs},
32     db::DefDatabase,
33     generics::GenericParams,
34     path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
35     type_ref::{Mutability, TypeBound, TypeRef},
36     visibility::RawVisibility,
37 };
38
39 #[derive(Copy, Clone, Eq, PartialEq)]
40 pub struct RawVisibilityId(u32);
41
42 impl RawVisibilityId {
43     pub const PUB: Self = RawVisibilityId(u32::max_value());
44     pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1);
45     pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2);
46 }
47
48 impl fmt::Debug for RawVisibilityId {
49     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50         let mut f = f.debug_tuple("RawVisibilityId");
51         match *self {
52             Self::PUB => f.field(&"pub"),
53             Self::PRIV => f.field(&"pub(self)"),
54             Self::PUB_CRATE => f.field(&"pub(crate)"),
55             _ => f.field(&self.0),
56         };
57         f.finish()
58     }
59 }
60
61 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
62 pub struct GenericParamsId(u32);
63
64 impl GenericParamsId {
65     pub const EMPTY: Self = GenericParamsId(u32::max_value());
66 }
67
68 /// The item tree of a source file.
69 #[derive(Debug, Default, Eq, PartialEq)]
70 pub struct ItemTree {
71     _c: Count<Self>,
72
73     top_level: SmallVec<[ModItem; 1]>,
74     attrs: FxHashMap<AttrOwner, RawAttrs>,
75
76     data: Option<Box<ItemTreeData>>,
77 }
78
79 impl ItemTree {
80     pub(crate) fn item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
81         let _p = profile::span("item_tree_query").detail(|| format!("{:?}", file_id));
82         let syntax = if let Some(node) = db.parse_or_expand(file_id) {
83             if node.kind() == SyntaxKind::ERROR {
84                 // FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic
85                 return Default::default();
86             }
87             node
88         } else {
89             return Default::default();
90         };
91
92         let hygiene = Hygiene::new(db.upcast(), file_id);
93         let ctx = lower::Ctx::new(db, hygiene.clone(), file_id);
94         let mut top_attrs = None;
95         let mut item_tree = match_ast! {
96             match syntax {
97                 ast::SourceFile(file) => {
98                     top_attrs = Some(RawAttrs::new(&file, &hygiene));
99                     ctx.lower_module_items(&file)
100                 },
101                 ast::MacroItems(items) => {
102                     ctx.lower_module_items(&items)
103                 },
104                 ast::MacroStmts(stmts) => {
105                     // The produced statements can include items, which should be added as top-level
106                     // items.
107                     ctx.lower_macro_stmts(stmts)
108                 },
109                 ast::Expr(e) => {
110                     // Macros can expand to expressions. We return an empty item tree in this case, but
111                     // still need to collect inner items.
112                     ctx.lower_inner_items(e.syntax())
113                 },
114                 _ => {
115                     panic!("cannot create item tree from {:?} {}", syntax, syntax);
116                 },
117             }
118         };
119
120         if let Some(attrs) = top_attrs {
121             item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
122         }
123         item_tree.shrink_to_fit();
124         Arc::new(item_tree)
125     }
126
127     fn shrink_to_fit(&mut self) {
128         if let Some(data) = &mut self.data {
129             let ItemTreeData {
130                 imports,
131                 extern_crates,
132                 functions,
133                 structs,
134                 fields,
135                 unions,
136                 enums,
137                 variants,
138                 consts,
139                 statics,
140                 traits,
141                 impls,
142                 type_aliases,
143                 mods,
144                 macro_calls,
145                 macro_rules,
146                 macro_defs,
147                 vis,
148                 generics,
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
173             inner_items.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     pub fn all_inner_items(&self) -> impl Iterator<Item = ModItem> + '_ {
197         match &self.data {
198             Some(data) => Some(data.inner_items.values().flatten().copied()).into_iter().flatten(),
199             None => None.into_iter().flatten(),
200         }
201     }
202
203     pub fn inner_items_of_block(&self, block: FileAstId<ast::BlockExpr>) -> &[ModItem] {
204         match &self.data {
205             Some(data) => data.inner_items.get(&block).map(|it| &**it).unwrap_or(&[]),
206             None => &[],
207         }
208     }
209
210     pub fn source<S: ItemTreeNode>(&self, db: &dyn DefDatabase, of: ItemTreeId<S>) -> S::Source {
211         // This unwrap cannot fail, since it has either succeeded above, or resulted in an empty
212         // ItemTree (in which case there is no valid `FileItemTreeId` to call this method with).
213         let root =
214             db.parse_or_expand(of.file_id).expect("parse_or_expand failed on constructed ItemTree");
215
216         let id = self[of.value].ast_id();
217         let map = db.ast_id_map(of.file_id);
218         let ptr = map.get(id);
219         ptr.to_node(&root)
220     }
221
222     fn data(&self) -> &ItemTreeData {
223         self.data.as_ref().expect("attempted to access data of empty ItemTree")
224     }
225
226     fn data_mut(&mut self) -> &mut ItemTreeData {
227         self.data.get_or_insert_with(Box::default)
228     }
229 }
230
231 #[derive(Default, Debug, Eq, PartialEq)]
232 struct ItemVisibilities {
233     arena: Arena<RawVisibility>,
234 }
235
236 impl ItemVisibilities {
237     fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
238         match &vis {
239             RawVisibility::Public => RawVisibilityId::PUB,
240             RawVisibility::Module(path) if path.segments.is_empty() => match &path.kind {
241                 PathKind::Super(0) => RawVisibilityId::PRIV,
242                 PathKind::Crate => RawVisibilityId::PUB_CRATE,
243                 _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
244             },
245             _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
246         }
247     }
248 }
249
250 static VIS_PUB: RawVisibility = RawVisibility::Public;
251 static VIS_PRIV: RawVisibility =
252     RawVisibility::Module(ModPath { kind: PathKind::Super(0), segments: Vec::new() });
253 static VIS_PUB_CRATE: RawVisibility =
254     RawVisibility::Module(ModPath { kind: PathKind::Crate, segments: Vec::new() });
255
256 #[derive(Default, Debug, Eq, PartialEq)]
257 struct GenericParamsStorage {
258     arena: Arena<GenericParams>,
259 }
260
261 impl GenericParamsStorage {
262     fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
263         if params.types.is_empty()
264             && params.lifetimes.is_empty()
265             && params.consts.is_empty()
266             && params.where_predicates.is_empty()
267         {
268             return GenericParamsId::EMPTY;
269         }
270
271         GenericParamsId(self.arena.alloc(params).into_raw().into())
272     }
273 }
274
275 static EMPTY_GENERICS: GenericParams = GenericParams {
276     types: Arena::new(),
277     lifetimes: Arena::new(),
278     consts: Arena::new(),
279     where_predicates: Vec::new(),
280 };
281
282 #[derive(Default, Debug, Eq, PartialEq)]
283 struct ItemTreeData {
284     imports: Arena<Import>,
285     extern_crates: Arena<ExternCrate>,
286     functions: Arena<Function>,
287     structs: Arena<Struct>,
288     fields: Arena<Field>,
289     unions: Arena<Union>,
290     enums: Arena<Enum>,
291     variants: Arena<Variant>,
292     consts: Arena<Const>,
293     statics: Arena<Static>,
294     traits: Arena<Trait>,
295     impls: Arena<Impl>,
296     type_aliases: Arena<TypeAlias>,
297     mods: Arena<Mod>,
298     macro_calls: Arena<MacroCall>,
299     macro_rules: Arena<MacroRules>,
300     macro_defs: Arena<MacroDef>,
301
302     vis: ItemVisibilities,
303     generics: GenericParamsStorage,
304
305     inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
306 }
307
308 #[derive(Debug, Eq, PartialEq, Hash)]
309 pub enum AttrOwner {
310     /// Attributes on an item.
311     ModItem(ModItem),
312     /// Inner attributes of the source file.
313     TopLevel,
314
315     Variant(Idx<Variant>),
316     Field(Idx<Field>),
317 }
318
319 macro_rules! from_attrs {
320     ( $( $var:ident($t:ty) ),+ ) => {
321         $(
322             impl From<$t> for AttrOwner {
323                 fn from(t: $t) -> AttrOwner {
324                     AttrOwner::$var(t)
325                 }
326             }
327         )+
328     };
329 }
330
331 from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>));
332
333 /// Trait implemented by all item nodes in the item tree.
334 pub trait ItemTreeNode: Clone {
335     type Source: AstNode + Into<ast::Item>;
336
337     fn ast_id(&self) -> FileAstId<Self::Source>;
338
339     /// Looks up an instance of `Self` in an item tree.
340     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
341
342     /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
343     fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
344
345     /// Upcasts a `FileItemTreeId` to a generic `ModItem`.
346     fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
347 }
348
349 pub struct FileItemTreeId<N: ItemTreeNode> {
350     index: Idx<N>,
351     _p: PhantomData<N>,
352 }
353
354 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
355     fn clone(&self) -> Self {
356         Self { index: self.index, _p: PhantomData }
357     }
358 }
359 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
360
361 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
362     fn eq(&self, other: &FileItemTreeId<N>) -> bool {
363         self.index == other.index
364     }
365 }
366 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
367
368 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
369     fn hash<H: Hasher>(&self, state: &mut H) {
370         self.index.hash(state)
371     }
372 }
373
374 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
375     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376         self.index.fmt(f)
377     }
378 }
379
380 pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>;
381
382 macro_rules! mod_items {
383     ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
384         #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
385         pub enum ModItem {
386             $(
387                 $typ(FileItemTreeId<$typ>),
388             )+
389         }
390
391         $(
392             impl From<FileItemTreeId<$typ>> for ModItem {
393                 fn from(id: FileItemTreeId<$typ>) -> ModItem {
394                     ModItem::$typ(id)
395                 }
396             }
397         )+
398
399         $(
400             impl ItemTreeNode for $typ {
401                 type Source = $ast;
402
403                 fn ast_id(&self) -> FileAstId<Self::Source> {
404                     self.ast_id
405                 }
406
407                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
408                     &tree.data().$fld[index]
409                 }
410
411                 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
412                     if let ModItem::$typ(id) = mod_item {
413                         Some(id)
414                     } else {
415                         None
416                     }
417                 }
418
419                 fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
420                     ModItem::$typ(id)
421                 }
422             }
423
424             impl Index<Idx<$typ>> for ItemTree {
425                 type Output = $typ;
426
427                 fn index(&self, index: Idx<$typ>) -> &Self::Output {
428                     &self.data().$fld[index]
429                 }
430             }
431         )+
432     };
433 }
434
435 mod_items! {
436     Import in imports -> ast::Use,
437     ExternCrate in extern_crates -> ast::ExternCrate,
438     Function in functions -> ast::Fn,
439     Struct in structs -> ast::Struct,
440     Union in unions -> ast::Union,
441     Enum in enums -> ast::Enum,
442     Const in consts -> ast::Const,
443     Static in statics -> ast::Static,
444     Trait in traits -> ast::Trait,
445     Impl in impls -> ast::Impl,
446     TypeAlias in type_aliases -> ast::TypeAlias,
447     Mod in mods -> ast::Module,
448     MacroCall in macro_calls -> ast::MacroCall,
449     MacroRules in macro_rules -> ast::MacroRules,
450     MacroDef in macro_defs -> ast::MacroDef,
451 }
452
453 macro_rules! impl_index {
454     ( $($fld:ident: $t:ty),+ $(,)? ) => {
455         $(
456             impl Index<Idx<$t>> for ItemTree {
457                 type Output = $t;
458
459                 fn index(&self, index: Idx<$t>) -> &Self::Output {
460                     &self.data().$fld[index]
461                 }
462             }
463         )+
464     };
465 }
466
467 impl_index!(fields: Field, variants: Variant);
468
469 impl Index<RawVisibilityId> for ItemTree {
470     type Output = RawVisibility;
471     fn index(&self, index: RawVisibilityId) -> &Self::Output {
472         match index {
473             RawVisibilityId::PRIV => &VIS_PRIV,
474             RawVisibilityId::PUB => &VIS_PUB,
475             RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE,
476             _ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
477         }
478     }
479 }
480
481 impl Index<GenericParamsId> for ItemTree {
482     type Output = GenericParams;
483
484     fn index(&self, index: GenericParamsId) -> &Self::Output {
485         match index {
486             GenericParamsId::EMPTY => &EMPTY_GENERICS,
487             _ => &self.data().generics.arena[Idx::from_raw(index.0.into())],
488         }
489     }
490 }
491
492 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
493     type Output = N;
494     fn index(&self, id: FileItemTreeId<N>) -> &N {
495         N::lookup(self, id.index)
496     }
497 }
498
499 /// A desugared `use` import.
500 #[derive(Debug, Clone, Eq, PartialEq)]
501 pub struct Import {
502     pub path: ModPath,
503     pub alias: Option<ImportAlias>,
504     pub visibility: RawVisibilityId,
505     pub is_glob: bool,
506     /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
507     /// `Import`s can map to the same `use` item.
508     pub ast_id: FileAstId<ast::Use>,
509     /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`.
510     ///
511     /// This can be used to get the `UseTree` this `Import` corresponds to and allows emitting
512     /// precise diagnostics.
513     pub index: usize,
514 }
515
516 #[derive(Debug, Clone, Eq, PartialEq)]
517 pub struct ExternCrate {
518     pub name: Name,
519     pub alias: Option<ImportAlias>,
520     pub visibility: RawVisibilityId,
521     pub ast_id: FileAstId<ast::ExternCrate>,
522 }
523
524 #[derive(Debug, Clone, Eq, PartialEq)]
525 pub struct Function {
526     pub name: Name,
527     pub visibility: RawVisibilityId,
528     pub generic_params: GenericParamsId,
529     pub has_self_param: bool,
530     pub has_body: bool,
531     pub is_unsafe: bool,
532     /// Whether the function is located in an `extern` block (*not* whether it is an
533     /// `extern "abi" fn`).
534     pub is_extern: bool,
535     pub params: Box<[TypeRef]>,
536     pub is_varargs: bool,
537     pub ret_type: TypeRef,
538     pub ast_id: FileAstId<ast::Fn>,
539 }
540
541 #[derive(Debug, Clone, Eq, PartialEq)]
542 pub struct Struct {
543     pub name: Name,
544     pub visibility: RawVisibilityId,
545     pub generic_params: GenericParamsId,
546     pub fields: Fields,
547     pub ast_id: FileAstId<ast::Struct>,
548     pub kind: StructDefKind,
549 }
550
551 #[derive(Debug, Clone, Eq, PartialEq)]
552 pub enum StructDefKind {
553     /// `struct S { ... }` - type namespace only.
554     Record,
555     /// `struct S(...);`
556     Tuple,
557     /// `struct S;`
558     Unit,
559 }
560
561 #[derive(Debug, Clone, Eq, PartialEq)]
562 pub struct Union {
563     pub name: Name,
564     pub visibility: RawVisibilityId,
565     pub generic_params: GenericParamsId,
566     pub fields: Fields,
567     pub ast_id: FileAstId<ast::Union>,
568 }
569
570 #[derive(Debug, Clone, Eq, PartialEq)]
571 pub struct Enum {
572     pub name: Name,
573     pub visibility: RawVisibilityId,
574     pub generic_params: GenericParamsId,
575     pub variants: IdRange<Variant>,
576     pub ast_id: FileAstId<ast::Enum>,
577 }
578
579 #[derive(Debug, Clone, Eq, PartialEq)]
580 pub struct Const {
581     /// const _: () = ();
582     pub name: Option<Name>,
583     pub visibility: RawVisibilityId,
584     pub type_ref: TypeRef,
585     pub ast_id: FileAstId<ast::Const>,
586 }
587
588 #[derive(Debug, Clone, Eq, PartialEq)]
589 pub struct Static {
590     pub name: Name,
591     pub visibility: RawVisibilityId,
592     pub mutable: bool,
593     /// Whether the static is in an `extern` block.
594     pub is_extern: bool,
595     pub type_ref: TypeRef,
596     pub ast_id: FileAstId<ast::Static>,
597 }
598
599 #[derive(Debug, Clone, Eq, PartialEq)]
600 pub struct Trait {
601     pub name: Name,
602     pub visibility: RawVisibilityId,
603     pub generic_params: GenericParamsId,
604     pub auto: bool,
605     pub items: Box<[AssocItem]>,
606     pub ast_id: FileAstId<ast::Trait>,
607 }
608
609 #[derive(Debug, Clone, Eq, PartialEq)]
610 pub struct Impl {
611     pub generic_params: GenericParamsId,
612     pub target_trait: Option<TypeRef>,
613     pub target_type: TypeRef,
614     pub is_negative: bool,
615     pub items: Box<[AssocItem]>,
616     pub ast_id: FileAstId<ast::Impl>,
617 }
618
619 #[derive(Debug, Clone, PartialEq, Eq)]
620 pub struct TypeAlias {
621     pub name: Name,
622     pub visibility: RawVisibilityId,
623     /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
624     pub bounds: Box<[TypeBound]>,
625     pub generic_params: GenericParamsId,
626     pub type_ref: Option<TypeRef>,
627     pub is_extern: bool,
628     pub ast_id: FileAstId<ast::TypeAlias>,
629 }
630
631 #[derive(Debug, Clone, Eq, PartialEq)]
632 pub struct Mod {
633     pub name: Name,
634     pub visibility: RawVisibilityId,
635     pub kind: ModKind,
636     pub ast_id: FileAstId<ast::Module>,
637 }
638
639 #[derive(Debug, Clone, Eq, PartialEq)]
640 pub enum ModKind {
641     /// `mod m { ... }`
642     Inline { items: Box<[ModItem]> },
643
644     /// `mod m;`
645     Outline {},
646 }
647
648 #[derive(Debug, Clone, Eq, PartialEq)]
649 pub struct MacroCall {
650     /// Path to the called macro.
651     pub path: ModPath,
652     pub ast_id: FileAstId<ast::MacroCall>,
653 }
654
655 #[derive(Debug, Clone, Eq, PartialEq)]
656 pub struct MacroRules {
657     /// The name of the declared macro.
658     pub name: Name,
659     pub ast_id: FileAstId<ast::MacroRules>,
660 }
661
662 /// "Macros 2.0" macro definition.
663 #[derive(Debug, Clone, Eq, PartialEq)]
664 pub struct MacroDef {
665     pub name: Name,
666     pub visibility: RawVisibilityId,
667     pub ast_id: FileAstId<ast::MacroDef>,
668 }
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 }