mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
resolve: Not all imports have their own NodeId
This commit is contained in:
parent
2afca78a0b
commit
637bfe68a1
@ -364,7 +364,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
module_path: Vec<Segment>,
|
||||
kind: ImportKind<'a>,
|
||||
span: Span,
|
||||
id: NodeId,
|
||||
item: &ast::Item,
|
||||
root_span: Span,
|
||||
root_id: NodeId,
|
||||
@ -377,7 +376,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
module_path,
|
||||
imported_module: Cell::new(None),
|
||||
span,
|
||||
id,
|
||||
use_span: item.span,
|
||||
use_span_with_attributes: item.span_with_attributes(),
|
||||
has_attributes: !item.attrs.is_empty(),
|
||||
@ -574,27 +572,20 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
},
|
||||
type_ns_only,
|
||||
nested,
|
||||
id,
|
||||
additional_ids: (id1, id2),
|
||||
};
|
||||
|
||||
self.add_import(
|
||||
module_path,
|
||||
kind,
|
||||
use_tree.span,
|
||||
id,
|
||||
item,
|
||||
root_span,
|
||||
item.id,
|
||||
vis,
|
||||
);
|
||||
self.add_import(module_path, kind, use_tree.span, item, root_span, item.id, vis);
|
||||
}
|
||||
ast::UseTreeKind::Glob => {
|
||||
let kind = ImportKind::Glob {
|
||||
is_prelude: self.r.session.contains_name(&item.attrs, sym::prelude_import),
|
||||
max_vis: Cell::new(None),
|
||||
id,
|
||||
};
|
||||
self.r.visibilities.insert(self.r.local_def_id(id), vis);
|
||||
self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
|
||||
self.add_import(prefix, kind, use_tree.span, item, root_span, item.id, vis);
|
||||
}
|
||||
ast::UseTreeKind::Nested(ref items) => {
|
||||
// Ensure there is at most one `self` in the list
|
||||
@ -881,9 +872,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
})
|
||||
.unwrap_or((true, None, self.r.dummy_binding));
|
||||
let import = self.r.arenas.alloc_import(Import {
|
||||
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
|
||||
kind: ImportKind::ExternCrate { source: orig_name, target: ident, id: item.id },
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent_scope: self.parent_scope,
|
||||
imported_module: Cell::new(module),
|
||||
has_attributes: !item.attrs.is_empty(),
|
||||
@ -1118,7 +1108,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
|
||||
this.r.arenas.alloc_import(Import {
|
||||
kind: ImportKind::MacroUse,
|
||||
root_id: item.id,
|
||||
id: item.id,
|
||||
parent_scope: this.parent_scope,
|
||||
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
|
||||
use_span_with_attributes: item.span_with_attributes(),
|
||||
|
@ -234,7 +234,7 @@ impl Resolver<'_> {
|
||||
if !import.span.is_dummy() {
|
||||
self.lint_buffer.buffer_lint(
|
||||
MACRO_USE_EXTERN_CRATE,
|
||||
import.id,
|
||||
import.root_id,
|
||||
import.span,
|
||||
"deprecated `#[macro_use]` attribute used to \
|
||||
import macros should be replaced at use sites \
|
||||
@ -244,13 +244,13 @@ impl Resolver<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ImportKind::ExternCrate { .. } => {
|
||||
let def_id = self.local_def_id(import.id);
|
||||
ImportKind::ExternCrate { id, .. } => {
|
||||
let def_id = self.local_def_id(id);
|
||||
self.maybe_unused_extern_crates.push((def_id, import.span));
|
||||
}
|
||||
ImportKind::MacroUse => {
|
||||
let msg = "unused `#[macro_use]` import";
|
||||
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
|
||||
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -353,7 +353,7 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
ImportKind::ExternCrate { source, target } => {
|
||||
ImportKind::ExternCrate { source, target, .. } => {
|
||||
suggestion = Some(format!(
|
||||
"extern crate {} as {};",
|
||||
source.unwrap_or(target.name),
|
||||
|
@ -57,26 +57,40 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
|
||||
while let NameBindingKind::Import { binding: nested_binding, import, .. } =
|
||||
binding.kind
|
||||
{
|
||||
let mut update = |node_id| self.update(
|
||||
self.r.local_def_id(node_id),
|
||||
binding.vis.expect_local(),
|
||||
prev_parent_id,
|
||||
level,
|
||||
);
|
||||
// In theory all the import IDs have individual visibilities and effective
|
||||
// visibilities, but in practice these IDs go straigth to HIR where all
|
||||
// their few uses assume that their (effective) visibility applies to the
|
||||
// whole syntactic `use` item. So we update them all to the maximum value
|
||||
// among the potential individual effective visibilities. Maybe HIR for
|
||||
// imports shouldn't use three IDs at all.
|
||||
update(import.id);
|
||||
if let ImportKind::Single { additional_ids, .. } = import.kind {
|
||||
update(additional_ids.0);
|
||||
update(additional_ids.1);
|
||||
let mut update = |node_id| {
|
||||
self.update(
|
||||
self.r.local_def_id(node_id),
|
||||
binding.vis.expect_local(),
|
||||
prev_parent_id,
|
||||
level,
|
||||
)
|
||||
};
|
||||
match import.kind {
|
||||
ImportKind::Single { id, additional_ids, .. } => {
|
||||
// In theory all the import IDs have individual visibilities and
|
||||
// effective visibilities, but in practice these IDs go straigth to
|
||||
// HIR where all their few uses assume that their (effective)
|
||||
// visibility applies to the whole syntactic `use` item. So we
|
||||
// update them all to the maximum value among the potential
|
||||
// individual effective visibilities. Maybe HIR for imports
|
||||
// shouldn't use three IDs at all.
|
||||
update(id);
|
||||
update(additional_ids.0);
|
||||
update(additional_ids.1);
|
||||
prev_parent_id = self.r.local_def_id(id);
|
||||
}
|
||||
ImportKind::Glob { id, .. } | ImportKind::ExternCrate { id, .. } => {
|
||||
update(id);
|
||||
prev_parent_id = self.r.local_def_id(id);
|
||||
}
|
||||
ImportKind::MacroUse => {
|
||||
// In theory we should reset the parent id to something private
|
||||
// here, but `macro_use` imports always refer to external items,
|
||||
// so it doesn't matter and we can just do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
level = Level::Reexported;
|
||||
prev_parent_id = self.r.local_def_id(import.id);
|
||||
binding = nested_binding;
|
||||
}
|
||||
}
|
||||
|
@ -44,18 +44,33 @@ pub enum ImportKind<'a> {
|
||||
type_ns_only: bool,
|
||||
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
|
||||
nested: bool,
|
||||
/// The ID of the `UseTree` that imported this `Import`.
|
||||
///
|
||||
/// In the case where the `Import` was expanded from a "nested" use tree,
|
||||
/// this id is the ID of the leaf tree. For example:
|
||||
///
|
||||
/// ```ignore (pacify the merciless tidy)
|
||||
/// use foo::bar::{a, b}
|
||||
/// ```
|
||||
///
|
||||
/// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
|
||||
/// for `a` in this field.
|
||||
id: NodeId,
|
||||
/// Additional `NodeId`s allocated to a `ast::UseTree` for automatically generated `use` statement
|
||||
/// (eg. implicit struct constructors)
|
||||
additional_ids: (NodeId, NodeId),
|
||||
},
|
||||
Glob {
|
||||
is_prelude: bool,
|
||||
max_vis: Cell<Option<ty::Visibility>>, // The visibility of the greatest re-export.
|
||||
// n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
|
||||
// The visibility of the greatest re-export.
|
||||
// n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
|
||||
max_vis: Cell<Option<ty::Visibility>>,
|
||||
id: NodeId,
|
||||
},
|
||||
ExternCrate {
|
||||
source: Option<Symbol>,
|
||||
target: Ident,
|
||||
id: NodeId,
|
||||
},
|
||||
MacroUse,
|
||||
}
|
||||
@ -71,6 +86,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
|
||||
ref target,
|
||||
ref type_ns_only,
|
||||
ref nested,
|
||||
ref id,
|
||||
ref additional_ids,
|
||||
// Ignore the following to avoid an infinite loop while printing.
|
||||
source_bindings: _,
|
||||
@ -81,17 +97,20 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
|
||||
.field("target", target)
|
||||
.field("type_ns_only", type_ns_only)
|
||||
.field("nested", nested)
|
||||
.field("id", id)
|
||||
.field("additional_ids", additional_ids)
|
||||
.finish_non_exhaustive(),
|
||||
Glob { ref is_prelude, ref max_vis } => f
|
||||
Glob { ref is_prelude, ref max_vis, ref id } => f
|
||||
.debug_struct("Glob")
|
||||
.field("is_prelude", is_prelude)
|
||||
.field("max_vis", max_vis)
|
||||
.field("id", id)
|
||||
.finish(),
|
||||
ExternCrate { ref source, ref target } => f
|
||||
ExternCrate { ref source, ref target, ref id } => f
|
||||
.debug_struct("ExternCrate")
|
||||
.field("source", source)
|
||||
.field("target", target)
|
||||
.field("id", id)
|
||||
.finish(),
|
||||
MacroUse => f.debug_struct("MacroUse").finish(),
|
||||
}
|
||||
@ -103,24 +122,15 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
|
||||
pub(crate) struct Import<'a> {
|
||||
pub kind: ImportKind<'a>,
|
||||
|
||||
/// The ID of the `extern crate`, `UseTree` etc that imported this `Import`.
|
||||
///
|
||||
/// In the case where the `Import` was expanded from a "nested" use tree,
|
||||
/// this id is the ID of the leaf tree. For example:
|
||||
///
|
||||
/// ```ignore (pacify the merciless tidy)
|
||||
/// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`
|
||||
/// (if it exists) except in the case of "nested" use trees, in which case
|
||||
/// it will be the ID of the root use tree. e.g., in the example
|
||||
/// ```ignore (incomplete code)
|
||||
/// use foo::bar::{a, b}
|
||||
/// ```
|
||||
///
|
||||
/// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
|
||||
/// for `a` in this field.
|
||||
pub id: NodeId,
|
||||
|
||||
/// The `id` of the "root" use-kind -- this is always the same as
|
||||
/// `id` except in the case of "nested" use trees, in which case
|
||||
/// it will be the `id` of the root use tree. e.g., in the example
|
||||
/// from `id`, this would be the ID of the `use foo::bar`
|
||||
/// `UseTree` node.
|
||||
/// this would be the ID of the `use foo::bar` `UseTree` node.
|
||||
/// In case of imports without their own node ID it's the closest node that can be used,
|
||||
/// for example, for reporting lints.
|
||||
pub root_id: NodeId,
|
||||
|
||||
/// Span of the entire use statement.
|
||||
@ -161,6 +171,15 @@ impl<'a> Import<'a> {
|
||||
pub(crate) fn expect_vis(&self) -> ty::Visibility {
|
||||
self.vis.get().expect("encountered cleared import visibility")
|
||||
}
|
||||
|
||||
pub(crate) fn id(&self) -> Option<NodeId> {
|
||||
match self.kind {
|
||||
ImportKind::Single { id, .. }
|
||||
| ImportKind::Glob { id, .. }
|
||||
| ImportKind::ExternCrate { id, .. } => Some(id),
|
||||
ImportKind::MacroUse => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Records information about the resolution of a name in a namespace of a module.
|
||||
@ -368,7 +387,9 @@ impl<'a> Resolver<'a> {
|
||||
self.record_use(target, dummy_binding, false);
|
||||
} else if import.imported_module.get().is_none() {
|
||||
import.used.set(true);
|
||||
self.used_imports.insert(import.id);
|
||||
if let Some(id) = import.id() {
|
||||
self.used_imports.insert(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -718,47 +739,51 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
PathResult::Indeterminate => unreachable!(),
|
||||
};
|
||||
|
||||
let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
|
||||
ImportKind::Single {
|
||||
source,
|
||||
target,
|
||||
ref source_bindings,
|
||||
ref target_bindings,
|
||||
type_ns_only,
|
||||
..
|
||||
} => (source, target, source_bindings, target_bindings, type_ns_only),
|
||||
ImportKind::Glob { is_prelude, ref max_vis } => {
|
||||
if import.module_path.len() <= 1 {
|
||||
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||
let mut full_path = import.module_path.clone();
|
||||
full_path.push(Segment::from_ident(Ident::empty()));
|
||||
self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
||||
}
|
||||
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
if ptr::eq(module, import.parent_scope.module) {
|
||||
// Importing a module into itself is not allowed.
|
||||
return Some(UnresolvedImportError {
|
||||
span: import.span,
|
||||
label: Some(String::from("cannot glob-import a module into itself")),
|
||||
note: None,
|
||||
suggestion: None,
|
||||
candidate: None,
|
||||
});
|
||||
let (ident, target, source_bindings, target_bindings, type_ns_only, import_id) =
|
||||
match import.kind {
|
||||
ImportKind::Single {
|
||||
source,
|
||||
target,
|
||||
ref source_bindings,
|
||||
ref target_bindings,
|
||||
type_ns_only,
|
||||
id,
|
||||
..
|
||||
} => (source, target, source_bindings, target_bindings, type_ns_only, id),
|
||||
ImportKind::Glob { is_prelude, ref max_vis, id } => {
|
||||
if import.module_path.len() <= 1 {
|
||||
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
||||
// 2 segments, so the `resolve_path` above won't trigger it.
|
||||
let mut full_path = import.module_path.clone();
|
||||
full_path.push(Segment::from_ident(Ident::empty()));
|
||||
self.r.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
||||
}
|
||||
}
|
||||
if !is_prelude
|
||||
|
||||
if let ModuleOrUniformRoot::Module(module) = module {
|
||||
if ptr::eq(module, import.parent_scope.module) {
|
||||
// Importing a module into itself is not allowed.
|
||||
return Some(UnresolvedImportError {
|
||||
span: import.span,
|
||||
label: Some(String::from(
|
||||
"cannot glob-import a module into itself",
|
||||
)),
|
||||
note: None,
|
||||
suggestion: None,
|
||||
candidate: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
if !is_prelude
|
||||
&& let Some(max_vis) = max_vis.get()
|
||||
&& !max_vis.is_at_least(import.expect_vis(), &*self.r)
|
||||
{
|
||||
let msg = "glob import doesn't reexport anything because no candidate is public enough";
|
||||
self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
|
||||
self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, id, import.span, msg);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
return None;
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let mut all_ns_err = true;
|
||||
self.r.per_ns(|this, ns| {
|
||||
@ -960,7 +985,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
);
|
||||
self.r.lint_buffer.buffer_lint(
|
||||
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
||||
import.id,
|
||||
import_id,
|
||||
import.span,
|
||||
&msg,
|
||||
);
|
||||
@ -1029,7 +1054,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
// purposes it's good enough to just favor one over the other.
|
||||
self.r.per_ns(|this, ns| {
|
||||
if let Ok(binding) = source_bindings[ns].get() {
|
||||
this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res());
|
||||
this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
|
||||
}
|
||||
});
|
||||
|
||||
@ -1047,6 +1072,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
|
||||
target: Ident,
|
||||
) {
|
||||
// This function is only called for single imports.
|
||||
let ImportKind::Single { id, .. } = import.kind else { unreachable!() };
|
||||
|
||||
// Skip if the import was produced by a macro.
|
||||
if import.parent_scope.expansion != LocalExpnId::ROOT {
|
||||
return;
|
||||
@ -1094,7 +1122,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
redundant_spans.dedup();
|
||||
self.r.lint_buffer.buffer_lint_with_diagnostic(
|
||||
UNUSED_IMPORTS,
|
||||
import.id,
|
||||
id,
|
||||
import.span,
|
||||
&format!("the item `{}` is imported redundantly", ident),
|
||||
BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
|
||||
@ -1103,6 +1131,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
}
|
||||
|
||||
fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
|
||||
// This function is only called for glob imports.
|
||||
let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
|
||||
|
||||
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
|
||||
self.r.session.span_err(import.span, "cannot glob-import all possible crates");
|
||||
return;
|
||||
@ -1113,7 +1144,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
return;
|
||||
} else if ptr::eq(module, import.parent_scope.module) {
|
||||
return;
|
||||
} else if let ImportKind::Glob { is_prelude: true, .. } = import.kind {
|
||||
} else if is_prelude {
|
||||
self.r.prelude = Some(module);
|
||||
return;
|
||||
}
|
||||
@ -1145,7 +1176,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
|
||||
}
|
||||
|
||||
// Record the destination of this import
|
||||
self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap()));
|
||||
self.r.record_partial_res(id, PartialRes::new(module.res().unwrap()));
|
||||
}
|
||||
|
||||
// Miscellaneous post-processing, including recording re-exports,
|
||||
|
@ -1613,10 +1613,12 @@ impl<'a> Resolver<'a> {
|
||||
) -> SmallVec<[LocalDefId; 1]> {
|
||||
let mut import_ids = smallvec![];
|
||||
while let NameBindingKind::Import { import, binding, .. } = kind {
|
||||
let id = self.local_def_id(import.id);
|
||||
self.maybe_unused_trait_imports.insert(id);
|
||||
if let Some(node_id) = import.id() {
|
||||
let def_id = self.local_def_id(node_id);
|
||||
self.maybe_unused_trait_imports.insert(def_id);
|
||||
import_ids.push(def_id);
|
||||
}
|
||||
self.add_to_glob_map(&import, trait_name);
|
||||
import_ids.push(id);
|
||||
kind = &binding.kind;
|
||||
}
|
||||
import_ids
|
||||
@ -1683,7 +1685,9 @@ impl<'a> Resolver<'a> {
|
||||
}
|
||||
used.set(true);
|
||||
import.used.set(true);
|
||||
self.used_imports.insert(import.id);
|
||||
if let Some(id) = import.id() {
|
||||
self.used_imports.insert(id);
|
||||
}
|
||||
self.add_to_glob_map(&import, ident);
|
||||
self.record_use(ident, binding, false);
|
||||
}
|
||||
@ -1691,8 +1695,8 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
#[inline]
|
||||
fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
|
||||
if import.is_glob() {
|
||||
let def_id = self.local_def_id(import.id);
|
||||
if let ImportKind::Glob { id, .. } = import.kind {
|
||||
let def_id = self.local_def_id(id);
|
||||
self.glob_map.entry(def_id).or_default().insert(ident.name);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user