2019-08-13 02:46:42 +03:00
|
|
|
//! After we obtain a fresh AST fragment from a macro, code in this module helps to integrate
|
|
|
|
|
//! that fragment into the module structures that are already partially built.
|
2014-12-30 12:16:42 -06:00
|
|
|
//!
|
2019-08-13 02:46:42 +03:00
|
|
|
//! Items from the fragment are placed into modules,
|
|
|
|
|
//! unexpanded macros in the fragment are visited and registered.
|
|
|
|
|
//! Imports are also considered items and placed into modules here, but not resolved yet.
|
2014-12-30 12:16:42 -06:00
|
|
|
|
2019-11-23 18:19:57 +03:00
|
|
|
use std::cell::Cell;
|
2025-02-03 06:44:41 +03:00
|
|
|
use std::sync::Arc;
|
2014-12-30 12:16:42 -06:00
|
|
|
|
2024-06-18 16:45:50 +03:00
|
|
|
use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind};
|
2021-01-29 08:31:08 +01:00
|
|
|
use rustc_ast::{
|
2025-04-01 14:49:58 +11:00
|
|
|
self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem,
|
|
|
|
|
ForeignItemKind, Impl, Item, ItemKind, MetaItemKind, NodeId, StaticItem, StmtKind, TyAlias,
|
2023-11-26 15:57:31 +03:00
|
|
|
};
|
2024-12-13 14:47:11 +01:00
|
|
|
use rustc_attr_parsing as attr;
|
2024-03-15 14:21:03 +03:00
|
|
|
use rustc_expand::base::ResolverExpand;
|
2019-12-29 17:23:55 +03:00
|
|
|
use rustc_expand::expand::AstFragment;
|
2020-01-09 11:18:47 +01:00
|
|
|
use rustc_hir::def::{self, *};
|
2022-04-15 19:27:53 +02:00
|
|
|
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
|
2025-07-04 14:00:32 -07:00
|
|
|
use rustc_index::bit_set::DenseBitSet;
|
2020-01-09 11:18:47 +01:00
|
|
|
use rustc_metadata::creader::LoadedMacro;
|
2021-12-21 11:24:43 +08:00
|
|
|
use rustc_middle::metadata::ModChild;
|
2024-02-14 15:28:40 +00:00
|
|
|
use rustc_middle::ty::Feed;
|
2023-02-22 19:51:17 +04:00
|
|
|
use rustc_middle::{bug, ty};
|
2021-06-25 20:43:04 +02:00
|
|
|
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
|
2024-12-13 10:29:23 +11:00
|
|
|
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
2024-05-10 13:46:24 +10:00
|
|
|
use tracing::debug;
|
|
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
use crate::Namespace::{MacroNS, TypeNS, ValueNS};
|
2019-11-23 18:19:57 +03:00
|
|
|
use crate::def_collector::collect_definitions;
|
2023-07-04 18:51:35 +03:00
|
|
|
use crate::imports::{ImportData, ImportKind};
|
2020-11-06 16:11:21 +03:00
|
|
|
use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
|
2023-11-10 10:11:24 +08:00
|
|
|
use crate::{
|
2023-04-18 22:46:51 +08:00
|
|
|
BindingKey, Determinacy, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind,
|
2023-11-10 10:11:24 +08:00
|
|
|
ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
|
|
|
|
|
ResolutionError, Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError,
|
2024-09-22 19:05:04 -04:00
|
|
|
errors,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
type Res = def::Res<NodeId>;
|
2019-04-03 09:07:45 +02:00
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra, Id: Into<DefId>> ToNameBinding<'ra>
|
|
|
|
|
for (Module<'ra>, ty::Visibility<Id>, Span, LocalExpnId)
|
2022-08-28 00:10:06 +03:00
|
|
|
{
|
2024-09-10 16:19:40 +10:00
|
|
|
fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> {
|
2023-07-04 17:28:57 +03:00
|
|
|
arenas.alloc_name_binding(NameBindingData {
|
2016-11-07 22:23:26 +00:00
|
|
|
kind: NameBindingKind::Module(self.0),
|
2018-12-29 18:15:29 +03:00
|
|
|
ambiguity: None,
|
2023-07-26 22:46:49 +08:00
|
|
|
warn_ambiguity: false,
|
2022-08-28 00:10:06 +03:00
|
|
|
vis: self.1.to_def_id(),
|
2016-11-07 22:23:26 +00:00
|
|
|
span: self.2,
|
|
|
|
|
expansion: self.3,
|
2016-11-29 02:53:00 +00:00
|
|
|
})
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra, Id: Into<DefId>> ToNameBinding<'ra> for (Res, ty::Visibility<Id>, Span, LocalExpnId) {
|
|
|
|
|
fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> {
|
2023-07-04 17:28:57 +03:00
|
|
|
arenas.alloc_name_binding(NameBindingData {
|
2022-10-30 15:55:58 +04:00
|
|
|
kind: NameBindingKind::Res(self.0),
|
2018-12-29 18:15:29 +03:00
|
|
|
ambiguity: None,
|
2023-07-26 22:46:49 +08:00
|
|
|
warn_ambiguity: false,
|
2022-08-28 00:10:06 +03:00
|
|
|
vis: self.1.to_def_id(),
|
2016-11-07 22:23:26 +00:00
|
|
|
span: self.2,
|
|
|
|
|
expansion: self.3,
|
2016-11-29 02:53:00 +00:00
|
|
|
})
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
2016-01-14 01:42:45 +00:00
|
|
|
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
|
|
|
|
|
/// otherwise, reports an error.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn define<T>(&mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, def: T)
|
2016-11-26 12:48:46 +00:00
|
|
|
where
|
2024-09-10 16:19:40 +10:00
|
|
|
T: ToNameBinding<'ra>,
|
2016-07-28 02:34:01 +00:00
|
|
|
{
|
2016-11-29 02:53:00 +00:00
|
|
|
let binding = def.to_name_binding(self.arenas);
|
2023-04-18 22:46:51 +08:00
|
|
|
let key = self.new_disambiguated_key(ident, ns);
|
2023-07-26 22:46:49 +08:00
|
|
|
if let Err(old_binding) = self.try_define(parent, key, binding, false) {
|
2023-07-04 17:28:57 +03:00
|
|
|
self.report_conflict(parent, ident, ns, old_binding, binding);
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-15 14:19:54 -04:00
|
|
|
/// Walks up the tree of definitions starting at `def_id`,
|
2021-09-12 02:06:27 +03:00
|
|
|
/// stopping at the first encountered module.
|
|
|
|
|
/// Parent block modules for arbitrary def-ids are not recorded for the local crate,
|
|
|
|
|
/// and are not preserved in metadata for foreign crates, so block modules are never
|
|
|
|
|
/// returned by this function.
|
|
|
|
|
///
|
|
|
|
|
/// For the local crate ignoring block modules may be incorrect, so use this method with care.
|
|
|
|
|
///
|
|
|
|
|
/// For foreign crates block modules can be ignored without introducing observable differences,
|
|
|
|
|
/// moreover they has to be ignored right now because they are not kept in metadata.
|
|
|
|
|
/// Foreign parent modules are used for resolving names used by foreign macros with def-site
|
|
|
|
|
/// hygiene, therefore block module ignorability relies on macros with def-site hygiene and
|
|
|
|
|
/// block module parents being unreachable from other crates.
|
|
|
|
|
/// Reachable macros with block module parents exist due to `#[macro_export] macro_rules!`,
|
|
|
|
|
/// but they cannot use def-site hygiene, so the assumption holds
|
|
|
|
|
/// (<https://github.com/rust-lang/rust/pull/77984#issuecomment-712445508>).
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn get_nearest_non_block_module(&mut self, mut def_id: DefId) -> Module<'ra> {
|
2021-09-12 02:06:27 +03:00
|
|
|
loop {
|
|
|
|
|
match self.get_module(def_id) {
|
|
|
|
|
Some(module) => return module,
|
2023-02-22 19:51:17 +04:00
|
|
|
None => def_id = self.tcx.parent(def_id),
|
2021-09-12 02:06:27 +03:00
|
|
|
}
|
2020-10-15 14:19:54 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn expect_module(&mut self, def_id: DefId) -> Module<'ra> {
|
2021-09-12 02:06:27 +03:00
|
|
|
self.get_module(def_id).expect("argument `DefId` is not a module")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// If `def_id` refers to a module (in resolver's sense, i.e. a module item, crate root, enum,
|
|
|
|
|
/// or trait), then this function returns that module's resolver representation, otherwise it
|
|
|
|
|
/// returns `None`.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn get_module(&mut self, def_id: DefId) -> Option<Module<'ra>> {
|
2021-09-12 02:06:27 +03:00
|
|
|
if let module @ Some(..) = self.module_map.get(&def_id) {
|
|
|
|
|
return module.copied();
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
|
2021-09-12 02:06:27 +03:00
|
|
|
if !def_id.is_local() {
|
2023-03-23 20:15:04 +04:00
|
|
|
// Query `def_kind` is not used because query system overhead is too expensive here.
|
|
|
|
|
let def_kind = self.cstore().def_kind_untracked(def_id);
|
2023-03-14 19:01:09 +04:00
|
|
|
if let DefKind::Mod | DefKind::Enum | DefKind::Trait = def_kind {
|
|
|
|
|
let parent = self
|
|
|
|
|
.tcx
|
|
|
|
|
.opt_parent(def_id)
|
|
|
|
|
.map(|parent_id| self.get_nearest_non_block_module(parent_id));
|
2023-03-23 20:15:04 +04:00
|
|
|
// Query `expn_that_defined` is not used because
|
|
|
|
|
// hashing spans in its result is expensive.
|
2023-11-21 20:07:32 +01:00
|
|
|
let expn_id = self.cstore().expn_that_defined_untracked(def_id, self.tcx.sess);
|
2023-03-14 19:01:09 +04:00
|
|
|
return Some(self.new_module(
|
|
|
|
|
parent,
|
2025-03-25 09:09:01 +11:00
|
|
|
ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))),
|
2023-03-14 19:01:09 +04:00
|
|
|
expn_id,
|
|
|
|
|
self.def_span(def_id),
|
|
|
|
|
// FIXME: Account for `#[no_implicit_prelude]` attributes.
|
2023-05-24 14:19:22 +00:00
|
|
|
parent.is_some_and(|module| module.no_implicit_prelude),
|
2023-03-14 19:01:09 +04:00
|
|
|
));
|
2021-09-12 02:06:27 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-03-14 19:01:09 +04:00
|
|
|
|
|
|
|
|
None
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn expn_def_scope(&mut self, expn_id: ExpnId) -> Module<'ra> {
|
2021-09-12 01:47:46 +03:00
|
|
|
match expn_id.expn_data().macro_def_id {
|
|
|
|
|
Some(def_id) => self.macro_def_scope(def_id),
|
|
|
|
|
None => expn_id
|
|
|
|
|
.as_local()
|
2023-07-04 20:00:42 +03:00
|
|
|
.and_then(|expn_id| self.ast_transform_scopes.get(&expn_id).copied())
|
|
|
|
|
.unwrap_or(self.graph_root),
|
2021-09-12 01:47:46 +03:00
|
|
|
}
|
2021-06-28 19:29:55 +02:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn macro_def_scope(&mut self, def_id: DefId) -> Module<'ra> {
|
2020-05-24 12:18:22 +01:00
|
|
|
if let Some(id) = def_id.as_local() {
|
2019-08-08 23:57:35 +03:00
|
|
|
self.local_macro_def_scopes[&id]
|
|
|
|
|
} else {
|
2021-09-12 02:06:27 +03:00
|
|
|
self.get_nearest_non_block_module(def_id)
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-08 23:52:20 +02:00
|
|
|
pub(crate) fn get_macro(&self, res: Res) -> Option<&'ra MacroData> {
|
2019-08-08 23:57:35 +03:00
|
|
|
match res {
|
2020-12-29 22:24:15 +01:00
|
|
|
Res::Def(DefKind::Macro(..), def_id) => Some(self.get_macro_by_def_id(def_id)),
|
2025-07-08 23:52:20 +02:00
|
|
|
Res::NonMacroAttr(_) => Some(self.non_macro_attr),
|
2019-08-08 23:57:35 +03:00
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-08 23:52:20 +02:00
|
|
|
pub(crate) fn get_macro_by_def_id(&self, def_id: DefId) -> &'ra MacroData {
|
|
|
|
|
// Local macros are always compiled.
|
|
|
|
|
match def_id.as_local() {
|
|
|
|
|
Some(local_def_id) => self.local_macro_map[&local_def_id],
|
|
|
|
|
None => *self.extern_macro_map.borrow_mut().entry(def_id).or_insert_with(|| {
|
|
|
|
|
let loaded_macro = self.cstore().load_macro_untracked(def_id, self.tcx);
|
|
|
|
|
let macro_data = match loaded_macro {
|
|
|
|
|
LoadedMacro::MacroDef { def, ident, attrs, span, edition } => {
|
|
|
|
|
self.compile_macro(&def, ident, &attrs, span, ast::DUMMY_NODE_ID, edition)
|
|
|
|
|
}
|
|
|
|
|
LoadedMacro::ProcMacro(ext) => MacroData::new(Arc::new(ext)),
|
|
|
|
|
};
|
2019-08-08 23:57:35 +03:00
|
|
|
|
2025-07-08 23:52:20 +02:00
|
|
|
self.arenas.alloc_macro(macro_data)
|
|
|
|
|
}),
|
|
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
|
2022-05-20 19:51:09 -04:00
|
|
|
pub(crate) fn build_reduced_graph(
|
2019-08-17 19:32:52 +03:00
|
|
|
&mut self,
|
|
|
|
|
fragment: &AstFragment,
|
2024-09-10 16:19:40 +10:00
|
|
|
parent_scope: ParentScope<'ra>,
|
|
|
|
|
) -> MacroRulesScopeRef<'ra> {
|
2020-06-20 19:59:29 +01:00
|
|
|
collect_definitions(self, fragment, parent_scope.expansion);
|
2019-08-13 02:13:36 +03:00
|
|
|
let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope };
|
|
|
|
|
fragment.visit_with(&mut visitor);
|
2020-03-14 01:06:36 +03:00
|
|
|
visitor.parent_scope.macro_rules
|
2019-08-13 02:13:36 +03:00
|
|
|
}
|
2019-08-16 21:19:43 +03:00
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'ra>) {
|
2023-04-19 16:27:31 +03:00
|
|
|
for child in self.tcx.module_children(module.def_id()) {
|
2020-11-06 16:11:21 +03:00
|
|
|
let parent_scope = ParentScope::module(module, self);
|
2024-08-26 09:24:42 +08:00
|
|
|
self.build_reduced_graph_for_external_crate_res(child, parent_scope)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Builds the reduced graph for a single item in an external crate.
|
|
|
|
|
fn build_reduced_graph_for_external_crate_res(
|
|
|
|
|
&mut self,
|
|
|
|
|
child: &ModChild,
|
2024-09-10 16:19:40 +10:00
|
|
|
parent_scope: ParentScope<'ra>,
|
2024-08-26 09:24:42 +08:00
|
|
|
) {
|
|
|
|
|
let parent = parent_scope.module;
|
|
|
|
|
let ModChild { ident, res, vis, ref reexport_chain } = *child;
|
|
|
|
|
let span = self.def_span(
|
|
|
|
|
reexport_chain
|
|
|
|
|
.first()
|
|
|
|
|
.and_then(|reexport| reexport.id())
|
|
|
|
|
.unwrap_or_else(|| res.def_id()),
|
|
|
|
|
);
|
|
|
|
|
let res = res.expect_non_local();
|
|
|
|
|
let expansion = parent_scope.expansion;
|
|
|
|
|
// Record primary definitions.
|
|
|
|
|
match res {
|
|
|
|
|
Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => {
|
|
|
|
|
let module = self.expect_module(def_id);
|
|
|
|
|
self.define(parent, ident, TypeNS, (module, vis, span, expansion));
|
|
|
|
|
}
|
|
|
|
|
Res::Def(
|
|
|
|
|
DefKind::Struct
|
|
|
|
|
| DefKind::Union
|
|
|
|
|
| DefKind::Variant
|
|
|
|
|
| DefKind::TyAlias
|
|
|
|
|
| DefKind::ForeignTy
|
|
|
|
|
| DefKind::OpaqueTy
|
|
|
|
|
| DefKind::TraitAlias
|
|
|
|
|
| DefKind::AssocTy,
|
|
|
|
|
_,
|
|
|
|
|
)
|
|
|
|
|
| Res::PrimTy(..)
|
|
|
|
|
| Res::ToolMod => self.define(parent, ident, TypeNS, (res, vis, span, expansion)),
|
|
|
|
|
Res::Def(
|
|
|
|
|
DefKind::Fn
|
|
|
|
|
| DefKind::AssocFn
|
|
|
|
|
| DefKind::Static { .. }
|
|
|
|
|
| DefKind::Const
|
|
|
|
|
| DefKind::AssocConst
|
|
|
|
|
| DefKind::Ctor(..),
|
|
|
|
|
_,
|
|
|
|
|
) => self.define(parent, ident, ValueNS, (res, vis, span, expansion)),
|
|
|
|
|
Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
|
|
|
|
|
self.define(parent, ident, MacroNS, (res, vis, span, expansion))
|
|
|
|
|
}
|
|
|
|
|
Res::Def(
|
|
|
|
|
DefKind::TyParam
|
|
|
|
|
| DefKind::ConstParam
|
|
|
|
|
| DefKind::ExternCrate
|
|
|
|
|
| DefKind::Use
|
|
|
|
|
| DefKind::ForeignMod
|
|
|
|
|
| DefKind::AnonConst
|
|
|
|
|
| DefKind::InlineConst
|
|
|
|
|
| DefKind::Field
|
|
|
|
|
| DefKind::LifetimeParam
|
|
|
|
|
| DefKind::GlobalAsm
|
|
|
|
|
| DefKind::Closure
|
2024-08-01 13:05:17 -04:00
|
|
|
| DefKind::SyntheticCoroutineBody
|
2024-08-26 09:24:42 +08:00
|
|
|
| DefKind::Impl { .. },
|
|
|
|
|
_,
|
|
|
|
|
)
|
|
|
|
|
| Res::Local(..)
|
|
|
|
|
| Res::SelfTyParam { .. }
|
|
|
|
|
| Res::SelfTyAlias { .. }
|
|
|
|
|
| Res::SelfCtor(..)
|
|
|
|
|
| Res::Err => bug!("unexpected resolution: {:?}", res),
|
2019-08-16 21:19:43 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
struct BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|
|
|
|
r: &'a mut Resolver<'ra, 'tcx>,
|
|
|
|
|
parent_scope: ParentScope<'ra>,
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra, 'tcx> AsMut<Resolver<'ra, 'tcx>> for BuildReducedGraphVisitor<'_, 'ra, 'tcx> {
|
|
|
|
|
fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> {
|
2019-07-29 21:19:50 +03:00
|
|
|
self.r
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
2023-11-21 23:40:23 +03:00
|
|
|
fn res(&self, def_id: impl Into<DefId>) -> Res {
|
|
|
|
|
let def_id = def_id.into();
|
|
|
|
|
Res::Def(self.r.tcx.def_kind(def_id), def_id)
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-08 23:57:35 +03:00
|
|
|
fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
|
2022-03-24 02:55:22 +03:00
|
|
|
self.try_resolve_visibility(vis, true).unwrap_or_else(|err| {
|
2019-12-07 01:49:21 +03:00
|
|
|
self.r.report_vis_error(err);
|
|
|
|
|
ty::Visibility::Public
|
|
|
|
|
})
|
2019-12-07 00:03:58 +03:00
|
|
|
}
|
|
|
|
|
|
2022-03-24 02:55:22 +03:00
|
|
|
fn try_resolve_visibility<'ast>(
|
2019-12-07 00:03:58 +03:00
|
|
|
&mut self,
|
2019-12-07 01:49:21 +03:00
|
|
|
vis: &'ast ast::Visibility,
|
2022-03-24 02:55:22 +03:00
|
|
|
finalize: bool,
|
2019-12-07 01:49:21 +03:00
|
|
|
) -> Result<ty::Visibility, VisResolutionError<'ast>> {
|
2019-08-08 23:57:35 +03:00
|
|
|
let parent_scope = &self.parent_scope;
|
2020-08-21 19:11:00 -04:00
|
|
|
match vis.kind {
|
2019-12-07 01:49:21 +03:00
|
|
|
ast::VisibilityKind::Public => Ok(ty::Visibility::Public),
|
2019-08-08 23:57:35 +03:00
|
|
|
ast::VisibilityKind::Inherited => {
|
2021-01-06 17:19:47 +03:00
|
|
|
Ok(match self.parent_scope.module.kind {
|
|
|
|
|
// Any inherited visibility resolved directly inside an enum or trait
|
|
|
|
|
// (i.e. variants, fields, and trait items) inherits from the visibility
|
|
|
|
|
// of the enum or trait.
|
|
|
|
|
ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => {
|
2023-12-05 23:16:08 +03:00
|
|
|
self.r.tcx.visibility(def_id).expect_local()
|
2021-01-06 17:19:47 +03:00
|
|
|
}
|
|
|
|
|
// Otherwise, the visibility is restricted to the nearest parent `mod` item.
|
2022-08-28 00:10:06 +03:00
|
|
|
_ => ty::Visibility::Restricted(
|
|
|
|
|
self.parent_scope.module.nearest_parent_mod().expect_local(),
|
|
|
|
|
),
|
2021-01-06 17:19:47 +03:00
|
|
|
})
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
ast::VisibilityKind::Restricted { ref path, id, .. } => {
|
|
|
|
|
// For visibilities we are not ready to provide correct implementation of "uniform
|
|
|
|
|
// paths" right now, so on 2018 edition we only allow module-relative paths for now.
|
|
|
|
|
// On 2015 edition visibilities are resolved as crate-relative by default,
|
|
|
|
|
// so we are prepending a root segment if necessary.
|
|
|
|
|
let ident = path.segments.get(0).expect("empty path in visibility").ident;
|
|
|
|
|
let crate_root = if ident.is_path_segment_keyword() {
|
|
|
|
|
None
|
2023-02-01 10:42:20 +00:00
|
|
|
} else if ident.span.is_rust_2015() {
|
2019-08-08 23:57:35 +03:00
|
|
|
Some(Segment::from_ident(Ident::new(
|
2019-12-07 01:49:21 +03:00
|
|
|
kw::PathRoot,
|
|
|
|
|
path.span.shrink_to_lo().with_ctxt(ident.span.ctxt()),
|
2019-08-08 23:57:35 +03:00
|
|
|
)))
|
2019-12-07 01:49:21 +03:00
|
|
|
} else {
|
|
|
|
|
return Err(VisResolutionError::Relative2018(ident.span, path));
|
2019-08-08 23:57:35 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let segments = crate_root
|
|
|
|
|
.into_iter()
|
|
|
|
|
.chain(path.segments.iter().map(|seg| seg.into()))
|
|
|
|
|
.collect::<Vec<_>>();
|
2019-12-07 01:49:21 +03:00
|
|
|
let expected_found_error = |res| {
|
|
|
|
|
Err(VisResolutionError::ExpectedFound(
|
|
|
|
|
path.span,
|
|
|
|
|
Segment::names_to_string(&segments),
|
|
|
|
|
res,
|
|
|
|
|
))
|
|
|
|
|
};
|
2019-08-08 23:57:35 +03:00
|
|
|
match self.r.resolve_path(
|
|
|
|
|
&segments,
|
2023-03-19 10:46:19 +00:00
|
|
|
None,
|
2019-08-08 23:57:35 +03:00
|
|
|
parent_scope,
|
2022-04-30 16:26:36 +03:00
|
|
|
finalize.then(|| Finalize::new(id, path.span)),
|
2022-04-08 22:50:56 +02:00
|
|
|
None,
|
2024-08-06 19:27:15 +08:00
|
|
|
None,
|
2019-08-08 23:57:35 +03:00
|
|
|
) {
|
|
|
|
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
|
|
|
|
|
let res = module.res().expect("visibility resolved to unnamed block");
|
2022-03-24 02:55:22 +03:00
|
|
|
if finalize {
|
2019-12-07 00:03:58 +03:00
|
|
|
self.r.record_partial_res(id, PartialRes::new(res));
|
|
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
if module.is_normal() {
|
2023-01-30 11:03:32 +00:00
|
|
|
match res {
|
|
|
|
|
Res::Err => Ok(ty::Visibility::Public),
|
|
|
|
|
_ => {
|
|
|
|
|
let vis = ty::Visibility::Restricted(res.def_id());
|
|
|
|
|
if self.r.is_accessible_from(vis, parent_scope.module) {
|
|
|
|
|
Ok(vis.expect_local())
|
|
|
|
|
} else {
|
|
|
|
|
Err(VisResolutionError::AncestorOnly(path.span))
|
|
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2019-12-07 01:49:21 +03:00
|
|
|
expected_found_error(res)
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
2019-12-07 01:49:21 +03:00
|
|
|
PathResult::Module(..) => Err(VisResolutionError::ModuleOnly(path.span)),
|
|
|
|
|
PathResult::NonModule(partial_res) => {
|
2022-10-10 19:21:35 +04:00
|
|
|
expected_found_error(partial_res.expect_full_res())
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-12-07 01:49:21 +03:00
|
|
|
PathResult::Failed { span, label, suggestion, .. } => {
|
|
|
|
|
Err(VisResolutionError::FailedToResolve(span, label, suggestion))
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-12-07 01:49:21 +03:00
|
|
|
PathResult::Indeterminate => Err(VisResolutionError::Indeterminate(path.span)),
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-06 19:21:22 +00:00
|
|
|
fn insert_field_idents(&mut self, def_id: LocalDefId, fields: &[ast::FieldDef]) {
|
2024-01-04 21:45:06 +08:00
|
|
|
if fields.iter().any(|field| field.is_placeholder) {
|
2023-02-22 13:55:06 +04:00
|
|
|
// The fields are not expanded yet.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2024-07-06 19:21:22 +00:00
|
|
|
let fields = fields
|
|
|
|
|
.iter()
|
|
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, field)| {
|
|
|
|
|
field.ident.unwrap_or_else(|| Ident::from_str_and_span(&format!("{i}"), field.span))
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
self.r.field_names.insert(def_id, fields);
|
2023-01-10 20:57:02 +00:00
|
|
|
}
|
|
|
|
|
|
2024-01-04 21:45:06 +08:00
|
|
|
fn insert_field_visibilities_local(&mut self, def_id: DefId, fields: &[ast::FieldDef]) {
|
|
|
|
|
let field_vis = fields
|
2023-01-10 20:57:02 +00:00
|
|
|
.iter()
|
|
|
|
|
.map(|field| field.vis.span.until(field.ident.map_or(field.ty.span, |i| i.span)))
|
|
|
|
|
.collect();
|
2023-01-08 01:15:28 +00:00
|
|
|
self.r.field_visibility_spans.insert(def_id, field_vis);
|
2019-12-07 00:55:02 +03:00
|
|
|
}
|
|
|
|
|
|
2014-12-30 12:16:42 -06:00
|
|
|
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
|
2016-01-27 10:51:22 +00:00
|
|
|
// If any statements are items, we need to create an anonymous module
|
2020-10-26 21:02:48 -04:00
|
|
|
block
|
|
|
|
|
.stmts
|
|
|
|
|
.iter()
|
|
|
|
|
.any(|statement| matches!(statement.kind, StmtKind::Item(_) | StmtKind::MacCall(_)))
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
// Add an import to the current module.
|
|
|
|
|
fn add_import(
|
2019-08-08 23:57:35 +03:00
|
|
|
&mut self,
|
|
|
|
|
module_path: Vec<Segment>,
|
2024-09-10 16:19:40 +10:00
|
|
|
kind: ImportKind<'ra>,
|
2019-08-08 23:57:35 +03:00
|
|
|
span: Span,
|
|
|
|
|
item: &ast::Item,
|
|
|
|
|
root_span: Span,
|
|
|
|
|
root_id: NodeId,
|
|
|
|
|
vis: ty::Visibility,
|
|
|
|
|
) {
|
2019-08-13 01:39:10 +03:00
|
|
|
let current_module = self.parent_scope.module;
|
2023-07-04 18:51:35 +03:00
|
|
|
let import = self.r.arenas.alloc_import(ImportData {
|
2020-03-07 18:49:13 +03:00
|
|
|
kind,
|
2019-08-13 01:39:10 +03:00
|
|
|
parent_scope: self.parent_scope,
|
2019-08-08 23:57:35 +03:00
|
|
|
module_path,
|
|
|
|
|
imported_module: Cell::new(None),
|
|
|
|
|
span,
|
|
|
|
|
use_span: item.span,
|
|
|
|
|
use_span_with_attributes: item.span_with_attributes(),
|
|
|
|
|
has_attributes: !item.attrs.is_empty(),
|
|
|
|
|
root_span,
|
|
|
|
|
root_id,
|
2024-08-06 19:27:15 +08:00
|
|
|
vis,
|
2019-08-08 23:57:35 +03:00
|
|
|
});
|
|
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
self.r.indeterminate_imports.push(import);
|
|
|
|
|
match import.kind {
|
2019-09-09 21:04:26 +01:00
|
|
|
// Don't add unresolved underscore imports to modules
|
2020-03-07 18:49:13 +03:00
|
|
|
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
|
|
|
|
|
ImportKind::Single { target, type_ns_only, .. } => {
|
2019-08-08 23:57:35 +03:00
|
|
|
self.r.per_ns(|this, ns| {
|
|
|
|
|
if !type_ns_only || ns == TypeNS {
|
2023-04-18 22:46:51 +08:00
|
|
|
let key = BindingKey::new(target, ns);
|
2019-09-09 21:04:26 +01:00
|
|
|
let mut resolution = this.resolution(current_module, key).borrow_mut();
|
2023-07-04 18:51:35 +03:00
|
|
|
resolution.single_imports.insert(import);
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
// We don't add prelude imports to the globs since they only affect lexical scopes,
|
|
|
|
|
// which are not relevant to import resolution.
|
2020-03-07 18:49:13 +03:00
|
|
|
ImportKind::Glob { is_prelude: true, .. } => {}
|
2020-03-07 19:02:32 +03:00
|
|
|
ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(import),
|
2019-08-08 23:57:35 +03:00
|
|
|
_ => unreachable!(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-08-11 11:13:57 +03:00
|
|
|
fn build_reduced_graph_for_use_tree(
|
|
|
|
|
&mut self,
|
2018-10-27 20:23:54 +03:00
|
|
|
// This particular use tree
|
2018-08-11 11:13:57 +03:00
|
|
|
use_tree: &ast::UseTree,
|
|
|
|
|
id: NodeId,
|
2018-09-12 15:21:50 +12:00
|
|
|
parent_prefix: &[Segment],
|
2018-08-11 11:13:57 +03:00
|
|
|
nested: bool,
|
2023-12-20 20:02:40 +03:00
|
|
|
list_stem: bool,
|
2018-10-27 20:23:54 +03:00
|
|
|
// The whole `use` item
|
|
|
|
|
item: &Item,
|
|
|
|
|
vis: ty::Visibility,
|
|
|
|
|
root_span: Span,
|
2018-08-11 11:13:57 +03:00
|
|
|
) {
|
2018-11-03 19:41:44 +03:00
|
|
|
debug!(
|
|
|
|
|
"build_reduced_graph_for_use_tree(parent_prefix={:?}, use_tree={:?}, nested={})",
|
|
|
|
|
parent_prefix, use_tree, nested
|
|
|
|
|
);
|
2018-08-11 11:13:57 +03:00
|
|
|
|
2023-12-20 20:02:40 +03:00
|
|
|
// Top level use tree reuses the item's id and list stems reuse their parent
|
|
|
|
|
// use tree's ids, so in both cases their visibilities are already filled.
|
|
|
|
|
if nested && !list_stem {
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(self.r.feed(id), vis);
|
2023-12-05 23:16:08 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-03 22:02:36 +03:00
|
|
|
let mut prefix_iter = parent_prefix
|
|
|
|
|
.iter()
|
|
|
|
|
.cloned()
|
2018-11-18 14:41:06 +03:00
|
|
|
.chain(use_tree.prefix.segments.iter().map(|seg| seg.into()))
|
|
|
|
|
.peekable();
|
2018-11-03 22:02:36 +03:00
|
|
|
|
|
|
|
|
// On 2015 edition imports are resolved as crate-relative by default,
|
|
|
|
|
// so prefixes are prepended with crate root segment if necessary.
|
|
|
|
|
// The root is prepended lazily, when the first non-empty prefix or terminating glob
|
|
|
|
|
// appears, so imports in braced groups can have roots prepended independently.
|
2020-09-18 19:11:06 +02:00
|
|
|
let is_glob = matches!(use_tree.kind, ast::UseTreeKind::Glob);
|
2018-11-18 03:25:59 +03:00
|
|
|
let crate_root = match prefix_iter.peek() {
|
2023-02-01 10:42:20 +00:00
|
|
|
Some(seg) if !seg.ident.is_path_segment_keyword() && seg.ident.span.is_rust_2015() => {
|
2018-11-18 03:25:59 +03:00
|
|
|
Some(seg.ident.span.ctxt())
|
|
|
|
|
}
|
2023-02-01 10:42:20 +00:00
|
|
|
None if is_glob && use_tree.span.is_rust_2015() => Some(use_tree.span.ctxt()),
|
2018-11-18 03:25:59 +03:00
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
.map(|ctxt| {
|
|
|
|
|
Segment::from_ident(Ident::new(
|
2019-05-11 17:41:37 +03:00
|
|
|
kw::PathRoot,
|
|
|
|
|
use_tree.prefix.span.shrink_to_lo().with_ctxt(ctxt),
|
2018-11-18 03:25:59 +03:00
|
|
|
))
|
|
|
|
|
});
|
2014-12-30 12:16:42 -06:00
|
|
|
|
2018-11-03 22:02:36 +03:00
|
|
|
let prefix = crate_root.into_iter().chain(prefix_iter).collect::<Vec<_>>();
|
2018-09-06 13:29:45 +03:00
|
|
|
debug!("build_reduced_graph_for_use_tree: prefix={:?}", prefix);
|
2018-11-03 22:02:36 +03:00
|
|
|
|
2018-10-27 23:38:09 +03:00
|
|
|
let empty_for_self = |prefix: &[Segment]| {
|
2019-05-11 17:41:37 +03:00
|
|
|
prefix.is_empty() || prefix.len() == 1 && prefix[0].ident.name == kw::PathRoot
|
2018-10-27 23:38:09 +03:00
|
|
|
};
|
2017-09-26 23:04:00 +02:00
|
|
|
match use_tree.kind {
|
2022-12-01 18:51:20 +03:00
|
|
|
ast::UseTreeKind::Simple(rename) => {
|
2019-09-09 21:04:26 +01:00
|
|
|
let mut ident = use_tree.ident();
|
2018-09-06 13:29:45 +03:00
|
|
|
let mut module_path = prefix;
|
2018-03-18 16:47:09 +03:00
|
|
|
let mut source = module_path.pop().unwrap();
|
2017-09-26 23:04:00 +02:00
|
|
|
let mut type_ns_only = false;
|
|
|
|
|
|
|
|
|
|
if nested {
|
|
|
|
|
// Correctly handle `self`
|
2019-05-11 17:41:37 +03:00
|
|
|
if source.ident.name == kw::SelfLower {
|
2017-09-26 23:04:00 +02:00
|
|
|
type_ns_only = true;
|
|
|
|
|
|
2018-10-27 23:38:09 +03:00
|
|
|
if empty_for_self(&module_path) {
|
2019-08-08 23:32:58 +03:00
|
|
|
self.r.report_error(
|
2017-09-26 23:04:00 +02:00
|
|
|
use_tree.span,
|
|
|
|
|
ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix,
|
|
|
|
|
);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-12-23 21:34:36 +02:00
|
|
|
|
2020-05-03 18:56:52 +02:00
|
|
|
// Replace `use foo::{ self };` with `use foo;`
|
2022-11-13 13:46:11 +05:30
|
|
|
let self_span = source.ident.span;
|
2018-07-13 12:38:49 -07:00
|
|
|
source = module_path.pop().unwrap();
|
2018-03-09 18:58:44 +03:00
|
|
|
if rename.is_none() {
|
2022-11-13 13:46:11 +05:30
|
|
|
// Keep the span of `self`, but the name of `foo`
|
2025-04-24 11:56:44 +10:00
|
|
|
ident = Ident::new(source.ident.name, self_span);
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Disallow `self`
|
2019-05-11 17:41:37 +03:00
|
|
|
if source.ident.name == kw::SelfLower {
|
2020-05-03 18:54:21 +02:00
|
|
|
let parent = module_path.last();
|
|
|
|
|
|
|
|
|
|
let span = match parent {
|
|
|
|
|
// only `::self` from `use foo::self as bar`
|
|
|
|
|
Some(seg) => seg.ident.span.shrink_to_hi().to(source.ident.span),
|
|
|
|
|
None => source.ident.span,
|
|
|
|
|
};
|
|
|
|
|
let span_with_rename = match rename {
|
|
|
|
|
// only `self as bar` from `use foo::self as bar`
|
|
|
|
|
Some(rename) => source.ident.span.to(rename.span),
|
|
|
|
|
None => source.ident.span,
|
|
|
|
|
};
|
|
|
|
|
self.r.report_error(
|
|
|
|
|
span,
|
|
|
|
|
ResolutionError::SelfImportsOnlyAllowedWithin {
|
|
|
|
|
root: parent.is_none(),
|
|
|
|
|
span_with_rename,
|
2019-08-08 23:32:58 +03:00
|
|
|
},
|
|
|
|
|
);
|
2020-05-03 18:56:52 +02:00
|
|
|
|
|
|
|
|
// Error recovery: replace `use foo::self;` with `use foo;`
|
|
|
|
|
if let Some(parent) = module_path.pop() {
|
|
|
|
|
source = parent;
|
|
|
|
|
if rename.is_none() {
|
|
|
|
|
ident = source.ident;
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
2014-12-23 21:34:36 +02:00
|
|
|
|
2017-09-26 23:04:00 +02:00
|
|
|
// Disallow `use $crate;`
|
2019-05-11 17:41:37 +03:00
|
|
|
if source.ident.name == kw::DollarCrate && module_path.is_empty() {
|
2019-08-08 14:06:42 +03:00
|
|
|
let crate_root = self.r.resolve_crate_root(source.ident);
|
2017-09-26 23:04:00 +02:00
|
|
|
let crate_name = match crate_root.kind {
|
2019-04-20 19:46:19 +03:00
|
|
|
ModuleKind::Def(.., name) => name,
|
2022-07-25 19:45:26 +02:00
|
|
|
ModuleKind::Block => unreachable!(),
|
2016-11-10 06:19:54 +00:00
|
|
|
};
|
2018-08-09 16:29:22 +03:00
|
|
|
// HACK(eddyb) unclear how good this is, but keeping `$crate`
|
2023-01-05 09:45:44 +01:00
|
|
|
// in `source` breaks `tests/ui/imports/import-crate-var.rs`,
|
2018-08-09 16:29:22 +03:00
|
|
|
// while the current crate doesn't have a valid `crate_name`.
|
2025-03-25 09:09:01 +11:00
|
|
|
if let Some(crate_name) = crate_name {
|
2018-07-13 12:38:49 -07:00
|
|
|
// `crate_name` should not be interpreted as relative.
|
2022-03-10 23:12:35 +01:00
|
|
|
module_path.push(Segment::from_ident_and_id(
|
2025-04-24 11:56:44 +10:00
|
|
|
Ident::new(kw::PathRoot, source.ident.span),
|
2022-03-10 23:12:35 +01:00
|
|
|
self.r.next_node_id(),
|
|
|
|
|
));
|
2018-09-12 15:21:50 +12:00
|
|
|
source.ident.name = crate_name;
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
2018-03-09 18:58:44 +03:00
|
|
|
if rename.is_none() {
|
2025-03-25 09:09:01 +11:00
|
|
|
ident.name = sym::dummy;
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
|
|
|
|
|
2023-12-18 22:21:37 +11:00
|
|
|
self.r.dcx().emit_err(errors::CrateImported { span: item.span });
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-11 17:41:37 +03:00
|
|
|
if ident.name == kw::Crate {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::UnnamedCrateRootImport { span: ident.span });
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
|
|
|
|
|
2020-03-07 18:49:13 +03:00
|
|
|
let kind = ImportKind::Single {
|
2018-09-12 15:21:50 +12:00
|
|
|
source: source.ident,
|
2018-11-30 21:16:21 +03:00
|
|
|
target: ident,
|
|
|
|
|
source_bindings: PerNS {
|
2019-07-03 11:44:57 +03:00
|
|
|
type_ns: Cell::new(Err(Determinacy::Undetermined)),
|
|
|
|
|
value_ns: Cell::new(Err(Determinacy::Undetermined)),
|
|
|
|
|
macro_ns: Cell::new(Err(Determinacy::Undetermined)),
|
2018-04-30 02:20:14 +03:00
|
|
|
},
|
2018-11-30 21:16:21 +03:00
|
|
|
target_bindings: PerNS {
|
|
|
|
|
type_ns: Cell::new(None),
|
|
|
|
|
value_ns: Cell::new(None),
|
|
|
|
|
macro_ns: Cell::new(None),
|
|
|
|
|
},
|
2017-09-26 23:04:00 +02:00
|
|
|
type_ns_only,
|
2019-01-29 13:34:40 +01:00
|
|
|
nested,
|
2022-10-30 13:35:31 +04:00
|
|
|
id,
|
2017-09-26 23:04:00 +02:00
|
|
|
};
|
2021-07-26 05:38:16 +02:00
|
|
|
|
2022-10-30 13:35:31 +04:00
|
|
|
self.add_import(module_path, kind, use_tree.span, item, root_span, item.id, vis);
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
|
|
|
|
ast::UseTreeKind::Glob => {
|
2020-03-07 18:49:13 +03:00
|
|
|
let kind = ImportKind::Glob {
|
2024-12-07 15:27:17 +01:00
|
|
|
is_prelude: ast::attr::contains_name(&item.attrs, sym::prelude_import),
|
2022-08-27 18:36:57 +03:00
|
|
|
max_vis: Cell::new(None),
|
2022-10-30 13:35:31 +04:00
|
|
|
id,
|
2017-09-26 23:04:00 +02:00
|
|
|
};
|
2023-12-05 23:16:08 +03:00
|
|
|
|
2022-10-30 13:35:31 +04:00
|
|
|
self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
2024-04-02 00:26:10 +02:00
|
|
|
ast::UseTreeKind::Nested { ref items, .. } => {
|
2017-09-26 23:04:00 +02:00
|
|
|
// Ensure there is at most one `self` in the list
|
|
|
|
|
let self_spans = items
|
|
|
|
|
.iter()
|
2022-12-18 17:01:58 +01:00
|
|
|
.filter_map(|(use_tree, _)| {
|
2025-01-20 17:41:03 +00:00
|
|
|
if let ast::UseTreeKind::Simple(..) = use_tree.kind
|
|
|
|
|
&& use_tree.ident().name == kw::SelfLower
|
|
|
|
|
{
|
|
|
|
|
return Some(use_tree.span);
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2017-09-26 23:04:00 +02:00
|
|
|
|
|
|
|
|
None
|
|
|
|
|
})
|
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
if self_spans.len() > 1 {
|
2019-08-08 23:32:58 +03:00
|
|
|
let mut e = self.r.into_struct_error(
|
2017-09-26 23:04:00 +02:00
|
|
|
self_spans[0],
|
|
|
|
|
ResolutionError::SelfImportCanOnlyAppearOnceInTheList,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
for other_span in self_spans.iter().skip(1) {
|
2017-12-19 19:53:39 -08:00
|
|
|
e.span_label(*other_span, "another `self` import appears here");
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2017-09-26 23:04:00 +02:00
|
|
|
|
|
|
|
|
e.emit();
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-11 15:08:47 +12:00
|
|
|
for &(ref tree, id) in items {
|
2017-09-26 23:04:00 +02:00
|
|
|
self.build_reduced_graph_for_use_tree(
|
2018-10-27 20:23:54 +03:00
|
|
|
// This particular use tree
|
2023-12-20 20:02:40 +03:00
|
|
|
tree, id, &prefix, true, false, // The whole `use` item
|
2019-08-08 23:57:35 +03:00
|
|
|
item, vis, root_span,
|
2017-09-26 23:04:00 +02:00
|
|
|
);
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2018-10-27 23:38:09 +03:00
|
|
|
|
|
|
|
|
// Empty groups `a::b::{}` are turned into synthetic `self` imports
|
2019-06-11 19:47:52 +01:00
|
|
|
// `a::b::c::{self as _}`, so that their prefixes are correctly
|
2018-10-27 23:38:09 +03:00
|
|
|
// resolved and checked for privacy/stability/etc.
|
|
|
|
|
if items.is_empty() && !empty_for_self(&prefix) {
|
|
|
|
|
let new_span = prefix[prefix.len() - 1].ident.span;
|
|
|
|
|
let tree = ast::UseTree {
|
2019-05-11 17:41:37 +03:00
|
|
|
prefix: ast::Path::from_ident(Ident::new(kw::SelfLower, new_span)),
|
2022-12-01 18:51:20 +03:00
|
|
|
kind: ast::UseTreeKind::Simple(Some(Ident::new(kw::Underscore, new_span))),
|
2018-10-27 23:38:09 +03:00
|
|
|
span: use_tree.span,
|
|
|
|
|
};
|
|
|
|
|
self.build_reduced_graph_for_use_tree(
|
|
|
|
|
// This particular use tree
|
2018-11-03 19:41:44 +03:00
|
|
|
&tree,
|
|
|
|
|
id,
|
|
|
|
|
&prefix,
|
|
|
|
|
true,
|
2023-12-20 20:02:40 +03:00
|
|
|
true,
|
2018-10-27 23:38:09 +03:00
|
|
|
// The whole `use` item
|
2019-08-08 23:57:35 +03:00
|
|
|
item,
|
2022-08-28 00:10:06 +03:00
|
|
|
ty::Visibility::Restricted(
|
|
|
|
|
self.parent_scope.module.nearest_parent_mod().expect_local(),
|
|
|
|
|
),
|
2019-08-08 23:57:35 +03:00
|
|
|
root_span,
|
2018-10-27 23:38:09 +03:00
|
|
|
);
|
|
|
|
|
}
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
2017-09-26 23:04:00 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-29 15:08:11 +08:00
|
|
|
fn build_reduced_graph_for_struct_variant(
|
2024-01-04 21:45:06 +08:00
|
|
|
&mut self,
|
|
|
|
|
fields: &[ast::FieldDef],
|
|
|
|
|
ident: Ident,
|
2024-02-14 15:28:40 +00:00
|
|
|
feed: Feed<'tcx, LocalDefId>,
|
2024-01-04 21:45:06 +08:00
|
|
|
adt_res: Res,
|
|
|
|
|
adt_vis: ty::Visibility,
|
|
|
|
|
adt_span: Span,
|
|
|
|
|
) {
|
|
|
|
|
let parent_scope = &self.parent_scope;
|
|
|
|
|
let parent = parent_scope.module;
|
|
|
|
|
let expansion = parent_scope.expansion;
|
|
|
|
|
|
|
|
|
|
// Define a name in the type namespace if it is not anonymous.
|
|
|
|
|
self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, adt_vis);
|
|
|
|
|
let def_id = feed.key();
|
2024-01-04 21:45:06 +08:00
|
|
|
|
|
|
|
|
// Record field names for error reporting.
|
2024-07-06 19:21:22 +00:00
|
|
|
self.insert_field_idents(def_id, fields);
|
2024-01-04 21:45:06 +08:00
|
|
|
self.insert_field_visibilities_local(def_id.to_def_id(), fields);
|
|
|
|
|
}
|
|
|
|
|
|
2017-09-26 23:04:00 +02:00
|
|
|
/// Constructs the reduced graph for one item.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn build_reduced_graph_for_item(&mut self, item: &'a Item) {
|
2019-08-08 23:57:35 +03:00
|
|
|
let parent_scope = &self.parent_scope;
|
2018-10-22 01:28:59 +03:00
|
|
|
let parent = parent_scope.module;
|
|
|
|
|
let expansion = parent_scope.expansion;
|
2017-09-26 23:04:00 +02:00
|
|
|
let sp = item.span;
|
2019-08-08 23:57:35 +03:00
|
|
|
let vis = self.resolve_visibility(&item.vis);
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(item.id);
|
|
|
|
|
let local_def_id = feed.key();
|
2020-10-17 02:28:11 +03:00
|
|
|
let def_id = local_def_id.to_def_id();
|
2023-11-21 23:40:23 +03:00
|
|
|
let def_kind = self.r.tcx.def_kind(def_id);
|
|
|
|
|
let res = Res::Def(def_kind, def_id);
|
2020-10-17 02:28:11 +03:00
|
|
|
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2017-09-26 23:04:00 +02:00
|
|
|
|
2019-09-26 17:51:36 +01:00
|
|
|
match item.kind {
|
2017-09-26 23:04:00 +02:00
|
|
|
ItemKind::Use(ref use_tree) => {
|
|
|
|
|
self.build_reduced_graph_for_use_tree(
|
2018-10-27 20:23:54 +03:00
|
|
|
// This particular use tree
|
2018-11-03 19:41:44 +03:00
|
|
|
use_tree,
|
|
|
|
|
item.id,
|
|
|
|
|
&[],
|
|
|
|
|
false,
|
2023-12-20 20:02:40 +03:00
|
|
|
false,
|
2018-10-27 20:23:54 +03:00
|
|
|
// The whole `use` item
|
2019-08-08 23:57:35 +03:00
|
|
|
item,
|
|
|
|
|
vis,
|
|
|
|
|
use_tree.span,
|
2017-09-26 23:04:00 +02:00
|
|
|
);
|
|
|
|
|
}
|
2014-12-23 21:34:36 +02:00
|
|
|
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
ItemKind::ExternCrate(orig_name, ident) => {
|
2021-11-26 19:18:51 +00:00
|
|
|
self.build_reduced_graph_for_extern_crate(
|
|
|
|
|
orig_name,
|
|
|
|
|
item,
|
2025-04-01 14:49:58 +11:00
|
|
|
ident,
|
2021-11-26 19:18:51 +00:00
|
|
|
local_def_id,
|
|
|
|
|
vis,
|
|
|
|
|
parent,
|
|
|
|
|
);
|
2014-12-23 21:34:36 +02:00
|
|
|
}
|
|
|
|
|
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
ItemKind::Mod(_, ident, ref mod_kind) => {
|
2021-09-25 02:27:00 +03:00
|
|
|
let module = self.r.new_module(
|
2021-09-11 16:37:34 +03:00
|
|
|
Some(parent),
|
2025-03-25 09:09:01 +11:00
|
|
|
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
|
2021-09-11 16:37:34 +03:00
|
|
|
expansion.to_expn_id(),
|
|
|
|
|
item.span,
|
|
|
|
|
parent.no_implicit_prelude
|
2024-12-07 15:27:17 +01:00
|
|
|
|| ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude),
|
2021-09-11 16:37:34 +03:00
|
|
|
);
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
2016-08-14 23:42:05 +00:00
|
|
|
|
2024-12-05 21:19:08 +00:00
|
|
|
if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
|
|
|
|
|
self.r.mods_with_parse_errors.insert(def_id);
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-14 23:42:05 +00:00
|
|
|
// Descend into the module.
|
2019-08-08 03:44:16 +03:00
|
|
|
self.parent_scope.module = module;
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These items live in the value namespace.
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
ItemKind::Const(box ConstItem { ident, .. })
|
|
|
|
|
| ItemKind::Delegation(box Delegation { ident, .. })
|
|
|
|
|
| ItemKind::Static(box StaticItem { ident, .. }) => {
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
2025-04-01 14:49:58 +11:00
|
|
|
ItemKind::Fn(box Fn { ident, .. }) => {
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
|
2018-07-12 13:24:59 +03:00
|
|
|
|
|
|
|
|
// Functions introducing procedural macros reserve a slot
|
|
|
|
|
// in the macro namespace as well (see #52225).
|
2019-08-08 23:57:35 +03:00
|
|
|
self.define_macro(item);
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These items live in the type namespace.
|
2025-04-01 14:49:58 +11:00
|
|
|
ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
|
2018-07-03 19:38:14 +02:00
|
|
|
}
|
|
|
|
|
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
|
2021-09-25 02:27:00 +03:00
|
|
|
let module = self.r.new_module(
|
2021-09-11 16:37:34 +03:00
|
|
|
Some(parent),
|
2025-03-25 09:09:01 +11:00
|
|
|
ModuleKind::Def(def_kind, def_id, Some(ident.name)),
|
2021-09-11 16:37:34 +03:00
|
|
|
expansion.to_expn_id(),
|
|
|
|
|
item.span,
|
|
|
|
|
parent.no_implicit_prelude,
|
|
|
|
|
);
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
|
2019-09-05 18:04:58 +03:00
|
|
|
self.parent_scope.module = module;
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// These items live in both the type and value namespaces.
|
2025-05-28 08:20:30 +10:00
|
|
|
ItemKind::Struct(ident, _, ref vdata) => {
|
2024-01-29 15:08:11 +08:00
|
|
|
self.build_reduced_graph_for_struct_variant(
|
2024-01-04 21:45:06 +08:00
|
|
|
vdata.fields(),
|
|
|
|
|
ident,
|
2024-02-14 15:28:40 +00:00
|
|
|
feed,
|
2024-01-04 21:45:06 +08:00
|
|
|
res,
|
|
|
|
|
vis,
|
|
|
|
|
sp,
|
|
|
|
|
);
|
2017-01-09 00:21:35 +03:00
|
|
|
|
|
|
|
|
// If this is a tuple or unit struct, define a name
|
|
|
|
|
// in the value namespace as well.
|
2023-11-21 23:40:23 +03:00
|
|
|
if let Some(ctor_node_id) = vdata.ctor_node_id() {
|
2019-12-07 00:55:02 +03:00
|
|
|
// If the structure is marked as non_exhaustive then lower the visibility
|
|
|
|
|
// to within the crate.
|
2022-08-28 00:10:06 +03:00
|
|
|
let mut ctor_vis = if vis.is_public()
|
2024-12-07 15:27:17 +01:00
|
|
|
&& ast::attr::contains_name(&item.attrs, sym::non_exhaustive)
|
2019-12-07 00:55:02 +03:00
|
|
|
{
|
2022-08-28 00:10:06 +03:00
|
|
|
ty::Visibility::Restricted(CRATE_DEF_ID)
|
2020-03-21 14:44:17 +01:00
|
|
|
} else {
|
|
|
|
|
vis
|
|
|
|
|
};
|
|
|
|
|
|
2020-09-08 15:14:09 -07:00
|
|
|
let mut ret_fields = Vec::with_capacity(vdata.fields().len());
|
|
|
|
|
|
2019-12-07 00:55:02 +03:00
|
|
|
for field in vdata.fields() {
|
|
|
|
|
// NOTE: The field may be an expansion placeholder, but expansion sets
|
|
|
|
|
// correct visibilities for unnamed field placeholders specifically, so the
|
|
|
|
|
// constructor visibility should still be determined correctly.
|
2020-09-08 15:14:09 -07:00
|
|
|
let field_vis = self
|
2022-03-24 02:55:22 +03:00
|
|
|
.try_resolve_visibility(&field.vis, false)
|
2020-09-08 15:14:09 -07:00
|
|
|
.unwrap_or(ty::Visibility::Public);
|
2023-02-22 19:51:17 +04:00
|
|
|
if ctor_vis.is_at_least(field_vis, self.r.tcx) {
|
2020-09-08 15:14:09 -07:00
|
|
|
ctor_vis = field_vis;
|
2019-12-07 00:55:02 +03:00
|
|
|
}
|
2022-08-28 00:10:06 +03:00
|
|
|
ret_fields.push(field_vis.to_def_id());
|
2019-12-07 00:55:02 +03:00
|
|
|
}
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(ctor_node_id);
|
|
|
|
|
let ctor_def_id = feed.key();
|
2023-11-21 23:40:23 +03:00
|
|
|
let ctor_res = self.res(ctor_def_id);
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, ctor_vis);
|
2023-01-10 20:57:02 +00:00
|
|
|
// We need the field visibility spans also for the constructor for E0603.
|
2024-01-04 21:45:06 +08:00
|
|
|
self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields());
|
2020-10-17 02:28:11 +03:00
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
self.r
|
|
|
|
|
.struct_constructors
|
2023-02-22 02:03:29 +04:00
|
|
|
.insert(local_def_id, (ctor_res, ctor_vis.to_def_id(), ret_fields));
|
2017-01-09 00:21:35 +03:00
|
|
|
}
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2025-05-28 08:20:30 +10:00
|
|
|
ItemKind::Union(ident, _, ref vdata) => {
|
2024-01-29 15:08:11 +08:00
|
|
|
self.build_reduced_graph_for_struct_variant(
|
2024-01-04 21:45:06 +08:00
|
|
|
vdata.fields(),
|
|
|
|
|
ident,
|
2024-02-14 15:28:40 +00:00
|
|
|
feed,
|
2024-01-04 21:45:06 +08:00
|
|
|
res,
|
|
|
|
|
vis,
|
|
|
|
|
sp,
|
|
|
|
|
);
|
2016-08-06 21:56:02 +03:00
|
|
|
}
|
2016-08-29 05:04:31 +00:00
|
|
|
|
2019-12-11 21:58:00 +03:00
|
|
|
// These items do not add names to modules.
|
2025-03-25 09:00:35 +00:00
|
|
|
ItemKind::Impl(box Impl { of_trait: Some(..), .. })
|
|
|
|
|
| ItemKind::Impl { .. }
|
|
|
|
|
| ItemKind::ForeignMod(..)
|
|
|
|
|
| ItemKind::GlobalAsm(..) => {}
|
2019-12-11 21:58:00 +03:00
|
|
|
|
2024-03-15 14:21:03 +03:00
|
|
|
ItemKind::MacroDef(..) | ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
|
|
|
|
|
unreachable!()
|
|
|
|
|
}
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-26 19:18:51 +00:00
|
|
|
fn build_reduced_graph_for_extern_crate(
|
|
|
|
|
&mut self,
|
|
|
|
|
orig_name: Option<Symbol>,
|
|
|
|
|
item: &Item,
|
2025-04-01 14:49:58 +11:00
|
|
|
ident: Ident,
|
2021-11-26 19:18:51 +00:00
|
|
|
local_def_id: LocalDefId,
|
|
|
|
|
vis: ty::Visibility,
|
2024-09-10 16:19:40 +10:00
|
|
|
parent: Module<'ra>,
|
2021-11-26 19:18:51 +00:00
|
|
|
) {
|
2021-11-26 20:37:56 +00:00
|
|
|
let sp = item.span;
|
|
|
|
|
let parent_scope = self.parent_scope;
|
|
|
|
|
let expansion = parent_scope.expansion;
|
|
|
|
|
|
2021-11-26 21:39:44 +00:00
|
|
|
let (used, module, binding) = if orig_name.is_none() && ident.name == kw::SelfLower {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::ExternCrateSelfRequiresRenaming { span: sp });
|
2021-11-26 19:18:51 +00:00
|
|
|
return;
|
|
|
|
|
} else if orig_name == Some(kw::SelfLower) {
|
2021-11-26 21:39:44 +00:00
|
|
|
Some(self.r.graph_root)
|
2021-11-26 19:18:51 +00:00
|
|
|
} else {
|
2022-12-13 10:01:53 +00:00
|
|
|
let tcx = self.r.tcx;
|
|
|
|
|
let crate_id = self.r.crate_loader(|c| {
|
|
|
|
|
c.process_extern_crate(item, local_def_id, &tcx.definitions_untracked())
|
|
|
|
|
});
|
2022-12-08 08:52:07 +00:00
|
|
|
crate_id.map(|crate_id| {
|
2022-12-07 13:37:47 +00:00
|
|
|
self.r.extern_crate_map.insert(local_def_id, crate_id);
|
|
|
|
|
self.r.expect_module(crate_id.as_def_id())
|
|
|
|
|
})
|
2021-11-26 21:39:44 +00:00
|
|
|
}
|
|
|
|
|
.map(|module| {
|
|
|
|
|
let used = self.process_macro_use_imports(item, module);
|
2022-08-28 00:10:06 +03:00
|
|
|
let vis = ty::Visibility::<LocalDefId>::Public;
|
|
|
|
|
let binding = (module, vis, sp, expansion).to_name_binding(self.r.arenas);
|
2021-11-26 21:39:44 +00:00
|
|
|
(used, Some(ModuleOrUniformRoot::Module(module)), binding)
|
|
|
|
|
})
|
|
|
|
|
.unwrap_or((true, None, self.r.dummy_binding));
|
2023-07-04 18:51:35 +03:00
|
|
|
let import = self.r.arenas.alloc_import(ImportData {
|
2022-10-30 13:35:31 +04:00
|
|
|
kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
|
2021-11-26 19:18:51 +00:00
|
|
|
root_id: item.id,
|
|
|
|
|
parent_scope: self.parent_scope,
|
2021-11-26 21:39:44 +00:00
|
|
|
imported_module: Cell::new(module),
|
2021-11-26 19:18:51 +00:00
|
|
|
has_attributes: !item.attrs.is_empty(),
|
|
|
|
|
use_span_with_attributes: item.span_with_attributes(),
|
|
|
|
|
use_span: item.span,
|
|
|
|
|
root_span: item.span,
|
|
|
|
|
span: item.span,
|
|
|
|
|
module_path: Vec::new(),
|
2024-08-06 19:27:15 +08:00
|
|
|
vis,
|
2021-11-26 19:18:51 +00:00
|
|
|
});
|
2024-08-09 18:33:20 +08:00
|
|
|
if used {
|
|
|
|
|
self.r.import_use_map.insert(import, Used::Other);
|
|
|
|
|
}
|
2021-11-26 19:18:51 +00:00
|
|
|
self.r.potentially_unused_imports.push(import);
|
|
|
|
|
let imported_binding = self.r.import(binding, import);
|
2023-07-04 20:00:42 +03:00
|
|
|
if parent == self.r.graph_root {
|
2024-08-16 23:58:19 +08:00
|
|
|
let ident = ident.normalize_to_macros_2_0();
|
2025-01-20 17:41:03 +00:00
|
|
|
if let Some(entry) = self.r.extern_prelude.get(&ident)
|
|
|
|
|
&& expansion != LocalExpnId::ROOT
|
|
|
|
|
&& orig_name.is_some()
|
|
|
|
|
&& !entry.is_import()
|
|
|
|
|
{
|
|
|
|
|
self.r.dcx().emit_err(
|
|
|
|
|
errors::MacroExpandedExternCrateCannotShadowExternArguments { span: item.span },
|
|
|
|
|
);
|
|
|
|
|
// `return` is intended to discard this binding because it's an
|
|
|
|
|
// unregistered ambiguity error which would result in a panic
|
|
|
|
|
// caused by inconsistency `path_res`
|
|
|
|
|
// more details: https://github.com/rust-lang/rust/pull/111761
|
|
|
|
|
return;
|
2021-11-26 19:18:51 +00:00
|
|
|
}
|
2023-08-18 14:21:12 +08:00
|
|
|
let entry = self
|
|
|
|
|
.r
|
|
|
|
|
.extern_prelude
|
2024-08-16 23:58:19 +08:00
|
|
|
.entry(ident)
|
2023-08-18 14:21:12 +08:00
|
|
|
.or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
|
2021-11-26 19:18:51 +00:00
|
|
|
if orig_name.is_some() {
|
|
|
|
|
entry.introduced_by_item = true;
|
|
|
|
|
}
|
2024-08-16 23:58:19 +08:00
|
|
|
// Binding from `extern crate` item in source code can replace
|
|
|
|
|
// a binding from `--extern` on command line here.
|
|
|
|
|
if !entry.is_import() {
|
|
|
|
|
entry.binding = Some(imported_binding)
|
|
|
|
|
} else if ident.name != kw::Underscore {
|
|
|
|
|
self.r.dcx().span_delayed_bug(
|
|
|
|
|
item.span,
|
|
|
|
|
format!("it had been define the external module '{ident}' multiple times"),
|
|
|
|
|
);
|
|
|
|
|
}
|
2021-11-26 19:18:51 +00:00
|
|
|
}
|
|
|
|
|
self.r.define(parent, ident, TypeNS, imported_binding);
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-30 12:16:42 -06:00
|
|
|
/// Constructs the reduced graph for one foreign item.
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem, ident: Ident) {
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(item.id);
|
|
|
|
|
let local_def_id = feed.key();
|
2020-10-17 02:28:11 +03:00
|
|
|
let def_id = local_def_id.to_def_id();
|
2023-11-21 23:40:23 +03:00
|
|
|
let ns = match item.kind {
|
|
|
|
|
ForeignItemKind::Fn(..) => ValueNS,
|
|
|
|
|
ForeignItemKind::Static(..) => ValueNS,
|
|
|
|
|
ForeignItemKind::TyAlias(..) => TypeNS,
|
|
|
|
|
ForeignItemKind::MacCall(..) => unreachable!(),
|
2015-02-05 09:19:07 +02:00
|
|
|
};
|
2019-08-08 03:44:16 +03:00
|
|
|
let parent = self.parent_scope.module;
|
|
|
|
|
let expansion = self.parent_scope.expansion;
|
2019-08-08 23:57:35 +03:00
|
|
|
let vis = self.resolve_visibility(&item.vis);
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2019-08-08 03:44:16 +03:00
|
|
|
fn build_reduced_graph_for_block(&mut self, block: &Block) {
|
|
|
|
|
let parent = self.parent_scope.module;
|
|
|
|
|
let expansion = self.parent_scope.expansion;
|
2014-12-30 12:16:42 -06:00
|
|
|
if self.block_needs_anonymous_module(block) {
|
2021-09-25 02:27:00 +03:00
|
|
|
let module = self.r.new_module(
|
2021-09-11 16:37:34 +03:00
|
|
|
Some(parent),
|
2022-07-25 19:45:26 +02:00
|
|
|
ModuleKind::Block,
|
2021-06-25 20:43:04 +02:00
|
|
|
expansion.to_expn_id(),
|
2017-05-10 13:58:41 +02:00
|
|
|
block.span,
|
2021-09-11 16:37:34 +03:00
|
|
|
parent.no_implicit_prelude,
|
2017-05-10 13:58:41 +02:00
|
|
|
);
|
2019-08-08 14:06:42 +03:00
|
|
|
self.r.block_map.insert(block.id, module);
|
2019-08-08 03:44:16 +03:00
|
|
|
self.parent_scope.module = module; // Descend into the block.
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-03-14 01:23:24 +03:00
|
|
|
fn add_macro_use_binding(
|
2016-11-17 08:16:32 +00:00
|
|
|
&mut self,
|
2020-04-19 13:00:18 +02:00
|
|
|
name: Symbol,
|
2024-09-10 16:19:40 +10:00
|
|
|
binding: NameBinding<'ra>,
|
2016-11-17 08:16:32 +00:00
|
|
|
span: Span,
|
|
|
|
|
allow_shadowing: bool,
|
|
|
|
|
) {
|
2019-08-08 14:06:42 +03:00
|
|
|
if self.r.macro_use_prelude.insert(name, binding).is_some() && !allow_shadowing {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::MacroUseNameAlreadyInUse { span, name });
|
2016-10-28 06:52:45 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-10-17 07:46:25 +00:00
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Returns `true` if we should consider the underlying `extern crate` to be used.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn process_macro_use_imports(&mut self, item: &Item, module: Module<'ra>) -> bool {
|
2018-10-26 01:15:51 +03:00
|
|
|
let mut import_all = None;
|
|
|
|
|
let mut single_imports = Vec::new();
|
|
|
|
|
for attr in &item.attrs {
|
2021-07-29 12:00:41 -05:00
|
|
|
if attr.has_name(sym::macro_use) {
|
2019-08-08 03:44:16 +03:00
|
|
|
if self.parent_scope.module.parent.is_some() {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::ExternCrateLoadingMacroNotAtCrateRoot {
|
|
|
|
|
span: item.span,
|
|
|
|
|
});
|
2018-10-26 01:15:51 +03:00
|
|
|
}
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
if let ItemKind::ExternCrate(Some(orig_name), _) = item.kind
|
2025-01-20 17:41:03 +00:00
|
|
|
&& orig_name == kw::SelfLower
|
|
|
|
|
{
|
|
|
|
|
self.r.dcx().emit_err(errors::MacroUseExternCrateSelf { span: attr.span });
|
2018-10-26 01:39:47 +03:00
|
|
|
}
|
2022-01-27 09:44:25 +00:00
|
|
|
let ill_formed = |span| {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::BadMacroImport { span });
|
2022-01-27 09:44:25 +00:00
|
|
|
};
|
2018-10-26 01:15:51 +03:00
|
|
|
match attr.meta() {
|
2019-09-26 18:04:05 +01:00
|
|
|
Some(meta) => match meta.kind {
|
2018-10-26 01:15:51 +03:00
|
|
|
MetaItemKind::Word => {
|
|
|
|
|
import_all = Some(meta.span);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2024-10-07 08:49:47 +09:00
|
|
|
MetaItemKind::List(meta_item_inners) => {
|
|
|
|
|
for meta_item_inner in meta_item_inners {
|
|
|
|
|
match meta_item_inner.ident() {
|
|
|
|
|
Some(ident) if meta_item_inner.is_word() => {
|
2019-02-28 09:17:24 +03:00
|
|
|
single_imports.push(ident)
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2024-10-07 08:49:47 +09:00
|
|
|
_ => ill_formed(meta_item_inner.span()),
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2018-10-26 01:15:51 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MetaItemKind::NameValue(..) => ill_formed(meta.span),
|
|
|
|
|
},
|
2019-03-03 20:56:24 +03:00
|
|
|
None => ill_formed(attr.span),
|
2018-10-26 01:15:51 +03:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-05 20:30:40 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-28 15:18:49 +08:00
|
|
|
let macro_use_import = |this: &Self, span, warn_private| {
|
2023-07-04 18:51:35 +03:00
|
|
|
this.r.arenas.alloc_import(ImportData {
|
2023-12-28 15:18:49 +08:00
|
|
|
kind: ImportKind::MacroUse { warn_private },
|
2018-05-18 17:18:04 -04:00
|
|
|
root_id: item.id,
|
2019-08-13 01:39:10 +03:00
|
|
|
parent_scope: this.parent_scope,
|
2018-08-09 16:29:22 +03:00
|
|
|
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
2019-01-29 13:34:40 +01:00
|
|
|
use_span_with_attributes: item.span_with_attributes(),
|
|
|
|
|
has_attributes: !item.attrs.is_empty(),
|
|
|
|
|
use_span: item.span,
|
2018-05-18 17:18:04 -04:00
|
|
|
root_span: span,
|
2017-08-06 22:54:09 -07:00
|
|
|
span,
|
2017-01-14 08:58:50 +00:00
|
|
|
module_path: Vec::new(),
|
2024-08-06 19:27:15 +08:00
|
|
|
vis: ty::Visibility::Restricted(CRATE_DEF_ID),
|
2017-01-14 08:58:50 +00:00
|
|
|
})
|
|
|
|
|
};
|
|
|
|
|
|
2021-06-25 20:43:04 +02:00
|
|
|
let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
|
2018-10-26 01:15:51 +03:00
|
|
|
if let Some(span) = import_all {
|
2023-12-28 15:18:49 +08:00
|
|
|
let import = macro_use_import(self, span, false);
|
2020-03-07 19:02:32 +03:00
|
|
|
self.r.potentially_unused_imports.push(import);
|
2019-07-29 21:19:50 +03:00
|
|
|
module.for_each_child(self, |this, ident, ns, binding| {
|
|
|
|
|
if ns == MacroNS {
|
2025-06-02 19:03:55 +03:00
|
|
|
let import = if this.r.is_accessible_from(binding.vis, this.parent_scope.module)
|
|
|
|
|
{
|
|
|
|
|
import
|
|
|
|
|
} else {
|
|
|
|
|
// FIXME: This branch is used for reporting the `private_macro_use` lint
|
|
|
|
|
// and should eventually be removed.
|
|
|
|
|
if this.r.macro_use_prelude.contains_key(&ident.name) {
|
|
|
|
|
// Do not override already existing entries with compatibility entries.
|
2023-12-28 15:18:49 +08:00
|
|
|
return;
|
2025-06-02 19:03:55 +03:00
|
|
|
}
|
|
|
|
|
macro_use_import(this, span, true)
|
|
|
|
|
};
|
|
|
|
|
let import_binding = this.r.import(binding, import);
|
|
|
|
|
this.add_macro_use_binding(ident.name, import_binding, span, allow_shadowing);
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2016-10-28 06:52:45 +00:00
|
|
|
});
|
|
|
|
|
} else {
|
2019-02-28 09:17:24 +03:00
|
|
|
for ident in single_imports.iter().cloned() {
|
2022-04-08 22:50:56 +02:00
|
|
|
let result = self.r.maybe_resolve_ident_in_module(
|
2018-08-09 16:29:22 +03:00
|
|
|
ModuleOrUniformRoot::Module(module),
|
|
|
|
|
ident,
|
|
|
|
|
MacroNS,
|
2019-08-08 23:57:35 +03:00
|
|
|
&self.parent_scope,
|
2024-08-06 19:27:15 +08:00
|
|
|
None,
|
2018-08-09 16:29:22 +03:00
|
|
|
);
|
2016-11-26 12:21:47 +00:00
|
|
|
if let Ok(binding) = result {
|
2023-12-28 15:18:49 +08:00
|
|
|
let import = macro_use_import(self, ident.span, false);
|
2020-03-07 19:02:32 +03:00
|
|
|
self.r.potentially_unused_imports.push(import);
|
|
|
|
|
let imported_binding = self.r.import(binding, import);
|
2020-03-14 01:23:24 +03:00
|
|
|
self.add_macro_use_binding(
|
2019-02-28 09:17:24 +03:00
|
|
|
ident.name,
|
|
|
|
|
imported_binding,
|
|
|
|
|
ident.span,
|
|
|
|
|
allow_shadowing,
|
|
|
|
|
);
|
2016-10-17 07:46:25 +00:00
|
|
|
} else {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::ImportedMacroNotFound { span: ident.span });
|
2016-10-17 07:46:25 +00:00
|
|
|
}
|
|
|
|
|
}
|
2016-10-28 06:52:45 +00:00
|
|
|
}
|
2018-10-26 01:15:51 +03:00
|
|
|
import_all.is_some() || !single_imports.is_empty()
|
2016-10-17 07:46:25 +00:00
|
|
|
}
|
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Returns `true` if this attribute list contains `macro_use`.
|
2016-09-16 06:45:03 +00:00
|
|
|
fn contains_macro_use(&mut self, attrs: &[ast::Attribute]) -> bool {
|
|
|
|
|
for attr in attrs {
|
2021-07-29 12:00:41 -05:00
|
|
|
if attr.has_name(sym::macro_escape) {
|
2024-08-21 00:57:58 -04:00
|
|
|
let inner_attribute = matches!(attr.style, ast::AttrStyle::Inner);
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r
|
|
|
|
|
.dcx()
|
|
|
|
|
.emit_warn(errors::MacroExternDeprecated { span: attr.span, inner_attribute });
|
2021-07-29 12:00:41 -05:00
|
|
|
} else if !attr.has_name(sym::macro_use) {
|
2016-09-16 06:45:03 +00:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !attr.is_word() {
|
2024-03-24 12:43:53 +00:00
|
|
|
self.r.dcx().emit_err(errors::ArgumentsMacroUseNotAllowed { span: attr.span });
|
2016-09-16 06:45:03 +00:00
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
2016-03-02 09:18:47 +00:00
|
|
|
|
2021-06-25 20:43:04 +02:00
|
|
|
fn visit_invoc(&mut self, id: NodeId) -> LocalExpnId {
|
2019-07-16 01:42:58 +03:00
|
|
|
let invoc_id = id.placeholder_to_expn_id();
|
2019-08-13 01:39:10 +03:00
|
|
|
let old_parent_scope = self.r.invocation_parent_scopes.insert(invoc_id, self.parent_scope);
|
2019-08-12 23:39:49 +03:00
|
|
|
assert!(old_parent_scope.is_none(), "invocation data is reset for an invocation");
|
2020-11-21 18:02:37 +03:00
|
|
|
invoc_id
|
|
|
|
|
}
|
2019-07-02 13:47:28 +03:00
|
|
|
|
2020-11-21 18:02:37 +03:00
|
|
|
/// Visit invocation in context in which it can emit a named item (possibly `macro_rules`)
|
|
|
|
|
/// directly into its parent scope's module.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_invoc_in_module(&mut self, id: NodeId) -> MacroRulesScopeRef<'ra> {
|
2020-11-21 18:02:37 +03:00
|
|
|
let invoc_id = self.visit_invoc(id);
|
|
|
|
|
self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id);
|
2020-11-14 00:05:05 +03:00
|
|
|
self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Invocation(invoc_id))
|
2016-09-14 21:03:09 +00:00
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
fn proc_macro_stub(
|
|
|
|
|
&self,
|
|
|
|
|
item: &ast::Item,
|
|
|
|
|
fn_ident: Ident,
|
|
|
|
|
) -> Option<(MacroKind, Ident, Span)> {
|
2024-12-07 15:27:17 +01:00
|
|
|
if ast::attr::contains_name(&item.attrs, sym::proc_macro) {
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
return Some((MacroKind::Bang, fn_ident, item.span));
|
2024-12-07 15:27:17 +01:00
|
|
|
} else if ast::attr::contains_name(&item.attrs, sym::proc_macro_attribute) {
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
return Some((MacroKind::Attr, fn_ident, item.span));
|
2025-01-20 17:41:03 +00:00
|
|
|
} else if let Some(attr) = ast::attr::find_by_name(&item.attrs, sym::proc_macro_derive)
|
|
|
|
|
&& let Some(meta_item_inner) =
|
2024-10-07 08:49:47 +09:00
|
|
|
attr.meta_item_list().and_then(|list| list.get(0).cloned())
|
2025-01-20 17:41:03 +00:00
|
|
|
&& let Some(ident) = meta_item_inner.ident()
|
|
|
|
|
{
|
|
|
|
|
return Some((MacroKind::Derive, ident, ident.span));
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2019-10-10 01:08:17 +03:00
|
|
|
// Mark the given macro as unused unless its name starts with `_`.
|
|
|
|
|
// Macro uses will remove items from this set, and the remaining
|
|
|
|
|
// items will be reported as `unused_macros`.
|
2023-11-24 23:39:42 +03:00
|
|
|
fn insert_unused_macro(&mut self, ident: Ident, def_id: LocalDefId, node_id: NodeId) {
|
2020-02-26 13:03:46 +01:00
|
|
|
if !ident.as_str().starts_with('_') {
|
2021-11-10 12:00:46 +01:00
|
|
|
self.r.unused_macros.insert(def_id, (node_id, ident));
|
2025-07-08 23:52:20 +02:00
|
|
|
let nrules = self.r.local_macro_map[&def_id].nrules;
|
2025-07-04 14:00:32 -07:00
|
|
|
self.r.unused_macro_rules.insert(node_id, DenseBitSet::new_filled(nrules));
|
2019-10-10 01:08:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'ra> {
|
2019-10-10 01:08:17 +03:00
|
|
|
let parent_scope = self.parent_scope;
|
2019-08-08 23:57:35 +03:00
|
|
|
let expansion = parent_scope.expansion;
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(item.id);
|
|
|
|
|
let def_id = feed.key();
|
2023-11-21 23:40:23 +03:00
|
|
|
let (res, ident, span, macro_rules) = match &item.kind {
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
ItemKind::MacroDef(ident, def) => {
|
|
|
|
|
(self.res(def_id), *ident, item.span, def.macro_rules)
|
|
|
|
|
}
|
|
|
|
|
ItemKind::Fn(box ast::Fn { ident: fn_ident, .. }) => {
|
|
|
|
|
match self.proc_macro_stub(item, *fn_ident) {
|
|
|
|
|
Some((macro_kind, ident, span)) => {
|
|
|
|
|
let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
|
|
|
|
|
let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
|
2025-07-08 23:52:20 +02:00
|
|
|
self.r.new_local_macro(def_id, macro_data);
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
self.r.proc_macro_stubs.insert(def_id);
|
|
|
|
|
(res, ident, span, false)
|
|
|
|
|
}
|
|
|
|
|
None => return parent_scope.macro_rules,
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
}
|
2019-08-08 23:57:35 +03:00
|
|
|
_ => unreachable!(),
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-24 12:18:22 +01:00
|
|
|
self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
|
2019-08-08 23:57:35 +03:00
|
|
|
|
2021-03-31 15:43:33 -03:00
|
|
|
if macro_rules {
|
2020-03-14 01:36:46 +03:00
|
|
|
let ident = ident.normalize_to_macros_2_0();
|
2019-08-08 23:57:35 +03:00
|
|
|
self.r.macro_names.insert(ident);
|
2024-12-07 15:27:17 +01:00
|
|
|
let is_macro_export = ast::attr::contains_name(&item.attrs, sym::macro_export);
|
2019-08-08 23:57:35 +03:00
|
|
|
let vis = if is_macro_export {
|
|
|
|
|
ty::Visibility::Public
|
|
|
|
|
} else {
|
2022-08-28 00:10:06 +03:00
|
|
|
ty::Visibility::Restricted(CRATE_DEF_ID)
|
2019-08-08 23:57:35 +03:00
|
|
|
};
|
|
|
|
|
let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
|
|
|
|
|
self.r.set_binding_parent_module(binding, parent_scope.module);
|
2025-02-21 15:29:17 +03:00
|
|
|
self.r.all_macro_rules.insert(ident.name);
|
2019-08-08 23:57:35 +03:00
|
|
|
if is_macro_export {
|
2023-07-04 18:51:35 +03:00
|
|
|
let import = self.r.arenas.alloc_import(ImportData {
|
2022-10-30 15:55:58 +04:00
|
|
|
kind: ImportKind::MacroExport,
|
|
|
|
|
root_id: item.id,
|
|
|
|
|
parent_scope: self.parent_scope,
|
|
|
|
|
imported_module: Cell::new(None),
|
|
|
|
|
has_attributes: false,
|
|
|
|
|
use_span_with_attributes: span,
|
|
|
|
|
use_span: span,
|
|
|
|
|
root_span: span,
|
2023-09-04 20:14:40 +08:00
|
|
|
span,
|
2022-10-30 15:55:58 +04:00
|
|
|
module_path: Vec::new(),
|
2024-08-06 19:27:15 +08:00
|
|
|
vis,
|
2022-10-30 15:55:58 +04:00
|
|
|
});
|
2024-08-09 18:33:20 +08:00
|
|
|
self.r.import_use_map.insert(import, Used::Other);
|
2022-10-30 15:55:58 +04:00
|
|
|
let import_binding = self.r.import(binding, import);
|
|
|
|
|
self.r.define(self.r.graph_root, ident, MacroNS, import_binding);
|
2019-08-08 23:57:35 +03:00
|
|
|
} else {
|
|
|
|
|
self.r.check_reserved_macro_name(ident, res);
|
2023-11-24 23:39:42 +03:00
|
|
|
self.insert_unused_macro(ident, def_id, item.id);
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2022-04-28 15:52:54 +03:00
|
|
|
let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding(
|
2020-11-06 16:11:21 +03:00
|
|
|
self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
|
|
|
|
|
parent_macro_rules_scope: parent_scope.macro_rules,
|
|
|
|
|
binding,
|
|
|
|
|
ident,
|
|
|
|
|
}),
|
2022-04-28 15:52:54 +03:00
|
|
|
));
|
|
|
|
|
self.r.macro_rules_scopes.insert(def_id, scope);
|
|
|
|
|
scope
|
2019-08-08 23:57:35 +03:00
|
|
|
} else {
|
|
|
|
|
let module = parent_scope.module;
|
2020-03-21 17:51:29 +03:00
|
|
|
let vis = match item.kind {
|
|
|
|
|
// Visibilities must not be resolved non-speculatively twice
|
|
|
|
|
// and we already resolved this one as a `fn` item visibility.
|
2022-03-24 02:55:22 +03:00
|
|
|
ItemKind::Fn(..) => {
|
|
|
|
|
self.try_resolve_visibility(&item.vis, false).unwrap_or(ty::Visibility::Public)
|
|
|
|
|
}
|
2020-03-21 17:51:29 +03:00
|
|
|
_ => self.resolve_visibility(&item.vis),
|
|
|
|
|
};
|
2022-08-28 00:10:06 +03:00
|
|
|
if !vis.is_public() {
|
2023-11-24 23:39:42 +03:00
|
|
|
self.insert_unused_macro(ident, def_id, item.id);
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2020-03-14 01:06:36 +03:00
|
|
|
self.parent_scope.macro_rules
|
2019-08-08 23:57:35 +03:00
|
|
|
}
|
|
|
|
|
}
|
2016-09-14 21:03:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
macro_rules! method {
|
2019-09-26 17:25:31 +01:00
|
|
|
($visit:ident: $ty:ty, $invoc:path, $walk:ident) => {
|
2024-09-10 16:19:40 +10:00
|
|
|
fn $visit(&mut self, node: &'a $ty) {
|
2019-09-26 17:25:31 +01:00
|
|
|
if let $invoc(..) = node.kind {
|
2016-10-06 08:04:30 +00:00
|
|
|
self.visit_invoc(node.id);
|
|
|
|
|
} else {
|
|
|
|
|
visit::$walk(self, node);
|
2016-09-14 21:03:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2020-03-21 14:44:17 +01:00
|
|
|
};
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
2020-02-29 19:32:20 +03:00
|
|
|
method!(visit_expr: ast::Expr, ast::ExprKind::MacCall, walk_expr);
|
|
|
|
|
method!(visit_pat: ast::Pat, ast::PatKind::MacCall, walk_pat);
|
|
|
|
|
method!(visit_ty: ast::Ty, ast::TyKind::MacCall, walk_ty);
|
2016-09-14 21:03:09 +00:00
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_item(&mut self, item: &'a Item) {
|
2020-12-31 17:59:09 +03:00
|
|
|
let orig_module_scope = self.parent_scope.module;
|
|
|
|
|
self.parent_scope.macro_rules = match item.kind {
|
2017-03-05 05:15:58 +00:00
|
|
|
ItemKind::MacroDef(..) => {
|
2020-12-31 17:59:09 +03:00
|
|
|
let macro_rules_scope = self.define_macro(item);
|
|
|
|
|
visit::walk_item(self, item);
|
|
|
|
|
macro_rules_scope
|
2017-03-05 05:15:58 +00:00
|
|
|
}
|
2024-04-24 19:56:56 +03:00
|
|
|
ItemKind::MacCall(..) => self.visit_invoc_in_module(item.id),
|
2020-12-31 17:59:09 +03:00
|
|
|
_ => {
|
|
|
|
|
let orig_macro_rules_scope = self.parent_scope.macro_rules;
|
|
|
|
|
self.build_reduced_graph_for_item(item);
|
2024-06-18 16:45:50 +03:00
|
|
|
match item.kind {
|
|
|
|
|
ItemKind::Mod(..) => {
|
|
|
|
|
// Visit attributes after items for backward compatibility.
|
|
|
|
|
// This way they can use `macro_rules` defined later.
|
|
|
|
|
self.visit_vis(&item.vis);
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
item.kind.walk(item.span, item.id, &item.vis, (), self);
|
2024-06-18 16:45:50 +03:00
|
|
|
visit::walk_list!(self, visit_attribute, &item.attrs);
|
|
|
|
|
}
|
|
|
|
|
_ => visit::walk_item(self, item),
|
|
|
|
|
}
|
2020-12-31 17:59:09 +03:00
|
|
|
match item.kind {
|
|
|
|
|
ItemKind::Mod(..) if self.contains_macro_use(&item.attrs) => {
|
|
|
|
|
self.parent_scope.macro_rules
|
|
|
|
|
}
|
|
|
|
|
_ => orig_macro_rules_scope,
|
|
|
|
|
}
|
2016-10-06 08:04:30 +00:00
|
|
|
}
|
|
|
|
|
};
|
2020-12-31 17:59:09 +03:00
|
|
|
self.parent_scope.module = orig_module_scope;
|
2016-10-06 08:04:30 +00:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_stmt(&mut self, stmt: &'a ast::Stmt) {
|
2020-02-29 19:32:20 +03:00
|
|
|
if let ast::StmtKind::MacCall(..) = stmt.kind {
|
2020-11-21 18:02:37 +03:00
|
|
|
self.parent_scope.macro_rules = self.visit_invoc_in_module(stmt.id);
|
2016-10-06 08:04:30 +00:00
|
|
|
} else {
|
|
|
|
|
visit::walk_stmt(self, stmt);
|
|
|
|
|
}
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
|
2025-04-01 14:49:58 +11:00
|
|
|
let ident = match foreign_item.kind {
|
|
|
|
|
ForeignItemKind::Static(box StaticItem { ident, .. })
|
|
|
|
|
| ForeignItemKind::Fn(box Fn { ident, .. })
|
|
|
|
|
| ForeignItemKind::TyAlias(box TyAlias { ident, .. }) => ident,
|
|
|
|
|
ForeignItemKind::MacCall(_) => {
|
|
|
|
|
self.visit_invoc_in_module(foreign_item.id);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
2018-03-10 18:16:26 -08:00
|
|
|
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
self.build_reduced_graph_for_foreign_item(foreign_item, ident);
|
2024-04-24 20:31:51 +03:00
|
|
|
visit::walk_item(self, foreign_item);
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_block(&mut self, block: &'a Block) {
|
2019-08-08 03:44:16 +03:00
|
|
|
let orig_current_module = self.parent_scope.module;
|
2020-03-14 01:06:36 +03:00
|
|
|
let orig_current_macro_rules_scope = self.parent_scope.macro_rules;
|
2019-08-08 03:44:16 +03:00
|
|
|
self.build_reduced_graph_for_block(block);
|
2016-09-16 22:21:46 +00:00
|
|
|
visit::walk_block(self, block);
|
2019-08-08 03:44:16 +03:00
|
|
|
self.parent_scope.module = orig_current_module;
|
2020-03-14 01:06:36 +03:00
|
|
|
self.parent_scope.macro_rules = orig_current_macro_rules_scope;
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|
2016-09-14 23:39:13 +00:00
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) {
|
2025-04-01 14:49:58 +11:00
|
|
|
let (ident, ns) = match item.kind {
|
|
|
|
|
AssocItemKind::Const(box ConstItem { ident, .. })
|
|
|
|
|
| AssocItemKind::Fn(box Fn { ident, .. })
|
|
|
|
|
| AssocItemKind::Delegation(box Delegation { ident, .. }) => (ident, ValueNS),
|
|
|
|
|
|
|
|
|
|
AssocItemKind::Type(box TyAlias { ident, .. }) => (ident, TypeNS),
|
|
|
|
|
|
|
|
|
|
AssocItemKind::MacCall(_) => {
|
|
|
|
|
match ctxt {
|
|
|
|
|
AssocCtxt::Trait => {
|
|
|
|
|
self.visit_invoc_in_module(item.id);
|
|
|
|
|
}
|
|
|
|
|
AssocCtxt::Impl { .. } => {
|
|
|
|
|
let invoc_id = item.id.placeholder_to_expn_id();
|
|
|
|
|
if !self.r.glob_delegation_invoc_ids.contains(&invoc_id) {
|
|
|
|
|
self.r
|
|
|
|
|
.impl_unexpanded_invocations
|
|
|
|
|
.entry(self.r.invocation_parent(invoc_id))
|
|
|
|
|
.or_default()
|
|
|
|
|
.insert(invoc_id);
|
|
|
|
|
}
|
|
|
|
|
self.visit_invoc(item.id);
|
2024-03-15 14:21:03 +03:00
|
|
|
}
|
2020-11-21 18:02:37 +03:00
|
|
|
}
|
2025-04-01 14:49:58 +11:00
|
|
|
return;
|
2020-11-21 18:02:37 +03:00
|
|
|
}
|
2016-10-04 16:36:14 +11:00
|
|
|
|
2025-04-01 14:49:58 +11:00
|
|
|
AssocItemKind::DelegationMac(..) => bug!(),
|
|
|
|
|
};
|
2021-01-06 17:19:47 +03:00
|
|
|
let vis = self.resolve_visibility(&item.vis);
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(item.id);
|
|
|
|
|
let local_def_id = feed.key();
|
2020-10-17 02:28:11 +03:00
|
|
|
let def_id = local_def_id.to_def_id();
|
2020-01-30 00:18:54 +01:00
|
|
|
|
2025-03-25 09:00:35 +00:00
|
|
|
if !(matches!(ctxt, AssocCtxt::Impl { of_trait: true })
|
|
|
|
|
&& matches!(item.vis.kind, ast::VisibilityKind::Inherited))
|
2021-01-06 17:19:47 +03:00
|
|
|
{
|
|
|
|
|
// Trait impl item visibility is inherited from its trait when not specified
|
|
|
|
|
// explicitly. In that case we cannot determine it here in early resolve,
|
|
|
|
|
// so we leave a hole in the visibility table to be filled later.
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2021-01-06 17:19:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ctxt == AssocCtxt::Trait {
|
|
|
|
|
let parent = self.parent_scope.module;
|
|
|
|
|
let expansion = self.parent_scope.expansion;
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
|
2024-03-15 14:21:03 +03:00
|
|
|
} else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
|
|
|
|
|
let impl_def_id = self.r.tcx.local_parent(local_def_id);
|
Move `ast::Item::ident` into `ast::ItemKind`.
`ast::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
`Trait`, `TraitAlias`, `MacroDef`, `Delegation`.
- It's always empty for these item kinds: `Use`, `ForeignMod`,
`GlobalAsm`, `Impl`, `MacCall`, `DelegationMac`.
There is a similar story for `AssocItemKind` and `ForeignItemKind`.
Some sites that handle items check for an empty ident, some don't. This
is a very C-like way of doing things, but this is Rust, we have sum
types, we can do this properly and never forget to check for the
exceptional case and never YOLO possibly empty identifiers (or possibly
dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- `ast::Item` got 8 bytes bigger. This could be avoided by boxing the
fields within some of the `ast::ItemKind` variants (specifically:
`Struct`, `Union`, `Enum`). I might do that in a follow-up; this
commit is big enough already.
- For the visitors: `FnKind` no longer needs an `ident` field because
the `Fn` within how has one.
- In the parser, the `ItemInfo` typedef is no longer needed. It was used
in various places to return an `Ident` alongside an `ItemKind`, but
now the `Ident` (if present) is within the `ItemKind`.
- In a few places I renamed identifier variables called `name` (or
`foo_name`) as `ident` (or `foo_ident`), to better match the type, and
because `name` is normally used for `Symbol`s. It's confusing to see
something like `foo_name.name`.
2025-03-21 09:47:43 +11:00
|
|
|
let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
|
2024-03-15 14:21:03 +03:00
|
|
|
self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
|
2020-10-17 02:28:11 +03:00
|
|
|
}
|
2016-09-14 23:39:13 +00:00
|
|
|
|
2020-01-30 00:18:54 +01:00
|
|
|
visit::walk_assoc_item(self, item, ctxt);
|
2019-12-11 21:58:00 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_attribute(&mut self, attr: &'a ast::Attribute) {
|
2019-11-30 02:20:07 +01:00
|
|
|
if !attr.is_doc_comment() && attr::is_builtin_attr(attr) {
|
2019-10-24 06:33:12 +11:00
|
|
|
self.r
|
|
|
|
|
.builtin_attrs
|
|
|
|
|
.push((attr.get_normal_item().path.segments[0].ident, self.parent_scope));
|
2018-09-03 00:04:54 +03:00
|
|
|
}
|
|
|
|
|
visit::walk_attribute(self, attr);
|
|
|
|
|
}
|
2019-09-09 09:26:25 -03:00
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_arm(&mut self, arm: &'a ast::Arm) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if arm.is_placeholder {
|
|
|
|
|
self.visit_invoc(arm.id);
|
|
|
|
|
} else {
|
|
|
|
|
visit::walk_arm(self, arm);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_expr_field(&mut self, f: &'a ast::ExprField) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if f.is_placeholder {
|
|
|
|
|
self.visit_invoc(f.id);
|
|
|
|
|
} else {
|
2021-03-16 00:36:07 +03:00
|
|
|
visit::walk_expr_field(self, f);
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_pat_field(&mut self, fp: &'a ast::PatField) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if fp.is_placeholder {
|
|
|
|
|
self.visit_invoc(fp.id);
|
|
|
|
|
} else {
|
2021-03-16 00:36:07 +03:00
|
|
|
visit::walk_pat_field(self, fp);
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if param.is_placeholder {
|
|
|
|
|
self.visit_invoc(param.id);
|
|
|
|
|
} else {
|
|
|
|
|
visit::walk_generic_param(self, param);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_param(&mut self, p: &'a ast::Param) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if p.is_placeholder {
|
|
|
|
|
self.visit_invoc(p.id);
|
|
|
|
|
} else {
|
|
|
|
|
visit::walk_param(self, p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_field_def(&mut self, sf: &'a ast::FieldDef) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if sf.is_placeholder {
|
|
|
|
|
self.visit_invoc(sf.id);
|
|
|
|
|
} else {
|
2020-10-17 02:28:11 +03:00
|
|
|
let vis = self.resolve_visibility(&sf.vis);
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(self.r.feed(sf.id), vis);
|
2021-03-16 00:36:07 +03:00
|
|
|
visit::walk_field_def(self, sf);
|
2019-09-09 09:26:25 -03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Constructs the reduced graph for one variant. Variants exist in the
|
|
|
|
|
// type and value namespaces.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_variant(&mut self, variant: &'a ast::Variant) {
|
2019-09-09 09:26:25 -03:00
|
|
|
if variant.is_placeholder {
|
2020-11-21 18:02:37 +03:00
|
|
|
self.visit_invoc_in_module(variant.id);
|
2019-09-09 09:26:25 -03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let parent = self.parent_scope.module;
|
|
|
|
|
let expn_id = self.parent_scope.expansion;
|
|
|
|
|
let ident = variant.ident;
|
|
|
|
|
|
|
|
|
|
// Define a name in the type namespace.
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(variant.id);
|
|
|
|
|
let def_id = feed.key();
|
2021-01-06 17:19:47 +03:00
|
|
|
let vis = self.resolve_visibility(&variant.vis);
|
2023-11-21 23:40:23 +03:00
|
|
|
self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, vis);
|
2019-09-09 09:26:25 -03:00
|
|
|
|
2020-10-17 02:28:11 +03:00
|
|
|
// If the variant is marked as non_exhaustive then lower the visibility to within the crate.
|
2023-03-19 21:32:34 +04:00
|
|
|
let ctor_vis =
|
2024-12-07 15:27:17 +01:00
|
|
|
if vis.is_public() && ast::attr::contains_name(&variant.attrs, sym::non_exhaustive) {
|
2023-03-19 21:32:34 +04:00
|
|
|
ty::Visibility::Restricted(CRATE_DEF_ID)
|
|
|
|
|
} else {
|
|
|
|
|
vis
|
|
|
|
|
};
|
2019-09-09 09:26:25 -03:00
|
|
|
|
|
|
|
|
// Define a constructor name in the value namespace.
|
2023-11-21 23:40:23 +03:00
|
|
|
if let Some(ctor_node_id) = variant.data.ctor_node_id() {
|
2024-02-14 15:28:40 +00:00
|
|
|
let feed = self.r.feed(ctor_node_id);
|
|
|
|
|
let ctor_def_id = feed.key();
|
2023-11-21 23:40:23 +03:00
|
|
|
let ctor_res = self.res(ctor_def_id);
|
2022-10-25 20:15:15 +04:00
|
|
|
self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
|
2024-02-14 15:28:40 +00:00
|
|
|
self.r.feed_visibility(feed, ctor_vis);
|
2022-11-23 00:08:17 +03:00
|
|
|
}
|
2022-10-25 20:15:15 +04:00
|
|
|
|
2020-07-09 17:42:07 -07:00
|
|
|
// Record field names for error reporting.
|
2024-07-06 19:21:22 +00:00
|
|
|
self.insert_field_idents(def_id, variant.data.fields());
|
2024-01-04 21:45:06 +08:00
|
|
|
self.insert_field_visibilities_local(def_id.to_def_id(), variant.data.fields());
|
2019-09-09 09:26:25 -03:00
|
|
|
|
|
|
|
|
visit::walk_variant(self, variant);
|
|
|
|
|
}
|
2021-10-17 19:32:34 +03:00
|
|
|
|
2025-02-05 18:58:29 +08:00
|
|
|
fn visit_where_predicate(&mut self, p: &'a ast::WherePredicate) {
|
|
|
|
|
if p.is_placeholder {
|
|
|
|
|
self.visit_invoc(p.id);
|
|
|
|
|
} else {
|
|
|
|
|
visit::walk_where_predicate(self, p);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn visit_crate(&mut self, krate: &'a ast::Crate) {
|
2022-01-05 16:09:55 +08:00
|
|
|
if krate.is_placeholder {
|
|
|
|
|
self.visit_invoc_in_module(krate.id);
|
2021-10-17 19:32:34 +03:00
|
|
|
} else {
|
2024-06-18 16:45:50 +03:00
|
|
|
// Visit attributes after items for backward compatibility.
|
|
|
|
|
// This way they can use `macro_rules` defined later.
|
|
|
|
|
visit::walk_list!(self, visit_item, &krate.items);
|
|
|
|
|
visit::walk_list!(self, visit_attribute, &krate.attrs);
|
2021-10-17 19:32:34 +03:00
|
|
|
self.contains_macro_use(&krate.attrs);
|
|
|
|
|
}
|
|
|
|
|
}
|
2014-12-30 12:16:42 -06:00
|
|
|
}
|