• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! A simplified AST that only contains items.
2 //!
3 //! This is the primary IR used throughout `hir_def`. It is the input to the name resolution
4 //! algorithm, as well as to the queries defined in `adt.rs`, `data.rs`, and most things in
5 //! `attr.rs`.
6 //!
7 //! `ItemTree`s are built per `HirFileId`, from the syntax tree of the parsed file. This means that
8 //! they are crate-independent: they don't know which `#[cfg]`s are active or which module they
9 //! belong to, since those concepts don't exist at this level (a single `ItemTree` might be part of
10 //! multiple crates, or might be included into the same crate twice via `#[path]`).
11 //!
12 //! One important purpose of this layer is to provide an "invalidation barrier" for incremental
13 //! computations: when typing inside an item body, the `ItemTree` of the modified file is typically
14 //! unaffected, so we don't have to recompute name resolution results or item data (see `data.rs`).
15 //!
16 //! The `ItemTree` for the currently open file can be displayed by using the VS Code command
17 //! "rust-analyzer: Debug ItemTree".
18 //!
19 //! Compared to rustc's architecture, `ItemTree` has properties from both rustc's AST and HIR: many
20 //! syntax-level Rust features are already desugared to simpler forms in the `ItemTree`, but name
21 //! resolution has not yet been performed. `ItemTree`s are per-file, while rustc's AST and HIR are
22 //! per-crate, because we are interested in incrementally computing it.
23 //!
24 //! The representation of items in the `ItemTree` should generally mirror the surface syntax: it is
25 //! usually a bad idea to desugar a syntax-level construct to something that is structurally
26 //! different here. Name resolution needs to be able to process attributes and expand macros
27 //! (including attribute macros), and having a 1-to-1 mapping between syntax and the `ItemTree`
28 //! avoids introducing subtle bugs.
29 //!
30 //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
31 //! surface syntax.
32 
33 mod lower;
34 mod pretty;
35 #[cfg(test)]
36 mod tests;
37 
38 use std::{
39     fmt::{self, Debug},
40     hash::{Hash, Hasher},
41     marker::PhantomData,
42     ops::Index,
43 };
44 
45 use ast::{AstNode, HasName, StructKind};
46 use base_db::CrateId;
47 use either::Either;
48 use hir_expand::{
49     ast_id_map::FileAstId,
50     attrs::RawAttrs,
51     hygiene::Hygiene,
52     name::{name, AsName, Name},
53     ExpandTo, HirFileId, InFile,
54 };
55 use intern::Interned;
56 use la_arena::{Arena, Idx, IdxRange, RawIdx};
57 use profile::Count;
58 use rustc_hash::FxHashMap;
59 use smallvec::SmallVec;
60 use stdx::never;
61 use syntax::{ast, match_ast, SyntaxKind};
62 use triomphe::Arc;
63 
64 use crate::{
65     attr::Attrs,
66     db::DefDatabase,
67     generics::GenericParams,
68     path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
69     type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
70     visibility::RawVisibility,
71     BlockId,
72 };
73 
74 #[derive(Copy, Clone, Eq, PartialEq)]
75 pub struct RawVisibilityId(u32);
76 
77 impl RawVisibilityId {
78     pub const PUB: Self = RawVisibilityId(u32::max_value());
79     pub const PRIV: Self = RawVisibilityId(u32::max_value() - 1);
80     pub const PUB_CRATE: Self = RawVisibilityId(u32::max_value() - 2);
81 }
82 
83 impl fmt::Debug for RawVisibilityId {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85         let mut f = f.debug_tuple("RawVisibilityId");
86         match *self {
87             Self::PUB => f.field(&"pub"),
88             Self::PRIV => f.field(&"pub(self)"),
89             Self::PUB_CRATE => f.field(&"pub(crate)"),
90             _ => f.field(&self.0),
91         };
92         f.finish()
93     }
94 }
95 
96 /// The item tree of a source file.
97 #[derive(Debug, Default, Eq, PartialEq)]
98 pub struct ItemTree {
99     _c: Count<Self>,
100 
101     top_level: SmallVec<[ModItem; 1]>,
102     attrs: FxHashMap<AttrOwner, RawAttrs>,
103 
104     data: Option<Box<ItemTreeData>>,
105 }
106 
107 impl ItemTree {
file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree>108     pub(crate) fn file_item_tree_query(db: &dyn DefDatabase, file_id: HirFileId) -> Arc<ItemTree> {
109         let _p = profile::span("file_item_tree_query").detail(|| format!("{file_id:?}"));
110         let syntax = db.parse_or_expand(file_id);
111         if never!(syntax.kind() == SyntaxKind::ERROR, "{:?} from {:?} {}", file_id, syntax, syntax)
112         {
113             // FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic
114             return Default::default();
115         }
116 
117         let ctx = lower::Ctx::new(db, file_id);
118         let mut top_attrs = None;
119         let mut item_tree = match_ast! {
120             match syntax {
121                 ast::SourceFile(file) => {
122                     top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.hygiene()));
123                     ctx.lower_module_items(&file)
124                 },
125                 ast::MacroItems(items) => {
126                     ctx.lower_module_items(&items)
127                 },
128                 ast::MacroStmts(stmts) => {
129                     // The produced statements can include items, which should be added as top-level
130                     // items.
131                     ctx.lower_macro_stmts(stmts)
132                 },
133                 _ => {
134                     panic!("cannot create item tree for file {file_id:?} from {syntax:?} {syntax}");
135                 },
136             }
137         };
138 
139         if let Some(attrs) = top_attrs {
140             item_tree.attrs.insert(AttrOwner::TopLevel, attrs);
141         }
142         item_tree.shrink_to_fit();
143         Arc::new(item_tree)
144     }
145 
146     /// Returns an iterator over all items located at the top level of the `HirFileId` this
147     /// `ItemTree` was created from.
top_level_items(&self) -> &[ModItem]148     pub fn top_level_items(&self) -> &[ModItem] {
149         &self.top_level
150     }
151 
152     /// Returns the inner attributes of the source file.
top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs153     pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
154         Attrs::filter(
155             db,
156             krate,
157             self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(),
158         )
159     }
160 
raw_attrs(&self, of: AttrOwner) -> &RawAttrs161     pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
162         self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
163     }
164 
attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs165     pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
166         Attrs::filter(db, krate, self.raw_attrs(of).clone())
167     }
168 
pretty_print(&self, db: &dyn DefDatabase) -> String169     pub fn pretty_print(&self, db: &dyn DefDatabase) -> String {
170         pretty::print_item_tree(db.upcast(), self)
171     }
172 
data(&self) -> &ItemTreeData173     fn data(&self) -> &ItemTreeData {
174         self.data.as_ref().expect("attempted to access data of empty ItemTree")
175     }
176 
data_mut(&mut self) -> &mut ItemTreeData177     fn data_mut(&mut self) -> &mut ItemTreeData {
178         self.data.get_or_insert_with(Box::default)
179     }
180 
block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree>181     fn block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
182         let loc = db.lookup_intern_block(block);
183         let block = loc.ast_id.to_node(db.upcast());
184         let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
185         Arc::new(ctx.lower_block(&block))
186     }
187 
shrink_to_fit(&mut self)188     fn shrink_to_fit(&mut self) {
189         if let Some(data) = &mut self.data {
190             let ItemTreeData {
191                 imports,
192                 extern_crates,
193                 extern_blocks,
194                 functions,
195                 params,
196                 structs,
197                 fields,
198                 unions,
199                 enums,
200                 variants,
201                 consts,
202                 statics,
203                 traits,
204                 trait_aliases,
205                 impls,
206                 type_aliases,
207                 mods,
208                 macro_calls,
209                 macro_rules,
210                 macro_defs,
211                 vis,
212             } = &mut **data;
213 
214             imports.shrink_to_fit();
215             extern_crates.shrink_to_fit();
216             extern_blocks.shrink_to_fit();
217             functions.shrink_to_fit();
218             params.shrink_to_fit();
219             structs.shrink_to_fit();
220             fields.shrink_to_fit();
221             unions.shrink_to_fit();
222             enums.shrink_to_fit();
223             variants.shrink_to_fit();
224             consts.shrink_to_fit();
225             statics.shrink_to_fit();
226             traits.shrink_to_fit();
227             trait_aliases.shrink_to_fit();
228             impls.shrink_to_fit();
229             type_aliases.shrink_to_fit();
230             mods.shrink_to_fit();
231             macro_calls.shrink_to_fit();
232             macro_rules.shrink_to_fit();
233             macro_defs.shrink_to_fit();
234 
235             vis.arena.shrink_to_fit();
236         }
237     }
238 }
239 
240 #[derive(Default, Debug, Eq, PartialEq)]
241 struct ItemVisibilities {
242     arena: Arena<RawVisibility>,
243 }
244 
245 impl ItemVisibilities {
alloc(&mut self, vis: RawVisibility) -> RawVisibilityId246     fn alloc(&mut self, vis: RawVisibility) -> RawVisibilityId {
247         match &vis {
248             RawVisibility::Public => RawVisibilityId::PUB,
249             RawVisibility::Module(path) if path.segments().is_empty() => match &path.kind {
250                 PathKind::Super(0) => RawVisibilityId::PRIV,
251                 PathKind::Crate => RawVisibilityId::PUB_CRATE,
252                 _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
253             },
254             _ => RawVisibilityId(self.arena.alloc(vis).into_raw().into()),
255         }
256     }
257 }
258 
259 static VIS_PUB: RawVisibility = RawVisibility::Public;
260 static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)));
261 static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
262 
263 #[derive(Default, Debug, Eq, PartialEq)]
264 struct ItemTreeData {
265     imports: Arena<Import>,
266     extern_crates: Arena<ExternCrate>,
267     extern_blocks: Arena<ExternBlock>,
268     functions: Arena<Function>,
269     params: Arena<Param>,
270     structs: Arena<Struct>,
271     fields: Arena<Field>,
272     unions: Arena<Union>,
273     enums: Arena<Enum>,
274     variants: Arena<Variant>,
275     consts: Arena<Const>,
276     statics: Arena<Static>,
277     traits: Arena<Trait>,
278     trait_aliases: Arena<TraitAlias>,
279     impls: Arena<Impl>,
280     type_aliases: Arena<TypeAlias>,
281     mods: Arena<Mod>,
282     macro_calls: Arena<MacroCall>,
283     macro_rules: Arena<MacroRules>,
284     macro_defs: Arena<MacroDef>,
285 
286     vis: ItemVisibilities,
287 }
288 
289 #[derive(Debug, Eq, PartialEq, Hash)]
290 pub enum AttrOwner {
291     /// Attributes on an item.
292     ModItem(ModItem),
293     /// Inner attributes of the source file.
294     TopLevel,
295 
296     Variant(Idx<Variant>),
297     Field(Idx<Field>),
298     Param(Idx<Param>),
299 }
300 
301 macro_rules! from_attrs {
302     ( $( $var:ident($t:ty) ),+ ) => {
303         $(
304             impl From<$t> for AttrOwner {
305                 fn from(t: $t) -> AttrOwner {
306                     AttrOwner::$var(t)
307                 }
308             }
309         )+
310     };
311 }
312 
313 from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>));
314 
315 /// Trait implemented by all item nodes in the item tree.
316 pub trait ItemTreeNode: Clone {
317     type Source: AstNode + Into<ast::Item>;
318 
ast_id(&self) -> FileAstId<Self::Source>319     fn ast_id(&self) -> FileAstId<Self::Source>;
320 
321     /// Looks up an instance of `Self` in an item tree.
lookup(tree: &ItemTree, index: Idx<Self>) -> &Self322     fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self;
323 
324     /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>325     fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>>;
326 
327     /// Upcasts a `FileItemTreeId` to a generic `ModItem`.
id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem328     fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem;
329 }
330 
331 pub struct FileItemTreeId<N: ItemTreeNode> {
332     index: Idx<N>,
333     _p: PhantomData<N>,
334 }
335 
336 impl<N: ItemTreeNode> Clone for FileItemTreeId<N> {
clone(&self) -> Self337     fn clone(&self) -> Self {
338         Self { index: self.index, _p: PhantomData }
339     }
340 }
341 impl<N: ItemTreeNode> Copy for FileItemTreeId<N> {}
342 
343 impl<N: ItemTreeNode> PartialEq for FileItemTreeId<N> {
eq(&self, other: &FileItemTreeId<N>) -> bool344     fn eq(&self, other: &FileItemTreeId<N>) -> bool {
345         self.index == other.index
346     }
347 }
348 impl<N: ItemTreeNode> Eq for FileItemTreeId<N> {}
349 
350 impl<N: ItemTreeNode> Hash for FileItemTreeId<N> {
hash<H: Hasher>(&self, state: &mut H)351     fn hash<H: Hasher>(&self, state: &mut H) {
352         self.index.hash(state)
353     }
354 }
355 
356 impl<N: ItemTreeNode> fmt::Debug for FileItemTreeId<N> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result357     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
358         self.index.fmt(f)
359     }
360 }
361 
362 /// Identifies a particular [`ItemTree`].
363 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
364 pub struct TreeId {
365     file: HirFileId,
366     block: Option<BlockId>,
367 }
368 
369 impl TreeId {
new(file: HirFileId, block: Option<BlockId>) -> Self370     pub(crate) fn new(file: HirFileId, block: Option<BlockId>) -> Self {
371         Self { file, block }
372     }
373 
item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree>374     pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
375         match self.block {
376             Some(block) => ItemTree::block_item_tree(db, block),
377             None => db.file_item_tree(self.file),
378         }
379     }
380 
file_id(self) -> HirFileId381     pub(crate) fn file_id(self) -> HirFileId {
382         self.file
383     }
384 
is_block(self) -> bool385     pub(crate) fn is_block(self) -> bool {
386         self.block.is_some()
387     }
388 }
389 
390 #[derive(Debug)]
391 pub struct ItemTreeId<N: ItemTreeNode> {
392     tree: TreeId,
393     pub value: FileItemTreeId<N>,
394 }
395 
396 impl<N: ItemTreeNode> ItemTreeId<N> {
new(tree: TreeId, idx: FileItemTreeId<N>) -> Self397     pub fn new(tree: TreeId, idx: FileItemTreeId<N>) -> Self {
398         Self { tree, value: idx }
399     }
400 
file_id(self) -> HirFileId401     pub fn file_id(self) -> HirFileId {
402         self.tree.file
403     }
404 
tree_id(self) -> TreeId405     pub fn tree_id(self) -> TreeId {
406         self.tree
407     }
408 
item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree>409     pub fn item_tree(self, db: &dyn DefDatabase) -> Arc<ItemTree> {
410         self.tree.item_tree(db)
411     }
412 }
413 
414 impl<N: ItemTreeNode> Copy for ItemTreeId<N> {}
415 impl<N: ItemTreeNode> Clone for ItemTreeId<N> {
clone(&self) -> Self416     fn clone(&self) -> Self {
417         *self
418     }
419 }
420 
421 impl<N: ItemTreeNode> PartialEq for ItemTreeId<N> {
eq(&self, other: &Self) -> bool422     fn eq(&self, other: &Self) -> bool {
423         self.tree == other.tree && self.value == other.value
424     }
425 }
426 
427 impl<N: ItemTreeNode> Eq for ItemTreeId<N> {}
428 
429 impl<N: ItemTreeNode> Hash for ItemTreeId<N> {
hash<H: Hasher>(&self, state: &mut H)430     fn hash<H: Hasher>(&self, state: &mut H) {
431         self.tree.hash(state);
432         self.value.hash(state);
433     }
434 }
435 
436 macro_rules! mod_items {
437     ( $( $typ:ident in $fld:ident -> $ast:ty ),+ $(,)? ) => {
438         #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
439         pub enum ModItem {
440             $(
441                 $typ(FileItemTreeId<$typ>),
442             )+
443         }
444 
445         $(
446             impl From<FileItemTreeId<$typ>> for ModItem {
447                 fn from(id: FileItemTreeId<$typ>) -> ModItem {
448                     ModItem::$typ(id)
449                 }
450             }
451         )+
452 
453         $(
454             impl ItemTreeNode for $typ {
455                 type Source = $ast;
456 
457                 fn ast_id(&self) -> FileAstId<Self::Source> {
458                     self.ast_id
459                 }
460 
461                 fn lookup(tree: &ItemTree, index: Idx<Self>) -> &Self {
462                     &tree.data().$fld[index]
463                 }
464 
465                 fn id_from_mod_item(mod_item: ModItem) -> Option<FileItemTreeId<Self>> {
466                     match mod_item {
467                         ModItem::$typ(id) => Some(id),
468                         _ => None,
469                     }
470                 }
471 
472                 fn id_to_mod_item(id: FileItemTreeId<Self>) -> ModItem {
473                     ModItem::$typ(id)
474                 }
475             }
476 
477             impl Index<Idx<$typ>> for ItemTree {
478                 type Output = $typ;
479 
480                 fn index(&self, index: Idx<$typ>) -> &Self::Output {
481                     &self.data().$fld[index]
482                 }
483             }
484         )+
485     };
486 }
487 
488 mod_items! {
489     Import in imports -> ast::Use,
490     ExternCrate in extern_crates -> ast::ExternCrate,
491     ExternBlock in extern_blocks -> ast::ExternBlock,
492     Function in functions -> ast::Fn,
493     Struct in structs -> ast::Struct,
494     Union in unions -> ast::Union,
495     Enum in enums -> ast::Enum,
496     Const in consts -> ast::Const,
497     Static in statics -> ast::Static,
498     Trait in traits -> ast::Trait,
499     TraitAlias in trait_aliases -> ast::TraitAlias,
500     Impl in impls -> ast::Impl,
501     TypeAlias in type_aliases -> ast::TypeAlias,
502     Mod in mods -> ast::Module,
503     MacroCall in macro_calls -> ast::MacroCall,
504     MacroRules in macro_rules -> ast::MacroRules,
505     MacroDef in macro_defs -> ast::MacroDef,
506 }
507 
508 macro_rules! impl_index {
509     ( $($fld:ident: $t:ty),+ $(,)? ) => {
510         $(
511             impl Index<Idx<$t>> for ItemTree {
512                 type Output = $t;
513 
514                 fn index(&self, index: Idx<$t>) -> &Self::Output {
515                     &self.data().$fld[index]
516                 }
517             }
518         )+
519     };
520 }
521 
522 impl_index!(fields: Field, variants: Variant, params: Param);
523 
524 impl Index<RawVisibilityId> for ItemTree {
525     type Output = RawVisibility;
index(&self, index: RawVisibilityId) -> &Self::Output526     fn index(&self, index: RawVisibilityId) -> &Self::Output {
527         match index {
528             RawVisibilityId::PRIV => &VIS_PRIV,
529             RawVisibilityId::PUB => &VIS_PUB,
530             RawVisibilityId::PUB_CRATE => &VIS_PUB_CRATE,
531             _ => &self.data().vis.arena[Idx::from_raw(index.0.into())],
532         }
533     }
534 }
535 
536 impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
537     type Output = N;
index(&self, id: FileItemTreeId<N>) -> &N538     fn index(&self, id: FileItemTreeId<N>) -> &N {
539         N::lookup(self, id.index)
540     }
541 }
542 
543 #[derive(Debug, Clone, Eq, PartialEq)]
544 pub struct Import {
545     pub visibility: RawVisibilityId,
546     pub ast_id: FileAstId<ast::Use>,
547     pub use_tree: UseTree,
548 }
549 
550 #[derive(Debug, Clone, Eq, PartialEq)]
551 pub struct UseTree {
552     pub index: Idx<ast::UseTree>,
553     kind: UseTreeKind,
554 }
555 
556 #[derive(Debug, Clone, Eq, PartialEq)]
557 pub enum UseTreeKind {
558     /// ```
559     /// use path::to::Item;
560     /// use path::to::Item as Renamed;
561     /// use path::to::Trait as _;
562     /// ```
563     Single { path: Interned<ModPath>, alias: Option<ImportAlias> },
564 
565     /// ```
566     /// use *;  // (invalid, but can occur in nested tree)
567     /// use path::*;
568     /// ```
569     Glob { path: Option<Interned<ModPath>> },
570 
571     /// ```
572     /// use prefix::{self, Item, ...};
573     /// ```
574     Prefixed { prefix: Option<Interned<ModPath>>, list: Box<[UseTree]> },
575 }
576 
577 #[derive(Debug, Clone, Eq, PartialEq)]
578 pub struct ExternCrate {
579     pub name: Name,
580     pub alias: Option<ImportAlias>,
581     pub visibility: RawVisibilityId,
582     pub ast_id: FileAstId<ast::ExternCrate>,
583 }
584 
585 #[derive(Debug, Clone, Eq, PartialEq)]
586 pub struct ExternBlock {
587     pub abi: Option<Interned<str>>,
588     pub ast_id: FileAstId<ast::ExternBlock>,
589     pub children: Box<[ModItem]>,
590 }
591 
592 #[derive(Debug, Clone, Eq, PartialEq)]
593 pub struct Function {
594     pub name: Name,
595     pub visibility: RawVisibilityId,
596     pub explicit_generic_params: Interned<GenericParams>,
597     pub abi: Option<Interned<str>>,
598     pub params: IdxRange<Param>,
599     pub ret_type: Interned<TypeRef>,
600     pub ast_id: FileAstId<ast::Fn>,
601     pub(crate) flags: FnFlags,
602 }
603 
604 #[derive(Debug, Clone, Eq, PartialEq)]
605 pub enum Param {
606     Normal(Interned<TypeRef>),
607     Varargs,
608 }
609 
610 bitflags::bitflags! {
611     #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
612     pub(crate) struct FnFlags: u8 {
613         const HAS_SELF_PARAM = 1 << 0;
614         const HAS_BODY = 1 << 1;
615         const HAS_DEFAULT_KW = 1 << 2;
616         const HAS_CONST_KW = 1 << 3;
617         const HAS_ASYNC_KW = 1 << 4;
618         const HAS_UNSAFE_KW = 1 << 5;
619         const IS_VARARGS = 1 << 6;
620     }
621 }
622 
623 #[derive(Debug, Clone, Eq, PartialEq)]
624 pub struct Struct {
625     pub name: Name,
626     pub visibility: RawVisibilityId,
627     pub generic_params: Interned<GenericParams>,
628     pub fields: Fields,
629     pub ast_id: FileAstId<ast::Struct>,
630 }
631 
632 #[derive(Debug, Clone, Eq, PartialEq)]
633 pub struct Union {
634     pub name: Name,
635     pub visibility: RawVisibilityId,
636     pub generic_params: Interned<GenericParams>,
637     pub fields: Fields,
638     pub ast_id: FileAstId<ast::Union>,
639 }
640 
641 #[derive(Debug, Clone, Eq, PartialEq)]
642 pub struct Enum {
643     pub name: Name,
644     pub visibility: RawVisibilityId,
645     pub generic_params: Interned<GenericParams>,
646     pub variants: IdxRange<Variant>,
647     pub ast_id: FileAstId<ast::Enum>,
648 }
649 
650 #[derive(Debug, Clone, Eq, PartialEq)]
651 pub struct Const {
652     /// `None` for `const _: () = ();`
653     pub name: Option<Name>,
654     pub visibility: RawVisibilityId,
655     pub type_ref: Interned<TypeRef>,
656     pub ast_id: FileAstId<ast::Const>,
657 }
658 
659 #[derive(Debug, Clone, Eq, PartialEq)]
660 pub struct Static {
661     pub name: Name,
662     pub visibility: RawVisibilityId,
663     pub mutable: bool,
664     pub type_ref: Interned<TypeRef>,
665     pub ast_id: FileAstId<ast::Static>,
666 }
667 
668 #[derive(Debug, Clone, Eq, PartialEq)]
669 pub struct Trait {
670     pub name: Name,
671     pub visibility: RawVisibilityId,
672     pub generic_params: Interned<GenericParams>,
673     pub is_auto: bool,
674     pub is_unsafe: bool,
675     pub items: Box<[AssocItem]>,
676     pub ast_id: FileAstId<ast::Trait>,
677 }
678 
679 #[derive(Debug, Clone, Eq, PartialEq)]
680 pub struct TraitAlias {
681     pub name: Name,
682     pub visibility: RawVisibilityId,
683     pub generic_params: Interned<GenericParams>,
684     pub ast_id: FileAstId<ast::TraitAlias>,
685 }
686 
687 #[derive(Debug, Clone, Eq, PartialEq)]
688 pub struct Impl {
689     pub generic_params: Interned<GenericParams>,
690     pub target_trait: Option<Interned<TraitRef>>,
691     pub self_ty: Interned<TypeRef>,
692     pub is_negative: bool,
693     pub items: Box<[AssocItem]>,
694     pub ast_id: FileAstId<ast::Impl>,
695 }
696 
697 #[derive(Debug, Clone, PartialEq, Eq)]
698 pub struct TypeAlias {
699     pub name: Name,
700     pub visibility: RawVisibilityId,
701     /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
702     pub bounds: Box<[Interned<TypeBound>]>,
703     pub generic_params: Interned<GenericParams>,
704     pub type_ref: Option<Interned<TypeRef>>,
705     pub ast_id: FileAstId<ast::TypeAlias>,
706 }
707 
708 #[derive(Debug, Clone, Eq, PartialEq)]
709 pub struct Mod {
710     pub name: Name,
711     pub visibility: RawVisibilityId,
712     pub kind: ModKind,
713     pub ast_id: FileAstId<ast::Module>,
714 }
715 
716 #[derive(Debug, Clone, Eq, PartialEq)]
717 pub enum ModKind {
718     /// `mod m { ... }`
719     Inline { items: Box<[ModItem]> },
720     /// `mod m;`
721     Outline,
722 }
723 
724 #[derive(Debug, Clone, Eq, PartialEq)]
725 pub struct MacroCall {
726     /// Path to the called macro.
727     pub path: Interned<ModPath>,
728     pub ast_id: FileAstId<ast::MacroCall>,
729     pub expand_to: ExpandTo,
730 }
731 
732 #[derive(Debug, Clone, Eq, PartialEq)]
733 pub struct MacroRules {
734     /// The name of the declared macro.
735     pub name: Name,
736     pub ast_id: FileAstId<ast::MacroRules>,
737 }
738 
739 /// "Macros 2.0" macro definition.
740 #[derive(Debug, Clone, Eq, PartialEq)]
741 pub struct MacroDef {
742     pub name: Name,
743     pub visibility: RawVisibilityId,
744     pub ast_id: FileAstId<ast::MacroDef>,
745 }
746 
747 impl Import {
748     /// Maps a `UseTree` contained in this import back to its AST node.
use_tree_to_ast( &self, db: &dyn DefDatabase, file_id: HirFileId, index: Idx<ast::UseTree>, ) -> ast::UseTree749     pub fn use_tree_to_ast(
750         &self,
751         db: &dyn DefDatabase,
752         file_id: HirFileId,
753         index: Idx<ast::UseTree>,
754     ) -> ast::UseTree {
755         // Re-lower the AST item and get the source map.
756         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
757         let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
758         let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
759         let hygiene = Hygiene::new(db.upcast(), file_id);
760         let (_, source_map) =
761             lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree");
762         source_map[index].clone()
763     }
764 }
765 
766 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
767 pub enum ImportKind {
768     /// The `ModPath` is imported normally.
769     Plain,
770     /// This is a glob-import of all names in the `ModPath`.
771     Glob,
772     /// This is a `some::path::self` import, which imports `some::path` only in type namespace.
773     TypeOnly,
774 }
775 
776 impl UseTree {
777     /// Expands the `UseTree` into individually imported `ModPath`s.
expand( &self, mut cb: impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>), )778     pub fn expand(
779         &self,
780         mut cb: impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
781     ) {
782         self.expand_impl(None, &mut cb)
783     }
784 
expand_impl( &self, prefix: Option<ModPath>, cb: &mut dyn FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>), )785     fn expand_impl(
786         &self,
787         prefix: Option<ModPath>,
788         cb: &mut dyn FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
789     ) {
790         fn concat_mod_paths(
791             prefix: Option<ModPath>,
792             path: &ModPath,
793         ) -> Option<(ModPath, ImportKind)> {
794             match (prefix, &path.kind) {
795                 (None, _) => Some((path.clone(), ImportKind::Plain)),
796                 (Some(mut prefix), PathKind::Plain) => {
797                     for segment in path.segments() {
798                         prefix.push_segment(segment.clone());
799                     }
800                     Some((prefix, ImportKind::Plain))
801                 }
802                 (Some(mut prefix), PathKind::Super(n))
803                     if *n > 0 && prefix.segments().is_empty() =>
804                 {
805                     // `super::super` + `super::rest`
806                     match &mut prefix.kind {
807                         PathKind::Super(m) => {
808                             cov_mark::hit!(concat_super_mod_paths);
809                             *m += *n;
810                             for segment in path.segments() {
811                                 prefix.push_segment(segment.clone());
812                             }
813                             Some((prefix, ImportKind::Plain))
814                         }
815                         _ => None,
816                     }
817                 }
818                 (Some(prefix), PathKind::Super(0)) if path.segments().is_empty() => {
819                     // `some::path::self` == `some::path`
820                     Some((prefix, ImportKind::TypeOnly))
821                 }
822                 (Some(_), _) => None,
823             }
824         }
825 
826         match &self.kind {
827             UseTreeKind::Single { path, alias } => {
828                 if let Some((path, kind)) = concat_mod_paths(prefix, path) {
829                     cb(self.index, path, kind, alias.clone());
830                 }
831             }
832             UseTreeKind::Glob { path: Some(path) } => {
833                 if let Some((path, _)) = concat_mod_paths(prefix, path) {
834                     cb(self.index, path, ImportKind::Glob, None);
835                 }
836             }
837             UseTreeKind::Glob { path: None } => {
838                 if let Some(prefix) = prefix {
839                     cb(self.index, prefix, ImportKind::Glob, None);
840                 }
841             }
842             UseTreeKind::Prefixed { prefix: additional_prefix, list } => {
843                 let prefix = match additional_prefix {
844                     Some(path) => match concat_mod_paths(prefix, path) {
845                         Some((path, ImportKind::Plain)) => Some(path),
846                         _ => return,
847                     },
848                     None => prefix,
849                 };
850                 for tree in &**list {
851                     tree.expand_impl(prefix.clone(), cb);
852                 }
853             }
854         }
855     }
856 }
857 
858 macro_rules! impl_froms {
859     ($e:ident { $($v:ident ($t:ty)),* $(,)? }) => {
860         $(
861             impl From<$t> for $e {
862                 fn from(it: $t) -> $e {
863                     $e::$v(it)
864                 }
865             }
866         )*
867     }
868 }
869 
870 impl ModItem {
as_assoc_item(&self) -> Option<AssocItem>871     pub fn as_assoc_item(&self) -> Option<AssocItem> {
872         match self {
873             ModItem::Import(_)
874             | ModItem::ExternCrate(_)
875             | ModItem::ExternBlock(_)
876             | ModItem::Struct(_)
877             | ModItem::Union(_)
878             | ModItem::Enum(_)
879             | ModItem::Static(_)
880             | ModItem::Trait(_)
881             | ModItem::TraitAlias(_)
882             | ModItem::Impl(_)
883             | ModItem::Mod(_)
884             | ModItem::MacroRules(_)
885             | ModItem::MacroDef(_) => None,
886             ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
887             ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
888             ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
889             ModItem::Function(func) => Some(AssocItem::Function(*func)),
890         }
891     }
892 
ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item>893     pub fn ast_id(&self, tree: &ItemTree) -> FileAstId<ast::Item> {
894         match self {
895             ModItem::Import(it) => tree[it.index].ast_id().upcast(),
896             ModItem::ExternCrate(it) => tree[it.index].ast_id().upcast(),
897             ModItem::ExternBlock(it) => tree[it.index].ast_id().upcast(),
898             ModItem::Function(it) => tree[it.index].ast_id().upcast(),
899             ModItem::Struct(it) => tree[it.index].ast_id().upcast(),
900             ModItem::Union(it) => tree[it.index].ast_id().upcast(),
901             ModItem::Enum(it) => tree[it.index].ast_id().upcast(),
902             ModItem::Const(it) => tree[it.index].ast_id().upcast(),
903             ModItem::Static(it) => tree[it.index].ast_id().upcast(),
904             ModItem::Trait(it) => tree[it.index].ast_id().upcast(),
905             ModItem::TraitAlias(it) => tree[it.index].ast_id().upcast(),
906             ModItem::Impl(it) => tree[it.index].ast_id().upcast(),
907             ModItem::TypeAlias(it) => tree[it.index].ast_id().upcast(),
908             ModItem::Mod(it) => tree[it.index].ast_id().upcast(),
909             ModItem::MacroCall(it) => tree[it.index].ast_id().upcast(),
910             ModItem::MacroRules(it) => tree[it.index].ast_id().upcast(),
911             ModItem::MacroDef(it) => tree[it.index].ast_id().upcast(),
912         }
913     }
914 }
915 
916 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
917 pub enum AssocItem {
918     Function(FileItemTreeId<Function>),
919     TypeAlias(FileItemTreeId<TypeAlias>),
920     Const(FileItemTreeId<Const>),
921     MacroCall(FileItemTreeId<MacroCall>),
922 }
923 
924 impl_froms!(AssocItem {
925     Function(FileItemTreeId<Function>),
926     TypeAlias(FileItemTreeId<TypeAlias>),
927     Const(FileItemTreeId<Const>),
928     MacroCall(FileItemTreeId<MacroCall>),
929 });
930 
931 impl From<AssocItem> for ModItem {
from(item: AssocItem) -> Self932     fn from(item: AssocItem) -> Self {
933         match item {
934             AssocItem::Function(it) => it.into(),
935             AssocItem::TypeAlias(it) => it.into(),
936             AssocItem::Const(it) => it.into(),
937             AssocItem::MacroCall(it) => it.into(),
938         }
939     }
940 }
941 
942 impl AssocItem {
ast_id(self, tree: &ItemTree) -> FileAstId<ast::AssocItem>943     pub fn ast_id(self, tree: &ItemTree) -> FileAstId<ast::AssocItem> {
944         match self {
945             AssocItem::Function(id) => tree[id].ast_id.upcast(),
946             AssocItem::TypeAlias(id) => tree[id].ast_id.upcast(),
947             AssocItem::Const(id) => tree[id].ast_id.upcast(),
948             AssocItem::MacroCall(id) => tree[id].ast_id.upcast(),
949         }
950     }
951 }
952 
953 #[derive(Debug, Eq, PartialEq)]
954 pub struct Variant {
955     pub name: Name,
956     pub fields: Fields,
957     pub ast_id: FileAstId<ast::Variant>,
958 }
959 
960 #[derive(Debug, Clone, PartialEq, Eq)]
961 pub enum Fields {
962     Record(IdxRange<Field>),
963     Tuple(IdxRange<Field>),
964     Unit,
965 }
966 
967 #[derive(Debug, Clone, PartialEq, Eq)]
968 pub enum FieldAstId {
969     Record(FileAstId<ast::RecordField>),
970     Tuple(FileAstId<ast::TupleField>),
971 }
972 
973 /// A single field of an enum variant or struct
974 #[derive(Debug, Clone, PartialEq, Eq)]
975 pub struct Field {
976     pub name: Name,
977     pub type_ref: Interned<TypeRef>,
978     pub visibility: RawVisibilityId,
979     pub ast_id: FieldAstId,
980 }
981