Rollup merge of #128732 - bvanjoi:immutable-import-vis, r=petrochenkov

make `import.vis` is immutable

r? `@petrochenkov`
This commit is contained in:
Matthias Krüger 2024-08-07 20:28:18 +02:00 committed by GitHub
commit 8f5b50d4ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 129 additions and 63 deletions

View File

@ -283,6 +283,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
parent_scope, parent_scope,
finalize.then(|| Finalize::new(id, path.span)), finalize.then(|| Finalize::new(id, path.span)),
None, None,
None,
) { ) {
PathResult::Module(ModuleOrUniformRoot::Module(module)) => { PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
let res = module.res().expect("visibility resolved to unnamed block"); let res = module.res().expect("visibility resolved to unnamed block");
@ -372,7 +373,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
has_attributes: !item.attrs.is_empty(), has_attributes: !item.attrs.is_empty(),
root_span, root_span,
root_id, root_id,
vis: Cell::new(Some(vis)), vis,
used: Default::default(), used: Default::default(),
}); });
@ -888,7 +889,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
root_span: item.span, root_span: item.span,
span: item.span, span: item.span,
module_path: Vec::new(), module_path: Vec::new(),
vis: Cell::new(Some(vis)), vis,
used: Cell::new(used.then_some(Used::Other)), used: Cell::new(used.then_some(Used::Other)),
}); });
self.r.potentially_unused_imports.push(import); self.r.potentially_unused_imports.push(import);
@ -1089,7 +1090,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
root_span: span, root_span: span,
span, span,
module_path: Vec::new(), module_path: Vec::new(),
vis: Cell::new(Some(ty::Visibility::Restricted(CRATE_DEF_ID))), vis: ty::Visibility::Restricted(CRATE_DEF_ID),
used: Default::default(), used: Default::default(),
}) })
}; };
@ -1125,6 +1126,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
ident, ident,
MacroNS, MacroNS,
&self.parent_scope, &self.parent_scope,
None,
); );
if let Ok(binding) = result { if let Ok(binding) = result {
let import = macro_use_import(self, ident.span, false); let import = macro_use_import(self, ident.span, false);
@ -1253,7 +1255,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
root_span: span, root_span: span,
span, span,
module_path: Vec::new(), module_path: Vec::new(),
vis: Cell::new(Some(vis)), vis,
used: Cell::new(Some(Used::Other)), used: Cell::new(Some(Used::Other)),
}); });
let import_binding = self.r.import(binding, import); let import_binding = self.r.import(binding, import);

View File

@ -382,7 +382,7 @@ impl Resolver<'_, '_> {
for import in self.potentially_unused_imports.iter() { for import in self.potentially_unused_imports.iter() {
match import.kind { match import.kind {
_ if import.used.get().is_some() _ if import.used.get().is_some()
|| import.expect_vis().is_public() || import.vis.is_public()
|| import.span.is_dummy() => || import.span.is_dummy() =>
{ {
if let ImportKind::MacroUse { .. } = import.kind { if let ImportKind::MacroUse { .. } = import.kind {

View File

@ -1052,6 +1052,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
false, false,
false, false,
None,
) { ) {
suggestions.extend( suggestions.extend(
ext.helper_attrs ext.helper_attrs
@ -1506,6 +1507,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
false, false,
None, None,
None,
) { ) {
let desc = match binding.res() { let desc = match binding.res() {
Res::Def(DefKind::Macro(MacroKind::Bang), _) => { Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
@ -1983,6 +1985,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>, ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
module: Option<ModuleOrUniformRoot<'a>>, module: Option<ModuleOrUniformRoot<'a>>,
failed_segment_idx: usize, failed_segment_idx: usize,
ident: Ident, ident: Ident,
@ -2066,11 +2069,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
None, None,
ignore_binding, ignore_binding,
ignore_import,
) )
.ok() .ok()
} else if let Some(ribs) = ribs } else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns && let Some(TypeNS | ValueNS) = opt_ns
{ {
assert!(ignore_import.is_none());
match self.resolve_ident_in_lexical_scope( match self.resolve_ident_in_lexical_scope(
ident, ident,
ns_to_try, ns_to_try,
@ -2091,6 +2096,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
false, false,
ignore_binding, ignore_binding,
ignore_import,
) )
.ok() .ok()
}; };
@ -2132,6 +2138,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) { } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
// Check whether the name refers to an item in the value namespace. // Check whether the name refers to an item in the value namespace.
let binding = if let Some(ribs) = ribs { let binding = if let Some(ribs) = ribs {
assert!(ignore_import.is_none());
self.resolve_ident_in_lexical_scope( self.resolve_ident_in_lexical_scope(
ident, ident,
ValueNS, ValueNS,
@ -2206,6 +2213,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
false, false,
ignore_binding, ignore_binding,
ignore_import,
) { ) {
let descr = binding.res().descr(); let descr = binding.res().descr();
(format!("{descr} `{ident}` is not a crate or module"), suggestion) (format!("{descr} `{ident}` is not a crate or module"), suggestion)
@ -2259,7 +2267,7 @@ impl<'a, 'tcx> Resolver<'a, '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); let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result); debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None } if let PathResult::Module(..) = result { Some((path, None)) } else { None }
} }
@ -2278,7 +2286,7 @@ impl<'a, 'tcx> Resolver<'a, '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); let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result); debug!("make_missing_crate_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { if let PathResult::Module(..) = result {
Some(( Some((
@ -2309,7 +2317,7 @@ impl<'a, 'tcx> Resolver<'a, '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); let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result); debug!("make_missing_super_suggestion: path={:?} result={:?}", path, result);
if let PathResult::Module(..) = result { Some((path, None)) } else { None } if let PathResult::Module(..) = result { Some((path, None)) } else { None }
} }
@ -2343,7 +2351,7 @@ impl<'a, 'tcx> Resolver<'a, '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); let result = self.maybe_resolve_path(&path, None, parent_scope, None);
debug!( debug!(
"make_external_crate_suggestion: name={:?} path={:?} result={:?}", "make_external_crate_suggestion: name={:?} path={:?} result={:?}",
name, path, result name, path, result
@ -2509,12 +2517,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
/// Finds a cfg-ed out item inside `module` with the matching name. /// Finds a cfg-ed out item inside `module` with the matching name.
pub(crate) fn find_cfg_stripped( pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
&mut self,
err: &mut Diag<'_>,
segment: &Symbol,
module: DefId,
) {
let local_items; let local_items;
let symbols = if module.is_local() { let symbols = if module.is_local() {
local_items = self local_items = self

View File

@ -14,6 +14,7 @@ use Determinacy::*;
use Namespace::*; use Namespace::*;
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst}; use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::imports::Import;
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind}; use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
use crate::macros::{sub_namespace_match, MacroRulesScope}; use crate::macros::{sub_namespace_match, MacroRulesScope};
use crate::{ use crate::{
@ -351,6 +352,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding, ignore_binding,
None,
); );
if let Ok(binding) = item { if let Ok(binding) = item {
// The ident resolves to an item. // The ident resolves to an item.
@ -364,6 +366,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize, finalize,
finalize.is_some(), finalize.is_some(),
ignore_binding, ignore_binding,
None,
) )
.ok() .ok()
.map(LexicalScopeBinding::Item) .map(LexicalScopeBinding::Item)
@ -383,6 +386,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize: Option<Finalize>, finalize: Option<Finalize>,
force: bool, force: bool,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> { ) -> Result<NameBinding<'a>, Determinacy> {
bitflags::bitflags! { bitflags::bitflags! {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
@ -455,6 +459,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
true, true,
force, force,
ignore_import,
) { ) {
Ok((Some(ext), _)) => { Ok((Some(ext), _)) => {
if ext.helper_attrs.contains(&ident.name) { if ext.helper_attrs.contains(&ident.name) {
@ -496,6 +501,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
finalize, finalize,
ignore_binding, ignore_binding,
ignore_import,
); );
match binding { match binding {
Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)), Ok(binding) => Ok((binding, Flags::MODULE | Flags::MISC_SUGGEST_CRATE)),
@ -518,6 +524,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
!matches!(scope_set, ScopeSet::Late(..)), !matches!(scope_set, ScopeSet::Late(..)),
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding, ignore_binding,
ignore_import,
); );
match binding { match binding {
Ok(binding) => { Ok(binding) => {
@ -585,6 +592,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
None, None,
ignore_binding, ignore_binding,
ignore_import,
) { ) {
if matches!(use_prelude, UsePrelude::Yes) if matches!(use_prelude, UsePrelude::Yes)
|| this.is_builtin_macro(binding.res()) || this.is_builtin_macro(binding.res())
@ -738,8 +746,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident: Ident, ident: Ident,
ns: Namespace, ns: Namespace,
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> { ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None) self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import)
.map_err(|(determinacy, _)| determinacy) .map_err(|(determinacy, _)| determinacy)
} }
@ -752,9 +761,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>, finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> { ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, finalize, ignore_binding) self.resolve_ident_in_module_ext(
.map_err(|(determinacy, _)| determinacy) module,
ident,
ns,
parent_scope,
finalize,
ignore_binding,
ignore_import,
)
.map_err(|(determinacy, _)| determinacy)
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
@ -766,6 +784,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>, finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, (Determinacy, Weak)> { ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let tmp_parent_scope; let tmp_parent_scope;
let mut adjusted_parent_scope = parent_scope; let mut adjusted_parent_scope = parent_scope;
@ -792,6 +811,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
false, false,
finalize, finalize,
ignore_binding, ignore_binding,
ignore_import,
) )
} }
@ -804,6 +824,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>, finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, Determinacy> { ) -> Result<NameBinding<'a>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext( self.resolve_ident_in_module_unadjusted_ext(
module, module,
@ -813,6 +834,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
false, false,
finalize, finalize,
ignore_binding, ignore_binding,
ignore_import,
) )
.map_err(|(determinacy, _)| determinacy) .map_err(|(determinacy, _)| determinacy)
} }
@ -831,6 +853,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// This binding should be ignored during in-module resolution, so that we don't get // This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking. // "self-confirming" import resolutions during import validation and checking.
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> Result<NameBinding<'a>, (Determinacy, Weak)> { ) -> Result<NameBinding<'a>, (Determinacy, Weak)> {
let module = match module { let module = match module {
ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::Module(module) => module,
@ -843,6 +866,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize, finalize,
finalize.is_some(), finalize.is_some(),
ignore_binding, ignore_binding,
ignore_import,
); );
return binding.map_err(|determinacy| (determinacy, Weak::No)); return binding.map_err(|determinacy| (determinacy, Weak::No));
} }
@ -879,6 +903,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize, finalize,
finalize.is_some(), finalize.is_some(),
ignore_binding, ignore_binding,
ignore_import,
); );
return binding.map_err(|determinacy| (determinacy, Weak::No)); return binding.map_err(|determinacy| (determinacy, Weak::No));
} }
@ -962,25 +987,23 @@ impl<'a, 'tcx> Resolver<'a, '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.
for single_import in &resolution.single_imports { for single_import in &resolution.single_imports {
let Some(import_vis) = single_import.vis.get() else { if ignore_import == Some(*single_import) {
// This branch handles a cycle in single imports, which occurs // This branch handles a cycle in single imports.
// when we've previously **steal** the `vis` value during an import
// process.
// //
// For example: // For example:
// ``` // ```
// use a::b; // use a::b;
// use b as a; // use b as a;
// ``` // ```
// 1. Steal the `vis` in `use a::b` and attempt to locate `a` in the // 1. Record `use a::b` as the `ignore_import` and attempt to locate `a` in the
// current module. // current module.
// 2. Encounter the import `use b as a`, which is a `single_import` for `a`, // 2. Encounter the import `use b as a`, which is a `single_import` for `a`,
// and try to find `b` in the current module. // and try to find `b` in the current module.
// 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`. // 3. Re-encounter the `use a::b` import since it's a `single_import` of `b`.
// This leads to entering this branch. // This leads to entering this branch.
continue; continue;
}; }
if !self.is_accessible_from(import_vis, parent_scope.module) { if !self.is_accessible_from(single_import.vis, parent_scope.module) {
continue; continue;
} }
if let Some(ignored) = ignore_binding if let Some(ignored) = ignore_binding
@ -1022,6 +1045,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&single_import.parent_scope, &single_import.parent_scope,
None, None,
ignore_binding, ignore_binding,
ignore_import,
) { ) {
Err(Determined) => continue, Err(Determined) => continue,
Ok(binding) Ok(binding)
@ -1070,10 +1094,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Check if one of glob imports can still define the name, // Check if one of glob imports can still define the name,
// if it can then our "no resolution" result is not determined and can be invalidated. // if it can then our "no resolution" result is not determined and can be invalidated.
for glob_import in module.globs.borrow().iter() { for glob_import in module.globs.borrow().iter() {
let Some(import_vis) = glob_import.vis.get() else { if ignore_import == Some(*glob_import) {
continue; continue;
}; }
if !self.is_accessible_from(import_vis, parent_scope.module) { if !self.is_accessible_from(glob_import.vis, parent_scope.module) {
continue; continue;
} }
let module = match glob_import.imported_module.get() { let module = match glob_import.imported_module.get() {
@ -1100,6 +1124,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
adjusted_parent_scope, adjusted_parent_scope,
None, None,
ignore_binding, ignore_binding,
ignore_import,
); );
match result { match result {
@ -1412,8 +1437,9 @@ impl<'a, 'tcx> Resolver<'a, '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<'a>, parent_scope: &ParentScope<'a>,
ignore_import: Option<Import<'a>>,
) -> PathResult<'a> { ) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, None, None, None) 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))]
@ -1424,8 +1450,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
finalize: Option<Finalize>, finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> PathResult<'a> { ) -> PathResult<'a> {
self.resolve_path_with_ribs(path, opt_ns, parent_scope, finalize, None, ignore_binding) self.resolve_path_with_ribs(
path,
opt_ns,
parent_scope,
finalize,
None,
ignore_binding,
ignore_import,
)
} }
pub(crate) fn resolve_path_with_ribs( pub(crate) fn resolve_path_with_ribs(
@ -1436,6 +1471,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize: Option<Finalize>, finalize: Option<Finalize>,
ribs: Option<&PerNS<Vec<Rib<'a>>>>, ribs: Option<&PerNS<Vec<Rib<'a>>>>,
ignore_binding: Option<NameBinding<'a>>, ignore_binding: Option<NameBinding<'a>>,
ignore_import: Option<Import<'a>>,
) -> PathResult<'a> { ) -> PathResult<'a> {
let mut module = None; let mut module = None;
let mut allow_super = true; let mut allow_super = true;
@ -1538,10 +1574,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
finalize, finalize,
ignore_binding, ignore_binding,
ignore_import,
) )
} else if let Some(ribs) = ribs } else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns && let Some(TypeNS | ValueNS) = opt_ns
{ {
assert!(ignore_import.is_none());
match self.resolve_ident_in_lexical_scope( match self.resolve_ident_in_lexical_scope(
ident, ident,
ns, ns,
@ -1570,6 +1608,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
finalize, finalize,
finalize.is_some(), finalize.is_some(),
ignore_binding, ignore_binding,
ignore_import,
) )
}; };
@ -1644,6 +1683,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope, parent_scope,
ribs, ribs,
ignore_binding, ignore_binding,
ignore_import,
module, module,
segment_idx, segment_idx,
ident, ident,

View File

@ -175,7 +175,7 @@ pub(crate) struct ImportData<'a> {
pub module_path: Vec<Segment>, pub module_path: Vec<Segment>,
/// The resolution of `module_path`. /// The resolution of `module_path`.
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>, pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
pub vis: Cell<Option<ty::Visibility>>, pub vis: ty::Visibility,
pub used: Cell<Option<Used>>, pub used: Cell<Option<Used>>,
} }
@ -195,10 +195,6 @@ impl<'a> ImportData<'a> {
} }
} }
pub(crate) fn expect_vis(&self) -> ty::Visibility {
self.vis.get().expect("encountered cleared import visibility")
}
pub(crate) fn id(&self) -> Option<NodeId> { pub(crate) fn id(&self) -> Option<NodeId> {
match self.kind { match self.kind {
ImportKind::Single { id, .. } ImportKind::Single { id, .. }
@ -267,7 +263,7 @@ fn pub_use_of_private_extern_crate_hack(
match (&import.kind, &binding.kind) { match (&import.kind, &binding.kind) {
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) (ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
if let ImportKind::ExternCrate { id, .. } = binding_import.kind if let ImportKind::ExternCrate { id, .. } = binding_import.kind
&& import.expect_vis().is_public() => && import.vis.is_public() =>
{ {
Some(id) Some(id)
} }
@ -279,7 +275,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Given a binding and an import that resolves to it, /// Given a binding and an import that resolves to it,
/// return the corresponding binding defined by the import. /// return the corresponding binding defined by the import.
pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> { pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
let import_vis = import.expect_vis().to_def_id(); let import_vis = import.vis.to_def_id();
let vis = if binding.vis.is_at_least(import_vis, self.tcx) let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|| pub_use_of_private_extern_crate_hack(import, binding).is_some() || pub_use_of_private_extern_crate_hack(import, binding).is_some()
{ {
@ -773,11 +769,12 @@ impl<'a, 'tcx> Resolver<'a, '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 {
// For better failure detection, pretend that the import will let path_res = self.maybe_resolve_path(
// not define any names while resolving its module path. &import.module_path,
let orig_vis = import.vis.take(); None,
let path_res = self.maybe_resolve_path(&import.module_path, None, &import.parent_scope); &import.parent_scope,
import.vis.set(orig_vis); Some(import),
);
match path_res { match path_res {
PathResult::Module(module) => module, PathResult::Module(module) => module,
@ -807,16 +804,13 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS { if !type_ns_only || ns == TypeNS {
if let Err(Undetermined) = source_bindings[ns].get() { if let Err(Undetermined) = source_bindings[ns].get() {
// For better failure detection, pretend that the import will
// not define any names while resolving its module path.
let orig_vis = import.vis.take();
let binding = this.maybe_resolve_ident_in_module( let binding = this.maybe_resolve_ident_in_module(
module, module,
source, source,
ns, ns,
&import.parent_scope, &import.parent_scope,
Some(import),
); );
import.vis.set(orig_vis);
source_bindings[ns].set(binding); source_bindings[ns].set(binding);
} else { } else {
return; return;
@ -855,7 +849,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
/// Optionally returns an unresolved import error. This error is buffered and used to /// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic. /// consolidate multiple unresolved import errors into a single diagnostic.
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> { fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
let orig_vis = import.vis.take();
let ignore_binding = match &import.kind { let ignore_binding = match &import.kind {
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(), ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
_ => None, _ => None,
@ -874,11 +867,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&import.parent_scope, &import.parent_scope,
Some(finalize), Some(finalize),
ignore_binding, ignore_binding,
Some(import),
); );
let no_ambiguity = let no_ambiguity =
ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len; ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
import.vis.set(orig_vis);
let module = match path_res { let module = match path_res {
PathResult::Module(module) => { PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_macro_resolutions`. // Consistency checks, analogous to `finalize_macro_resolutions`.
@ -1013,8 +1007,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
if !is_prelude if !is_prelude
&& let Some(max_vis) = max_vis.get() && let Some(max_vis) = max_vis.get()
&& let import_vis = import.expect_vis() && !max_vis.is_at_least(import.vis, self.tcx)
&& !max_vis.is_at_least(import_vis, self.tcx)
{ {
let def_id = self.local_def_id(id); let def_id = self.local_def_id(id);
self.lint_buffer.buffer_lint( self.lint_buffer.buffer_lint(
@ -1023,7 +1016,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
import.span, import.span,
BuiltinLintDiag::RedundantImportVisibility { BuiltinLintDiag::RedundantImportVisibility {
max_vis: max_vis.to_string(def_id, self.tcx), max_vis: max_vis.to_string(def_id, self.tcx),
import_vis: import_vis.to_string(def_id, self.tcx), import_vis: import.vis.to_string(def_id, self.tcx),
span: import.span, span: import.span,
}, },
); );
@ -1038,9 +1031,14 @@ impl<'a, 'tcx> Resolver<'a, '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)) = if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(
self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding) &path,
{ None,
&import.parent_scope,
Some(finalize),
ignore_binding,
None,
) {
let res = module.res().map(|r| (r, ident)); let res = module.res().map(|r| (r, ident));
for error in &mut self.privacy_errors[privacy_errors_len..] { for error in &mut self.privacy_errors[privacy_errors_len..] {
error.outermost_res = res; error.outermost_res = res;
@ -1051,7 +1049,6 @@ impl<'a, 'tcx> Resolver<'a, '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 orig_vis = import.vis.take();
let binding = this.resolve_ident_in_module( let binding = this.resolve_ident_in_module(
module, module,
ident, ident,
@ -1059,8 +1056,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&import.parent_scope, &import.parent_scope,
Some(Finalize { report_private: false, ..finalize }), Some(Finalize { report_private: false, ..finalize }),
target_bindings[ns].get(), target_bindings[ns].get(),
Some(import),
); );
import.vis.set(orig_vis);
match binding { match binding {
Ok(binding) => { Ok(binding) => {
@ -1123,6 +1120,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&import.parent_scope, &import.parent_scope,
Some(finalize), Some(finalize),
None, None,
None,
); );
if binding.is_ok() { if binding.is_ok() {
all_ns_failed = false; all_ns_failed = false;
@ -1233,7 +1231,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut crate_private_reexport = false; let mut crate_private_reexport = false;
self.per_ns(|this, ns| { self.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() { if let Ok(binding) = source_bindings[ns].get() {
if !binding.vis.is_at_least(import.expect_vis(), this.tcx) { if !binding.vis.is_at_least(import.vis, this.tcx) {
reexport_error = Some((ns, binding)); reexport_error = Some((ns, binding));
if let ty::Visibility::Restricted(binding_def_id) = binding.vis { if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
if binding_def_id.is_top_level_module() { if binding_def_id.is_top_level_module() {
@ -1370,6 +1368,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
false, false,
target_bindings[ns].get(), target_bindings[ns].get(),
None,
) { ) {
Ok(other_binding) => { Ok(other_binding) => {
is_redundant = binding.res() == other_binding.res() is_redundant = binding.res() == other_binding.res()

View File

@ -1388,6 +1388,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
finalize, finalize,
Some(&self.ribs), Some(&self.ribs),
None, None,
None,
) )
} }
@ -4186,7 +4187,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
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.resolve_macro_path(&path, None, &self.parent_scope, false, false) self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
{ {
return Ok(Some(PartialRes::new(res))); return Ok(Some(PartialRes::new(res)));
} }

View File

@ -2058,6 +2058,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
ident, ident,
ns, ns,
&self.parent_scope, &self.parent_scope,
None,
) { ) {
let res = binding.res(); let res = binding.res();
if filter_fn(res) { if filter_fn(res) {

View File

@ -2120,7 +2120,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
} }
} }
match self.maybe_resolve_path(&segments, Some(ns), &parent_scope) { match self.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) => path_res.full_res(), PathResult::NonModule(path_res) => path_res.full_res(),
PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => { PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
@ -2204,6 +2204,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ident, ident,
ValueNS, ValueNS,
parent_scope, parent_scope,
None,
) else { ) else {
return; return;
}; };

View File

@ -39,6 +39,7 @@ use crate::errors::{
self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope, self, AddAsNonDerive, CannotDetermineMacroResolution, CannotFindIdentInThisScope,
MacroExpectedFound, RemoveSurroundingDerive, MacroExpectedFound, RemoveSurroundingDerive,
}; };
use crate::imports::Import;
use crate::Namespace::*; use crate::Namespace::*;
use crate::{ use crate::{
BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind, BindingKey, BuiltinMacroState, DeriveData, Determinacy, Finalize, MacroData, ModuleKind,
@ -399,6 +400,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> {
&parent_scope, &parent_scope,
true, true,
force, force,
None,
) { ) {
Ok((Some(ext), _)) => { Ok((Some(ext), _)) => {
if !ext.helper_attrs.is_empty() { if !ext.helper_attrs.is_empty() {
@ -551,6 +553,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
force, force,
deleg_impl, deleg_impl,
invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)), invoc_in_mod_inert_attr.map(|def_id| (def_id, node_id)),
None,
) { ) {
Ok((Some(ext), res)) => (ext, res), Ok((Some(ext), res)) => (ext, res),
Ok((None, res)) => (self.dummy_ext(kind), res), Ok((None, res)) => (self.dummy_ext(kind), res),
@ -704,8 +707,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
parent_scope: &ParentScope<'a>, parent_scope: &ParentScope<'a>,
trace: bool, trace: bool,
force: bool, force: bool,
ignore_import: Option<Import<'a>>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> { ) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
self.resolve_macro_or_delegation_path(path, kind, parent_scope, trace, force, None, None) self.resolve_macro_or_delegation_path(
path,
kind,
parent_scope,
trace,
force,
None,
None,
ignore_import,
)
} }
fn resolve_macro_or_delegation_path( fn resolve_macro_or_delegation_path(
@ -717,6 +730,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
force: bool, force: bool,
deleg_impl: Option<LocalDefId>, deleg_impl: Option<LocalDefId>,
invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>, invoc_in_mod_inert_attr: Option<(LocalDefId, NodeId)>,
ignore_import: Option<Import<'a>>,
) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> { ) -> Result<(Option<Lrc<SyntaxExtension>>, Res), Determinacy> {
let path_span = ast_path.span; let path_span = ast_path.span;
let mut path = Segment::from_path(ast_path); let mut path = Segment::from_path(ast_path);
@ -733,7 +747,7 @@ impl<'a, 'tcx> Resolver<'a, '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) { let res = match self.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(..)
@ -768,6 +782,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
force, force,
None, None,
None,
); );
if let Err(Determinacy::Undetermined) = binding { if let Err(Determinacy::Undetermined) = binding {
return Err(Determinacy::Undetermined); return Err(Determinacy::Undetermined);
@ -852,6 +867,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
&parent_scope, &parent_scope,
Some(Finalize::new(ast::CRATE_NODE_ID, path_span)), Some(Finalize::new(ast::CRATE_NODE_ID, path_span)),
None, None,
None,
) { ) {
PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => { PathResult::NonModule(path_res) if let Some(res) = path_res.full_res() => {
check_consistency(self, &path, path_span, kind, initial_res, res) check_consistency(self, &path, path_span, kind, initial_res, res)
@ -871,7 +887,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
if let PathResult::Failed { span, label, module, .. } = path_res { if let PathResult::Failed { span, label, module, .. } = 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.maybe_resolve_path(&path, Some(ValueNS), &parent_scope) self.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();
@ -921,6 +937,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
true, true,
None, None,
None,
) { ) {
Ok(binding) => { Ok(binding) => {
let initial_res = initial_binding.map(|initial_binding| { let initial_res = initial_binding.map(|initial_binding| {
@ -966,6 +983,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)), Some(Finalize::new(ast::CRATE_NODE_ID, ident.span)),
true, true,
None, None,
None,
); );
} }
} }
@ -1070,6 +1088,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None, None,
false, false,
None, None,
None,
); );
if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) { if fallback_binding.ok().and_then(|b| b.res().opt_def_id()) != Some(def_id) {
self.tcx.sess.psess.buffer_lint( self.tcx.sess.psess.buffer_lint(
@ -1143,7 +1162,7 @@ impl<'a, 'tcx> Resolver<'a, '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) { match self.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);