Skip to main content

DefCollector

Struct DefCollector 

Source
struct DefCollector<'db> {
Show 18 fields db: &'db dyn SourceDatabase, def_map: DefMap, local_def_map: LocalDefMap, crate_local_def_map: Option<&'db LocalDefMap>, deps: IndexMap<Name, BuiltDependency, FxBuildHasher>, glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, Visibility, GlobId)>>, unresolved_imports: Vec<ImportDirective>, indeterminate_imports: Vec<(ImportDirective, PerNs)>, unresolved_macros: Vec<MacroDirective<'db>>, unresolved_extern_crates: FxHashSet<Name>, mod_dirs: FxHashMap<ModuleId, ModDir>, cfg_options: &'db CfgOptions, proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>, is_proc_macro: bool, from_glob_import: PerNsGlobImports, skip_attrs: FxHashMap<InFile<ModItemId>, AttrId>, prev_active_attrs: FxHashMap<AstId<Item>, SmallVec<[AttrId; 1]>>, deferred_builtin_derives: FxHashMap<AstId<Item>, Vec<DeferredBuiltinDerive>>,
}
Expand description

Walks the tree of module recursively

Fields§

§db: &'db dyn SourceDatabase§def_map: DefMap§local_def_map: LocalDefMap§crate_local_def_map: Option<&'db LocalDefMap>

Set only in case of blocks.

§deps: IndexMap<Name, BuiltDependency, FxBuildHasher>§glob_imports: FxHashMap<ModuleId, Vec<(ModuleId, Visibility, GlobId)>>§unresolved_imports: Vec<ImportDirective>§indeterminate_imports: Vec<(ImportDirective, PerNs)>§unresolved_macros: Vec<MacroDirective<'db>>§unresolved_extern_crates: FxHashSet<Name>§mod_dirs: FxHashMap<ModuleId, ModDir>§cfg_options: &'db CfgOptions§proc_macros: Box<[(Name, CustomProcMacroExpander, bool)]>

List of procedural macros defined by this crate. This is read from the dynamic library built by the build system, and is the list of proc-macros we can actually expand. It is empty when proc-macro support is disabled (in which case we still do name resolution for them). The bool signals whether the proc-macro has been explicitly disabled for name-resolution.

§is_proc_macro: bool§from_glob_import: PerNsGlobImports§skip_attrs: FxHashMap<InFile<ModItemId>, AttrId>

If we fail to resolve an attribute on a ModItem, we fall back to ignoring the attribute. This map is used to skip all attributes up to and including the one that failed to resolve, in order to not expand them twice.

This also stores the attributes to skip when we resolve derive helpers and non-macro non-builtin attributes in general.

§prev_active_attrs: FxHashMap<AstId<Item>, SmallVec<[AttrId; 1]>>

When we expand attributes, we need to censor all previous active attributes on the same item. Therefore, this holds all active attributes that we already expanded.

§deferred_builtin_derives: FxHashMap<AstId<Item>, Vec<DeferredBuiltinDerive>>

To save memory, we do not really expand builtin derives. Instead, we save them as a BuiltinDeriveImplId.

However, we can only do that when the derive is directly above the item, and there is no attribute in between. Otherwise, all sorts of weird things can happen, like the item name resolving to something else.

Implementations§

Source§

impl<'db> DefCollector<'db>

Source

fn seed_with_top_level(&mut self)

Source

fn seed_with_inner(&mut self, tree_id: TreeId)

Source

fn resolution_loop(&mut self)

Source

fn collect(&mut self)

Source

fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint

When the fixed-point loop reaches a stable state, we might still have some unresolved attributes left over. This takes one of them, and feeds the item it’s applied to back into name resolution.

This effectively ignores the fact that the macro is there and just treats the items as normal code.

This improves UX for unresolved attributes, and replicates the behavior before we supported proc. attribute macros.

Source

fn inject_prelude(&mut self)

Source

fn local_def_map(&mut self) -> &LocalDefMap

Source

fn export_proc_macro( &mut self, def: ProcMacroDef, ast_id: AstId<Fn>, fn_id: FunctionId, )

Adds a definition of procedural macro name to the root module.

§Notes on procedural macro resolution

Procedural macro functionality is provided by the build system: It has to build the proc macro and pass the resulting dynamic library to rust-analyzer.

When procedural macro support is enabled, the list of proc macros exported by a crate is known before we resolve names in the crate. This list is stored in self.proc_macros and is derived from the dynamic library.

However, we also would like to be able to at least resolve macros on our own, without help by the build system. So, when the macro isn’t found in self.proc_macros, we instead use a dummy expander that always errors. This comes with the drawback of macros potentially going out of sync with what the build system sees (since we resolve using VFS state, but Cargo builds only on-disk files). We could and probably should add diagnostics for that.

Source

fn define_macro_rules( &mut self, module_id: ModuleId, name: Name, macro_: MacroRulesId, export: bool, )

Define a macro with macro_rules.

It will define the macro in legacy textual scope, and if it has #[macro_export], then it is also defined in the root module scope. You can use or invoke it by crate::macro_name anywhere, before or after the definition.

It is surprising that the macro will never be in the current module scope. These code fails with “unresolved import/macro”,

ⓘ
mod m { macro_rules! foo { () => {} } }
use m::foo as bar;
ⓘ
macro_rules! foo { () => {} }
self::foo!();
crate::foo!();

Well, this code compiles, because the plain path foo in use is searched in the legacy textual scope only.

macro_rules! foo { () => {} }
use foo as bar;
Source

fn define_legacy_macro(&mut self, module_id: ModuleId, name: Name, mac: MacroId)

Define a legacy textual scoped macro in module

We use a map legacy_macros to store all legacy textual scoped macros visible per module. It will clone all macros from parent legacy scope, whose definition is prior to the definition of current module. And also, macro_use on a module will import all legacy macros visible inside to current legacy scope, with possible shadowing.

Source

fn define_macro_def( &mut self, module_id: ModuleId, name: Name, macro_: Macro2Id, vis: &RawVisibility, )

Define a macro 2.0 macro

The scoped of macro 2.0 macro is equal to normal function

Source

fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId)

Define a proc macro

A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped. And unconditionally exported.

Source

fn import_macros_from_extern_crate( &mut self, krate: Crate, names: Option<Vec<Name>>, extern_crate: Option<ExternCrateId>, )

Import exported macros from another crate. names, if Some(_), specifies the name of macros to be imported. Otherwise this method imports all exported macros.

Exported macros are just all macros in the root module scope. Note that it contains not only all #[macro_export] macros, but also all aliases created by use in the root module, ignoring the visibility of use.

Source

fn resolve_imports(&mut self) -> ReachedFixedPoint

Tries to resolve every currently unresolved import.

Source

fn resolve_import( &self, module_id: ModuleId, import: &Import, ) -> PartialResolvedImport

Source

fn record_resolved_import(&mut self, directive: &ImportDirective)

Source

fn update( &mut self, module_id: ModuleId, resolutions: &[(Option<Name>, PerNs)], vis: Visibility, import: Option<ImportOrExternCrate>, )

Source

fn update_recursive( &mut self, module_id: ModuleId, resolutions: &[(Option<Name>, PerNs)], vis: Visibility, import: Option<ImportOrExternCrate>, depth: usize, )

Source

fn push_res_and_update_glob_vis( &mut self, module_id: ModuleId, name: &Name, defs: PerNs, vis: Visibility, def_import_type: Option<ImportOrExternCrate>, ) -> bool

Source

fn resolve_macros(&mut self) -> ReachedFixedPoint

Source

fn collect_macro_expansion( &mut self, module_id: ModuleId, macro_call_id: MacroCallId, depth: u32, container: ItemContainerId, attr_macro_item: Option<AstId<Item>>, )

Source

fn finish(self) -> (DefMap, LocalDefMap)

Auto Trait Implementations§

§

impl<'db> !RefUnwindSafe for DefCollector<'db>

§

impl<'db> !Send for DefCollector<'db>

§

impl<'db> !Sync for DefCollector<'db>

§

impl<'db> !UnwindSafe for DefCollector<'db>

§

impl<'db> Freeze for DefCollector<'db>

§

impl<'db> Unpin for DefCollector<'db>

§

impl<'db> UnsafeUnpin for DefCollector<'db>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<T> IntoBox<dyn Any> for T
where T: Any,

§

fn into_box(self) -> Box<dyn Any>

Convert self into the appropriate boxed form.
Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> Lookup<T> for T

§

fn into_owned(self) -> T

§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more