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>
impl<'db> DefCollector<'db>
fn seed_with_top_level(&mut self)
fn seed_with_inner(&mut self, tree_id: TreeId)
fn resolution_loop(&mut self)
fn collect(&mut self)
Sourcefn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint
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.
fn inject_prelude(&mut self)
fn local_def_map(&mut self) -> &LocalDefMap
Sourcefn export_proc_macro(
&mut self,
def: ProcMacroDef,
ast_id: AstId<Fn>,
fn_id: FunctionId,
)
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.
Sourcefn define_macro_rules(
&mut self,
module_id: ModuleId,
name: Name,
macro_: MacroRulesId,
export: bool,
)
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;Sourcefn define_legacy_macro(&mut self, module_id: ModuleId, name: Name, mac: MacroId)
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.
Sourcefn define_macro_def(
&mut self,
module_id: ModuleId,
name: Name,
macro_: Macro2Id,
vis: &RawVisibility,
)
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
Sourcefn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId)
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.
Sourcefn import_macros_from_extern_crate(
&mut self,
krate: Crate,
names: Option<Vec<Name>>,
extern_crate: Option<ExternCrateId>,
)
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.
Sourcefn resolve_imports(&mut self) -> ReachedFixedPoint
fn resolve_imports(&mut self) -> ReachedFixedPoint
Tries to resolve every currently unresolved import.
fn resolve_import( &self, module_id: ModuleId, import: &Import, ) -> PartialResolvedImport
fn record_resolved_import(&mut self, directive: &ImportDirective)
fn update( &mut self, module_id: ModuleId, resolutions: &[(Option<Name>, PerNs)], vis: Visibility, import: Option<ImportOrExternCrate>, )
fn update_recursive( &mut self, module_id: ModuleId, resolutions: &[(Option<Name>, PerNs)], vis: Visibility, import: Option<ImportOrExternCrate>, depth: usize, )
fn push_res_and_update_glob_vis( &mut self, module_id: ModuleId, name: &Name, defs: PerNs, vis: Visibility, def_import_type: Option<ImportOrExternCrate>, ) -> bool
fn resolve_macros(&mut self) -> ReachedFixedPoint
fn collect_macro_expansion( &mut self, module_id: ModuleId, macro_call_id: MacroCallId, depth: u32, container: ItemContainerId, attr_macro_item: Option<AstId<Item>>, )
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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