Rollup merge of #144912 - LorrensP-2158466:smart-resolver, r=petrochenkov
Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.
This pr introduces a `CmResolver`, a wrapper around the main resolver which gives out mutable access given a condition.
`CmResolver` only allows mutation when we’re not in speculative import resolution. This ensures we can’t accidentally mutate the resolver during this process, which is important as we move towards a batched resolution algorithm.
This also changes functions that are used during speculative import resolution to take a `CmResolver` instead of a `&mut Resolver`.
Also introduces a new kind of "smart pointer" which has the behaviour described above:
```rust
/// A wrapper around a mutable reference that conditionally allows mutable access.
pub(crate) struct RefOrMut<'a, T> {
p: &'a mut T,
mutable: bool,
}
type CmResolver<'r, 'ra, 'tcx> = RefOrMut<'r, Resolver<'ra, 'tcx>>;
```
r? petrochenkov
This commit is contained in:
@@ -223,7 +223,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) {
|
pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) {
|
||||||
for child in self.tcx.module_children(module.def_id()) {
|
for child in self.tcx.module_children(module.def_id()) {
|
||||||
let parent_scope = ParentScope::module(module, self);
|
let parent_scope = ParentScope::module(module, self.arenas);
|
||||||
self.build_reduced_graph_for_external_crate_res(child, parent_scope)
|
self.build_reduced_graph_for_external_crate_res(child, parent_scope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -373,7 +373,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
res,
|
res,
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
match self.r.resolve_path(
|
match self.r.cm().resolve_path(
|
||||||
&segments,
|
&segments,
|
||||||
None,
|
None,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -1128,7 +1128,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
for ident in single_imports.iter().cloned() {
|
for ident in single_imports.iter().cloned() {
|
||||||
let result = self.r.maybe_resolve_ident_in_module(
|
let result = self.r.cm().maybe_resolve_ident_in_module(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
MacroNS,
|
MacroNS,
|
||||||
|
|||||||
@@ -469,13 +469,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
pub(crate) fn lint_if_path_starts_with_module(
|
pub(crate) fn lint_if_path_starts_with_module(
|
||||||
&mut self,
|
&mut self,
|
||||||
finalize: Option<Finalize>,
|
finalize: Finalize,
|
||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
second_binding: Option<NameBinding<'_>>,
|
second_binding: Option<NameBinding<'_>>,
|
||||||
) {
|
) {
|
||||||
let Some(Finalize { node_id, root_span, .. }) = finalize else {
|
let Finalize { node_id, root_span, .. } = finalize;
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
let first_name = match path.get(0) {
|
let first_name = match path.get(0) {
|
||||||
// In the 2018 edition this lint is a hard error, so nothing to do
|
// In the 2018 edition this lint is a hard error, so nothing to do
|
||||||
@@ -1029,7 +1027,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) -> Option<TypoSuggestion> {
|
) -> Option<TypoSuggestion> {
|
||||||
let mut suggestions = Vec::new();
|
let mut suggestions = Vec::new();
|
||||||
let ctxt = ident.span.ctxt();
|
let ctxt = ident.span.ctxt();
|
||||||
self.visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
|
self.cm().visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::DeriveHelpers(expn_id) => {
|
Scope::DeriveHelpers(expn_id) => {
|
||||||
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
|
let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
|
||||||
@@ -1048,7 +1046,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
if filter_fn(res) {
|
if filter_fn(res) {
|
||||||
for derive in parent_scope.derives {
|
for derive in parent_scope.derives {
|
||||||
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
||||||
let Ok((Some(ext), _)) = this.resolve_macro_path(
|
let Ok((Some(ext), _)) = this.reborrow().resolve_macro_path(
|
||||||
derive,
|
derive,
|
||||||
Some(MacroKind::Derive),
|
Some(MacroKind::Derive),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -1482,7 +1480,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) {
|
) {
|
||||||
// Bring imported but unused `derive` macros into `macro_map` so we ensure they can be used
|
// Bring imported but unused `derive` macros into `macro_map` so we ensure they can be used
|
||||||
// for suggestions.
|
// for suggestions.
|
||||||
self.visit_scopes(
|
self.cm().visit_scopes(
|
||||||
ScopeSet::Macro(MacroKind::Derive),
|
ScopeSet::Macro(MacroKind::Derive),
|
||||||
&parent_scope,
|
&parent_scope,
|
||||||
ident.span.ctxt(),
|
ident.span.ctxt(),
|
||||||
@@ -1591,7 +1589,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
|
||||||
let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
let Ok(binding) = self.cm().early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::All(ns),
|
ScopeSet::All(ns),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -2271,7 +2269,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
if ns == TypeNS || ns == ValueNS {
|
if ns == TypeNS || ns == ValueNS {
|
||||||
let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
|
let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
|
||||||
let binding = if let Some(module) = module {
|
let binding = if let Some(module) = module {
|
||||||
self.resolve_ident_in_module(
|
self.cm()
|
||||||
|
.resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
ident,
|
||||||
ns_to_try,
|
ns_to_try,
|
||||||
@@ -2298,7 +2297,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.early_resolve_ident_in_lexical_scope(
|
self.cm()
|
||||||
|
.early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::All(ns_to_try),
|
ScopeSet::All(ns_to_try),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -2401,7 +2401,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
|
if let Ok(binding) = self.cm().early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::All(ValueNS),
|
ScopeSet::All(ValueNS),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -2531,7 +2531,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `self` and check if that is valid.
|
// Replace first ident with `self` and check if that is valid.
|
||||||
path[0].ident.name = kw::SelfLower;
|
path[0].ident.name = kw::SelfLower;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!(?path, ?result);
|
debug!(?path, ?result);
|
||||||
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
||||||
}
|
}
|
||||||
@@ -2551,7 +2551,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `crate` and check if that is valid.
|
// Replace first ident with `crate` and check if that is valid.
|
||||||
path[0].ident.name = kw::Crate;
|
path[0].ident.name = kw::Crate;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!(?path, ?result);
|
debug!(?path, ?result);
|
||||||
if let PathResult::Module(..) = result {
|
if let PathResult::Module(..) = result {
|
||||||
Some((
|
Some((
|
||||||
@@ -2583,7 +2583,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) -> Option<(Vec<Segment>, Option<String>)> {
|
) -> Option<(Vec<Segment>, Option<String>)> {
|
||||||
// Replace first ident with `crate` and check if that is valid.
|
// Replace first ident with `crate` and check if that is valid.
|
||||||
path[0].ident.name = kw::Super;
|
path[0].ident.name = kw::Super;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!(?path, ?result);
|
debug!(?path, ?result);
|
||||||
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
if let PathResult::Module(..) = result { Some((path, None)) } else { None }
|
||||||
}
|
}
|
||||||
@@ -2618,7 +2618,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
for name in extern_crate_names.into_iter() {
|
for name in extern_crate_names.into_iter() {
|
||||||
// Replace first ident with a crate name and check if that is valid.
|
// Replace first ident with a crate name and check if that is valid.
|
||||||
path[0].ident.name = name;
|
path[0].ident.name = name;
|
||||||
let result = self.maybe_resolve_path(&path, None, parent_scope, None);
|
let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
|
||||||
debug!(?path, ?name, ?result);
|
debug!(?path, ?name, ?result);
|
||||||
if let PathResult::Module(..) = result {
|
if let PathResult::Module(..) = result {
|
||||||
return Some((path, None));
|
return Some((path, None));
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ use crate::imports::{Import, NameResolution};
|
|||||||
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
|
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
|
||||||
use crate::macros::{MacroRulesScope, sub_namespace_match};
|
use crate::macros::{MacroRulesScope, sub_namespace_match};
|
||||||
use crate::{
|
use crate::{
|
||||||
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, Determinacy, Finalize,
|
AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
|
||||||
ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding,
|
Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
|
||||||
NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope,
|
NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
|
||||||
ScopeSet, Segment, Used, Weak, errors,
|
Resolver, Scope, ScopeSet, Segment, Used, Weak, errors,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
@@ -44,12 +44,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
/// A generic scope visitor.
|
/// A generic scope visitor.
|
||||||
/// Visits scopes in order to resolve some identifier in them or perform other actions.
|
/// Visits scopes in order to resolve some identifier in them or perform other actions.
|
||||||
/// If the callback returns `Some` result, we stop visiting scopes and return it.
|
/// If the callback returns `Some` result, we stop visiting scopes and return it.
|
||||||
pub(crate) fn visit_scopes<T>(
|
pub(crate) fn visit_scopes<'r, T>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
scope_set: ScopeSet<'ra>,
|
scope_set: ScopeSet<'ra>,
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
ctxt: SyntaxContext,
|
ctxt: SyntaxContext,
|
||||||
mut visitor: impl FnMut(&mut Self, Scope<'ra>, UsePrelude, SyntaxContext) -> Option<T>,
|
mut visitor: impl FnMut(
|
||||||
|
&mut CmResolver<'r, 'ra, 'tcx>,
|
||||||
|
Scope<'ra>,
|
||||||
|
UsePrelude,
|
||||||
|
SyntaxContext,
|
||||||
|
) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
// General principles:
|
// General principles:
|
||||||
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
// 1. Not controlled (user-defined) names should have higher priority than controlled names
|
||||||
@@ -146,7 +151,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
if visit {
|
if visit {
|
||||||
let use_prelude = if use_prelude { UsePrelude::Yes } else { UsePrelude::No };
|
let use_prelude = if use_prelude { UsePrelude::Yes } else { UsePrelude::No };
|
||||||
if let break_result @ Some(..) = visitor(self, scope, use_prelude, ctxt) {
|
if let break_result @ Some(..) = visitor(&mut self, scope, use_prelude, ctxt) {
|
||||||
return break_result;
|
return break_result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,7 +346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
_ => break,
|
_ => break,
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = self.resolve_ident_in_module_unadjusted(
|
let item = self.cm().resolve_ident_in_module_unadjusted(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -356,7 +361,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
return Some(LexicalScopeBinding::Item(binding));
|
return Some(LexicalScopeBinding::Item(binding));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.early_resolve_ident_in_lexical_scope(
|
self.cm()
|
||||||
|
.early_resolve_ident_in_lexical_scope(
|
||||||
orig_ident,
|
orig_ident,
|
||||||
ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
|
ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -375,8 +381,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
|
/// The function is used for resolving initial segments of macro paths (e.g., `foo` in
|
||||||
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
|
/// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn early_resolve_ident_in_lexical_scope(
|
pub(crate) fn early_resolve_ident_in_lexical_scope<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
orig_ident: Ident,
|
orig_ident: Ident,
|
||||||
scope_set: ScopeSet<'ra>,
|
scope_set: ScopeSet<'ra>,
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -450,7 +456,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let mut result = Err(Determinacy::Determined);
|
let mut result = Err(Determinacy::Determined);
|
||||||
for derive in parent_scope.derives {
|
for derive in parent_scope.derives {
|
||||||
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
|
||||||
match this.resolve_macro_path(
|
match this.reborrow().resolve_macro_path(
|
||||||
derive,
|
derive,
|
||||||
Some(MacroKind::Derive),
|
Some(MacroKind::Derive),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -497,7 +503,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
|
finalize.map(|f| Finalize { used: Used::Scope, ..f }),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
let binding = this.resolve_ident_in_module_unadjusted(
|
let binding = this.reborrow().resolve_ident_in_module_unadjusted(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -514,7 +520,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
match binding {
|
match binding {
|
||||||
Ok(binding) => {
|
Ok(binding) => {
|
||||||
if let Some(lint_id) = derive_fallback_lint_id {
|
if let Some(lint_id) = derive_fallback_lint_id {
|
||||||
this.lint_buffer.buffer_lint(
|
this.get_mut().lint_buffer.buffer_lint(
|
||||||
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
|
||||||
lint_id,
|
lint_id,
|
||||||
orig_ident.span,
|
orig_ident.span,
|
||||||
@@ -556,7 +562,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
None => Err(Determinacy::Determined),
|
None => Err(Determinacy::Determined),
|
||||||
},
|
},
|
||||||
Scope::ExternPrelude => {
|
Scope::ExternPrelude => {
|
||||||
match this.extern_prelude_get(ident, finalize.is_some()) {
|
match this.reborrow().extern_prelude_get(ident, finalize.is_some()) {
|
||||||
Some(binding) => Ok((binding, Flags::empty())),
|
Some(binding) => Ok((binding, Flags::empty())),
|
||||||
None => Err(Determinacy::determined(
|
None => Err(Determinacy::determined(
|
||||||
this.graph_root.unexpanded_invocations.borrow().is_empty(),
|
this.graph_root.unexpanded_invocations.borrow().is_empty(),
|
||||||
@@ -570,7 +576,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Scope::StdLibPrelude => {
|
Scope::StdLibPrelude => {
|
||||||
let mut result = Err(Determinacy::Determined);
|
let mut result = Err(Determinacy::Determined);
|
||||||
if let Some(prelude) = this.prelude
|
if let Some(prelude) = this.prelude
|
||||||
&& let Ok(binding) = this.resolve_ident_in_module_unadjusted(
|
&& let Ok(binding) = this.reborrow().resolve_ident_in_module_unadjusted(
|
||||||
ModuleOrUniformRoot::Module(prelude),
|
ModuleOrUniformRoot::Module(prelude),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -687,7 +693,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
AmbiguityErrorMisc::None
|
AmbiguityErrorMisc::None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
this.ambiguity_errors.push(AmbiguityError {
|
this.get_mut().ambiguity_errors.push(AmbiguityError {
|
||||||
kind,
|
kind,
|
||||||
ident: orig_ident,
|
ident: orig_ident,
|
||||||
b1: innermost_binding,
|
b1: innermost_binding,
|
||||||
@@ -725,8 +731,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn maybe_resolve_ident_in_module(
|
pub(crate) fn maybe_resolve_ident_in_module<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
module: ModuleOrUniformRoot<'ra>,
|
module: ModuleOrUniformRoot<'ra>,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
@@ -738,8 +744,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn resolve_ident_in_module(
|
pub(crate) fn resolve_ident_in_module<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
module: ModuleOrUniformRoot<'ra>,
|
module: ModuleOrUniformRoot<'ra>,
|
||||||
mut ident: Ident,
|
mut ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
@@ -776,12 +782,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
ignore_import,
|
ignore_import,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
|
||||||
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
|
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn resolve_ident_in_module_unadjusted(
|
fn resolve_ident_in_module_unadjusted<'r>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
module: ModuleOrUniformRoot<'ra>,
|
module: ModuleOrUniformRoot<'ra>,
|
||||||
ident: Ident,
|
ident: Ident,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
@@ -812,7 +817,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
assert_eq!(shadowing, Shadowing::Unrestricted);
|
assert_eq!(shadowing, Shadowing::Unrestricted);
|
||||||
return if ns != TypeNS {
|
return if ns != TypeNS {
|
||||||
Err((Determined, Weak::No))
|
Err((Determined, Weak::No))
|
||||||
} else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
|
} else if let Some(binding) =
|
||||||
|
self.reborrow().extern_prelude_get(ident, finalize.is_some())
|
||||||
|
{
|
||||||
Ok(binding)
|
Ok(binding)
|
||||||
} else if !self.graph_root.unexpanded_invocations.borrow().is_empty() {
|
} else if !self.graph_root.unexpanded_invocations.borrow().is_empty() {
|
||||||
// Macro-expanded `extern crate` items can add names to extern prelude.
|
// Macro-expanded `extern crate` items can add names to extern prelude.
|
||||||
@@ -865,7 +872,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
.find_map(|binding| if binding == ignore_binding { None } else { binding });
|
.find_map(|binding| if binding == ignore_binding { None } else { binding });
|
||||||
|
|
||||||
if let Some(finalize) = finalize {
|
if let Some(finalize) = finalize {
|
||||||
return self.finalize_module_binding(
|
return self.get_mut().finalize_module_binding(
|
||||||
ident,
|
ident,
|
||||||
binding,
|
binding,
|
||||||
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
|
if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
|
||||||
@@ -875,7 +882,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let check_usable = |this: &Self, binding: NameBinding<'ra>| {
|
let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| {
|
||||||
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
|
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
|
||||||
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
|
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
|
||||||
};
|
};
|
||||||
@@ -891,7 +898,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
// Check if one of single imports can still define the name,
|
// Check if one of single imports can still define the name,
|
||||||
// if it can then our result is not determined and can be invalidated.
|
// if it can then our result is not determined and can be invalidated.
|
||||||
if self.single_import_can_define_name(
|
if self.reborrow().single_import_can_define_name(
|
||||||
&resolution,
|
&resolution,
|
||||||
binding,
|
binding,
|
||||||
ns,
|
ns,
|
||||||
@@ -962,7 +969,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Some(None) => {}
|
Some(None) => {}
|
||||||
None => continue,
|
None => continue,
|
||||||
};
|
};
|
||||||
let result = self.resolve_ident_in_module_unadjusted(
|
let result = self.reborrow().resolve_ident_in_module_unadjusted(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -1049,8 +1056,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
// Checks if a single import can define the `Ident` corresponding to `binding`.
|
// Checks if a single import can define the `Ident` corresponding to `binding`.
|
||||||
// This is used to check whether we can definitively accept a glob as a resolution.
|
// This is used to check whether we can definitively accept a glob as a resolution.
|
||||||
fn single_import_can_define_name(
|
fn single_import_can_define_name<'r>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
resolution: &NameResolution<'ra>,
|
resolution: &NameResolution<'ra>,
|
||||||
binding: Option<NameBinding<'ra>>,
|
binding: Option<NameBinding<'ra>>,
|
||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
@@ -1086,7 +1093,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.resolve_ident_in_module(
|
match self.reborrow().resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
*source,
|
*source,
|
||||||
ns,
|
ns,
|
||||||
@@ -1409,8 +1416,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn maybe_resolve_path(
|
pub(crate) fn maybe_resolve_path<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -1418,10 +1425,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
) -> PathResult<'ra> {
|
) -> PathResult<'ra> {
|
||||||
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import)
|
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None, ignore_import)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument(level = "debug", skip(self))]
|
#[instrument(level = "debug", skip(self))]
|
||||||
pub(crate) fn resolve_path(
|
pub(crate) fn resolve_path<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -1440,8 +1446,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_path_with_ribs(
|
pub(crate) fn resolve_path_with_ribs<'r>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
path: &[Segment],
|
path: &[Segment],
|
||||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -1457,18 +1463,23 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
// We'll provide more context to the privacy errors later, up to `len`.
|
// We'll provide more context to the privacy errors later, up to `len`.
|
||||||
let privacy_errors_len = self.privacy_errors.len();
|
let privacy_errors_len = self.privacy_errors.len();
|
||||||
|
fn record_segment_res<'r, 'ra, 'tcx>(
|
||||||
for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
|
mut this: CmResolver<'r, 'ra, 'tcx>,
|
||||||
debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
|
finalize: Option<Finalize>,
|
||||||
let record_segment_res = |this: &mut Self, res| {
|
res: Res,
|
||||||
|
id: Option<NodeId>,
|
||||||
|
) {
|
||||||
if finalize.is_some()
|
if finalize.is_some()
|
||||||
&& let Some(id) = id
|
&& let Some(id) = id
|
||||||
&& !this.partial_res_map.contains_key(&id)
|
&& !this.partial_res_map.contains_key(&id)
|
||||||
{
|
{
|
||||||
assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
|
assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
|
||||||
this.record_partial_res(id, PartialRes::new(res));
|
this.get_mut().record_partial_res(id, PartialRes::new(res));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
|
||||||
|
debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
|
||||||
|
|
||||||
let is_last = segment_idx + 1 == path.len();
|
let is_last = segment_idx + 1 == path.len();
|
||||||
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
|
||||||
@@ -1507,7 +1518,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
|
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
|
||||||
let self_mod = self.resolve_self(&mut ctxt, parent_scope.module);
|
let self_mod = self.resolve_self(&mut ctxt, parent_scope.module);
|
||||||
if let Some(res) = self_mod.res() {
|
if let Some(res) = self_mod.res() {
|
||||||
record_segment_res(self, res);
|
record_segment_res(self.reborrow(), finalize, res, id);
|
||||||
}
|
}
|
||||||
module = Some(ModuleOrUniformRoot::Module(self_mod));
|
module = Some(ModuleOrUniformRoot::Module(self_mod));
|
||||||
continue;
|
continue;
|
||||||
@@ -1529,7 +1540,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// `::a::b`, `crate::a::b` or `$crate::a::b`
|
// `::a::b`, `crate::a::b` or `$crate::a::b`
|
||||||
let crate_root = self.resolve_crate_root(ident);
|
let crate_root = self.resolve_crate_root(ident);
|
||||||
if let Some(res) = crate_root.res() {
|
if let Some(res) = crate_root.res() {
|
||||||
record_segment_res(self, res);
|
record_segment_res(self.reborrow(), finalize, res, id);
|
||||||
}
|
}
|
||||||
module = Some(ModuleOrUniformRoot::Module(crate_root));
|
module = Some(ModuleOrUniformRoot::Module(crate_root));
|
||||||
continue;
|
continue;
|
||||||
@@ -1562,7 +1573,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let binding = if let Some(module) = module {
|
let binding = if let Some(module) = module {
|
||||||
self.resolve_ident_in_module(
|
self.reborrow()
|
||||||
|
.resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -1576,7 +1588,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
&& let Some(TypeNS | ValueNS) = opt_ns
|
&& let Some(TypeNS | ValueNS) = opt_ns
|
||||||
{
|
{
|
||||||
assert!(ignore_import.is_none());
|
assert!(ignore_import.is_none());
|
||||||
match self.resolve_ident_in_lexical_scope(
|
match self.get_mut().resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -1588,7 +1600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
|
||||||
// we found a local variable or type param
|
// we found a local variable or type param
|
||||||
Some(LexicalScopeBinding::Res(res)) => {
|
Some(LexicalScopeBinding::Res(res)) => {
|
||||||
record_segment_res(self, res);
|
record_segment_res(self.reborrow(), finalize, res, id);
|
||||||
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
||||||
res,
|
res,
|
||||||
path.len() - 1,
|
path.len() - 1,
|
||||||
@@ -1597,7 +1609,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
_ => Err(Determinacy::determined(finalize.is_some())),
|
_ => Err(Determinacy::determined(finalize.is_some())),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.early_resolve_ident_in_lexical_scope(
|
self.reborrow().early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::All(ns),
|
ScopeSet::All(ns),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -1618,9 +1630,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// Mark every privacy error in this path with the res to the last element. This allows us
|
// Mark every privacy error in this path with the res to the last element. This allows us
|
||||||
// to detect the item the user cares about and either find an alternative import, or tell
|
// to detect the item the user cares about and either find an alternative import, or tell
|
||||||
// the user it is not accessible.
|
// the user it is not accessible.
|
||||||
for error in &mut self.privacy_errors[privacy_errors_len..] {
|
if finalize.is_some() {
|
||||||
|
for error in &mut self.get_mut().privacy_errors[privacy_errors_len..] {
|
||||||
error.outermost_res = Some((res, ident));
|
error.outermost_res = Some((res, ident));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
|
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
|
||||||
if let Some(def_id) = binding.res().module_like_def_id() {
|
if let Some(def_id) = binding.res().module_like_def_id() {
|
||||||
@@ -1628,7 +1642,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
module_had_parse_errors = true;
|
module_had_parse_errors = true;
|
||||||
}
|
}
|
||||||
module = Some(ModuleOrUniformRoot::Module(self.expect_module(def_id)));
|
module = Some(ModuleOrUniformRoot::Module(self.expect_module(def_id)));
|
||||||
record_segment_res(self, res);
|
record_segment_res(self.reborrow(), finalize, res, id);
|
||||||
} else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
|
} else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
|
||||||
if binding.is_import() {
|
if binding.is_import() {
|
||||||
self.dcx().emit_err(errors::ToolModuleImported {
|
self.dcx().emit_err(errors::ToolModuleImported {
|
||||||
@@ -1641,8 +1655,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
} else if res == Res::Err {
|
} else if res == Res::Err {
|
||||||
return PathResult::NonModule(PartialRes::new(Res::Err));
|
return PathResult::NonModule(PartialRes::new(Res::Err));
|
||||||
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
|
} else if opt_ns.is_some() && (is_last || maybe_assoc) {
|
||||||
self.lint_if_path_starts_with_module(finalize, path, second_binding);
|
if let Some(finalize) = finalize {
|
||||||
record_segment_res(self, res);
|
self.get_mut().lint_if_path_starts_with_module(
|
||||||
|
finalize,
|
||||||
|
path,
|
||||||
|
second_binding,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
record_segment_res(self.reborrow(), finalize, res, id);
|
||||||
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
return PathResult::NonModule(PartialRes::with_unresolved_segments(
|
||||||
res,
|
res,
|
||||||
path.len() - segment_idx - 1,
|
path.len() - segment_idx - 1,
|
||||||
@@ -1677,6 +1697,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut this = self.reborrow();
|
||||||
return PathResult::failed(
|
return PathResult::failed(
|
||||||
ident,
|
ident,
|
||||||
is_last,
|
is_last,
|
||||||
@@ -1684,7 +1705,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
module_had_parse_errors,
|
module_had_parse_errors,
|
||||||
module,
|
module,
|
||||||
|| {
|
|| {
|
||||||
self.report_path_resolution_error(
|
this.get_mut().report_path_resolution_error(
|
||||||
path,
|
path,
|
||||||
opt_ns,
|
opt_ns,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -1701,7 +1722,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.lint_if_path_starts_with_module(finalize, path, second_binding);
|
if let Some(finalize) = finalize {
|
||||||
|
self.get_mut().lint_if_path_starts_with_module(finalize, path, second_binding);
|
||||||
|
}
|
||||||
|
|
||||||
PathResult::Module(match module {
|
PathResult::Module(match module {
|
||||||
Some(module) => module,
|
Some(module) => module,
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ use crate::errors::{
|
|||||||
ConsiderAddingMacroExport, ConsiderMarkingAsPub,
|
ConsiderAddingMacroExport, ConsiderMarkingAsPub,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
AmbiguityError, AmbiguityKind, BindingKey, Determinacy, Finalize, ImportSuggestion, Module,
|
AmbiguityError, AmbiguityKind, BindingKey, CmResolver, Determinacy, Finalize, ImportSuggestion,
|
||||||
ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
|
Module, ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope,
|
||||||
PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string,
|
PathResult, PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string,
|
||||||
|
names_to_string,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Res = def::Res<NodeId>;
|
type Res = def::Res<NodeId>;
|
||||||
@@ -551,13 +552,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
/// Resolves all imports for the crate. This method performs the fixed-
|
/// Resolves all imports for the crate. This method performs the fixed-
|
||||||
/// point iteration.
|
/// point iteration.
|
||||||
pub(crate) fn resolve_imports(&mut self) {
|
pub(crate) fn resolve_imports(&mut self) {
|
||||||
|
self.assert_speculative = true;
|
||||||
let mut prev_indeterminate_count = usize::MAX;
|
let mut prev_indeterminate_count = usize::MAX;
|
||||||
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
|
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
|
||||||
while indeterminate_count < prev_indeterminate_count {
|
while indeterminate_count < prev_indeterminate_count {
|
||||||
prev_indeterminate_count = indeterminate_count;
|
prev_indeterminate_count = indeterminate_count;
|
||||||
indeterminate_count = 0;
|
indeterminate_count = 0;
|
||||||
for import in mem::take(&mut self.indeterminate_imports) {
|
for import in mem::take(&mut self.indeterminate_imports) {
|
||||||
let import_indeterminate_count = self.resolve_import(import);
|
let import_indeterminate_count = self.cm().resolve_import(import);
|
||||||
indeterminate_count += import_indeterminate_count;
|
indeterminate_count += import_indeterminate_count;
|
||||||
match import_indeterminate_count {
|
match import_indeterminate_count {
|
||||||
0 => self.determined_imports.push(import),
|
0 => self.determined_imports.push(import),
|
||||||
@@ -565,6 +567,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self.assert_speculative = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn finalize_imports(&mut self) {
|
pub(crate) fn finalize_imports(&mut self) {
|
||||||
@@ -837,7 +840,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
///
|
///
|
||||||
/// Meanwhile, if resolve successful, the resolved bindings are written
|
/// Meanwhile, if resolve successful, the resolved bindings are written
|
||||||
/// into the module.
|
/// into the module.
|
||||||
fn resolve_import(&mut self, import: Import<'ra>) -> usize {
|
fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize {
|
||||||
debug!(
|
debug!(
|
||||||
"(resolving import for module) resolving import `{}::...` in `{}`",
|
"(resolving import for module) resolving import `{}::...` in `{}`",
|
||||||
Segment::names_to_string(&import.module_path),
|
Segment::names_to_string(&import.module_path),
|
||||||
@@ -846,7 +849,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let module = if let Some(module) = import.imported_module.get() {
|
let module = if let Some(module) = import.imported_module.get() {
|
||||||
module
|
module
|
||||||
} else {
|
} else {
|
||||||
let path_res = self.maybe_resolve_path(
|
let path_res = self.reborrow().maybe_resolve_path(
|
||||||
&import.module_path,
|
&import.module_path,
|
||||||
None,
|
None,
|
||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
@@ -866,19 +869,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
(source, target, bindings, type_ns_only)
|
(source, target, bindings, type_ns_only)
|
||||||
}
|
}
|
||||||
ImportKind::Glob { .. } => {
|
ImportKind::Glob { .. } => {
|
||||||
self.resolve_glob_import(import);
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
|
// specualtive resolution.
|
||||||
|
self.get_mut_unchecked().resolve_glob_import(import);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut indeterminate_count = 0;
|
let mut indeterminate_count = 0;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns_cm(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
if bindings[ns].get() != PendingBinding::Pending {
|
if bindings[ns].get() != PendingBinding::Pending {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let binding_result = this.maybe_resolve_ident_in_module(
|
let binding_result = this.reborrow().maybe_resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
source,
|
source,
|
||||||
ns,
|
ns,
|
||||||
@@ -901,16 +906,30 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
// We need the `target`, `source` can be extracted.
|
// We need the `target`, `source` can be extracted.
|
||||||
let imported_binding = this.import(binding, import);
|
let imported_binding = this.import(binding, import);
|
||||||
this.define_binding_local(parent, target, ns, imported_binding);
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
|
// specualtive resolution.
|
||||||
|
this.get_mut_unchecked().define_binding_local(
|
||||||
|
parent,
|
||||||
|
target,
|
||||||
|
ns,
|
||||||
|
imported_binding,
|
||||||
|
);
|
||||||
PendingBinding::Ready(Some(imported_binding))
|
PendingBinding::Ready(Some(imported_binding))
|
||||||
}
|
}
|
||||||
Err(Determinacy::Determined) => {
|
Err(Determinacy::Determined) => {
|
||||||
// Don't remove underscores from `single_imports`, they were never added.
|
// Don't remove underscores from `single_imports`, they were never added.
|
||||||
if target.name != kw::Underscore {
|
if target.name != kw::Underscore {
|
||||||
let key = BindingKey::new(target, ns);
|
let key = BindingKey::new(target, ns);
|
||||||
this.update_local_resolution(parent, key, false, |_, resolution| {
|
// FIXME: Use mutable resolver directly as a hack, this should be an output of
|
||||||
|
// specualtive resolution.
|
||||||
|
this.get_mut_unchecked().update_local_resolution(
|
||||||
|
parent,
|
||||||
|
key,
|
||||||
|
false,
|
||||||
|
|_, resolution| {
|
||||||
resolution.single_imports.swap_remove(&import);
|
resolution.single_imports.swap_remove(&import);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
PendingBinding::Ready(None)
|
PendingBinding::Ready(None)
|
||||||
}
|
}
|
||||||
@@ -943,7 +962,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// We'll provide more context to the privacy errors later, up to `len`.
|
// We'll provide more context to the privacy errors later, up to `len`.
|
||||||
let privacy_errors_len = self.privacy_errors.len();
|
let privacy_errors_len = self.privacy_errors.len();
|
||||||
|
|
||||||
let path_res = self.resolve_path(
|
let path_res = self.cm().resolve_path(
|
||||||
&import.module_path,
|
&import.module_path,
|
||||||
None,
|
None,
|
||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
@@ -1060,7 +1079,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||||
let mut full_path = import.module_path.clone();
|
let mut full_path = import.module_path.clone();
|
||||||
full_path.push(Segment::from_ident(Ident::dummy()));
|
full_path.push(Segment::from_ident(Ident::dummy()));
|
||||||
self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
self.lint_if_path_starts_with_module(finalize, &full_path, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let ModuleOrUniformRoot::Module(module) = module
|
if let ModuleOrUniformRoot::Module(module) = module
|
||||||
@@ -1103,7 +1122,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// importing it if available.
|
// importing it if available.
|
||||||
let mut path = import.module_path.clone();
|
let mut path = import.module_path.clone();
|
||||||
path.push(Segment::from_ident(ident));
|
path.push(Segment::from_ident(ident));
|
||||||
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(
|
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.cm().resolve_path(
|
||||||
&path,
|
&path,
|
||||||
None,
|
None,
|
||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
@@ -1121,7 +1140,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let mut all_ns_err = true;
|
let mut all_ns_err = true;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
let binding = this.resolve_ident_in_module(
|
let binding = this.cm().resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -1184,7 +1203,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
let mut all_ns_failed = true;
|
let mut all_ns_failed = true;
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if !type_ns_only || ns == TypeNS {
|
if !type_ns_only || ns == TypeNS {
|
||||||
let binding = this.resolve_ident_in_module(
|
let binding = this.cm().resolve_ident_in_module(
|
||||||
module,
|
module,
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
@@ -1373,7 +1392,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
full_path.push(Segment::from_ident(ident));
|
full_path.push(Segment::from_ident(ident));
|
||||||
self.per_ns(|this, ns| {
|
self.per_ns(|this, ns| {
|
||||||
if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
|
if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
|
||||||
this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding));
|
this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1426,7 +1445,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match this.early_resolve_ident_in_lexical_scope(
|
match this.cm().early_resolve_ident_in_lexical_scope(
|
||||||
target,
|
target,
|
||||||
ScopeSet::All(ns),
|
ScopeSet::All(ns),
|
||||||
&import.parent_scope,
|
&import.parent_scope,
|
||||||
|
|||||||
@@ -1424,7 +1424,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
// During late resolution we only track the module component of the parent scope,
|
// During late resolution we only track the module component of the parent scope,
|
||||||
// although it may be useful to track other components as well for diagnostics.
|
// although it may be useful to track other components as well for diagnostics.
|
||||||
let graph_root = resolver.graph_root;
|
let graph_root = resolver.graph_root;
|
||||||
let parent_scope = ParentScope::module(graph_root, resolver);
|
let parent_scope = ParentScope::module(graph_root, resolver.arenas);
|
||||||
let start_rib_kind = RibKind::Module(graph_root);
|
let start_rib_kind = RibKind::Module(graph_root);
|
||||||
LateResolutionVisitor {
|
LateResolutionVisitor {
|
||||||
r: resolver,
|
r: resolver,
|
||||||
@@ -1484,7 +1484,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
opt_ns: Option<Namespace>, // `None` indicates a module path in import
|
||||||
finalize: Option<Finalize>,
|
finalize: Option<Finalize>,
|
||||||
) -> PathResult<'ra> {
|
) -> PathResult<'ra> {
|
||||||
self.r.resolve_path_with_ribs(
|
self.r.cm().resolve_path_with_ribs(
|
||||||
path,
|
path,
|
||||||
opt_ns,
|
opt_ns,
|
||||||
&self.parent_scope,
|
&self.parent_scope,
|
||||||
@@ -4466,9 +4466,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
|
|||||||
if qself.is_none() {
|
if qself.is_none() {
|
||||||
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
|
let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
|
||||||
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
|
let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
|
||||||
if let Ok((_, res)) =
|
if let Ok((_, res)) = self.r.cm().resolve_macro_path(
|
||||||
self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None, None)
|
&path,
|
||||||
{
|
None,
|
||||||
|
&self.parent_scope,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
) {
|
||||||
return Ok(Some(PartialRes::new(res)));
|
return Ok(Some(PartialRes::new(res)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2389,7 +2389,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
|
|||||||
|
|
||||||
// Look for associated items in the current trait.
|
// Look for associated items in the current trait.
|
||||||
if let Some((module, _)) = self.current_trait_ref
|
if let Some((module, _)) = self.current_trait_ref
|
||||||
&& let Ok(binding) = self.r.maybe_resolve_ident_in_module(
|
&& let Ok(binding) = self.r.cm().maybe_resolve_ident_in_module(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ns,
|
ns,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||||
#![doc(rust_logo)]
|
#![doc(rust_logo)]
|
||||||
|
#![feature(arbitrary_self_types)]
|
||||||
#![feature(assert_matches)]
|
#![feature(assert_matches)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(if_let_guard)]
|
#![feature(if_let_guard)]
|
||||||
@@ -162,11 +163,11 @@ struct ParentScope<'ra> {
|
|||||||
impl<'ra> ParentScope<'ra> {
|
impl<'ra> ParentScope<'ra> {
|
||||||
/// Creates a parent scope with the passed argument used as the module scope component,
|
/// Creates a parent scope with the passed argument used as the module scope component,
|
||||||
/// and other scope components set to default empty values.
|
/// and other scope components set to default empty values.
|
||||||
fn module(module: Module<'ra>, resolver: &Resolver<'ra, '_>) -> ParentScope<'ra> {
|
fn module(module: Module<'ra>, arenas: &'ra ResolverArenas<'ra>) -> ParentScope<'ra> {
|
||||||
ParentScope {
|
ParentScope {
|
||||||
module,
|
module,
|
||||||
expansion: LocalExpnId::ROOT,
|
expansion: LocalExpnId::ROOT,
|
||||||
macro_rules: resolver.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
|
macro_rules: arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
|
||||||
derives: &[],
|
derives: &[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1054,6 +1055,9 @@ pub struct Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
graph_root: Module<'ra>,
|
graph_root: Module<'ra>,
|
||||||
|
|
||||||
|
/// Assert that we are in speculative resolution mode.
|
||||||
|
assert_speculative: bool,
|
||||||
|
|
||||||
prelude: Option<Module<'ra>>,
|
prelude: Option<Module<'ra>>,
|
||||||
extern_prelude: FxIndexMap<Macros20NormalizedIdent, ExternPreludeEntry<'ra>>,
|
extern_prelude: FxIndexMap<Macros20NormalizedIdent, ExternPreludeEntry<'ra>>,
|
||||||
|
|
||||||
@@ -1156,10 +1160,11 @@ pub struct Resolver<'ra, 'tcx> {
|
|||||||
unused_macro_rules: FxIndexMap<NodeId, DenseBitSet<usize>>,
|
unused_macro_rules: FxIndexMap<NodeId, DenseBitSet<usize>>,
|
||||||
proc_macro_stubs: FxHashSet<LocalDefId>,
|
proc_macro_stubs: FxHashSet<LocalDefId>,
|
||||||
/// Traces collected during macro resolution and validated when it's complete.
|
/// Traces collected during macro resolution and validated when it's complete.
|
||||||
|
// FIXME: Remove interior mutability when speculative resolution produces these as outputs.
|
||||||
single_segment_macro_resolutions:
|
single_segment_macro_resolutions:
|
||||||
Vec<(Ident, MacroKind, ParentScope<'ra>, Option<NameBinding<'ra>>, Option<Span>)>,
|
RefCell<Vec<(Ident, MacroKind, ParentScope<'ra>, Option<NameBinding<'ra>>, Option<Span>)>>,
|
||||||
multi_segment_macro_resolutions:
|
multi_segment_macro_resolutions:
|
||||||
Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'ra>, Option<Res>, Namespace)>,
|
RefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'ra>, Option<Res>, Namespace)>>,
|
||||||
builtin_attrs: Vec<(Ident, ParentScope<'ra>)>,
|
builtin_attrs: Vec<(Ident, ParentScope<'ra>)>,
|
||||||
/// `derive(Copy)` marks items they are applied to so they are treated specially later.
|
/// `derive(Copy)` marks items they are applied to so they are treated specially later.
|
||||||
/// Derive macros cannot modify the item themselves and have to store the markers in the global
|
/// Derive macros cannot modify the item themselves and have to store the markers in the global
|
||||||
@@ -1527,6 +1532,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// The outermost module has def ID 0; this is not reflected in the
|
// The outermost module has def ID 0; this is not reflected in the
|
||||||
// AST.
|
// AST.
|
||||||
graph_root,
|
graph_root,
|
||||||
|
assert_speculative: false, // Only set/cleared in Resolver::resolve_imports for now
|
||||||
prelude: None,
|
prelude: None,
|
||||||
extern_prelude,
|
extern_prelude,
|
||||||
|
|
||||||
@@ -1644,7 +1650,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
impl_trait_names: Default::default(),
|
impl_trait_names: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let root_parent_scope = ParentScope::module(graph_root, &resolver);
|
let root_parent_scope = ParentScope::module(graph_root, resolver.arenas);
|
||||||
resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
|
resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
|
||||||
resolver.feed_visibility(crate_feed, Visibility::Public);
|
resolver.feed_visibility(crate_feed, Visibility::Public);
|
||||||
|
|
||||||
@@ -1792,6 +1798,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns a conditionally mutable resolver.
|
||||||
|
///
|
||||||
|
/// Currently only dependent on `assert_speculative`, if `assert_speculative` is false,
|
||||||
|
/// the resolver will allow mutation; otherwise, it will be immutable.
|
||||||
|
fn cm(&mut self) -> CmResolver<'_, 'ra, 'tcx> {
|
||||||
|
CmResolver::new(self, !self.assert_speculative)
|
||||||
|
}
|
||||||
|
|
||||||
/// Runs the function on each namespace.
|
/// Runs the function on each namespace.
|
||||||
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
|
fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
|
||||||
f(self, TypeNS);
|
f(self, TypeNS);
|
||||||
@@ -1799,6 +1813,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
f(self, MacroNS);
|
f(self, MacroNS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn per_ns_cm<'r, F: FnMut(&mut CmResolver<'r, 'ra, 'tcx>, Namespace)>(
|
||||||
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
|
mut f: F,
|
||||||
|
) {
|
||||||
|
f(&mut self, TypeNS);
|
||||||
|
f(&mut self, ValueNS);
|
||||||
|
f(&mut self, MacroNS);
|
||||||
|
}
|
||||||
|
|
||||||
fn is_builtin_macro(&self, res: Res) -> bool {
|
fn is_builtin_macro(&self, res: Res) -> bool {
|
||||||
self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
|
self.get_macro(res).is_some_and(|macro_data| macro_data.ext.builtin_name.is_some())
|
||||||
}
|
}
|
||||||
@@ -1852,14 +1875,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| {
|
self.cm().visit_scopes(ScopeSet::All(TypeNS), parent_scope, ctxt, |this, scope, _, _| {
|
||||||
match scope {
|
match scope {
|
||||||
Scope::Module(module, _) => {
|
Scope::Module(module, _) => {
|
||||||
this.traits_in_module(module, assoc_item, &mut found_traits);
|
this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
|
||||||
}
|
}
|
||||||
Scope::StdLibPrelude => {
|
Scope::StdLibPrelude => {
|
||||||
if let Some(module) = this.prelude {
|
if let Some(module) = this.prelude {
|
||||||
this.traits_in_module(module, assoc_item, &mut found_traits);
|
this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {}
|
Scope::ExternPrelude | Scope::ToolPrelude | Scope::BuiltinTypes => {}
|
||||||
@@ -2002,11 +2025,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// Do not report the lint if the macro name resolves in stdlib prelude
|
// Do not report the lint if the macro name resolves in stdlib prelude
|
||||||
// even without the problematic `macro_use` import.
|
// even without the problematic `macro_use` import.
|
||||||
let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| {
|
let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| {
|
||||||
self.maybe_resolve_ident_in_module(
|
let empty_module = self.empty_module;
|
||||||
|
let arenas = self.arenas;
|
||||||
|
self.cm()
|
||||||
|
.maybe_resolve_ident_in_module(
|
||||||
ModuleOrUniformRoot::Module(prelude),
|
ModuleOrUniformRoot::Module(prelude),
|
||||||
ident,
|
ident,
|
||||||
MacroNS,
|
MacroNS,
|
||||||
&ParentScope::module(self.empty_module, self),
|
&ParentScope::module(empty_module, arenas),
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
@@ -2180,7 +2206,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extern_prelude_get(&mut self, ident: Ident, finalize: bool) -> Option<NameBinding<'ra>> {
|
fn extern_prelude_get<'r>(
|
||||||
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
|
ident: Ident,
|
||||||
|
finalize: bool,
|
||||||
|
) -> Option<NameBinding<'ra>> {
|
||||||
let mut record_use = None;
|
let mut record_use = None;
|
||||||
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
|
let entry = self.extern_prelude.get(&Macros20NormalizedIdent::new(ident));
|
||||||
let binding = entry.and_then(|entry| match entry.binding.get() {
|
let binding = entry.and_then(|entry| match entry.binding.get() {
|
||||||
@@ -2216,7 +2246,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(binding) = record_use {
|
if let Some(binding) = record_use {
|
||||||
self.record_use(ident, binding, Used::Scope);
|
self.get_mut().record_use(ident, binding, Used::Scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
binding
|
binding
|
||||||
@@ -2251,7 +2281,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
.collect();
|
.collect();
|
||||||
let Ok(segments) = segments else { return None };
|
let Ok(segments) = segments else { return None };
|
||||||
|
|
||||||
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
|
match self.cm().maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
|
PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
|
||||||
PathResult::NonModule(path_res) => {
|
PathResult::NonModule(path_res) => {
|
||||||
path_res.full_res().filter(|res| !matches!(res, Res::Def(DefKind::Ctor(..), _)))
|
path_res.full_res().filter(|res| !matches!(res, Res::Def(DefKind::Ctor(..), _)))
|
||||||
@@ -2330,9 +2360,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
fn resolve_main(&mut self) {
|
fn resolve_main(&mut self) {
|
||||||
let module = self.graph_root;
|
let module = self.graph_root;
|
||||||
let ident = Ident::with_dummy_span(sym::main);
|
let ident = Ident::with_dummy_span(sym::main);
|
||||||
let parent_scope = &ParentScope::module(module, self);
|
let parent_scope = &ParentScope::module(module, self.arenas);
|
||||||
|
|
||||||
let Ok(name_binding) = self.maybe_resolve_ident_in_module(
|
let Ok(name_binding) = self.cm().maybe_resolve_ident_in_module(
|
||||||
ModuleOrUniformRoot::Module(module),
|
ModuleOrUniformRoot::Module(module),
|
||||||
ident,
|
ident,
|
||||||
ValueNS,
|
ValueNS,
|
||||||
@@ -2426,3 +2456,63 @@ impl Finalize {
|
|||||||
pub fn provide(providers: &mut Providers) {
|
pub fn provide(providers: &mut Providers) {
|
||||||
providers.registered_tools = macros::registered_tools;
|
providers.registered_tools = macros::registered_tools;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mod ref_mut {
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
/// A wrapper around a mutable reference that conditionally allows mutable access.
|
||||||
|
pub(crate) struct RefOrMut<'a, T> {
|
||||||
|
p: &'a mut T,
|
||||||
|
mutable: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Deref for RefOrMut<'a, T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
self.p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> AsRef<T> for RefOrMut<'a, T> {
|
||||||
|
fn as_ref(&self) -> &T {
|
||||||
|
self.p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> RefOrMut<'a, T> {
|
||||||
|
pub(crate) fn new(p: &'a mut T, mutable: bool) -> Self {
|
||||||
|
RefOrMut { p, mutable }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is needed because this wraps a `&mut T` and is therefore not `Copy`.
|
||||||
|
pub(crate) fn reborrow(&mut self) -> RefOrMut<'_, T> {
|
||||||
|
RefOrMut { p: self.p, mutable: self.mutable }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the inner value if allowed.
|
||||||
|
///
|
||||||
|
/// # Panics
|
||||||
|
/// Panics if the `mutable` flag is false.
|
||||||
|
#[track_caller]
|
||||||
|
pub(crate) fn get_mut(&mut self) -> &mut T {
|
||||||
|
match self.mutable {
|
||||||
|
false => panic!("Can't mutably borrow speculative resolver"),
|
||||||
|
true => self.p,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a mutable reference to the inner value without checking if
|
||||||
|
/// it's in a mutable state.
|
||||||
|
pub(crate) fn get_mut_unchecked(&mut self) -> &mut T {
|
||||||
|
self.p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A wrapper around `&mut Resolver` that may be mutable or immutable, depending on a conditions.
|
||||||
|
///
|
||||||
|
/// `Cm` stands for "conditionally mutable".
|
||||||
|
///
|
||||||
|
/// Prefer constructing it through [`Resolver::cm`] to ensure correctness.
|
||||||
|
type CmResolver<'r, 'ra, 'tcx> = ref_mut::RefOrMut<'r, Resolver<'ra, 'tcx>>;
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ use crate::errors::{
|
|||||||
};
|
};
|
||||||
use crate::imports::Import;
|
use crate::imports::Import;
|
||||||
use crate::{
|
use crate::{
|
||||||
BindingKey, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, ModuleKind,
|
BindingKey, CmResolver, DeriveData, Determinacy, Finalize, InvocationParent, MacroData,
|
||||||
ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError,
|
ModuleKind, ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult,
|
||||||
Resolver, ScopeSet, Segment, Used,
|
ResolutionError, Resolver, ScopeSet, Segment, Used,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Res = def::Res<NodeId>;
|
type Res = def::Res<NodeId>;
|
||||||
@@ -403,7 +403,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
|
|||||||
for (i, resolution) in entry.resolutions.iter_mut().enumerate() {
|
for (i, resolution) in entry.resolutions.iter_mut().enumerate() {
|
||||||
if resolution.exts.is_none() {
|
if resolution.exts.is_none() {
|
||||||
resolution.exts = Some(
|
resolution.exts = Some(
|
||||||
match self.resolve_macro_path(
|
match self.cm().resolve_macro_path(
|
||||||
&resolution.path,
|
&resolution.path,
|
||||||
Some(MacroKind::Derive),
|
Some(MacroKind::Derive),
|
||||||
&parent_scope,
|
&parent_scope,
|
||||||
@@ -568,7 +568,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
invoc_in_mod_inert_attr: Option<LocalDefId>,
|
invoc_in_mod_inert_attr: Option<LocalDefId>,
|
||||||
suggestion_span: Option<Span>,
|
suggestion_span: Option<Span>,
|
||||||
) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
|
) -> Result<(Arc<SyntaxExtension>, Res), Indeterminate> {
|
||||||
let (ext, res) = match self.resolve_macro_or_delegation_path(
|
let (ext, res) = match self.cm().resolve_macro_or_delegation_path(
|
||||||
path,
|
path,
|
||||||
Some(kind),
|
Some(kind),
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -713,8 +713,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
Ok((ext, res))
|
Ok((ext, res))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn resolve_macro_path(
|
pub(crate) fn resolve_macro_path<'r>(
|
||||||
&mut self,
|
self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
kind: Option<MacroKind>,
|
kind: Option<MacroKind>,
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -736,8 +736,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_macro_or_delegation_path(
|
fn resolve_macro_or_delegation_path<'r>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
ast_path: &ast::Path,
|
ast_path: &ast::Path,
|
||||||
kind: Option<MacroKind>,
|
kind: Option<MacroKind>,
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
@@ -763,7 +763,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
let res = if deleg_impl.is_some() || path.len() > 1 {
|
let res = if deleg_impl.is_some() || path.len() > 1 {
|
||||||
let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
|
let ns = if deleg_impl.is_some() { TypeNS } else { MacroNS };
|
||||||
let res = match self.maybe_resolve_path(&path, Some(ns), parent_scope, ignore_import) {
|
let res = match self.reborrow().maybe_resolve_path(
|
||||||
|
&path,
|
||||||
|
Some(ns),
|
||||||
|
parent_scope,
|
||||||
|
ignore_import,
|
||||||
|
) {
|
||||||
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
|
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => Ok(res),
|
||||||
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
|
||||||
PathResult::NonModule(..)
|
PathResult::NonModule(..)
|
||||||
@@ -777,7 +782,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
if trace {
|
if trace {
|
||||||
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||||
self.multi_segment_macro_resolutions.push((
|
// FIXME: Should be an output of Speculative Resolution.
|
||||||
|
self.multi_segment_macro_resolutions.borrow_mut().push((
|
||||||
path,
|
path,
|
||||||
path_span,
|
path_span,
|
||||||
kind,
|
kind,
|
||||||
@@ -791,7 +797,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
res
|
res
|
||||||
} else {
|
} else {
|
||||||
let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
|
let scope_set = kind.map_or(ScopeSet::All(MacroNS), ScopeSet::Macro);
|
||||||
let binding = self.early_resolve_ident_in_lexical_scope(
|
let binding = self.reborrow().early_resolve_ident_in_lexical_scope(
|
||||||
path[0].ident,
|
path[0].ident,
|
||||||
scope_set,
|
scope_set,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
@@ -806,7 +812,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
if trace {
|
if trace {
|
||||||
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
let kind = kind.expect("macro kind must be specified if tracing is enabled");
|
||||||
self.single_segment_macro_resolutions.push((
|
// FIXME: Should be an output of Speculative Resolution.
|
||||||
|
self.single_segment_macro_resolutions.borrow_mut().push((
|
||||||
path[0].ident,
|
path[0].ident,
|
||||||
kind,
|
kind,
|
||||||
*parent_scope,
|
*parent_scope,
|
||||||
@@ -817,7 +824,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
let res = binding.map(|binding| binding.res());
|
let res = binding.map(|binding| binding.res());
|
||||||
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
|
self.prohibit_imported_non_macro_attrs(binding.ok(), res.ok(), path_span);
|
||||||
self.report_out_of_scope_macro_calls(
|
self.reborrow().report_out_of_scope_macro_calls(
|
||||||
ast_path,
|
ast_path,
|
||||||
parent_scope,
|
parent_scope,
|
||||||
invoc_in_mod_inert_attr,
|
invoc_in_mod_inert_attr,
|
||||||
@@ -872,13 +879,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let macro_resolutions = mem::take(&mut self.multi_segment_macro_resolutions);
|
// FIXME: Should be an output of Speculative Resolution.
|
||||||
|
let macro_resolutions = self.multi_segment_macro_resolutions.take();
|
||||||
for (mut path, path_span, kind, parent_scope, initial_res, ns) in macro_resolutions {
|
for (mut path, path_span, kind, parent_scope, initial_res, ns) in macro_resolutions {
|
||||||
// FIXME: Path resolution will ICE if segment IDs present.
|
// FIXME: Path resolution will ICE if segment IDs present.
|
||||||
for seg in &mut path {
|
for seg in &mut path {
|
||||||
seg.id = None;
|
seg.id = None;
|
||||||
}
|
}
|
||||||
match self.resolve_path(
|
match self.cm().resolve_path(
|
||||||
&path,
|
&path,
|
||||||
Some(ns),
|
Some(ns),
|
||||||
&parent_scope,
|
&parent_scope,
|
||||||
@@ -905,8 +913,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
path_res
|
path_res
|
||||||
{
|
{
|
||||||
// try to suggest if it's not a macro, maybe a function
|
// try to suggest if it's not a macro, maybe a function
|
||||||
if let PathResult::NonModule(partial_res) =
|
if let PathResult::NonModule(partial_res) = self
|
||||||
self.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
|
.cm()
|
||||||
|
.maybe_resolve_path(&path, Some(ValueNS), &parent_scope, None)
|
||||||
&& partial_res.unresolved_segments() == 0
|
&& partial_res.unresolved_segments() == 0
|
||||||
{
|
{
|
||||||
let sm = self.tcx.sess.source_map();
|
let sm = self.tcx.sess.source_map();
|
||||||
@@ -948,9 +957,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let macro_resolutions = mem::take(&mut self.single_segment_macro_resolutions);
|
// FIXME: Should be an output of Speculative Resolution.
|
||||||
|
let macro_resolutions = self.single_segment_macro_resolutions.take();
|
||||||
for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions {
|
for (ident, kind, parent_scope, initial_binding, sugg_span) in macro_resolutions {
|
||||||
match self.early_resolve_ident_in_lexical_scope(
|
match self.cm().early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::Macro(kind),
|
ScopeSet::Macro(kind),
|
||||||
&parent_scope,
|
&parent_scope,
|
||||||
@@ -1005,7 +1015,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
let builtin_attrs = mem::take(&mut self.builtin_attrs);
|
let builtin_attrs = mem::take(&mut self.builtin_attrs);
|
||||||
for (ident, parent_scope) in builtin_attrs {
|
for (ident, parent_scope) in builtin_attrs {
|
||||||
let _ = self.early_resolve_ident_in_lexical_scope(
|
let _ = self.cm().early_resolve_ident_in_lexical_scope(
|
||||||
ident,
|
ident,
|
||||||
ScopeSet::Macro(MacroKind::Attr),
|
ScopeSet::Macro(MacroKind::Attr),
|
||||||
&parent_scope,
|
&parent_scope,
|
||||||
@@ -1090,8 +1100,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_out_of_scope_macro_calls(
|
fn report_out_of_scope_macro_calls<'r>(
|
||||||
&mut self,
|
mut self: CmResolver<'r, 'ra, 'tcx>,
|
||||||
path: &ast::Path,
|
path: &ast::Path,
|
||||||
parent_scope: &ParentScope<'ra>,
|
parent_scope: &ParentScope<'ra>,
|
||||||
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
|
||||||
@@ -1110,7 +1120,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
// If such resolution is successful and gives the same result
|
// If such resolution is successful and gives the same result
|
||||||
// (e.g. if the macro is re-imported), then silence the lint.
|
// (e.g. if the macro is re-imported), then silence the lint.
|
||||||
let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
|
let no_macro_rules = self.arenas.alloc_macro_rules_scope(MacroRulesScope::Empty);
|
||||||
let fallback_binding = self.early_resolve_ident_in_lexical_scope(
|
let fallback_binding = self.reborrow().early_resolve_ident_in_lexical_scope(
|
||||||
path.segments[0].ident,
|
path.segments[0].ident,
|
||||||
ScopeSet::Macro(MacroKind::Bang),
|
ScopeSet::Macro(MacroKind::Bang),
|
||||||
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
|
&ParentScope { macro_rules: no_macro_rules, ..*parent_scope },
|
||||||
@@ -1206,7 +1216,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||||||
|
|
||||||
let mut indeterminate = false;
|
let mut indeterminate = false;
|
||||||
for ns in namespaces {
|
for ns in namespaces {
|
||||||
match self.maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
|
match self.cm().maybe_resolve_path(path, Some(*ns), &parent_scope, None) {
|
||||||
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
|
PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true),
|
||||||
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
|
PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user