use crate::imports::ImportResolver;
use crate::Namespace::*;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BuiltinMacroState, Determinacy};
-use crate::{CrateLint, DeriveData, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
+use crate::{DeriveData, Finalize, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak};
use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding};
use rustc_ast::{self as ast, Inline, ItemKind, ModKind, NodeId};
use rustc_ast_lowering::ResolverAstLowering;
/// The reason is that we update scopes with value `MacroRulesScope::Invocation(invoc_id)`
/// in-place after `invoc_id` gets expanded.
/// This helps to avoid uncontrollable growth of `macro_rules!` scope chains,
-/// which usually grow lineraly with the number of macro invocations
+/// which usually grow linearly with the number of macro invocations
/// in a module (including derives) and hurt performance.
pub(crate) type MacroRulesScopeRef<'a> = Interned<'a, Cell<MacroRulesScope<'a>>>;
let mut indeterminate = false;
for ns in [TypeNS, ValueNS, MacroNS].iter().copied() {
- match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) {
+ match self.resolve_path(path, Some(ns), &parent_scope, Finalize::No) {
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
return Ok(true);
}
let res = if path.len() > 1 {
- let res = match self.resolve_path(
- &path,
- Some(MacroNS),
- parent_scope,
- false,
- path_span,
- CrateLint::No,
- ) {
+ let res = match self.resolve_path(&path, Some(MacroNS), parent_scope, Finalize::No) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
Ok(path_res.base_res())
}
path[0].ident,
scope_set,
parent_scope,
- false,
+ None,
force,
- path_span,
);
if let Err(Determinacy::Undetermined) = binding {
return Err(Determinacy::Undetermined);
orig_ident: Ident,
scope_set: ScopeSet<'a>,
parent_scope: &ParentScope<'a>,
- record_used: bool,
+ finalize: Option<Span>,
force: bool,
- path_span: Span,
) -> Result<&'a NameBinding<'a>, Determinacy> {
bitflags::bitflags! {
struct Flags: u8 {
}
}
- assert!(force || !record_used); // `record_used` implies `force`
+ assert!(force || !finalize.is_some()); // `finalize` implies `force`
// Make sure `self`, `super` etc produce an error when passed to here.
if orig_ident.is_path_segment_keyword() {
ident,
ns,
parent_scope,
- record_used,
- path_span,
+ finalize,
);
match binding {
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
ns,
adjusted_parent_scope,
!matches!(scope_set, ScopeSet::Late(..)),
- record_used,
- path_span,
+ finalize,
);
match binding {
Ok(binding) => {
Err(Determinacy::Determined)
}
}
- Scope::ExternPrelude => match this.extern_prelude_get(ident, !record_used) {
- Some(binding) => Ok((binding, Flags::empty())),
- None => Err(Determinacy::determined(
- this.graph_root.unexpanded_invocations.borrow().is_empty(),
- )),
- },
+ Scope::ExternPrelude => {
+ match this.extern_prelude_get(ident, finalize.is_some()) {
+ Some(binding) => Ok((binding, Flags::empty())),
+ None => Err(Determinacy::determined(
+ this.graph_root.unexpanded_invocations.borrow().is_empty(),
+ )),
+ }
+ }
Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() {
Some(ident) => ok(Res::ToolMod, ident.span, this.arenas),
None => Err(Determinacy::Determined),
ident,
ns,
parent_scope,
- false,
- path_span,
+ None,
) {
if use_prelude || this.is_builtin_macro(binding.res()) {
result = Ok((binding, Flags::MISC_FROM_PRELUDE));
Ok((binding, flags))
if sub_namespace_match(binding.macro_kind(), macro_kind) =>
{
- if !record_used || matches!(scope_set, ScopeSet::Late(..)) {
+ if finalize.is_none() || matches!(scope_set, ScopeSet::Late(..)) {
return Some(Ok(binding));
}
&path,
Some(MacroNS),
&parent_scope,
- true,
- path_span,
- CrateLint::No,
+ Finalize::SimplePath(ast::CRATE_NODE_ID, path_span),
) {
PathResult::NonModule(path_res) if path_res.unresolved_segments() == 0 => {
let res = path_res.base_res();
ident,
ScopeSet::Macro(kind),
&parent_scope,
+ Some(ident.span),
true,
- true,
- ident.span,
) {
Ok(binding) => {
let initial_res = initial_binding.map(|initial_binding| {
ident,
ScopeSet::Macro(MacroKind::Attr),
&parent_scope,
+ Some(ident.span),
true,
- true,
- ident.span,
);
}
}
// while still taking everything else from the source code.
// If we already loaded this builtin macro, give a better error message than 'no such builtin macro'.
match mem::replace(builtin_macro, BuiltinMacroState::AlreadySeen(item.span)) {
- BuiltinMacroState::NotYetSeen(ext) => result.kind = ext,
+ BuiltinMacroState::NotYetSeen(ext) => {
+ result.kind = ext;
+ if item.id != ast::DUMMY_NODE_ID {
+ self.builtin_macro_kinds
+ .insert(self.local_def_id(item.id), result.macro_kind());
+ }
+ }
BuiltinMacroState::AlreadySeen(span) => {
struct_span_err!(
self.session,