summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_resolve/src/ident.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve/src/ident.rs')
-rw-r--r--compiler/rustc_resolve/src/ident.rs274
1 files changed, 136 insertions, 138 deletions
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 945c7ce3a..520fab1f0 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -11,8 +11,6 @@ use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContex
use rustc_span::symbol::{kw, Ident};
use rustc_span::{Span, DUMMY_SP};
-use std::ptr;
-
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::late::{
ConstantHasGenerics, HasGenericParams, NoConstantGenericsReason, PathSource, Rib, RibKind,
@@ -20,7 +18,7 @@ use crate::late::{
use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::BindingKey;
use crate::{errors, AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy, Finalize};
-use crate::{Import, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
+use crate::{ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot};
use crate::{NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res};
use crate::{ResolutionError, Resolver, Scope, ScopeSet, Segment, ToNameBinding, Weak};
@@ -88,7 +86,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let rust_2015 = ctxt.edition().is_rust_2015();
let (ns, macro_kind, is_absolute_path) = match scope_set {
- ScopeSet::All(ns, _) => (ns, None, false),
+ ScopeSet::All(ns) => (ns, None, false),
ScopeSet::AbsolutePath(ns) => (ns, None, true),
ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
ScopeSet::Late(ns, ..) => (ns, None, false),
@@ -284,7 +282,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ribs: &[Rib<'a>],
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> Option<LexicalScopeBinding<'a>> {
assert!(ns == TypeNS || ns == ValueNS);
let orig_ident = ident;
@@ -370,7 +368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// expansion and import resolution (perhaps they can be merged in the future).
/// 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.
- #[instrument(level = "debug", skip(self, scope_set))]
+ #[instrument(level = "debug", skip(self))]
pub(crate) fn early_resolve_ident_in_lexical_scope(
&mut self,
orig_ident: Ident,
@@ -378,8 +376,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
force: bool,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
bitflags::bitflags! {
struct Flags: u8 {
const MACRO_RULES = 1 << 0;
@@ -397,11 +395,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Err(Determinacy::Determined);
}
- let (ns, macro_kind, is_import) = match scope_set {
- ScopeSet::All(ns, is_import) => (ns, None, is_import),
- ScopeSet::AbsolutePath(ns) => (ns, None, false),
- ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind), false),
- ScopeSet::Late(ns, ..) => (ns, None, false),
+ let (ns, macro_kind) = match scope_set {
+ ScopeSet::All(ns) => (ns, None),
+ ScopeSet::AbsolutePath(ns) => (ns, None),
+ ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
+ ScopeSet::Late(ns, ..) => (ns, None),
};
// This is *the* result, resolution from the scope closest to the resolved identifier.
@@ -415,7 +413,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// }
// So we have to save the innermost solution and continue searching in outer scopes
// to detect potential ambiguities.
- let mut innermost_result: Option<(&NameBinding<'_>, Flags)> = None;
+ let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
let mut determinacy = Determinacy::Determined;
// Go through all the scopes and try to resolve the name.
@@ -538,7 +536,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
),
);
}
- let misc_flags = if ptr::eq(module, this.graph_root) {
+ let misc_flags = if module == this.graph_root {
Flags::MISC_SUGGEST_CRATE
} else if module.is_normal() {
Flags::MISC_SUGGEST_SELF
@@ -631,9 +629,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let derive_helper_compat =
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
- let ambiguity_error_kind = if is_import {
- Some(AmbiguityKind::Import)
- } else if is_builtin(innermost_res) || is_builtin(res) {
+ let ambiguity_error_kind = if is_builtin(innermost_res)
+ || is_builtin(res)
+ {
Some(AmbiguityKind::BuiltinAttr)
} else if innermost_res == derive_helper_compat
|| res == derive_helper_compat && innermost_res != derive_helper
@@ -717,7 +715,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'a>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None)
.map_err(|(determinacy, _)| determinacy)
}
@@ -730,8 +728,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding)
.map_err(|(determinacy, _)| determinacy)
}
@@ -744,8 +742,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let tmp_parent_scope;
let mut adjusted_parent_scope = parent_scope;
match module {
@@ -782,8 +780,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ns: Namespace,
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, Determinacy> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext(
module,
ident,
@@ -809,8 +807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize: Option<Finalize>,
// This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking.
- ignore_binding: Option<&'a NameBinding<'a>>,
- ) -> Result<&'a NameBinding<'a>, (Determinacy, Weak)> {
+ ignore_binding: Option<NameBinding<'a>>,
+ ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let module = match module {
ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::CrateRootAndExternPrelude => {
@@ -853,10 +851,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
- let scopes = ScopeSet::All(ns, true);
let binding = self.early_resolve_ident_in_lexical_scope(
ident,
- scopes,
+ ScopeSet::All(ns),
parent_scope,
finalize,
finalize.is_some(),
@@ -874,13 +871,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// binding if it exists. What we really want here is having two separate scopes in
// a module - one for non-globs and one for globs, but until that's done use this
// hack to avoid inconsistent resolution ICEs during import validation.
- let binding =
- [resolution.binding, resolution.shadowed_glob].into_iter().find_map(|binding| {
- match (binding, ignore_binding) {
- (Some(binding), Some(ignored)) if ptr::eq(binding, ignored) => None,
- _ => binding,
- }
- });
+ let binding = [resolution.binding, resolution.shadowed_glob]
+ .into_iter()
+ .find_map(|binding| if binding == ignore_binding { None } else { binding });
if let Some(Finalize { path_span, report_private, .. }) = finalize {
let Some(binding) = binding else {
@@ -893,6 +886,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident,
binding,
dedup_span: path_span,
+ outermost_res: None,
+ parent_scope: *parent_scope,
});
} else {
return Err((Determined, Weak::No));
@@ -916,11 +911,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if !restricted_shadowing && binding.expansion != LocalExpnId::ROOT {
- if let NameBindingKind::Import {
- import: Import { kind: ImportKind::MacroExport, .. },
- ..
- } = binding.kind
- {
+ if let NameBindingKind::Import { import, .. } = binding.kind
+ && matches!(import.kind, ImportKind::MacroExport) {
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
}
}
@@ -929,7 +921,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return Ok(binding);
}
- let check_usable = |this: &mut Self, binding: &'a NameBinding<'a>| {
+ let check_usable = |this: &mut Self, binding: NameBinding<'a>| {
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
};
@@ -954,7 +946,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
if let Some(ignored) = ignore_binding &&
let NameBindingKind::Import { import, .. } = ignored.kind &&
- ptr::eq(import, &**single_import) {
+ import == *single_import {
// Ignore not just the binding itself, but if it has a shadowed_glob,
// ignore that, too, because this loop is supposed to only process
// named imports.
@@ -1351,7 +1343,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
opt_ns: Option<Namespace>, // `None` indicates a module path in import
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding)
}
@@ -1363,22 +1355,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>,
- ignore_binding: Option<&'a NameBinding<'a>>,
+ ignore_binding: Option<NameBinding<'a>>,
) -> PathResult<'a> {
- debug!(
- "resolve_path(path={:?}, opt_ns={:?}, finalize={:?}) path_len: {}",
- path,
- opt_ns,
- finalize,
- path.len()
- );
-
let mut module = None;
let mut allow_super = true;
let mut second_binding = None;
- for (i, &Segment { ident, id, .. }) in path.iter().enumerate() {
- debug!("resolve_path ident {} {:?} {:?}", i, ident, id);
+ // We'll provide more context to the privacy errors later, up to `len`.
+ let privacy_errors_len = self.privacy_errors.len();
+
+ for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
+ debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
let record_segment_res = |this: &mut Self, res| {
if finalize.is_some() {
if let Some(id) = id {
@@ -1390,7 +1377,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
};
- let is_last = i + 1 == path.len();
+ let is_last = segment_idx + 1 == path.len();
let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
let name = ident.name;
@@ -1399,7 +1386,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if ns == TypeNS {
if allow_super && name == kw::Super {
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
- let self_module = match i {
+ let self_module = match segment_idx {
0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
_ => match module {
Some(ModuleOrUniformRoot::Module(module)) => Some(module),
@@ -1414,11 +1401,15 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
continue;
}
}
- return PathResult::failed(ident.span, false, finalize.is_some(), || {
- ("there are too many leading `super` keywords".to_string(), None)
- });
+ return PathResult::failed(
+ ident.span,
+ false,
+ finalize.is_some(),
+ module,
+ || ("there are too many leading `super` keywords".to_string(), None),
+ );
}
- if i == 0 {
+ if segment_idx == 0 {
if name == kw::SelfLower {
let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
module = Some(ModuleOrUniformRoot::Module(
@@ -1447,14 +1438,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Report special messages for path segment keywords in wrong positions.
- if ident.is_path_segment_keyword() && i != 0 {
- return PathResult::failed(ident.span, false, finalize.is_some(), || {
+ if ident.is_path_segment_keyword() && segment_idx != 0 {
+ return PathResult::failed(ident.span, false, finalize.is_some(), module, || {
let name_str = if name == kw::PathRoot {
"crate root".to_string()
} else {
format!("`{}`", name)
};
- let label = if i == 1 && path[0].ident.name == kw::PathRoot {
+ let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
format!("global paths cannot start with {}", name_str)
} else {
format!("{} in paths can only be used in start position", name_str)
@@ -1463,66 +1454,61 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
});
}
- enum FindBindingResult<'a> {
- Binding(Result<&'a NameBinding<'a>, Determinacy>),
- Res(Res),
- }
- let find_binding_in_ns = |this: &mut Self, ns| {
- let binding = if let Some(module) = module {
- this.resolve_ident_in_module(
- module,
- ident,
- ns,
- parent_scope,
- finalize,
- ignore_binding,
- )
- } else if let Some(ribs) = ribs
- && let Some(TypeNS | ValueNS) = opt_ns
- {
- match this.resolve_ident_in_lexical_scope(
- ident,
- ns,
- parent_scope,
- finalize,
- &ribs[ns],
- ignore_binding,
- ) {
- // we found a locally-imported or available item/module
- Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
- // we found a local variable or type param
- Some(LexicalScopeBinding::Res(res)) => return FindBindingResult::Res(res),
- _ => Err(Determinacy::determined(finalize.is_some())),
+ let binding = if let Some(module) = module {
+ self.resolve_ident_in_module(
+ module,
+ ident,
+ ns,
+ parent_scope,
+ finalize,
+ ignore_binding,
+ )
+ } else if let Some(ribs) = ribs && let Some(TypeNS | ValueNS) = opt_ns {
+ match self.resolve_ident_in_lexical_scope(
+ ident,
+ ns,
+ parent_scope,
+ finalize,
+ &ribs[ns],
+ ignore_binding,
+ ) {
+ // we found a locally-imported or available item/module
+ Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
+ // we found a local variable or type param
+ Some(LexicalScopeBinding::Res(res)) => {
+ record_segment_res(self, res);
+ return PathResult::NonModule(PartialRes::with_unresolved_segments(
+ res,
+ path.len() - 1,
+ ));
}
- } else {
- let scopes = ScopeSet::All(ns, opt_ns.is_none());
- this.early_resolve_ident_in_lexical_scope(
- ident,
- scopes,
- parent_scope,
- finalize,
- finalize.is_some(),
- ignore_binding,
- )
- };
- FindBindingResult::Binding(binding)
- };
- let binding = match find_binding_in_ns(self, ns) {
- FindBindingResult::Res(res) => {
- record_segment_res(self, res);
- return PathResult::NonModule(PartialRes::with_unresolved_segments(
- res,
- path.len() - 1,
- ));
+ _ => Err(Determinacy::determined(finalize.is_some())),
}
- FindBindingResult::Binding(binding) => binding,
+ } else {
+ self.early_resolve_ident_in_lexical_scope(
+ ident,
+ ScopeSet::All(ns),
+ parent_scope,
+ finalize,
+ finalize.is_some(),
+ ignore_binding,
+ )
};
+
match binding {
Ok(binding) => {
- if i == 1 {
+ if segment_idx == 1 {
second_binding = Some(binding);
}
let res = binding.res();
+
+ // 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
+ // the user it is not accessible.
+ for error in &mut self.privacy_errors[privacy_errors_len..] {
+ error.outermost_res = Some((res, ident));
+ }
+
let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
if let Some(next_module) = binding.module() {
module = Some(ModuleOrUniformRoot::Module(next_module));
@@ -1543,17 +1529,23 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
record_segment_res(self, res);
return PathResult::NonModule(PartialRes::with_unresolved_segments(
res,
- path.len() - i - 1,
+ path.len() - segment_idx - 1,
));
} else {
- return PathResult::failed(ident.span, is_last, finalize.is_some(), || {
- let label = format!(
- "`{ident}` is {} {}, not a module",
- res.article(),
- res.descr()
- );
- (label, None)
- });
+ return PathResult::failed(
+ ident.span,
+ is_last,
+ finalize.is_some(),
+ module,
+ || {
+ let label = format!(
+ "`{ident}` is {} {}, not a module",
+ res.article(),
+ res.descr()
+ );
+ (label, None)
+ },
+ );
}
}
Err(Undetermined) => return PathResult::Indeterminate,
@@ -1562,23 +1554,29 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if opt_ns.is_some() && !module.is_normal() {
return PathResult::NonModule(PartialRes::with_unresolved_segments(
module.res().unwrap(),
- path.len() - i,
+ path.len() - segment_idx,
));
}
}
- return PathResult::failed(ident.span, is_last, finalize.is_some(), || {
- self.report_path_resolution_error(
- path,
- opt_ns,
- parent_scope,
- ribs,
- ignore_binding,
- module,
- i,
- ident,
- )
- });
+ return PathResult::failed(
+ ident.span,
+ is_last,
+ finalize.is_some(),
+ module,
+ || {
+ self.report_path_resolution_error(
+ path,
+ opt_ns,
+ parent_scope,
+ ribs,
+ ignore_binding,
+ module,
+ segment_idx,
+ ident,
+ )
+ },
+ );
}
}
}