Rollup merge of #69805 - petrochenkov:importname, r=Centril

resolve: Modernize some naming

`ImportDirective` -> `Import`
`ImportDirectiveSubclass` -> `ImportKind`
`ImportKind::SingleImport` -> `ImportKind::Single`
`ImportKind::GlobImport` -> `ImportKind::Glob`
This commit is contained in:
Mazdak Farrokhzad 2020-03-08 11:51:18 +01:00 committed by GitHub
commit 17b77913f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 283 additions and 325 deletions

View File

@ -6,8 +6,7 @@
//! Imports are also considered items and placed into modules here, but not resolved yet.
use crate::def_collector::collect_definitions;
use crate::imports::ImportDirective;
use crate::imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport};
use crate::imports::{Import, ImportKind};
use crate::macros::{LegacyBinding, LegacyScope};
use crate::Namespace::{self, MacroNS, TypeNS, ValueNS};
use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError};
@ -308,11 +307,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
})
}
// Add an import directive to the current module.
fn add_import_directive(
// Add an import to the current module.
fn add_import(
&mut self,
module_path: Vec<Segment>,
subclass: ImportDirectiveSubclass<'a>,
kind: ImportKind<'a>,
span: Span,
id: NodeId,
item: &ast::Item,
@ -321,11 +320,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
vis: ty::Visibility,
) {
let current_module = self.parent_scope.module;
let directive = self.r.arenas.alloc_import_directive(ImportDirective {
let import = self.r.arenas.alloc_import(Import {
kind,
parent_scope: self.parent_scope,
module_path,
imported_module: Cell::new(None),
subclass,
span,
id,
use_span: item.span,
@ -337,25 +336,25 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
used: Cell::new(false),
});
debug!("add_import_directive({:?})", directive);
debug!("add_import({:?})", import);
self.r.indeterminate_imports.push(directive);
match directive.subclass {
self.r.indeterminate_imports.push(import);
match import.kind {
// Don't add unresolved underscore imports to modules
SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {}
SingleImport { target, type_ns_only, .. } => {
ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
ImportKind::Single { target, type_ns_only, .. } => {
self.r.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let key = this.new_key(target, ns);
let mut resolution = this.resolution(current_module, key).borrow_mut();
resolution.add_single_import(directive);
resolution.add_single_import(import);
}
});
}
// We don't add prelude imports to the globs since they only affect lexical scopes,
// which are not relevant to import resolution.
GlobImport { is_prelude: true, .. } => {}
GlobImport { .. } => current_module.globs.borrow_mut().push(directive),
ImportKind::Glob { is_prelude: true, .. } => {}
ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(import),
_ => unreachable!(),
}
}
@ -480,7 +479,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
);
}
let subclass = SingleImport {
let kind = ImportKind::Single {
source: source.ident,
target: ident,
source_bindings: PerNS {
@ -496,9 +495,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
type_ns_only,
nested,
};
self.add_import_directive(
self.add_import(
module_path,
subclass,
kind,
use_tree.span,
id,
item,
@ -508,20 +507,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
);
}
ast::UseTreeKind::Glob => {
let subclass = GlobImport {
let kind = ImportKind::Glob {
is_prelude: attr::contains_name(&item.attrs, sym::prelude_import),
max_vis: Cell::new(ty::Visibility::Invisible),
};
self.add_import_directive(
prefix,
subclass,
use_tree.span,
id,
item,
root_span,
item.id,
vis,
);
self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis);
}
ast::UseTreeKind::Nested(ref items) => {
// Ensure there is at most one `self` in the list
@ -637,15 +627,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let used = self.process_legacy_macro_imports(item, module);
let binding =
(module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas);
let directive = self.r.arenas.alloc_import_directive(ImportDirective {
let import = self.r.arenas.alloc_import(Import {
kind: ImportKind::ExternCrate { source: orig_name, target: ident },
root_id: item.id,
id: item.id,
parent_scope: self.parent_scope,
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
subclass: ImportDirectiveSubclass::ExternCrate {
source: orig_name,
target: ident,
},
has_attributes: !item.attrs.is_empty(),
use_span_with_attributes: item.span_with_attributes(),
use_span: item.span,
@ -655,8 +642,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
vis: Cell::new(vis),
used: Cell::new(used),
});
self.r.potentially_unused_imports.push(directive);
let imported_binding = self.r.import(binding, directive);
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
if ptr::eq(parent, self.r.graph_root) {
if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) {
if expansion != ExpnId::root()
@ -992,13 +979,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
}
}
let macro_use_directive = |this: &Self, span| {
this.r.arenas.alloc_import_directive(ImportDirective {
let macro_use_import = |this: &Self, span| {
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))),
subclass: ImportDirectiveSubclass::MacroUse,
use_span_with_attributes: item.span_with_attributes(),
has_attributes: !item.attrs.is_empty(),
use_span: item.span,
@ -1012,11 +999,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
let allow_shadowing = self.parent_scope.expansion == ExpnId::root();
if let Some(span) = import_all {
let directive = macro_use_directive(self, span);
self.r.potentially_unused_imports.push(directive);
let import = macro_use_import(self, span);
self.r.potentially_unused_imports.push(import);
module.for_each_child(self, |this, ident, ns, binding| {
if ns == MacroNS {
let imported_binding = this.r.import(binding, directive);
let imported_binding = this.r.import(binding, import);
this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing);
}
});
@ -1031,9 +1018,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
ident.span,
);
if let Ok(binding) = result {
let directive = macro_use_directive(self, ident.span);
self.r.potentially_unused_imports.push(directive);
let imported_binding = self.r.import(binding, directive);
let import = macro_use_import(self, ident.span);
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
self.legacy_import_macro(
ident.name,
imported_binding,

View File

@ -3,7 +3,7 @@
//
// Although this is mostly a lint pass, it lives in here because it depends on
// resolve data structures and because it finalises the privacy information for
// `use` directives.
// `use` items.
//
// Unused trait imports can't be checked until the method resolution. We save
// candidates here, and do the actual check in librustc_typeck/check_unused.rs.
@ -23,7 +23,7 @@
// - `check_crate` finally emits the diagnostics based on the data generated
// in the last step
use crate::imports::ImportDirectiveSubclass;
use crate::imports::ImportKind;
use crate::Resolver;
use rustc::{lint, ty};
@ -58,7 +58,7 @@ struct UnusedImportCheckVisitor<'a, 'b> {
}
impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
// We have information about whether `use` (import) directives are actually
// We have information about whether `use` (import) items are actually
// used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId) {
let mut used = false;
@ -223,33 +223,33 @@ fn calc_unused_spans(
impl Resolver<'_> {
crate fn check_unused(&mut self, krate: &ast::Crate) {
for directive in self.potentially_unused_imports.iter() {
match directive.subclass {
_ if directive.used.get()
|| directive.vis.get() == ty::Visibility::Public
|| directive.span.is_dummy() =>
for import in self.potentially_unused_imports.iter() {
match import.kind {
_ if import.used.get()
|| import.vis.get() == ty::Visibility::Public
|| import.span.is_dummy() =>
{
if let ImportDirectiveSubclass::MacroUse = directive.subclass {
if !directive.span.is_dummy() {
if let ImportKind::MacroUse = import.kind {
if !import.span.is_dummy() {
self.lint_buffer.buffer_lint(
lint::builtin::MACRO_USE_EXTERN_CRATE,
directive.id,
directive.span,
"deprecated `#[macro_use]` directive used to \
import.id,
import.span,
"deprecated `#[macro_use]` attribute used to \
import macros should be replaced at use sites \
with a `use` statement to import the macro \
with a `use` item to import the macro \
instead",
);
}
}
}
ImportDirectiveSubclass::ExternCrate { .. } => {
self.maybe_unused_extern_crates.push((directive.id, directive.span));
ImportKind::ExternCrate { .. } => {
self.maybe_unused_extern_crates.push((import.id, import.span));
}
ImportDirectiveSubclass::MacroUse => {
ImportKind::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS;
let msg = "unused `#[macro_use]` import";
self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg);
self.lint_buffer.buffer_lint(lint, import.id, import.span, msg);
}
_ => {}
}

View File

@ -18,7 +18,7 @@ use rustc_span::source_map::SourceMap;
use rustc_span::symbol::{kw, Symbol};
use rustc_span::{BytePos, MultiSpan, Span};
use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
use crate::imports::{Import, ImportKind, ImportResolver};
use crate::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot};
@ -1125,7 +1125,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// ```
pub(crate) fn check_for_module_export_macro(
&mut self,
directive: &'b ImportDirective<'b>,
import: &'b Import<'b>,
module: ModuleOrUniformRoot<'b>,
ident: Ident,
) -> Option<(Option<Suggestion>, Vec<String>)> {
@ -1150,28 +1150,26 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let binding = resolution.borrow().binding()?;
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
let module_name = crate_module.kind.name().unwrap();
let import = match directive.subclass {
ImportDirectiveSubclass::SingleImport { source, target, .. }
if source != target =>
{
let import_snippet = match import.kind {
ImportKind::Single { source, target, .. } if source != target => {
format!("{} as {}", source, target)
}
_ => format!("{}", ident),
};
let mut corrections: Vec<(Span, String)> = Vec::new();
if !directive.is_nested() {
if !import.is_nested() {
// Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
// intermediate segments.
corrections.push((directive.span, format!("{}::{}", module_name, import)));
corrections.push((import.span, format!("{}::{}", module_name, import_snippet)));
} else {
// Find the binding span (and any trailing commas and spaces).
// ie. `use a::b::{c, d, e};`
// ^^^
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
self.r.session,
directive.span,
directive.use_span,
import.span,
import.use_span,
);
debug!(
"check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
@ -1208,7 +1206,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
self.r.session,
module_name,
directive.use_span,
import.use_span,
);
debug!(
"check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
@ -1224,11 +1222,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
start_point,
if has_nested {
// In this case, `start_snippet` must equal '{'.
format!("{}{}, ", start_snippet, import)
format!("{}{}, ", start_snippet, import_snippet)
} else {
// In this case, add a `{`, then the moved import, then whatever
// was there before.
format!("{{{}, {}", import, start_snippet)
format!("{{{}, {}", import_snippet, start_snippet)
},
));
}

View File

@ -1,7 +1,5 @@
//! A bunch of methods and structures more or less related to resolving imports.
use ImportDirectiveSubclass::*;
use crate::diagnostics::Suggestion;
use crate::Determinacy::{self, *};
use crate::Namespace::{self, MacroNS, TypeNS};
@ -36,10 +34,10 @@ use std::{mem, ptr};
type Res = def::Res<NodeId>;
/// Contains data for specific types of import directives.
/// Contains data for specific kinds of imports.
#[derive(Clone, Debug)]
pub enum ImportDirectiveSubclass<'a> {
SingleImport {
pub enum ImportKind<'a> {
Single {
/// `source` in `use prefix::source as target`.
source: Ident,
/// `target` in `use prefix::source as target`.
@ -53,7 +51,7 @@ pub enum ImportDirectiveSubclass<'a> {
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
nested: bool,
},
GlobImport {
Glob {
is_prelude: bool,
max_vis: Cell<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.
@ -65,19 +63,21 @@ pub enum ImportDirectiveSubclass<'a> {
MacroUse,
}
/// One import directive.
/// One import.
#[derive(Debug, Clone)]
crate struct ImportDirective<'a> {
/// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`.
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 `ImportDirective` was expanded from a "nested" use tree,
/// 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 mercilous tidy)
/// use foo::bar::{a, b}
/// ```
///
/// If this is the import directive for `foo::bar::a`, we would have the ID of the `UseTree`
/// 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,
@ -107,22 +107,21 @@ crate struct ImportDirective<'a> {
pub module_path: Vec<Segment>,
/// The resolution of `module_path`.
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
pub subclass: ImportDirectiveSubclass<'a>,
pub vis: Cell<ty::Visibility>,
pub used: Cell<bool>,
}
impl<'a> ImportDirective<'a> {
impl<'a> Import<'a> {
pub fn is_glob(&self) -> bool {
match self.subclass {
ImportDirectiveSubclass::GlobImport { .. } => true,
match self.kind {
ImportKind::Glob { .. } => true,
_ => false,
}
}
pub fn is_nested(&self) -> bool {
match self.subclass {
ImportDirectiveSubclass::SingleImport { nested, .. } => nested,
match self.kind {
ImportKind::Single { nested, .. } => nested,
_ => false,
}
}
@ -136,8 +135,8 @@ impl<'a> ImportDirective<'a> {
/// Records information about the resolution of a name in a namespace of a module.
pub struct NameResolution<'a> {
/// Single imports that may define the name in the namespace.
/// Import directives are arena-allocated, so it's ok to use pointers as keys.
single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>,
/// Imports are arena-allocated, so it's ok to use pointers as keys.
single_imports: FxHashSet<PtrKey<'a, Import<'a>>>,
/// The least shadowable known binding for this name, or None if there are no known bindings.
pub binding: Option<&'a NameBinding<'a>>,
shadowed_glob: Option<&'a NameBinding<'a>>,
@ -155,8 +154,8 @@ impl<'a> NameResolution<'a> {
})
}
crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) {
self.single_imports.insert(PtrKey(directive));
crate fn add_single_import(&mut self, import: &'a Import<'a>) {
self.single_imports.insert(PtrKey(import));
}
}
@ -348,8 +347,8 @@ impl<'a> Resolver<'a> {
single_import.imported_module.get(),
return Err((Undetermined, Weak::No))
);
let ident = match single_import.subclass {
SingleImport { source, .. } => source,
let ident = match single_import.kind {
ImportKind::Single { source, .. } => source,
_ => unreachable!(),
};
match self.resolve_ident_in_module(
@ -451,34 +450,34 @@ impl<'a> Resolver<'a> {
Err((Determined, Weak::No))
}
// Given a binding and an import directive that resolves to it,
// return the corresponding binding defined by the import directive.
// Given a binding and an import that resolves to it,
// return the corresponding binding defined by the import.
crate fn import(
&self,
binding: &'a NameBinding<'a>,
directive: &'a ImportDirective<'a>,
import: &'a Import<'a>,
) -> &'a NameBinding<'a> {
let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) ||
let vis = if binding.pseudo_vis().is_at_least(import.vis.get(), self) ||
// cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
!directive.is_glob() && binding.is_extern_crate()
!import.is_glob() && binding.is_extern_crate()
{
directive.vis.get()
import.vis.get()
} else {
binding.pseudo_vis()
};
if let GlobImport { ref max_vis, .. } = directive.subclass {
if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) {
if let ImportKind::Glob { ref max_vis, .. } = import.kind {
if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) {
max_vis.set(vis)
}
}
self.arenas.alloc_name_binding(NameBinding {
kind: NameBindingKind::Import { binding, directive, used: Cell::new(false) },
kind: NameBindingKind::Import { binding, import, used: Cell::new(false) },
ambiguity: None,
span: directive.span,
span: import.span,
vis,
expansion: directive.parent_scope.expansion,
expansion: import.parent_scope.expansion,
})
}
@ -577,17 +576,17 @@ impl<'a> Resolver<'a> {
};
// Define `binding` in `module`s glob importers.
for directive in module.glob_importers.borrow_mut().iter() {
for import in module.glob_importers.borrow_mut().iter() {
let mut ident = key.ident;
let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) {
let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
Some(Some(def)) => self.macro_def_scope(def),
Some(None) => directive.parent_scope.module,
Some(None) => import.parent_scope.module,
None => continue,
};
if self.is_accessible_from(binding.vis, scope) {
let imported_binding = self.import(binding, directive);
let imported_binding = self.import(binding, import);
let key = BindingKey { ident, ..key };
let _ = self.try_define(directive.parent_scope.module, key, imported_binding);
let _ = self.try_define(import.parent_scope.module, key, imported_binding);
}
}
@ -596,13 +595,13 @@ impl<'a> Resolver<'a> {
// Define a "dummy" resolution containing a Res::Err as a placeholder for a
// failed resolution
fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) {
if let SingleImport { target, .. } = directive.subclass {
fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
if let ImportKind::Single { target, .. } = import.kind {
let dummy_binding = self.dummy_binding;
let dummy_binding = self.import(dummy_binding, directive);
let dummy_binding = self.import(dummy_binding, import);
self.per_ns(|this, ns| {
let key = this.new_key(target, ns);
let _ = this.try_define(directive.parent_scope.module, key, dummy_binding);
let _ = this.try_define(import.parent_scope.module, key, dummy_binding);
// Consider erroneous imports used to avoid duplicate diagnostics.
this.record_use(target, ns, dummy_binding, false);
});
@ -671,7 +670,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
.chain(indeterminate_imports.into_iter().map(|i| (true, i)))
{
if let Some(err) = self.finalize_import(import) {
if let SingleImport { source, ref source_bindings, .. } = import.subclass {
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
if source.name == kw::SelfLower {
// Silence `unresolved import` error if E0429 is already emitted
if let Err(Determined) = source_bindings.value_ns.get() {
@ -695,7 +694,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
if seen_spans.insert(err.span) {
let path = import_path_to_string(
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
&import.subclass,
&import.kind,
err.span,
);
errors.push((path, err));
@ -706,7 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
self.r.used_imports.insert((import.id, TypeNS));
let path = import_path_to_string(
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
&import.subclass,
&import.kind,
import.span,
);
let err = UnresolvedImportError {
@ -767,28 +766,28 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
/// Attempts to resolve the given import, returning true if its resolution is determined.
/// If successful, the resolved bindings are written into the module.
fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool {
fn resolve_import(&mut self, import: &'b Import<'b>) -> bool {
debug!(
"(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&directive.module_path),
module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()),
Segment::names_to_string(&import.module_path),
module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),
);
let module = if let Some(module) = directive.imported_module.get() {
let module = if let Some(module) = import.imported_module.get() {
module
} else {
// For better failure detection, pretend that the import will
// not define any names while resolving its module path.
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
let path_res = self.r.resolve_path(
&directive.module_path,
&import.module_path,
None,
&directive.parent_scope,
&import.parent_scope,
false,
directive.span,
directive.crate_lint(),
import.span,
import.crate_lint(),
);
directive.vis.set(orig_vis);
import.vis.set(orig_vis);
match path_res {
PathResult::Module(module) => module,
@ -797,23 +796,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
};
directive.imported_module.set(Some(module));
let (source, target, source_bindings, target_bindings, type_ns_only) =
match directive.subclass {
SingleImport {
source,
target,
ref source_bindings,
ref target_bindings,
type_ns_only,
..
} => (source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { .. } => {
self.resolve_glob_import(directive);
return true;
}
_ => unreachable!(),
};
import.imported_module.set(Some(module));
let (source, 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 { .. } => {
self.resolve_glob_import(import);
return true;
}
_ => unreachable!(),
};
let mut indeterminate = false;
self.r.per_ns(|this, ns| {
@ -821,23 +819,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
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 = directive.vis.replace(ty::Visibility::Invisible);
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
let binding = this.resolve_ident_in_module(
module,
source,
ns,
&directive.parent_scope,
&import.parent_scope,
false,
directive.span,
import.span,
);
directive.vis.set(orig_vis);
import.vis.set(orig_vis);
source_bindings[ns].set(binding);
} else {
return;
};
let parent = directive.parent_scope.module;
let parent = import.parent_scope.module;
match source_bindings[ns].get() {
Err(Undetermined) => indeterminate = true,
// Don't update the resolution, because it was never added.
@ -845,20 +843,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
Err(Determined) => {
let key = this.new_key(target, ns);
this.update_resolution(parent, key, |_, resolution| {
resolution.single_imports.remove(&PtrKey(directive));
resolution.single_imports.remove(&PtrKey(import));
});
}
Ok(binding) if !binding.is_importable() => {
let msg = format!("`{}` is not directly importable", target);
struct_span_err!(this.session, directive.span, E0253, "{}", &msg)
.span_label(directive.span, "cannot be imported directly")
struct_span_err!(this.session, import.span, E0253, "{}", &msg)
.span_label(import.span, "cannot be imported directly")
.emit();
// Do not import this illegal binding. Import a dummy binding and pretend
// everything is fine
this.import_dummy_binding(directive);
this.import_dummy_binding(import);
}
Ok(binding) => {
let imported_binding = this.import(binding, directive);
let imported_binding = this.import(binding, import);
target_bindings[ns].set(Some(imported_binding));
this.define(parent, target, ns, imported_binding);
}
@ -873,38 +871,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
///
/// Optionally returns an unresolved import error. This error is buffered and used to
/// consolidate multiple unresolved import errors into a single diagnostic.
fn finalize_import(
&mut self,
directive: &'b ImportDirective<'b>,
) -> Option<UnresolvedImportError> {
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
let path_res = self.r.resolve_path(
&directive.module_path,
&import.module_path,
None,
&directive.parent_scope,
&import.parent_scope,
true,
directive.span,
directive.crate_lint(),
import.span,
import.crate_lint(),
);
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len;
directive.vis.set(orig_vis);
import.vis.set(orig_vis);
if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
// Consider erroneous imports used to avoid duplicate diagnostics.
self.r.used_imports.insert((directive.id, TypeNS));
self.r.used_imports.insert((import.id, TypeNS));
}
let module = match path_res {
PathResult::Module(module) => {
// Consistency checks, analogous to `finalize_macro_resolutions`.
if let Some(initial_module) = directive.imported_module.get() {
if let Some(initial_module) = import.imported_module.get() {
if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity {
span_bug!(directive.span, "inconsistent resolution for an import");
span_bug!(import.span, "inconsistent resolution for an import");
}
} else {
if self.r.privacy_errors.is_empty() {
let msg = "cannot determine resolution for the import";
let msg_note = "import resolution is stuck, try simplifying other imports";
self.r.session.struct_span_err(directive.span, msg).note(msg_note).emit();
self.r.session.struct_span_err(import.span, msg).note(msg_note).emit();
}
}
@ -912,7 +907,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
if no_ambiguity {
assert!(directive.imported_module.get().is_none());
assert!(import.imported_module.get().is_none());
self.r
.report_error(span, ResolutionError::FailedToResolve { label, suggestion });
}
@ -920,11 +915,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
if no_ambiguity {
assert!(directive.imported_module.get().is_none());
assert!(import.imported_module.get().is_none());
let err = match self.make_path_suggestion(
span,
directive.module_path.clone(),
&directive.parent_scope,
import.module_path.clone(),
&import.parent_scope,
) {
Some((suggestion, note)) => UnresolvedImportError {
span,
@ -949,7 +944,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => {
if no_ambiguity {
assert!(directive.imported_module.get().is_none());
assert!(import.imported_module.get().is_none());
}
// The error was already reported earlier.
return None;
@ -957,10 +952,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
};
let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive
.subclass
{
SingleImport {
let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
ImportKind::Single {
source,
target,
ref source_bindings,
@ -968,25 +961,25 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
type_ns_only,
..
} => (source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { is_prelude, ref max_vis } => {
if directive.module_path.len() <= 1 {
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 = directive.module_path.clone();
let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(Ident::invalid()));
self.r.lint_if_path_starts_with_module(
directive.crate_lint(),
import.crate_lint(),
&full_path,
directive.span,
import.span,
None,
);
}
if let ModuleOrUniformRoot::Module(module) = module {
if module.def_id() == directive.parent_scope.module.def_id() {
if module.def_id() == import.parent_scope.module.def_id() {
// Importing a module into itself is not allowed.
return Some(UnresolvedImportError {
span: directive.span,
span: import.span,
label: Some(String::from("cannot glob-import a module into itself")),
note: Vec::new(),
suggestion: None,
@ -995,15 +988,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
if !is_prelude &&
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs.
!max_vis.get().is_at_least(directive.vis.get(), &*self)
!max_vis.get().is_at_least(import.vis.get(), &*self)
{
let msg = "glob import doesn't reexport anything because no candidate is public enough";
self.r.lint_buffer.buffer_lint(
UNUSED_IMPORTS,
directive.id,
directive.span,
msg,
);
self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
}
return None;
}
@ -1013,7 +1001,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut all_ns_err = true;
self.r.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS {
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let orig_vis = import.vis.replace(ty::Visibility::Invisible);
let orig_blacklisted_binding =
mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
@ -1021,13 +1009,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
module,
ident,
ns,
&directive.parent_scope,
&import.parent_scope,
true,
directive.span,
import.span,
);
this.last_import_segment = orig_last_import_segment;
this.blacklisted_binding = orig_blacklisted_binding;
directive.vis.set(orig_vis);
import.vis.set(orig_vis);
match binding {
Ok(binding) => {
@ -1044,7 +1032,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
ident,
ns,
target_binding,
directive.module_path.is_empty(),
import.module_path.is_empty(),
);
}
}
@ -1053,7 +1041,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let res = binding.res();
if let Ok(initial_res) = initial_res {
if res != initial_res && this.ambiguity_errors.is_empty() {
span_bug!(directive.span, "inconsistent resolution for an import");
span_bug!(import.span, "inconsistent resolution for an import");
}
} else {
if res != Res::Err
@ -1064,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let msg_note =
"import resolution is stuck, try simplifying other imports";
this.session
.struct_span_err(directive.span, msg)
.struct_span_err(import.span, msg)
.note(msg_note)
.emit();
}
@ -1090,9 +1078,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
module,
ident,
ns,
&directive.parent_scope,
&import.parent_scope,
true,
directive.span,
import.span,
);
if binding.is_ok() {
all_ns_failed = false;
@ -1143,7 +1131,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
});
let (suggestion, note) =
match self.check_for_module_export_macro(directive, module, ident) {
match self.check_for_module_export_macro(import, module, ident) {
Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
_ => (lev_suggestion, Vec::new()),
};
@ -1169,14 +1157,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
};
Some(UnresolvedImportError {
span: directive.span,
span: import.span,
label: Some(label),
note,
suggestion,
})
} else {
// `resolve_ident_in_module` reported a privacy error.
self.r.import_dummy_binding(directive);
self.r.import_dummy_binding(import);
None
};
}
@ -1185,7 +1173,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut any_successful_reexport = false;
self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
let vis = directive.vis.get();
let vis = import.vis.get();
if !binding.pseudo_vis().is_at_least(vis, &*this) {
reexport_error = Some((ns, binding));
} else {
@ -1206,42 +1194,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
);
self.r.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
directive.id,
directive.span,
import.id,
import.span,
&msg,
);
} else if ns == TypeNS {
struct_span_err!(
self.r.session,
directive.span,
import.span,
E0365,
"`{}` is private, and cannot be re-exported",
ident
)
.span_label(directive.span, format!("re-export of private `{}`", ident))
.span_label(import.span, format!("re-export of private `{}`", ident))
.note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit();
} else {
let msg = format!("`{}` is private, and cannot be re-exported", ident);
let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident,);
struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg)
.span_note(directive.span, &note_msg)
struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
.span_note(import.span, &note_msg)
.emit();
}
}
if directive.module_path.len() <= 1 {
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 = directive.module_path.clone();
let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(ident));
self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() {
this.lint_if_path_starts_with_module(
directive.crate_lint(),
import.crate_lint(),
&full_path,
directive.span,
import.span,
Some(binding),
);
}
@ -1253,17 +1241,11 @@ 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(directive.id).or_default()[ns] = Some(binding.res());
this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res());
}
});
self.check_for_redundant_imports(
ident,
directive,
source_bindings,
target_bindings,
target,
);
self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target);
debug!("(resolving single import) successfully resolved import");
None
@ -1272,19 +1254,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn check_for_redundant_imports(
&mut self,
ident: Ident,
directive: &'b ImportDirective<'b>,
import: &'b Import<'b>,
source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
target: Ident,
) {
// Skip if the import was produced by a macro.
if directive.parent_scope.expansion != ExpnId::root() {
if import.parent_scope.expansion != ExpnId::root() {
return;
}
// Skip if we are inside a named module (in contrast to an anonymous
// module defined by a block).
if let ModuleKind::Def(..) = directive.parent_scope.module.kind {
if let ModuleKind::Def(..) = import.parent_scope.module.kind {
return;
}
@ -1304,10 +1286,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
match this.early_resolve_ident_in_lexical_scope(
target,
ScopeSet::All(ns, false),
&directive.parent_scope,
&import.parent_scope,
false,
false,
directive.span,
import.span,
) {
Ok(other_binding) => {
is_redundant[ns] = Some(
@ -1329,35 +1311,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
redundant_spans.dedup();
self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_IMPORTS,
directive.id,
directive.span,
import.id,
import.span,
&format!("the item `{}` is imported redundantly", ident),
BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
);
}
}
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) {
let module = match directive.imported_module.get().unwrap() {
fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
let module = match import.imported_module.get().unwrap() {
ModuleOrUniformRoot::Module(module) => module,
_ => {
self.r.session.span_err(directive.span, "cannot glob-import all possible crates");
self.r.session.span_err(import.span, "cannot glob-import all possible crates");
return;
}
};
if module.is_trait() {
self.r.session.span_err(directive.span, "items in traits are not importable.");
self.r.session.span_err(import.span, "items in traits are not importable.");
return;
} else if module.def_id() == directive.parent_scope.module.def_id() {
} else if module.def_id() == import.parent_scope.module.def_id() {
return;
} else if let GlobImport { is_prelude: true, .. } = directive.subclass {
} else if let ImportKind::Glob { is_prelude: true, .. } = import.kind {
self.r.prelude = Some(module);
return;
}
// Add to module's glob_importers
module.glob_importers.borrow_mut().push(directive);
module.glob_importers.borrow_mut().push(import);
// Ensure that `resolutions` isn't borrowed during `try_define`,
// since it might get updated via a glob cycle.
@ -1371,19 +1353,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
})
.collect::<Vec<_>>();
for (mut key, binding) in bindings {
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) {
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
Some(Some(def)) => self.r.macro_def_scope(def),
Some(None) => directive.parent_scope.module,
Some(None) => import.parent_scope.module,
None => continue,
};
if self.r.is_accessible_from(binding.pseudo_vis(), scope) {
let imported_binding = self.r.import(binding, directive);
let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding);
let imported_binding = self.r.import(binding, import);
let _ = self.r.try_define(import.parent_scope.module, key, imported_binding);
}
}
// Record the destination of this import
self.r.record_partial_res(directive.id, PartialRes::new(module.res().unwrap()));
self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap()));
}
// Miscellaneous post-processing, including recording re-exports,
@ -1407,16 +1389,16 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
}
if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind {
if let NameBindingKind::Import { binding: orig_binding, import, .. } = binding.kind {
if ns == TypeNS
&& orig_binding.is_variant()
&& !orig_binding.vis.is_at_least(binding.vis, &*this)
{
let msg = match directive.subclass {
ImportDirectiveSubclass::SingleImport { .. } => {
let msg = match import.kind {
ImportKind::Single { .. } => {
format!("variant `{}` is private and cannot be re-exported", ident)
}
ImportDirectiveSubclass::GlobImport { .. } => {
ImportKind::Glob { .. } => {
let msg = "enum is private and its variants \
cannot be re-exported"
.to_owned();
@ -1432,18 +1414,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
msg
}
ref s => bug!("unexpected import subclass {:?}", s),
ref s => bug!("unexpected import kind {:?}", s),
};
let mut err = this.session.struct_span_err(binding.span, &msg);
let imported_module = match directive.imported_module.get() {
let imported_module = match import.imported_module.get() {
Some(ModuleOrUniformRoot::Module(module)) => module,
_ => bug!("module should exist"),
};
let parent_module = imported_module.parent.expect("parent should exist");
let resolutions = this.resolutions(parent_module).borrow();
let enum_path_segment_index = directive.module_path.len() - 1;
let enum_ident = directive.module_path[enum_path_segment_index].ident;
let enum_path_segment_index = import.module_path.len() - 1;
let enum_ident = import.module_path[enum_path_segment_index].ident;
let key = this.new_key(enum_ident, TypeNS);
let enum_resolution = resolutions.get(&key).expect("resolution should exist");
@ -1481,11 +1463,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}
}
fn import_path_to_string(
names: &[Ident],
subclass: &ImportDirectiveSubclass<'_>,
span: Span,
) -> String {
fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {
let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);
let global = !names.is_empty() && names[0].name == kw::PathRoot;
if let Some(pos) = pos {
@ -1494,22 +1472,22 @@ fn import_path_to_string(
} else {
let names = if global { &names[1..] } else { names };
if names.is_empty() {
import_directive_subclass_to_string(subclass)
import_kind_to_string(import_kind)
} else {
format!(
"{}::{}",
names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
import_directive_subclass_to_string(subclass),
import_kind_to_string(import_kind),
)
}
}
}
fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass<'_>) -> String {
match *subclass {
SingleImport { source, .. } => source.to_string(),
GlobImport { .. } => "*".to_string(),
ExternCrate { .. } => "<extern crate>".to_string(),
MacroUse => "#[macro_use]".to_string(),
fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
match import_kind {
ImportKind::Single { source, .. } => source.to_string(),
ImportKind::Glob { .. } => "*".to_string(),
ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
ImportKind::MacroUse => "#[macro_use]".to_string(),
}
}

View File

@ -2189,10 +2189,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
trait_name: Ident,
) -> SmallVec<[NodeId; 1]> {
let mut import_ids = smallvec![];
while let NameBindingKind::Import { directive, binding, .. } = kind {
self.r.maybe_unused_trait_imports.insert(directive.id);
self.r.add_to_glob_map(&directive, trait_name);
import_ids.push(directive.id);
while let NameBindingKind::Import { import, binding, .. } = kind {
self.r.maybe_unused_trait_imports.insert(import.id);
self.r.add_to_glob_map(&import, trait_name);
import_ids.push(import.id);
kind = &binding.kind;
}
import_ids

View File

@ -56,7 +56,7 @@ use std::{cmp, fmt, iter, ptr};
use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
use diagnostics::{ImportSuggestion, Suggestion};
use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameResolution};
use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{LegacyBinding, LegacyScope};
@ -456,8 +456,8 @@ pub struct ModuleData<'a> {
no_implicit_prelude: bool,
glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>,
globs: RefCell<Vec<&'a ImportDirective<'a>>>,
glob_importers: RefCell<Vec<&'a Import<'a>>>,
globs: RefCell<Vec<&'a Import<'a>>>,
// Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
@ -584,7 +584,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
enum NameBindingKind<'a> {
Res(Res, /* is_macro_export */ bool),
Module(Module<'a>),
Import { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, used: Cell<bool> },
Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell<bool> },
}
impl<'a> NameBindingKind<'a> {
@ -713,8 +713,7 @@ impl<'a> NameBinding<'a> {
fn is_extern_crate(&self) -> bool {
match self.kind {
NameBindingKind::Import {
directive:
&ImportDirective { subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. },
import: &Import { kind: ImportKind::ExternCrate { .. }, .. },
..
} => true,
NameBindingKind::Module(&ModuleData {
@ -734,7 +733,7 @@ impl<'a> NameBinding<'a> {
fn is_glob_import(&self) -> bool {
match self.kind {
NameBindingKind::Import { directive, .. } => directive.is_glob(),
NameBindingKind::Import { import, .. } => import.is_glob(),
_ => false,
}
}
@ -839,10 +838,10 @@ pub struct Resolver<'a> {
field_names: FxHashMap<DefId, Vec<Spanned<Name>>>,
/// All imports known to succeed or fail.
determined_imports: Vec<&'a ImportDirective<'a>>,
determined_imports: Vec<&'a Import<'a>>,
/// All non-determined imports.
indeterminate_imports: Vec<&'a ImportDirective<'a>>,
indeterminate_imports: Vec<&'a Import<'a>>,
/// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
/// We are resolving a last import segment during import validation.
@ -947,7 +946,7 @@ pub struct Resolver<'a> {
/// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>,
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
potentially_unused_imports: Vec<&'a Import<'a>>,
/// Table for mapping struct IDs into struct constructor IDs,
/// it's not used during normal resolution, only for better error reporting.
@ -971,7 +970,7 @@ pub struct ResolverArenas<'a> {
modules: arena::TypedArena<ModuleData<'a>>,
local_modules: RefCell<Vec<Module<'a>>>,
name_bindings: arena::TypedArena<NameBinding<'a>>,
import_directives: arena::TypedArena<ImportDirective<'a>>,
imports: arena::TypedArena<Import<'a>>,
name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
ast_paths: arena::TypedArena<ast::Path>,
@ -991,11 +990,8 @@ impl<'a> ResolverArenas<'a> {
fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
self.name_bindings.alloc(name_binding)
}
fn alloc_import_directive(
&'a self,
import_directive: ImportDirective<'a>,
) -> &'a ImportDirective<'_> {
self.import_directives.alloc(import_directive)
fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> {
self.imports.alloc(import)
}
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default())
@ -1410,7 +1406,7 @@ impl<'a> Resolver<'a> {
misc2: AmbiguityErrorMisc::None,
});
}
if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind {
if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
// Avoid marking `extern crate` items that refer to a name from extern prelude,
// but not introduce it, as used if they are accessed from lexical scope.
if is_lexical_scope {
@ -1423,17 +1419,17 @@ impl<'a> Resolver<'a> {
}
}
used.set(true);
directive.used.set(true);
self.used_imports.insert((directive.id, ns));
self.add_to_glob_map(&directive, ident);
import.used.set(true);
self.used_imports.insert((import.id, ns));
self.add_to_glob_map(&import, ident);
self.record_use(ident, ns, binding, false);
}
}
#[inline]
fn add_to_glob_map(&mut self, directive: &ImportDirective<'_>, ident: Ident) {
if directive.is_glob() {
self.glob_map.entry(directive.id).or_default().insert(ident.name);
fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
if import.is_glob() {
self.glob_map.entry(import.id).or_default().insert(ident.name);
}
}
@ -2258,10 +2254,9 @@ impl<'a> Resolver<'a> {
// `ExternCrate` (also used for `crate::...`) then no need to issue a
// warning, this looks all good!
if let Some(binding) = second_binding {
if let NameBindingKind::Import { directive: d, .. } = binding.kind {
// Careful: we still want to rewrite paths from
// renamed extern crates.
if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass {
if let NameBindingKind::Import { import, .. } = binding.kind {
// Careful: we still want to rewrite paths from renamed extern crates.
if let ImportKind::ExternCrate { source: None, .. } = import.kind {
return;
}
}
@ -2564,10 +2559,10 @@ impl<'a> Resolver<'a> {
// See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import;
let directive = match (&new_binding.kind, &old_binding.kind) {
let import = match (&new_binding.kind, &old_binding.kind) {
// If there are two imports where one or both have attributes then prefer removing the
// import without attributes.
(Import { directive: new, .. }, Import { directive: old, .. })
(Import { import: new, .. }, Import { import: old, .. })
if {
!new_binding.span.is_dummy()
&& !old_binding.span.is_dummy()
@ -2581,11 +2576,11 @@ impl<'a> Resolver<'a> {
}
}
// Otherwise prioritize the new binding.
(Import { directive, .. }, other) if !new_binding.span.is_dummy() => {
Some((directive, new_binding.span, other.is_import()))
(Import { import, .. }, other) if !new_binding.span.is_dummy() => {
Some((import, new_binding.span, other.is_import()))
}
(other, Import { directive, .. }) if !old_binding.span.is_dummy() => {
Some((directive, old_binding.span, other.is_import()))
(other, Import { import, .. }) if !old_binding.span.is_dummy() => {
Some((import, old_binding.span, other.is_import()))
}
_ => None,
};
@ -2602,22 +2597,22 @@ impl<'a> Resolver<'a> {
&& !has_dummy_span
&& ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
match directive {
Some((directive, span, true)) if should_remove_import && directive.is_nested() => {
self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span)
match import {
Some((import, span, true)) if should_remove_import && import.is_nested() => {
self.add_suggestion_for_duplicate_nested_use(&mut err, import, span)
}
Some((directive, _, true)) if should_remove_import && !directive.is_glob() => {
Some((import, _, true)) if should_remove_import && !import.is_glob() => {
// Simple case - remove the entire import. Due to the above match arm, this can
// only be a single use so just remove it entirely.
err.tool_only_span_suggestion(
directive.use_span_with_attributes,
import.use_span_with_attributes,
"remove unnecessary import",
String::new(),
Applicability::MaybeIncorrect,
);
}
Some((directive, span, _)) => {
self.add_suggestion_for_rename_of_use(&mut err, name, directive, span)
Some((import, span, _)) => {
self.add_suggestion_for_rename_of_use(&mut err, name, import, span)
}
_ => {}
}
@ -2639,7 +2634,7 @@ impl<'a> Resolver<'a> {
&self,
err: &mut DiagnosticBuilder<'_>,
name: Name,
directive: &ImportDirective<'_>,
import: &Import<'_>,
binding_span: Span,
) {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
@ -2649,11 +2644,11 @@ impl<'a> Resolver<'a> {
};
let mut suggestion = None;
match directive.subclass {
ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => {
match import.kind {
ImportKind::Single { type_ns_only: true, .. } => {
suggestion = Some(format!("self as {}", suggested_name))
}
ImportDirectiveSubclass::SingleImport { source, .. } => {
ImportKind::Single { source, .. } => {
if let Some(pos) =
source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize)
{
@ -2669,7 +2664,7 @@ impl<'a> Resolver<'a> {
}
}
}
ImportDirectiveSubclass::ExternCrate { source, target, .. } => {
ImportKind::ExternCrate { source, target, .. } => {
suggestion = Some(format!(
"extern crate {} as {};",
source.unwrap_or(target.name),
@ -2711,27 +2706,27 @@ impl<'a> Resolver<'a> {
/// If the nested use contains only one import then the suggestion will remove the entire
/// line.
///
/// It is expected that the directive provided is a nested import - this isn't checked by the
/// It is expected that the provided import is nested - this isn't checked by the
/// function. If this invariant is not upheld, this function's behaviour will be unexpected
/// as characters expected by span manipulations won't be present.
fn add_suggestion_for_duplicate_nested_use(
&self,
err: &mut DiagnosticBuilder<'_>,
directive: &ImportDirective<'_>,
import: &Import<'_>,
binding_span: Span,
) {
assert!(directive.is_nested());
assert!(import.is_nested());
let message = "remove unnecessary import";
// Two examples will be used to illustrate the span manipulations we're doing:
//
// - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
// `a` and `directive.use_span` is `issue_52891::{d, a, e};`.
// `a` and `import.use_span` is `issue_52891::{d, a, e};`.
// - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
// `a` and `directive.use_span` is `issue_52891::{d, e, a};`.
// `a` and `import.use_span` is `issue_52891::{d, e, a};`.
let (found_closing_brace, span) =
find_span_of_binding_until_next_binding(self.session, binding_span, directive.use_span);
find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span);
// If there was a closing brace then identify the span to remove any trailing commas from
// previous imports.
@ -2747,7 +2742,7 @@ impl<'a> Resolver<'a> {
// Remove the entire line if we cannot extend the span back, this indicates a
// `issue_52891::{self}` case.
err.span_suggestion(
directive.use_span_with_attributes,
import.use_span_with_attributes,
message,
String::new(),
Applicability::MaybeIncorrect,

View File

@ -4,7 +4,7 @@
#![warn(macro_use_extern_crate, unused)]
#[macro_use] //~ WARN should be replaced at use sites with a `use` statement
#[macro_use] //~ WARN should be replaced at use sites with a `use` item
extern crate macro_use_warned_against;
#[macro_use] //~ WARN unused `#[macro_use]`
extern crate macro_use_warned_against2;

View File

@ -1,4 +1,4 @@
warning: deprecated `#[macro_use]` directive used to import macros should be replaced at use sites with a `use` statement to import the macro instead
warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead
--> $DIR/macro-use-warned-against.rs:7:1
|
LL | #[macro_use]