1 //! A simplified AST that only contains items.
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
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]`).
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`).
16 //! The `ItemTree` for the currently open file can be displayed by using the VS Code command
17 //! "rust-analyzer: Debug ItemTree".
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.
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.
30 //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
46 use ast
::{AstNode, HasName, StructKind}
;
50 ast_id_map
::FileAstId
,
52 name
::{name, AsName, Name}
,
53 ExpandTo
, HirFileId
, InFile
,
55 use la_arena
::{Arena, Idx, IdxRange, RawIdx}
;
57 use rustc_hash
::FxHashMap
;
58 use smallvec
::SmallVec
;
60 use syntax
::{ast, match_ast, SyntaxKind}
;
63 attr
::{Attrs, RawAttrs}
,
65 generics
::GenericParams
,
67 path
::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}
,
68 type_ref
::{Mutability, TraitRef, TypeBound, TypeRef}
,
69 visibility
::RawVisibility
,
73 #[derive(Copy, Clone, Eq, PartialEq)]
74 pub struct RawVisibilityId(u32);
76 impl RawVisibilityId
{
77 pub const PUB
: Self = RawVisibilityId(u32::max_value());
78 pub const PRIV
: Self = RawVisibilityId(u32::max_value() - 1);
79 pub const PUB_CRATE
: Self = RawVisibilityId(u32::max_value() - 2);
82 impl fmt
::Debug
for RawVisibilityId
{
83 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
84 let mut f
= f
.debug_tuple("RawVisibilityId");
86 Self::PUB
=> f
.field(&"pub"),
87 Self::PRIV
=> f
.field(&"pub(self)"),
88 Self::PUB_CRATE
=> f
.field(&"pub(crate)"),
89 _
=> f
.field(&self.0),
95 /// The item tree of a source file.
96 #[derive(Debug, Default, Eq, PartialEq)]
100 top_level
: SmallVec
<[ModItem
; 1]>,
101 attrs
: FxHashMap
<AttrOwner
, RawAttrs
>,
103 data
: Option
<Box
<ItemTreeData
>>,
107 pub(crate) fn file_item_tree_query(db
: &dyn DefDatabase
, file_id
: HirFileId
) -> Arc
<ItemTree
> {
108 let _p
= profile
::span("file_item_tree_query").detail(|| format
!("{:?}", file_id
));
109 let syntax
= match db
.parse_or_expand(file_id
) {
111 None
=> return Default
::default(),
113 if never
!(syntax
.kind() == SyntaxKind
::ERROR
) {
114 // FIXME: not 100% sure why these crop up, but return an empty tree to avoid a panic
115 return Default
::default();
118 let ctx
= lower
::Ctx
::new(db
, file_id
);
119 let mut top_attrs
= None
;
120 let mut item_tree
= match_ast
! {
122 ast
::SourceFile(file
) => {
123 top_attrs
= Some(RawAttrs
::new(db
, &file
, ctx
.hygiene()));
124 ctx
.lower_module_items(&file
)
126 ast
::MacroItems(items
) => {
127 ctx
.lower_module_items(&items
)
129 ast
::MacroStmts(stmts
) => {
130 // The produced statements can include items, which should be added as top-level
132 ctx
.lower_macro_stmts(stmts
)
135 panic
!("cannot create item tree from {:?} {}", syntax
, syntax
);
140 if let Some(attrs
) = top_attrs
{
141 item_tree
.attrs
.insert(AttrOwner
::TopLevel
, attrs
);
143 item_tree
.shrink_to_fit();
147 /// Returns an iterator over all items located at the top level of the `HirFileId` this
148 /// `ItemTree` was created from.
149 pub fn top_level_items(&self) -> &[ModItem
] {
153 /// Returns the inner attributes of the source file.
154 pub fn top_level_attrs(&self, db
: &dyn DefDatabase
, krate
: CrateId
) -> Attrs
{
155 self.attrs
.get(&AttrOwner
::TopLevel
).unwrap_or(&RawAttrs
::EMPTY
).clone().filter(db
, krate
)
158 pub(crate) fn raw_attrs(&self, of
: AttrOwner
) -> &RawAttrs
{
159 self.attrs
.get(&of
).unwrap_or(&RawAttrs
::EMPTY
)
162 pub(crate) fn attrs(&self, db
: &dyn DefDatabase
, krate
: CrateId
, of
: AttrOwner
) -> Attrs
{
163 self.raw_attrs(of
).clone().filter(db
, krate
)
166 pub fn pretty_print(&self) -> String
{
167 pretty
::print_item_tree(self)
170 fn data(&self) -> &ItemTreeData
{
171 self.data
.as_ref().expect("attempted to access data of empty ItemTree")
174 fn data_mut(&mut self) -> &mut ItemTreeData
{
175 self.data
.get_or_insert_with(Box
::default)
178 fn block_item_tree(db
: &dyn DefDatabase
, block
: BlockId
) -> Arc
<ItemTree
> {
179 let loc
= db
.lookup_intern_block(block
);
180 let block
= loc
.ast_id
.to_node(db
.upcast());
181 let ctx
= lower
::Ctx
::new(db
, loc
.ast_id
.file_id
);
182 Arc
::new(ctx
.lower_block(&block
))
185 fn shrink_to_fit(&mut self) {
186 if let Some(data
) = &mut self.data
{
210 imports
.shrink_to_fit();
211 extern_crates
.shrink_to_fit();
212 extern_blocks
.shrink_to_fit();
213 functions
.shrink_to_fit();
214 params
.shrink_to_fit();
215 structs
.shrink_to_fit();
216 fields
.shrink_to_fit();
217 unions
.shrink_to_fit();
218 enums
.shrink_to_fit();
219 variants
.shrink_to_fit();
220 consts
.shrink_to_fit();
221 statics
.shrink_to_fit();
222 traits
.shrink_to_fit();
223 impls
.shrink_to_fit();
224 type_aliases
.shrink_to_fit();
225 mods
.shrink_to_fit();
226 macro_calls
.shrink_to_fit();
227 macro_rules
.shrink_to_fit();
228 macro_defs
.shrink_to_fit();
230 vis
.arena
.shrink_to_fit();
235 #[derive(Default, Debug, Eq, PartialEq)]
236 struct ItemVisibilities
{
237 arena
: Arena
<RawVisibility
>,
240 impl ItemVisibilities
{
241 fn alloc(&mut self, vis
: RawVisibility
) -> RawVisibilityId
{
243 RawVisibility
::Public
=> RawVisibilityId
::PUB
,
244 RawVisibility
::Module(path
) if path
.segments().is_empty() => match &path
.kind
{
245 PathKind
::Super(0) => RawVisibilityId
::PRIV
,
246 PathKind
::Crate
=> RawVisibilityId
::PUB_CRATE
,
247 _
=> RawVisibilityId(self.arena
.alloc(vis
).into_raw().into()),
249 _
=> RawVisibilityId(self.arena
.alloc(vis
).into_raw().into()),
254 static VIS_PUB
: RawVisibility
= RawVisibility
::Public
;
255 static VIS_PRIV
: RawVisibility
= RawVisibility
::Module(ModPath
::from_kind(PathKind
::Super(0)));
256 static VIS_PUB_CRATE
: RawVisibility
= RawVisibility
::Module(ModPath
::from_kind(PathKind
::Crate
));
258 #[derive(Default, Debug, Eq, PartialEq)]
259 struct ItemTreeData
{
260 imports
: Arena
<Import
>,
261 extern_crates
: Arena
<ExternCrate
>,
262 extern_blocks
: Arena
<ExternBlock
>,
263 functions
: Arena
<Function
>,
264 params
: Arena
<Param
>,
265 structs
: Arena
<Struct
>,
266 fields
: Arena
<Field
>,
267 unions
: Arena
<Union
>,
269 variants
: Arena
<Variant
>,
270 consts
: Arena
<Const
>,
271 statics
: Arena
<Static
>,
272 traits
: Arena
<Trait
>,
274 type_aliases
: Arena
<TypeAlias
>,
276 macro_calls
: Arena
<MacroCall
>,
277 macro_rules
: Arena
<MacroRules
>,
278 macro_defs
: Arena
<MacroDef
>,
280 vis
: ItemVisibilities
,
283 #[derive(Debug, Eq, PartialEq, Hash)]
285 /// Attributes on an item.
287 /// Inner attributes of the source file.
290 Variant(Idx
<Variant
>),
295 macro_rules
! from_attrs
{
296 ( $
( $var
:ident($t
:ty
) ),+ ) => {
298 impl From
<$t
> for AttrOwner
{
299 fn from(t
: $t
) -> AttrOwner
{
307 from_attrs
!(ModItem(ModItem
), Variant(Idx
<Variant
>), Field(Idx
<Field
>), Param(Idx
<Param
>));
309 /// Trait implemented by all item nodes in the item tree.
310 pub trait ItemTreeNode
: Clone
{
311 type Source
: AstNode
+ Into
<ast
::Item
>;
313 fn ast_id(&self) -> FileAstId
<Self::Source
>;
315 /// Looks up an instance of `Self` in an item tree.
316 fn lookup(tree
: &ItemTree
, index
: Idx
<Self>) -> &Self;
318 /// Downcasts a `ModItem` to a `FileItemTreeId` specific to this type.
319 fn id_from_mod_item(mod_item
: ModItem
) -> Option
<FileItemTreeId
<Self>>;
321 /// Upcasts a `FileItemTreeId` to a generic `ModItem`.
322 fn id_to_mod_item(id
: FileItemTreeId
<Self>) -> ModItem
;
325 pub struct FileItemTreeId
<N
: ItemTreeNode
> {
330 impl<N
: ItemTreeNode
> Clone
for FileItemTreeId
<N
> {
331 fn clone(&self) -> Self {
332 Self { index: self.index, _p: PhantomData }
335 impl<N
: ItemTreeNode
> Copy
for FileItemTreeId
<N
> {}
337 impl<N
: ItemTreeNode
> PartialEq
for FileItemTreeId
<N
> {
338 fn eq(&self, other
: &FileItemTreeId
<N
>) -> bool
{
339 self.index
== other
.index
342 impl<N
: ItemTreeNode
> Eq
for FileItemTreeId
<N
> {}
344 impl<N
: ItemTreeNode
> Hash
for FileItemTreeId
<N
> {
345 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
346 self.index
.hash(state
)
350 impl<N
: ItemTreeNode
> fmt
::Debug
for FileItemTreeId
<N
> {
351 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
356 /// Identifies a particular [`ItemTree`].
357 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
360 block
: Option
<BlockId
>,
364 pub(crate) fn new(file
: HirFileId
, block
: Option
<BlockId
>) -> Self {
368 pub(crate) fn item_tree(&self, db
: &dyn DefDatabase
) -> Arc
<ItemTree
> {
370 Some(block
) => ItemTree
::block_item_tree(db
, block
),
371 None
=> db
.file_item_tree(self.file
),
375 pub(crate) fn file_id(self) -> HirFileId
{
379 pub(crate) fn is_block(self) -> bool
{
385 pub struct ItemTreeId
<N
: ItemTreeNode
> {
387 pub value
: FileItemTreeId
<N
>,
390 impl<N
: ItemTreeNode
> ItemTreeId
<N
> {
391 pub fn new(tree
: TreeId
, idx
: FileItemTreeId
<N
>) -> Self {
392 Self { tree, value: idx }
395 pub fn file_id(self) -> HirFileId
{
399 pub fn tree_id(self) -> TreeId
{
403 pub fn item_tree(self, db
: &dyn DefDatabase
) -> Arc
<ItemTree
> {
404 self.tree
.item_tree(db
)
408 impl<N
: ItemTreeNode
> Copy
for ItemTreeId
<N
> {}
409 impl<N
: ItemTreeNode
> Clone
for ItemTreeId
<N
> {
410 fn clone(&self) -> Self {
415 impl<N
: ItemTreeNode
> PartialEq
for ItemTreeId
<N
> {
416 fn eq(&self, other
: &Self) -> bool
{
417 self.tree
== other
.tree
&& self.value
== other
.value
421 impl<N
: ItemTreeNode
> Eq
for ItemTreeId
<N
> {}
423 impl<N
: ItemTreeNode
> Hash
for ItemTreeId
<N
> {
424 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
425 self.tree
.hash(state
);
426 self.value
.hash(state
);
430 macro_rules
! mod_items
{
431 ( $
( $typ
:ident
in $fld
:ident
-> $ast
:ty
),+ $
(,)?
) => {
432 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
435 $
typ(FileItemTreeId
<$typ
>),
440 impl From
<FileItemTreeId
<$typ
>> for ModItem
{
441 fn from(id
: FileItemTreeId
<$typ
>) -> ModItem
{
448 impl ItemTreeNode
for $typ
{
451 fn ast_id(&self) -> FileAstId
<Self::Source
> {
455 fn lookup(tree
: &ItemTree
, index
: Idx
<Self>) -> &Self {
456 &tree
.data().$fld
[index
]
459 fn id_from_mod_item(mod_item
: ModItem
) -> Option
<FileItemTreeId
<Self>> {
461 ModItem
::$
typ(id
) => Some(id
),
466 fn id_to_mod_item(id
: FileItemTreeId
<Self>) -> ModItem
{
471 impl Index
<Idx
<$typ
>> for ItemTree
{
474 fn index(&self, index
: Idx
<$typ
>) -> &Self::Output
{
475 &self.data().$fld
[index
]
483 Import
in imports
-> ast
::Use
,
484 ExternCrate
in extern_crates
-> ast
::ExternCrate
,
485 ExternBlock
in extern_blocks
-> ast
::ExternBlock
,
486 Function
in functions
-> ast
::Fn
,
487 Struct
in structs
-> ast
::Struct
,
488 Union
in unions
-> ast
::Union
,
489 Enum
in enums
-> ast
::Enum
,
490 Const
in consts
-> ast
::Const
,
491 Static
in statics
-> ast
::Static
,
492 Trait
in traits
-> ast
::Trait
,
493 Impl
in impls
-> ast
::Impl
,
494 TypeAlias
in type_aliases
-> ast
::TypeAlias
,
495 Mod
in mods
-> ast
::Module
,
496 MacroCall
in macro_calls
-> ast
::MacroCall
,
497 MacroRules
in macro_rules
-> ast
::MacroRules
,
498 MacroDef
in macro_defs
-> ast
::MacroDef
,
501 macro_rules
! impl_index
{
502 ( $
($fld
:ident
: $t
:ty
),+ $
(,)?
) => {
504 impl Index
<Idx
<$t
>> for ItemTree
{
507 fn index(&self, index
: Idx
<$t
>) -> &Self::Output
{
508 &self.data().$fld
[index
]
515 impl_index
!(fields
: Field
, variants
: Variant
, params
: Param
);
517 impl Index
<RawVisibilityId
> for ItemTree
{
518 type Output
= RawVisibility
;
519 fn index(&self, index
: RawVisibilityId
) -> &Self::Output
{
521 RawVisibilityId
::PRIV
=> &VIS_PRIV
,
522 RawVisibilityId
::PUB
=> &VIS_PUB
,
523 RawVisibilityId
::PUB_CRATE
=> &VIS_PUB_CRATE
,
524 _
=> &self.data().vis
.arena
[Idx
::from_raw(index
.0.into
())],
529 impl<N
: ItemTreeNode
> Index
<FileItemTreeId
<N
>> for ItemTree
{
531 fn index(&self, id
: FileItemTreeId
<N
>) -> &N
{
532 N
::lookup(self, id
.index
)
536 #[derive(Debug, Clone, Eq, PartialEq)]
538 pub visibility
: RawVisibilityId
,
539 pub ast_id
: FileAstId
<ast
::Use
>,
540 pub use_tree
: UseTree
,
543 #[derive(Debug, Clone, Eq, PartialEq)]
545 pub index
: Idx
<ast
::UseTree
>,
549 #[derive(Debug, Clone, Eq, PartialEq)]
550 pub enum UseTreeKind
{
552 /// use path::to::Item;
553 /// use path::to::Item as Renamed;
554 /// use path::to::Trait as _;
556 Single { path: Interned<ModPath>, alias: Option<ImportAlias> }
,
559 /// use *; // (invalid, but can occur in nested tree)
562 Glob { path: Option<Interned<ModPath>> }
,
565 /// use prefix::{self, Item, ...};
567 Prefixed { prefix: Option<Interned<ModPath>>, list: Box<[UseTree]> }
,
570 #[derive(Debug, Clone, Eq, PartialEq)]
571 pub struct ExternCrate
{
573 pub alias
: Option
<ImportAlias
>,
574 pub visibility
: RawVisibilityId
,
575 pub ast_id
: FileAstId
<ast
::ExternCrate
>,
578 #[derive(Debug, Clone, Eq, PartialEq)]
579 pub struct ExternBlock
{
580 pub abi
: Option
<Interned
<str>>,
581 pub ast_id
: FileAstId
<ast
::ExternBlock
>,
582 pub children
: Box
<[ModItem
]>,
585 #[derive(Debug, Clone, Eq, PartialEq)]
586 pub struct Function
{
588 pub visibility
: RawVisibilityId
,
589 pub explicit_generic_params
: Interned
<GenericParams
>,
590 pub abi
: Option
<Interned
<str>>,
591 pub params
: IdxRange
<Param
>,
592 pub ret_type
: Interned
<TypeRef
>,
593 pub async_ret_type
: Option
<Interned
<TypeRef
>>,
594 pub ast_id
: FileAstId
<ast
::Fn
>,
595 pub(crate) flags
: FnFlags
,
598 #[derive(Debug, Clone, Eq, PartialEq)]
600 Normal(Option
<Name
>, Interned
<TypeRef
>),
604 bitflags
::bitflags
! {
606 pub(crate) struct FnFlags
: u8 {
607 const HAS_SELF_PARAM
= 1 << 0;
608 const HAS_BODY
= 1 << 1;
609 const HAS_DEFAULT_KW
= 1 << 2;
610 const HAS_CONST_KW
= 1 << 3;
611 const HAS_ASYNC_KW
= 1 << 4;
612 const HAS_UNSAFE_KW
= 1 << 5;
613 const IS_VARARGS
= 1 << 6;
617 #[derive(Debug, Clone, Eq, PartialEq)]
620 pub visibility
: RawVisibilityId
,
621 pub generic_params
: Interned
<GenericParams
>,
623 pub ast_id
: FileAstId
<ast
::Struct
>,
626 #[derive(Debug, Clone, Eq, PartialEq)]
629 pub visibility
: RawVisibilityId
,
630 pub generic_params
: Interned
<GenericParams
>,
632 pub ast_id
: FileAstId
<ast
::Union
>,
635 #[derive(Debug, Clone, Eq, PartialEq)]
638 pub visibility
: RawVisibilityId
,
639 pub generic_params
: Interned
<GenericParams
>,
640 pub variants
: IdxRange
<Variant
>,
641 pub ast_id
: FileAstId
<ast
::Enum
>,
644 #[derive(Debug, Clone, Eq, PartialEq)]
646 /// `None` for `const _: () = ();`
647 pub name
: Option
<Name
>,
648 pub visibility
: RawVisibilityId
,
649 pub type_ref
: Interned
<TypeRef
>,
650 pub ast_id
: FileAstId
<ast
::Const
>,
653 #[derive(Debug, Clone, Eq, PartialEq)]
656 pub visibility
: RawVisibilityId
,
658 pub type_ref
: Interned
<TypeRef
>,
659 pub ast_id
: FileAstId
<ast
::Static
>,
662 #[derive(Debug, Clone, Eq, PartialEq)]
665 pub visibility
: RawVisibilityId
,
666 pub generic_params
: Interned
<GenericParams
>,
669 pub items
: Box
<[AssocItem
]>,
670 pub ast_id
: FileAstId
<ast
::Trait
>,
673 #[derive(Debug, Clone, Eq, PartialEq)]
675 pub generic_params
: Interned
<GenericParams
>,
676 pub target_trait
: Option
<Interned
<TraitRef
>>,
677 pub self_ty
: Interned
<TypeRef
>,
678 pub is_negative
: bool
,
679 pub items
: Box
<[AssocItem
]>,
680 pub ast_id
: FileAstId
<ast
::Impl
>,
683 #[derive(Debug, Clone, PartialEq, Eq)]
684 pub struct TypeAlias
{
686 pub visibility
: RawVisibilityId
,
687 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
688 pub bounds
: Box
<[Interned
<TypeBound
>]>,
689 pub generic_params
: Interned
<GenericParams
>,
690 pub type_ref
: Option
<Interned
<TypeRef
>>,
691 pub ast_id
: FileAstId
<ast
::TypeAlias
>,
694 #[derive(Debug, Clone, Eq, PartialEq)]
697 pub visibility
: RawVisibilityId
,
699 pub ast_id
: FileAstId
<ast
::Module
>,
702 #[derive(Debug, Clone, Eq, PartialEq)]
705 Inline { items: Box<[ModItem]> }
,
711 #[derive(Debug, Clone, Eq, PartialEq)]
712 pub struct MacroCall
{
713 /// Path to the called macro.
714 pub path
: Interned
<ModPath
>,
715 pub ast_id
: FileAstId
<ast
::MacroCall
>,
716 pub expand_to
: ExpandTo
,
719 #[derive(Debug, Clone, Eq, PartialEq)]
720 pub struct MacroRules
{
721 /// The name of the declared macro.
723 pub ast_id
: FileAstId
<ast
::MacroRules
>,
726 /// "Macros 2.0" macro definition.
727 #[derive(Debug, Clone, Eq, PartialEq)]
728 pub struct MacroDef
{
730 pub visibility
: RawVisibilityId
,
731 pub ast_id
: FileAstId
<ast
::MacroDef
>,
735 /// Maps a `UseTree` contained in this import back to its AST node.
736 pub fn use_tree_to_ast(
738 db
: &dyn DefDatabase
,
740 index
: Idx
<ast
::UseTree
>,
742 // Re-lower the AST item and get the source map.
743 // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
744 let ast
= InFile
::new(file_id
, self.ast_id
).to_node(db
.upcast());
745 let ast_use_tree
= ast
.use_tree().expect("missing `use_tree`");
746 let hygiene
= Hygiene
::new(db
.upcast(), file_id
);
747 let (_
, source_map
) =
748 lower
::lower_use_tree(db
, &hygiene
, ast_use_tree
).expect("failed to lower use tree");
749 source_map
[index
].clone()
753 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
754 pub enum ImportKind
{
755 /// The `ModPath` is imported normally.
757 /// This is a glob-import of all names in the `ModPath`.
759 /// This is a `some::path::self` import, which imports `some::path` only in type namespace.
764 /// Expands the `UseTree` into individually imported `ModPath`s.
767 mut cb
: impl FnMut(Idx
<ast
::UseTree
>, ModPath
, ImportKind
, Option
<ImportAlias
>),
769 self.expand_impl(None
, &mut cb
)
774 prefix
: Option
<ModPath
>,
775 cb
: &mut dyn FnMut(Idx
<ast
::UseTree
>, ModPath
, ImportKind
, Option
<ImportAlias
>),
778 prefix
: Option
<ModPath
>,
780 ) -> Option
<(ModPath
, ImportKind
)> {
781 match (prefix
, &path
.kind
) {
782 (None
, _
) => Some((path
.clone(), ImportKind
::Plain
)),
783 (Some(mut prefix
), PathKind
::Plain
) => {
784 for segment
in path
.segments() {
785 prefix
.push_segment(segment
.clone());
787 Some((prefix
, ImportKind
::Plain
))
789 (Some(mut prefix
), PathKind
::Super(n
))
790 if *n
> 0 && prefix
.segments().is_empty() =>
792 // `super::super` + `super::rest`
793 match &mut prefix
.kind
{
794 PathKind
::Super(m
) => {
795 cov_mark
::hit
!(concat_super_mod_paths
);
797 for segment
in path
.segments() {
798 prefix
.push_segment(segment
.clone());
800 Some((prefix
, ImportKind
::Plain
))
805 (Some(prefix
), PathKind
::Super(0)) if path
.segments().is_empty() => {
806 // `some::path::self` == `some::path`
807 Some((prefix
, ImportKind
::TypeOnly
))
809 (Some(_
), _
) => None
,
814 UseTreeKind
::Single { path, alias }
=> {
815 if let Some((path
, kind
)) = concat_mod_paths(prefix
, path
) {
816 cb(self.index
, path
, kind
, alias
.clone());
819 UseTreeKind
::Glob { path: Some(path) }
=> {
820 if let Some((path
, _
)) = concat_mod_paths(prefix
, path
) {
821 cb(self.index
, path
, ImportKind
::Glob
, None
);
824 UseTreeKind
::Glob { path: None }
=> {
825 if let Some(prefix
) = prefix
{
826 cb(self.index
, prefix
, ImportKind
::Glob
, None
);
829 UseTreeKind
::Prefixed { prefix: additional_prefix, list }
=> {
830 let prefix
= match additional_prefix
{
831 Some(path
) => match concat_mod_paths(prefix
, path
) {
832 Some((path
, ImportKind
::Plain
)) => Some(path
),
837 for tree
in &**list
{
838 tree
.expand_impl(prefix
.clone(), cb
);
845 macro_rules
! impl_froms
{
846 ($e
:ident { $($v:ident ($t:ty)),* $(,)? }
) => {
848 impl From
<$t
> for $e
{
849 fn from(it
: $t
) -> $e
{
858 pub fn as_assoc_item(&self) -> Option
<AssocItem
> {
861 | ModItem
::ExternCrate(_
)
862 | ModItem
::ExternBlock(_
)
870 | ModItem
::MacroRules(_
)
871 | ModItem
::MacroDef(_
) => None
,
872 ModItem
::MacroCall(call
) => Some(AssocItem
::MacroCall(*call
)),
873 ModItem
::Const(konst
) => Some(AssocItem
::Const(*konst
)),
874 ModItem
::TypeAlias(alias
) => Some(AssocItem
::TypeAlias(*alias
)),
875 ModItem
::Function(func
) => Some(AssocItem
::Function(*func
)),
879 pub fn downcast
<N
: ItemTreeNode
>(self) -> Option
<FileItemTreeId
<N
>> {
880 N
::id_from_mod_item(self)
883 pub fn ast_id(&self, tree
: &ItemTree
) -> FileAstId
<ast
::Item
> {
885 ModItem
::Import(it
) => tree
[it
.index
].ast_id().upcast(),
886 ModItem
::ExternCrate(it
) => tree
[it
.index
].ast_id().upcast(),
887 ModItem
::ExternBlock(it
) => tree
[it
.index
].ast_id().upcast(),
888 ModItem
::Function(it
) => tree
[it
.index
].ast_id().upcast(),
889 ModItem
::Struct(it
) => tree
[it
.index
].ast_id().upcast(),
890 ModItem
::Union(it
) => tree
[it
.index
].ast_id().upcast(),
891 ModItem
::Enum(it
) => tree
[it
.index
].ast_id().upcast(),
892 ModItem
::Const(it
) => tree
[it
.index
].ast_id().upcast(),
893 ModItem
::Static(it
) => tree
[it
.index
].ast_id().upcast(),
894 ModItem
::Trait(it
) => tree
[it
.index
].ast_id().upcast(),
895 ModItem
::Impl(it
) => tree
[it
.index
].ast_id().upcast(),
896 ModItem
::TypeAlias(it
) => tree
[it
.index
].ast_id().upcast(),
897 ModItem
::Mod(it
) => tree
[it
.index
].ast_id().upcast(),
898 ModItem
::MacroCall(it
) => tree
[it
.index
].ast_id().upcast(),
899 ModItem
::MacroRules(it
) => tree
[it
.index
].ast_id().upcast(),
900 ModItem
::MacroDef(it
) => tree
[it
.index
].ast_id().upcast(),
905 #[derive(Debug, Copy, Clone, Eq, PartialEq)]
907 Function(FileItemTreeId
<Function
>),
908 TypeAlias(FileItemTreeId
<TypeAlias
>),
909 Const(FileItemTreeId
<Const
>),
910 MacroCall(FileItemTreeId
<MacroCall
>),
913 impl_froms
!(AssocItem
{
914 Function(FileItemTreeId
<Function
>),
915 TypeAlias(FileItemTreeId
<TypeAlias
>),
916 Const(FileItemTreeId
<Const
>),
917 MacroCall(FileItemTreeId
<MacroCall
>),
920 impl From
<AssocItem
> for ModItem
{
921 fn from(item
: AssocItem
) -> Self {
923 AssocItem
::Function(it
) => it
.into(),
924 AssocItem
::TypeAlias(it
) => it
.into(),
925 AssocItem
::Const(it
) => it
.into(),
926 AssocItem
::MacroCall(it
) => it
.into(),
932 pub fn ast_id(self, tree
: &ItemTree
) -> FileAstId
<ast
::AssocItem
> {
934 AssocItem
::Function(id
) => tree
[id
].ast_id
.upcast(),
935 AssocItem
::TypeAlias(id
) => tree
[id
].ast_id
.upcast(),
936 AssocItem
::Const(id
) => tree
[id
].ast_id
.upcast(),
937 AssocItem
::MacroCall(id
) => tree
[id
].ast_id
.upcast(),
942 #[derive(Debug, Eq, PartialEq)]
946 pub ast_id
: FileAstId
<ast
::Variant
>,
949 #[derive(Debug, Clone, PartialEq, Eq)]
951 Record(IdxRange
<Field
>),
952 Tuple(IdxRange
<Field
>),
956 #[derive(Debug, Clone, PartialEq, Eq)]
957 pub enum FieldAstId
{
958 Record(FileAstId
<ast
::RecordField
>),
959 Tuple(FileAstId
<ast
::TupleField
>),
962 /// A single field of an enum variant or struct
963 #[derive(Debug, Clone, PartialEq, Eq)]
966 pub type_ref
: Interned
<TypeRef
>,
967 pub visibility
: RawVisibilityId
,
968 pub ast_id
: FieldAstId
,