]> git.lizzy.rs Git - rust.git/blob - crates/hir_def/src/item_tree.rs
Add ConstParams to the HIR
[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, 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.consts.is_empty()
264             && params.where_predicates.is_empty()
265         {
266             return GenericParamsId::EMPTY;
267         }
268
269         GenericParamsId(self.arena.alloc(params).into_raw().into())
270     }
271 }
272
273 static EMPTY_GENERICS: GenericParams = GenericParams {
274     types: Arena::new(),
275     lifetimes: Arena::new(),
276     consts: Arena::new(),
277     where_predicates: Vec::new(),
278 };
279
280 #[derive(Default, Debug, Eq, PartialEq)]
281 struct ItemTreeData {
282     imports: Arena<Import>,
283     extern_crates: Arena<ExternCrate>,
284     functions: Arena<Function>,
285     structs: Arena<Struct>,
286     fields: Arena<Field>,
287     unions: Arena<Union>,
288     enums: Arena<Enum>,
289     variants: Arena<Variant>,
290     consts: Arena<Const>,
291     statics: Arena<Static>,
292     traits: Arena<Trait>,
293     impls: Arena<Impl>,
294     type_aliases: Arena<TypeAlias>,
295     mods: Arena<Mod>,
296     macro_calls: Arena<MacroCall>,
297     macro_rules: Arena<MacroRules>,
298     macro_defs: Arena<MacroDef>,
299     exprs: Arena<Expr>,
300
301     vis: ItemVisibilities,
302     generics: GenericParamsStorage,
303 }
304
305 #[derive(Debug, Eq, PartialEq, Hash)]
306 pub enum AttrOwner {
307     /// Attributes on an item.
308     ModItem(ModItem),
309     /// Inner attributes of the source file.
310     TopLevel,
311
312     Variant(Idx<Variant>),
313     Field(Idx<Field>),
314 }
315
316 macro_rules! from_attrs {
317     ( $( $var:ident($t:ty) ),+ ) => {
318         $(
319             impl From<$t> for AttrOwner {
320                 fn from(t: $t) -> AttrOwner {
321                     AttrOwner::$var(t)
322                 }
323             }
324         )+
325     };
326 }
327
328 from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>));
329
330 /// Trait implemented by all item nodes in the item tree.
331 pub trait ItemTreeNode: Clone {
332     type Source: AstNode + Into<ast::Item>;
333
334     fn ast_id(&self) -> FileAstId<Self::Source>;
335
336     /// Looks up an instance of `Self` in an item tree.
337     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
338
339     /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
340     fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
341
342     /// Upcasts a `FileItemTreeId` to a generic `ModItem`.
343     fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
344 }
345
346 pub struct FileItemTreeId<N: ItemTreeNode> {
347     index: Idx<N>,
348     _p: PhantomData<N>,
349 }
350
351 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
352     fn clone(&self) -> Self {
353         Self { index: self.index, _p: PhantomData }
354     }
355 }
356 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
357
358 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
359     fn eq(&self, other: &FileItemTreeId<N>) -> bool {
360         self.index == other.index
361     }
362 }
363 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
364
365 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
366     fn hash<H: Hasher>(&self, state: &mut H) {
367         self.index.hash(state)
368     }
369 }
370
371 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
372     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
373         self.index.fmt(f)
374     }
375 }
376
377 pub type ItemTreeId<N> = InFile<FileItemTreeId<N>>;
378
379 macro_rules! mod_items {
380     ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
381         #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
382         pub enum ModItem {
383             $(
384                 $typ(FileItemTreeId<$typ>),
385             )+
386         }
387
388         $(
389             impl From<FileItemTreeId<$typ>> for ModItem {
390                 fn from(id: FileItemTreeId<$typ>) -> ModItem {
391                     ModItem::$typ(id)
392                 }
393             }
394         )+
395
396         $(
397             impl ItemTreeNode for $typ {
398                 type Source = $ast;
399
400                 fn ast_id(&self) -> FileAstId<Self::Source> {
401                     self.ast_id
402                 }
403
404                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
405                     &tree.data().$fld[index]
406                 }
407
408                 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
409                     if let ModItem::$typ(id) = mod_item {
410                         Some(id)
411                     } else {
412                         None
413                     }
414                 }
415
416                 fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
417                     ModItem::$typ(id)
418                 }
419             }
420
421             impl Index<Idx<$typ>> for ItemTree {
422                 type Output = $typ;
423
424                 fn index(&self, index: Idx<$typ>) -> &Self::Output {
425                     &self.data().$fld[index]
426                 }
427             }
428         )+
429     };
430 }
431
432 mod_items! {
433     Import in imports -> ast::Use,
434     ExternCrate in extern_crates -> ast::ExternCrate,
435     Function in functions -> ast::Fn,
436     Struct in structs -> ast::Struct,
437     Union in unions -> ast::Union,
438     Enum in enums -> ast::Enum,
439     Const in consts -> ast::Const,
440     Static in statics -> ast::Static,
441     Trait in traits -> ast::Trait,
442     Impl in impls -> ast::Impl,
443     TypeAlias in type_aliases -> ast::TypeAlias,
444     Mod in mods -> ast::Module,
445     MacroCall in macro_calls -> ast::MacroCall,
446     MacroRules in macro_rules -> ast::MacroRules,
447     MacroDef in macro_defs -> ast::MacroDef,
448 }
449
450 macro_rules! impl_index {
451     ( $($fld:ident: $t:ty),+ $(,)? ) => {
452         $(
453             impl Index<Idx<$t>> for ItemTree {
454                 type Output = $t;
455
456                 fn index(&self, index: Idx<$t>) -> &Self::Output {
457                     &self.data().$fld[index]
458                 }
459             }
460         )+
461     };
462 }
463
464 impl_index!(fields: Field, variants: Variant, exprs: Expr);
465
466 impl Index<RawVisibilityId> for ItemTree {
467     type Output = RawVisibility;
468     fn index(&self, index: RawVisibilityId) -> &Self::Output {
469         match index {
470             RawVisibilityId::PRIV => &VIS_PRIV,
471             RawVisibilityId::PUB => &VIS_PUB,
472             RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE,
473             _ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
474         }
475     }
476 }
477
478 impl Index<GenericParamsId> for ItemTree {
479     type Output = GenericParams;
480
481     fn index(&self, index: GenericParamsId) -> &Self::Output {
482         match index {
483             GenericParamsId::EMPTY => &EMPTY_GENERICS,
484             _ => &self.data().generics.arena[Idx::from_raw(index.0.into())],
485         }
486     }
487 }
488
489 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
490     type Output = N;
491     fn index(&self, id: FileItemTreeId<N>) -> &N {
492         N::lookup(self, id.index)
493     }
494 }
495
496 /// A desugared `use` import.
497 #[derive(Debug, Clone, Eq, PartialEq)]
498 pub struct Import {
499     pub path: ModPath,
500     pub alias: Option<ImportAlias>,
501     pub visibility: RawVisibilityId,
502     pub is_glob: bool,
503     /// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
504     /// `Import`s can map to the same `use` item.
505     pub ast_id: FileAstId<ast::Use>,
506     /// Index of this `Import` when the containing `Use` is visited via `ModPath::expand_use_item`.
507     ///
508     /// This can be used to get the `UseTree` this `Import` corresponds to and allows emitting
509     /// precise diagnostics.
510     pub index: usize,
511 }
512
513 #[derive(Debug, Clone, Eq, PartialEq)]
514 pub struct ExternCrate {
515     pub name: Name,
516     pub alias: Option<ImportAlias>,
517     pub visibility: RawVisibilityId,
518     pub ast_id: FileAstId<ast::ExternCrate>,
519 }
520
521 #[derive(Debug, Clone, Eq, PartialEq)]
522 pub struct Function {
523     pub name: Name,
524     pub visibility: RawVisibilityId,
525     pub generic_params: GenericParamsId,
526     pub has_self_param: bool,
527     pub has_body: bool,
528     pub is_unsafe: bool,
529     /// Whether the function is located in an `extern` block (*not* whether it is an
530     /// `extern "abi" fn`).
531     pub is_extern: bool,
532     pub params: Box<[TypeRef]>,
533     pub is_varargs: bool,
534     pub ret_type: TypeRef,
535     pub ast_id: FileAstId<ast::Fn>,
536 }
537
538 #[derive(Debug, Clone, Eq, PartialEq)]
539 pub struct Struct {
540     pub name: Name,
541     pub visibility: RawVisibilityId,
542     pub generic_params: GenericParamsId,
543     pub fields: Fields,
544     pub ast_id: FileAstId<ast::Struct>,
545     pub kind: StructDefKind,
546 }
547
548 #[derive(Debug, Clone, Eq, PartialEq)]
549 pub enum StructDefKind {
550     /// `struct S { ... }` - type namespace only.
551     Record,
552     /// `struct S(...);`
553     Tuple,
554     /// `struct S;`
555     Unit,
556 }
557
558 #[derive(Debug, Clone, Eq, PartialEq)]
559 pub struct Union {
560     pub name: Name,
561     pub visibility: RawVisibilityId,
562     pub generic_params: GenericParamsId,
563     pub fields: Fields,
564     pub ast_id: FileAstId<ast::Union>,
565 }
566
567 #[derive(Debug, Clone, Eq, PartialEq)]
568 pub struct Enum {
569     pub name: Name,
570     pub visibility: RawVisibilityId,
571     pub generic_params: GenericParamsId,
572     pub variants: IdRange<Variant>,
573     pub ast_id: FileAstId<ast::Enum>,
574 }
575
576 #[derive(Debug, Clone, Eq, PartialEq)]
577 pub struct Const {
578     /// const _: () = ();
579     pub name: Option<Name>,
580     pub visibility: RawVisibilityId,
581     pub type_ref: TypeRef,
582     pub ast_id: FileAstId<ast::Const>,
583 }
584
585 #[derive(Debug, Clone, Eq, PartialEq)]
586 pub struct Static {
587     pub name: Name,
588     pub visibility: RawVisibilityId,
589     pub mutable: bool,
590     /// Whether the static is in an `extern` block.
591     pub is_extern: bool,
592     pub type_ref: TypeRef,
593     pub ast_id: FileAstId<ast::Static>,
594 }
595
596 #[derive(Debug, Clone, Eq, PartialEq)]
597 pub struct Trait {
598     pub name: Name,
599     pub visibility: RawVisibilityId,
600     pub generic_params: GenericParamsId,
601     pub auto: bool,
602     pub items: Box<[AssocItem]>,
603     pub ast_id: FileAstId<ast::Trait>,
604 }
605
606 #[derive(Debug, Clone, Eq, PartialEq)]
607 pub struct Impl {
608     pub generic_params: GenericParamsId,
609     pub target_trait: Option<TypeRef>,
610     pub target_type: TypeRef,
611     pub is_negative: bool,
612     pub items: Box<[AssocItem]>,
613     pub ast_id: FileAstId<ast::Impl>,
614 }
615
616 #[derive(Debug, Clone, PartialEq, Eq)]
617 pub struct TypeAlias {
618     pub name: Name,
619     pub visibility: RawVisibilityId,
620     /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
621     pub bounds: Box<[TypeBound]>,
622     pub generic_params: GenericParamsId,
623     pub type_ref: Option<TypeRef>,
624     pub is_extern: bool,
625     pub ast_id: FileAstId<ast::TypeAlias>,
626 }
627
628 #[derive(Debug, Clone, Eq, PartialEq)]
629 pub struct Mod {
630     pub name: Name,
631     pub visibility: RawVisibilityId,
632     pub kind: ModKind,
633     pub ast_id: FileAstId<ast::Module>,
634 }
635
636 #[derive(Debug, Clone, Eq, PartialEq)]
637 pub enum ModKind {
638     /// `mod m { ... }`
639     Inline { items: Box<[ModItem]> },
640
641     /// `mod m;`
642     Outline {},
643 }
644
645 #[derive(Debug, Clone, Eq, PartialEq)]
646 pub struct MacroCall {
647     /// Path to the called macro.
648     pub path: ModPath,
649     pub ast_id: FileAstId<ast::MacroCall>,
650 }
651
652 #[derive(Debug, Clone, Eq, PartialEq)]
653 pub struct MacroRules {
654     /// The name of the declared macro.
655     pub name: Name,
656     pub ast_id: FileAstId<ast::MacroRules>,
657 }
658
659 /// "Macros 2.0" macro definition.
660 #[derive(Debug, Clone, Eq, PartialEq)]
661 pub struct MacroDef {
662     pub name: Name,
663     pub visibility: RawVisibilityId,
664     pub ast_id: FileAstId<ast::MacroDef>,
665 }
666
667 // NB: There's no `FileAstId` for `Expr`. The only case where this would be useful is for array
668 // lengths, but we don't do much with them yet.
669 #[derive(Debug, Clone, Eq, PartialEq)]
670 pub struct Expr;
671
672 macro_rules! impl_froms {
673     ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
674         $(
675             impl From<$t> for $e {
676                 fn from(it: $t) -> $e {
677                     $e::$v(it)
678                 }
679             }
680         )*
681     }
682 }
683
684 impl ModItem {
685     pub fn as_assoc_item(&self) -> Option<AssocItem> {
686         match self {
687             ModItem::Import(_)
688             | ModItem::ExternCrate(_)
689             | ModItem::Struct(_)
690             | ModItem::Union(_)
691             | ModItem::Enum(_)
692             | ModItem::Static(_)
693             | ModItem::Trait(_)
694             | ModItem::Impl(_)
695             | ModItem::Mod(_)
696             | ModItem::MacroRules(_)
697             | ModItem::MacroDef(_) => None,
698             ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
699             ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
700             ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
701             ModItem::Function(func) => Some(AssocItem::Function(*func)),
702         }
703     }
704
705     pub fn downcast<N: ItemTreeNode>(self) -> Option<FileItemTreeId<N>> {
706         N::id_from_mod_item(self)
707     }
708
709     pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
710         match self {
711             ModItem::Import(it) => tree[it.index].ast_id().upcast(),
712             ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
713             ModItem::Function(it) => tree[it.index].ast_id().upcast(),
714             ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
715             ModItem::Union(it) => tree[it.index].ast_id().upcast(),
716             ModItem::Enum(it) => tree[it.index].ast_id().upcast(),
717             ModItem::Const(it) => tree[it.index].ast_id().upcast(),
718             ModItem::Static(it) => tree[it.index].ast_id().upcast(),
719             ModItem::Trait(it) => tree[it.index].ast_id().upcast(),
720             ModItem::Impl(it) => tree[it.index].ast_id().upcast(),
721             ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
722             ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
723             ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
724             ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
725             ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
726         }
727     }
728 }
729
730 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
731 pub enum AssocItem {
732     Function(FileItemTreeId<Function>),
733     TypeAlias(FileItemTreeId<TypeAlias>),
734     Const(FileItemTreeId<Const>),
735     MacroCall(FileItemTreeId<MacroCall>),
736 }
737
738 impl_froms!(AssocItem {
739     Function(FileItemTreeId<Function>),
740     TypeAlias(FileItemTreeId<TypeAlias>),
741     Const(FileItemTreeId<Const>),
742     MacroCall(FileItemTreeId<MacroCall>),
743 });
744
745 impl From<AssocItem> for ModItem {
746     fn from(item: AssocItem) -> Self {
747         match item {
748             AssocItem::Function(it) => it.into(),
749             AssocItem::TypeAlias(it) => it.into(),
750             AssocItem::Const(it) => it.into(),
751             AssocItem::MacroCall(it) => it.into(),
752         }
753     }
754 }
755
756 #[derive(Debug, Eq, PartialEq)]
757 pub struct Variant {
758     pub name: Name,
759     pub fields: Fields,
760 }
761
762 pub struct IdRange<T> {
763     range: Range<u32>,
764     _p: PhantomData<T>,
765 }
766
767 impl<T> IdRange<T> {
768     fn new(range: Range<Idx<T>>) -> Self {
769         Self { range: range.start.into_raw().into()..range.end.into_raw().into(), _p: PhantomData }
770     }
771 }
772
773 impl<T> Iterator for IdRange<T> {
774     type Item = Idx<T>;
775     fn next(&mut self) -> Option<Self::Item> {
776         self.range.next().map(|raw| Idx::from_raw(raw.into()))
777     }
778 }
779
780 impl<T> fmt::Debug for IdRange<T> {
781     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
782         f.debug_tuple(&format!("IdRange::<{}>", type_name::<T>())).field(&self.range).finish()
783     }
784 }
785
786 impl<T> Clone for IdRange<T> {
787     fn clone(&self) -> Self {
788         Self { range: self.range.clone(), _p: PhantomData }
789     }
790 }
791
792 impl<T> PartialEq for IdRange<T> {
793     fn eq(&self, other: &Self) -> bool {
794         self.range == other.range
795     }
796 }
797
798 impl<T> Eq for IdRange<T> {}
799
800 #[derive(Debug, Clone, PartialEq, Eq)]
801 pub enum Fields {
802     Record(IdRange<Field>),
803     Tuple(IdRange<Field>),
804     Unit,
805 }
806
807 /// A single field of an enum variant or struct
808 #[derive(Debug, Clone, PartialEq, Eq)]
809 pub struct Field {
810     pub name: Name,
811     pub type_ref: TypeRef,
812     pub visibility: RawVisibilityId,
813 }