1
Fork 0

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

View file

@ -3,7 +3,7 @@
// //
// Although this is mostly a lint pass, it lives in here because it depends on // 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 // 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 // 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. // 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 // - `check_crate` finally emits the diagnostics based on the data generated
// in the last step // in the last step
use crate::imports::ImportDirectiveSubclass; use crate::imports::ImportKind;
use crate::Resolver; use crate::Resolver;
use rustc::{lint, ty}; use rustc::{lint, ty};
@ -58,7 +58,7 @@ struct UnusedImportCheckVisitor<'a, 'b> {
} }
impl<'a, 'b> 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. // used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId) { fn check_import(&mut self, id: ast::NodeId) {
let mut used = false; let mut used = false;
@ -223,33 +223,33 @@ fn calc_unused_spans(
impl Resolver<'_> { impl Resolver<'_> {
crate fn check_unused(&mut self, krate: &ast::Crate) { crate fn check_unused(&mut self, krate: &ast::Crate) {
for directive in self.potentially_unused_imports.iter() { for import in self.potentially_unused_imports.iter() {
match directive.subclass { match import.kind {
_ if directive.used.get() _ if import.used.get()
|| directive.vis.get() == ty::Visibility::Public || import.vis.get() == ty::Visibility::Public
|| directive.span.is_dummy() => || import.span.is_dummy() =>
{ {
if let ImportDirectiveSubclass::MacroUse = directive.subclass { if let ImportKind::MacroUse = import.kind {
if !directive.span.is_dummy() { if !import.span.is_dummy() {
self.lint_buffer.buffer_lint( self.lint_buffer.buffer_lint(
lint::builtin::MACRO_USE_EXTERN_CRATE, lint::builtin::MACRO_USE_EXTERN_CRATE,
directive.id, import.id,
directive.span, import.span,
"deprecated `#[macro_use]` directive used to \ "deprecated `#[macro_use]` attribute used to \
import macros should be replaced at use sites \ 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", instead",
); );
} }
} }
} }
ImportDirectiveSubclass::ExternCrate { .. } => { ImportKind::ExternCrate { .. } => {
self.maybe_unused_extern_crates.push((directive.id, directive.span)); self.maybe_unused_extern_crates.push((import.id, import.span));
} }
ImportDirectiveSubclass::MacroUse => { ImportKind::MacroUse => {
let lint = lint::builtin::UNUSED_IMPORTS; let lint = lint::builtin::UNUSED_IMPORTS;
let msg = "unused `#[macro_use]` import"; 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::symbol::{kw, Symbol};
use rustc_span::{BytePos, MultiSpan, Span}; 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::path_names_to_string;
use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind};
use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; 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( pub(crate) fn check_for_module_export_macro(
&mut self, &mut self,
directive: &'b ImportDirective<'b>, import: &'b Import<'b>,
module: ModuleOrUniformRoot<'b>, module: ModuleOrUniformRoot<'b>,
ident: Ident, ident: Ident,
) -> Option<(Option<Suggestion>, Vec<String>)> { ) -> Option<(Option<Suggestion>, Vec<String>)> {
@ -1150,28 +1150,26 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let binding = resolution.borrow().binding()?; let binding = resolution.borrow().binding()?;
if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
let module_name = crate_module.kind.name().unwrap(); let module_name = crate_module.kind.name().unwrap();
let import = match directive.subclass { let import_snippet = match import.kind {
ImportDirectiveSubclass::SingleImport { source, target, .. } ImportKind::Single { source, target, .. } if source != target => {
if source != target =>
{
format!("{} as {}", source, target) format!("{} as {}", source, target)
} }
_ => format!("{}", ident), _ => format!("{}", ident),
}; };
let mut corrections: Vec<(Span, String)> = Vec::new(); 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 // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
// intermediate segments. // intermediate segments.
corrections.push((directive.span, format!("{}::{}", module_name, import))); corrections.push((import.span, format!("{}::{}", module_name, import_snippet)));
} else { } else {
// Find the binding span (and any trailing commas and spaces). // Find the binding span (and any trailing commas and spaces).
// ie. `use a::b::{c, d, e};` // ie. `use a::b::{c, d, e};`
// ^^^ // ^^^
let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
self.r.session, self.r.session,
directive.span, import.span,
directive.use_span, import.use_span,
); );
debug!( debug!(
"check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", "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( let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
self.r.session, self.r.session,
module_name, module_name,
directive.use_span, import.use_span,
); );
debug!( debug!(
"check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
@ -1224,11 +1222,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
start_point, start_point,
if has_nested { if has_nested {
// In this case, `start_snippet` must equal '{'. // In this case, `start_snippet` must equal '{'.
format!("{}{}, ", start_snippet, import) format!("{}{}, ", start_snippet, import_snippet)
} else { } else {
// In this case, add a `{`, then the moved import, then whatever // In this case, add a `{`, then the moved import, then whatever
// was there before. // 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. //! A bunch of methods and structures more or less related to resolving imports.
use ImportDirectiveSubclass::*;
use crate::diagnostics::Suggestion; use crate::diagnostics::Suggestion;
use crate::Determinacy::{self, *}; use crate::Determinacy::{self, *};
use crate::Namespace::{self, MacroNS, TypeNS}; use crate::Namespace::{self, MacroNS, TypeNS};
@ -36,10 +34,10 @@ use std::{mem, ptr};
type Res = def::Res<NodeId>; type Res = def::Res<NodeId>;
/// Contains data for specific types of import directives. /// Contains data for specific kinds of imports.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum ImportDirectiveSubclass<'a> { pub enum ImportKind<'a> {
SingleImport { Single {
/// `source` in `use prefix::source as target`. /// `source` in `use prefix::source as target`.
source: Ident, source: Ident,
/// `target` in `use prefix::source as target`. /// `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};` /// Did this import result from a nested import? ie. `use foo::{bar, baz};`
nested: bool, nested: bool,
}, },
GlobImport { Glob {
is_prelude: bool, is_prelude: bool,
max_vis: Cell<ty::Visibility>, // The visibility of the greatest re-export. 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. // 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, MacroUse,
} }
/// One import directive. /// One import.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
crate struct ImportDirective<'a> { crate struct Import<'a> {
/// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. 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: /// this id is the ID of the leaf tree. For example:
/// ///
/// ```ignore (pacify the mercilous tidy) /// ```ignore (pacify the mercilous tidy)
/// use foo::bar::{a, b} /// 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. /// for `a` in this field.
pub id: NodeId, pub id: NodeId,
@ -107,22 +107,21 @@ crate struct ImportDirective<'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 subclass: ImportDirectiveSubclass<'a>,
pub vis: Cell<ty::Visibility>, pub vis: Cell<ty::Visibility>,
pub used: Cell<bool>, pub used: Cell<bool>,
} }
impl<'a> ImportDirective<'a> { impl<'a> Import<'a> {
pub fn is_glob(&self) -> bool { pub fn is_glob(&self) -> bool {
match self.subclass { match self.kind {
ImportDirectiveSubclass::GlobImport { .. } => true, ImportKind::Glob { .. } => true,
_ => false, _ => false,
} }
} }
pub fn is_nested(&self) -> bool { pub fn is_nested(&self) -> bool {
match self.subclass { match self.kind {
ImportDirectiveSubclass::SingleImport { nested, .. } => nested, ImportKind::Single { nested, .. } => nested,
_ => false, _ => false,
} }
} }
@ -136,8 +135,8 @@ impl<'a> ImportDirective<'a> {
/// Records information about the resolution of a name in a namespace of a module. /// Records information about the resolution of a name in a namespace of a module.
pub struct NameResolution<'a> { pub struct NameResolution<'a> {
/// Single imports that may define the name in the namespace. /// Single imports that may define the name in the namespace.
/// Import directives are arena-allocated, so it's ok to use pointers as keys. /// Imports are arena-allocated, so it's ok to use pointers as keys.
single_imports: FxHashSet<PtrKey<'a, ImportDirective<'a>>>, single_imports: FxHashSet<PtrKey<'a, Import<'a>>>,
/// The least shadowable known binding for this name, or None if there are no known bindings. /// The least shadowable known binding for this name, or None if there are no known bindings.
pub binding: Option<&'a NameBinding<'a>>, pub binding: Option<&'a NameBinding<'a>>,
shadowed_glob: 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>) { crate fn add_single_import(&mut self, import: &'a Import<'a>) {
self.single_imports.insert(PtrKey(directive)); self.single_imports.insert(PtrKey(import));
} }
} }
@ -348,8 +347,8 @@ impl<'a> Resolver<'a> {
single_import.imported_module.get(), single_import.imported_module.get(),
return Err((Undetermined, Weak::No)) return Err((Undetermined, Weak::No))
); );
let ident = match single_import.subclass { let ident = match single_import.kind {
SingleImport { source, .. } => source, ImportKind::Single { source, .. } => source,
_ => unreachable!(), _ => unreachable!(),
}; };
match self.resolve_ident_in_module( match self.resolve_ident_in_module(
@ -451,34 +450,34 @@ impl<'a> Resolver<'a> {
Err((Determined, Weak::No)) Err((Determined, Weak::No))
} }
// Given a binding and an import directive that resolves to it, // Given a binding and an import that resolves to it,
// return the corresponding binding defined by the import directive. // return the corresponding binding defined by the import.
crate fn import( crate fn import(
&self, &self,
binding: &'a NameBinding<'a>, binding: &'a NameBinding<'a>,
directive: &'a ImportDirective<'a>, import: &'a Import<'a>,
) -> &'a NameBinding<'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` // 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 { } else {
binding.pseudo_vis() binding.pseudo_vis()
}; };
if let GlobImport { ref max_vis, .. } = directive.subclass { if let ImportKind::Glob { ref max_vis, .. } = import.kind {
if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) { if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) {
max_vis.set(vis) max_vis.set(vis)
} }
} }
self.arenas.alloc_name_binding(NameBinding { 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, ambiguity: None,
span: directive.span, span: import.span,
vis, 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. // 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 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(Some(def)) => self.macro_def_scope(def),
Some(None) => directive.parent_scope.module, Some(None) => import.parent_scope.module,
None => continue, None => continue,
}; };
if self.is_accessible_from(binding.vis, scope) { 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 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 // Define a "dummy" resolution containing a Res::Err as a placeholder for a
// failed resolution // failed resolution
fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { fn import_dummy_binding(&mut self, import: &'a Import<'a>) {
if let SingleImport { target, .. } = directive.subclass { if let ImportKind::Single { target, .. } = import.kind {
let dummy_binding = self.dummy_binding; 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| { self.per_ns(|this, ns| {
let key = this.new_key(target, 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. // Consider erroneous imports used to avoid duplicate diagnostics.
this.record_use(target, ns, dummy_binding, false); 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))) .chain(indeterminate_imports.into_iter().map(|i| (true, i)))
{ {
if let Some(err) = self.finalize_import(import) { 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 { if source.name == kw::SelfLower {
// Silence `unresolved import` error if E0429 is already emitted // Silence `unresolved import` error if E0429 is already emitted
if let Err(Determined) = source_bindings.value_ns.get() { 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) { if seen_spans.insert(err.span) {
let path = import_path_to_string( let path = import_path_to_string(
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(), &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
&import.subclass, &import.kind,
err.span, err.span,
); );
errors.push((path, err)); errors.push((path, err));
@ -706,7 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
self.r.used_imports.insert((import.id, TypeNS)); self.r.used_imports.insert((import.id, TypeNS));
let path = import_path_to_string( let path = import_path_to_string(
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(), &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
&import.subclass, &import.kind,
import.span, import.span,
); );
let err = UnresolvedImportError { 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. /// Attempts to resolve the given import, returning true if its resolution is determined.
/// If successful, the resolved bindings are written into the module. /// 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!( debug!(
"(resolving import for module) resolving import `{}::...` in `{}`", "(resolving import for module) resolving import `{}::...` in `{}`",
Segment::names_to_string(&directive.module_path), Segment::names_to_string(&import.module_path),
module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()), 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 module
} else { } else {
// For better failure detection, pretend that the import will // For better failure detection, pretend that the import will
// not define any names while resolving its module path. // 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( let path_res = self.r.resolve_path(
&directive.module_path, &import.module_path,
None, None,
&directive.parent_scope, &import.parent_scope,
false, false,
directive.span, import.span,
directive.crate_lint(), import.crate_lint(),
); );
directive.vis.set(orig_vis); import.vis.set(orig_vis);
match path_res { match path_res {
PathResult::Module(module) => module, PathResult::Module(module) => module,
@ -797,23 +796,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
} }
}; };
directive.imported_module.set(Some(module)); import.imported_module.set(Some(module));
let (source, target, source_bindings, target_bindings, type_ns_only) = let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
match directive.subclass { ImportKind::Single {
SingleImport { source,
source, target,
target, ref source_bindings,
ref source_bindings, ref target_bindings,
ref target_bindings, type_ns_only,
type_ns_only, ..
.. } => (source, target, source_bindings, target_bindings, type_ns_only),
} => (source, target, source_bindings, target_bindings, type_ns_only), ImportKind::Glob { .. } => {
GlobImport { .. } => { self.resolve_glob_import(import);
self.resolve_glob_import(directive); return true;
return true; }
} _ => unreachable!(),
_ => unreachable!(), };
};
let mut indeterminate = false; let mut indeterminate = false;
self.r.per_ns(|this, ns| { self.r.per_ns(|this, ns| {
@ -821,23 +819,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
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 // For better failure detection, pretend that the import will
// not define any names while resolving its module path. // 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( let binding = this.resolve_ident_in_module(
module, module,
source, source,
ns, ns,
&directive.parent_scope, &import.parent_scope,
false, false,
directive.span, import.span,
); );
directive.vis.set(orig_vis); import.vis.set(orig_vis);
source_bindings[ns].set(binding); source_bindings[ns].set(binding);
} else { } else {
return; return;
}; };
let parent = directive.parent_scope.module; let parent = import.parent_scope.module;
match source_bindings[ns].get() { match source_bindings[ns].get() {
Err(Undetermined) => indeterminate = true, Err(Undetermined) => indeterminate = true,
// Don't update the resolution, because it was never added. // Don't update the resolution, because it was never added.
@ -845,20 +843,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
Err(Determined) => { Err(Determined) => {
let key = this.new_key(target, ns); let key = this.new_key(target, ns);
this.update_resolution(parent, key, |_, resolution| { this.update_resolution(parent, key, |_, resolution| {
resolution.single_imports.remove(&PtrKey(directive)); resolution.single_imports.remove(&PtrKey(import));
}); });
} }
Ok(binding) if !binding.is_importable() => { Ok(binding) if !binding.is_importable() => {
let msg = format!("`{}` is not directly importable", target); let msg = format!("`{}` is not directly importable", target);
struct_span_err!(this.session, directive.span, E0253, "{}", &msg) struct_span_err!(this.session, import.span, E0253, "{}", &msg)
.span_label(directive.span, "cannot be imported directly") .span_label(import.span, "cannot be imported directly")
.emit(); .emit();
// Do not import this illegal binding. Import a dummy binding and pretend // Do not import this illegal binding. Import a dummy binding and pretend
// everything is fine // everything is fine
this.import_dummy_binding(directive); this.import_dummy_binding(import);
} }
Ok(binding) => { Ok(binding) => {
let imported_binding = this.import(binding, directive); let imported_binding = this.import(binding, import);
target_bindings[ns].set(Some(imported_binding)); target_bindings[ns].set(Some(imported_binding));
this.define(parent, target, ns, 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 /// 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( fn finalize_import(&mut self, import: &'b Import<'b>) -> Option<UnresolvedImportError> {
&mut self, let orig_vis = import.vis.replace(ty::Visibility::Invisible);
directive: &'b ImportDirective<'b>,
) -> Option<UnresolvedImportError> {
let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len();
let path_res = self.r.resolve_path( let path_res = self.r.resolve_path(
&directive.module_path, &import.module_path,
None, None,
&directive.parent_scope, &import.parent_scope,
true, true,
directive.span, import.span,
directive.crate_lint(), import.crate_lint(),
); );
let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; 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 { if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res {
// Consider erroneous imports used to avoid duplicate diagnostics. // 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 { 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`.
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 { 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 { } else {
if self.r.privacy_errors.is_empty() { if self.r.privacy_errors.is_empty() {
let msg = "cannot determine resolution for the import"; let msg = "cannot determine resolution for the import";
let msg_note = "import resolution is stuck, try simplifying other imports"; 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 } => { PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => {
if no_ambiguity { if no_ambiguity {
assert!(directive.imported_module.get().is_none()); assert!(import.imported_module.get().is_none());
self.r self.r
.report_error(span, ResolutionError::FailedToResolve { label, suggestion }); .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 } => { PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => {
if no_ambiguity { if no_ambiguity {
assert!(directive.imported_module.get().is_none()); assert!(import.imported_module.get().is_none());
let err = match self.make_path_suggestion( let err = match self.make_path_suggestion(
span, span,
directive.module_path.clone(), import.module_path.clone(),
&directive.parent_scope, &import.parent_scope,
) { ) {
Some((suggestion, note)) => UnresolvedImportError { Some((suggestion, note)) => UnresolvedImportError {
span, span,
@ -949,7 +944,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
} }
PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => {
if no_ambiguity { if no_ambiguity {
assert!(directive.imported_module.get().is_none()); assert!(import.imported_module.get().is_none());
} }
// The error was already reported earlier. // The error was already reported earlier.
return None; return None;
@ -957,10 +952,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
}; };
let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
.subclass ImportKind::Single {
{
SingleImport {
source, source,
target, target,
ref source_bindings, ref source_bindings,
@ -968,25 +961,25 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
type_ns_only, type_ns_only,
.. ..
} => (source, target, source_bindings, target_bindings, type_ns_only), } => (source, target, source_bindings, target_bindings, type_ns_only),
GlobImport { is_prelude, ref max_vis } => { ImportKind::Glob { is_prelude, ref max_vis } => {
if directive.module_path.len() <= 1 { if import.module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it. // 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = directive.module_path.clone(); let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(Ident::invalid())); full_path.push(Segment::from_ident(Ident::invalid()));
self.r.lint_if_path_starts_with_module( self.r.lint_if_path_starts_with_module(
directive.crate_lint(), import.crate_lint(),
&full_path, &full_path,
directive.span, import.span,
None, None,
); );
} }
if let ModuleOrUniformRoot::Module(module) = module { 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. // Importing a module into itself is not allowed.
return Some(UnresolvedImportError { return Some(UnresolvedImportError {
span: directive.span, span: import.span,
label: Some(String::from("cannot glob-import a module into itself")), label: Some(String::from("cannot glob-import a module into itself")),
note: Vec::new(), note: Vec::new(),
suggestion: None, suggestion: None,
@ -995,15 +988,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
} }
if !is_prelude && if !is_prelude &&
max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. 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"; let msg = "glob import doesn't reexport anything because no candidate is public enough";
self.r.lint_buffer.buffer_lint( self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg);
UNUSED_IMPORTS,
directive.id,
directive.span,
msg,
);
} }
return None; return None;
} }
@ -1013,7 +1001,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut all_ns_err = true; let mut all_ns_err = true;
self.r.per_ns(|this, ns| { self.r.per_ns(|this, ns| {
if !type_ns_only || ns == TypeNS { 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 = let orig_blacklisted_binding =
mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get()); mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get());
let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true); let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true);
@ -1021,13 +1009,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
module, module,
ident, ident,
ns, ns,
&directive.parent_scope, &import.parent_scope,
true, true,
directive.span, import.span,
); );
this.last_import_segment = orig_last_import_segment; this.last_import_segment = orig_last_import_segment;
this.blacklisted_binding = orig_blacklisted_binding; this.blacklisted_binding = orig_blacklisted_binding;
directive.vis.set(orig_vis); import.vis.set(orig_vis);
match binding { match binding {
Ok(binding) => { Ok(binding) => {
@ -1044,7 +1032,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
ident, ident,
ns, ns,
target_binding, 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(); let res = binding.res();
if let Ok(initial_res) = initial_res { if let Ok(initial_res) = initial_res {
if res != initial_res && this.ambiguity_errors.is_empty() { 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 { } else {
if res != Res::Err if res != Res::Err
@ -1064,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let msg_note = let msg_note =
"import resolution is stuck, try simplifying other imports"; "import resolution is stuck, try simplifying other imports";
this.session this.session
.struct_span_err(directive.span, msg) .struct_span_err(import.span, msg)
.note(msg_note) .note(msg_note)
.emit(); .emit();
} }
@ -1090,9 +1078,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
module, module,
ident, ident,
ns, ns,
&directive.parent_scope, &import.parent_scope,
true, true,
directive.span, import.span,
); );
if binding.is_ok() { if binding.is_ok() {
all_ns_failed = false; all_ns_failed = false;
@ -1143,7 +1131,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}); });
let (suggestion, note) = 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), Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
_ => (lev_suggestion, Vec::new()), _ => (lev_suggestion, Vec::new()),
}; };
@ -1169,14 +1157,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}; };
Some(UnresolvedImportError { Some(UnresolvedImportError {
span: directive.span, span: import.span,
label: Some(label), label: Some(label),
note, note,
suggestion, suggestion,
}) })
} else { } else {
// `resolve_ident_in_module` reported a privacy error. // `resolve_ident_in_module` reported a privacy error.
self.r.import_dummy_binding(directive); self.r.import_dummy_binding(import);
None None
}; };
} }
@ -1185,7 +1173,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
let mut any_successful_reexport = false; let mut any_successful_reexport = false;
self.r.per_ns(|this, ns| { self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() { 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) { if !binding.pseudo_vis().is_at_least(vis, &*this) {
reexport_error = Some((ns, binding)); reexport_error = Some((ns, binding));
} else { } else {
@ -1206,42 +1194,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
); );
self.r.lint_buffer.buffer_lint( self.r.lint_buffer.buffer_lint(
PUB_USE_OF_PRIVATE_EXTERN_CRATE, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
directive.id, import.id,
directive.span, import.span,
&msg, &msg,
); );
} else if ns == TypeNS { } else if ns == TypeNS {
struct_span_err!( struct_span_err!(
self.r.session, self.r.session,
directive.span, import.span,
E0365, E0365,
"`{}` is private, and cannot be re-exported", "`{}` is private, and cannot be re-exported",
ident 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)) .note(&format!("consider declaring type or module `{}` with `pub`", ident))
.emit(); .emit();
} else { } else {
let msg = format!("`{}` is private, and cannot be re-exported", ident); let msg = format!("`{}` is private, and cannot be re-exported", ident);
let note_msg = let note_msg =
format!("consider marking `{}` as `pub` in the imported module", ident,); format!("consider marking `{}` as `pub` in the imported module", ident,);
struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg) struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
.span_note(directive.span, &note_msg) .span_note(import.span, &note_msg)
.emit(); .emit();
} }
} }
if directive.module_path.len() <= 1 { if import.module_path.len() <= 1 {
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
// 2 segments, so the `resolve_path` above won't trigger it. // 2 segments, so the `resolve_path` above won't trigger it.
let mut full_path = directive.module_path.clone(); let mut full_path = import.module_path.clone();
full_path.push(Segment::from_ident(ident)); full_path.push(Segment::from_ident(ident));
self.r.per_ns(|this, ns| { self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() { if let Ok(binding) = source_bindings[ns].get() {
this.lint_if_path_starts_with_module( this.lint_if_path_starts_with_module(
directive.crate_lint(), import.crate_lint(),
&full_path, &full_path,
directive.span, import.span,
Some(binding), Some(binding),
); );
} }
@ -1253,17 +1241,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
// purposes it's good enough to just favor one over the other. // purposes it's good enough to just favor one over the other.
self.r.per_ns(|this, ns| { self.r.per_ns(|this, ns| {
if let Ok(binding) = source_bindings[ns].get() { 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( self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target);
ident,
directive,
source_bindings,
target_bindings,
target,
);
debug!("(resolving single import) successfully resolved import"); debug!("(resolving single import) successfully resolved import");
None None
@ -1272,19 +1254,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
fn check_for_redundant_imports( fn check_for_redundant_imports(
&mut self, &mut self,
ident: Ident, ident: Ident,
directive: &'b ImportDirective<'b>, import: &'b Import<'b>,
source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>, source_bindings: &PerNS<Cell<Result<&'b NameBinding<'b>, Determinacy>>>,
target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>, target_bindings: &PerNS<Cell<Option<&'b NameBinding<'b>>>>,
target: Ident, target: Ident,
) { ) {
// Skip if the import was produced by a macro. // Skip if the import was produced by a macro.
if directive.parent_scope.expansion != ExpnId::root() { if import.parent_scope.expansion != ExpnId::root() {
return; return;
} }
// Skip if we are inside a named module (in contrast to an anonymous // Skip if we are inside a named module (in contrast to an anonymous
// module defined by a block). // module defined by a block).
if let ModuleKind::Def(..) = directive.parent_scope.module.kind { if let ModuleKind::Def(..) = import.parent_scope.module.kind {
return; return;
} }
@ -1304,10 +1286,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
match this.early_resolve_ident_in_lexical_scope( match this.early_resolve_ident_in_lexical_scope(
target, target,
ScopeSet::All(ns, false), ScopeSet::All(ns, false),
&directive.parent_scope, &import.parent_scope,
false, false,
false, false,
directive.span, import.span,
) { ) {
Ok(other_binding) => { Ok(other_binding) => {
is_redundant[ns] = Some( is_redundant[ns] = Some(
@ -1329,35 +1311,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
redundant_spans.dedup(); redundant_spans.dedup();
self.r.lint_buffer.buffer_lint_with_diagnostic( self.r.lint_buffer.buffer_lint_with_diagnostic(
UNUSED_IMPORTS, UNUSED_IMPORTS,
directive.id, import.id,
directive.span, import.span,
&format!("the item `{}` is imported redundantly", ident), &format!("the item `{}` is imported redundantly", ident),
BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident), BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident),
); );
} }
} }
fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { fn resolve_glob_import(&mut self, import: &'b Import<'b>) {
let module = match directive.imported_module.get().unwrap() { let module = match import.imported_module.get().unwrap() {
ModuleOrUniformRoot::Module(module) => module, 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; return;
} }
}; };
if module.is_trait() { 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; return;
} else if module.def_id() == directive.parent_scope.module.def_id() { } else if module.def_id() == import.parent_scope.module.def_id() {
return; 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); self.r.prelude = Some(module);
return; return;
} }
// Add to module's glob_importers // 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`, // Ensure that `resolutions` isn't borrowed during `try_define`,
// since it might get updated via a glob cycle. // since it might get updated via a glob cycle.
@ -1371,19 +1353,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
for (mut key, binding) in bindings { 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(Some(def)) => self.r.macro_def_scope(def),
Some(None) => directive.parent_scope.module, Some(None) => import.parent_scope.module,
None => continue, None => continue,
}; };
if self.r.is_accessible_from(binding.pseudo_vis(), scope) { if self.r.is_accessible_from(binding.pseudo_vis(), scope) {
let imported_binding = self.r.import(binding, directive); let imported_binding = self.r.import(binding, import);
let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding); let _ = self.r.try_define(import.parent_scope.module, key, imported_binding);
} }
} }
// Record the destination of this import // 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, // 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 if ns == TypeNS
&& orig_binding.is_variant() && orig_binding.is_variant()
&& !orig_binding.vis.is_at_least(binding.vis, &*this) && !orig_binding.vis.is_at_least(binding.vis, &*this)
{ {
let msg = match directive.subclass { let msg = match import.kind {
ImportDirectiveSubclass::SingleImport { .. } => { ImportKind::Single { .. } => {
format!("variant `{}` is private and cannot be re-exported", ident) format!("variant `{}` is private and cannot be re-exported", ident)
} }
ImportDirectiveSubclass::GlobImport { .. } => { ImportKind::Glob { .. } => {
let msg = "enum is private and its variants \ let msg = "enum is private and its variants \
cannot be re-exported" cannot be re-exported"
.to_owned(); .to_owned();
@ -1432,18 +1414,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
} }
msg 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 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, Some(ModuleOrUniformRoot::Module(module)) => module,
_ => bug!("module should exist"), _ => bug!("module should exist"),
}; };
let parent_module = imported_module.parent.expect("parent should exist"); let parent_module = imported_module.parent.expect("parent should exist");
let resolutions = this.resolutions(parent_module).borrow(); let resolutions = this.resolutions(parent_module).borrow();
let enum_path_segment_index = directive.module_path.len() - 1; let enum_path_segment_index = import.module_path.len() - 1;
let enum_ident = directive.module_path[enum_path_segment_index].ident; let enum_ident = import.module_path[enum_path_segment_index].ident;
let key = this.new_key(enum_ident, TypeNS); let key = this.new_key(enum_ident, TypeNS);
let enum_resolution = resolutions.get(&key).expect("resolution should exist"); 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( fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {
names: &[Ident],
subclass: &ImportDirectiveSubclass<'_>,
span: Span,
) -> String {
let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot); let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);
let global = !names.is_empty() && names[0].name == kw::PathRoot; let global = !names.is_empty() && names[0].name == kw::PathRoot;
if let Some(pos) = pos { if let Some(pos) = pos {
@ -1494,22 +1472,22 @@ fn import_path_to_string(
} else { } else {
let names = if global { &names[1..] } else { names }; let names = if global { &names[1..] } else { names };
if names.is_empty() { if names.is_empty() {
import_directive_subclass_to_string(subclass) import_kind_to_string(import_kind)
} else { } else {
format!( format!(
"{}::{}", "{}::{}",
names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()), 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 { fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
match *subclass { match import_kind {
SingleImport { source, .. } => source.to_string(), ImportKind::Single { source, .. } => source.to_string(),
GlobImport { .. } => "*".to_string(), ImportKind::Glob { .. } => "*".to_string(),
ExternCrate { .. } => "<extern crate>".to_string(), ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
MacroUse => "#[macro_use]".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, trait_name: Ident,
) -> SmallVec<[NodeId; 1]> { ) -> SmallVec<[NodeId; 1]> {
let mut import_ids = smallvec![]; let mut import_ids = smallvec![];
while let NameBindingKind::Import { directive, binding, .. } = kind { while let NameBindingKind::Import { import, binding, .. } = kind {
self.r.maybe_unused_trait_imports.insert(directive.id); self.r.maybe_unused_trait_imports.insert(import.id);
self.r.add_to_glob_map(&directive, trait_name); self.r.add_to_glob_map(&import, trait_name);
import_ids.push(directive.id); import_ids.push(import.id);
kind = &binding.kind; kind = &binding.kind;
} }
import_ids 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::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding};
use diagnostics::{ImportSuggestion, Suggestion}; use diagnostics::{ImportSuggestion, Suggestion};
use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameResolution}; use imports::{Import, ImportKind, ImportResolver, NameResolution};
use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use late::{HasGenericParams, PathSource, Rib, RibKind::*};
use macros::{LegacyBinding, LegacyScope}; use macros::{LegacyBinding, LegacyScope};
@ -456,8 +456,8 @@ pub struct ModuleData<'a> {
no_implicit_prelude: bool, no_implicit_prelude: bool,
glob_importers: RefCell<Vec<&'a ImportDirective<'a>>>, glob_importers: RefCell<Vec<&'a Import<'a>>>,
globs: RefCell<Vec<&'a ImportDirective<'a>>>, globs: RefCell<Vec<&'a Import<'a>>>,
// Used to memoize the traits in this module for faster searches through all traits in scope. // Used to memoize the traits in this module for faster searches through all traits in scope.
traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>, traits: RefCell<Option<Box<[(Ident, &'a NameBinding<'a>)]>>>,
@ -584,7 +584,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> {
enum NameBindingKind<'a> { enum NameBindingKind<'a> {
Res(Res, /* is_macro_export */ bool), Res(Res, /* is_macro_export */ bool),
Module(Module<'a>), 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> { impl<'a> NameBindingKind<'a> {
@ -713,8 +713,7 @@ impl<'a> NameBinding<'a> {
fn is_extern_crate(&self) -> bool { fn is_extern_crate(&self) -> bool {
match self.kind { match self.kind {
NameBindingKind::Import { NameBindingKind::Import {
directive: import: &Import { kind: ImportKind::ExternCrate { .. }, .. },
&ImportDirective { subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. },
.. ..
} => true, } => true,
NameBindingKind::Module(&ModuleData { NameBindingKind::Module(&ModuleData {
@ -734,7 +733,7 @@ impl<'a> NameBinding<'a> {
fn is_glob_import(&self) -> bool { fn is_glob_import(&self) -> bool {
match self.kind { match self.kind {
NameBindingKind::Import { directive, .. } => directive.is_glob(), NameBindingKind::Import { import, .. } => import.is_glob(),
_ => false, _ => false,
} }
} }
@ -839,10 +838,10 @@ pub struct Resolver<'a> {
field_names: FxHashMap<DefId, Vec<Spanned<Name>>>, field_names: FxHashMap<DefId, Vec<Spanned<Name>>>,
/// All imports known to succeed or fail. /// All imports known to succeed or fail.
determined_imports: Vec<&'a ImportDirective<'a>>, determined_imports: Vec<&'a Import<'a>>,
/// All non-determined imports. /// 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. /// FIXME: Refactor things so that these fields are passed through arguments and not resolver.
/// We are resolving a last import segment during import validation. /// 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". /// Avoid duplicated errors for "name already defined".
name_already_seen: FxHashMap<Name, Span>, 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, /// Table for mapping struct IDs into struct constructor IDs,
/// it's not used during normal resolution, only for better error reporting. /// 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>>, modules: arena::TypedArena<ModuleData<'a>>,
local_modules: RefCell<Vec<Module<'a>>>, local_modules: RefCell<Vec<Module<'a>>>,
name_bindings: arena::TypedArena<NameBinding<'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>>>, name_resolutions: arena::TypedArena<RefCell<NameResolution<'a>>>,
legacy_bindings: arena::TypedArena<LegacyBinding<'a>>, legacy_bindings: arena::TypedArena<LegacyBinding<'a>>,
ast_paths: arena::TypedArena<ast::Path>, 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> { fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> {
self.name_bindings.alloc(name_binding) self.name_bindings.alloc(name_binding)
} }
fn alloc_import_directive( fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> {
&'a self, self.imports.alloc(import)
import_directive: ImportDirective<'a>,
) -> &'a ImportDirective<'_> {
self.import_directives.alloc(import_directive)
} }
fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> { fn alloc_name_resolution(&'a self) -> &'a RefCell<NameResolution<'a>> {
self.name_resolutions.alloc(Default::default()) self.name_resolutions.alloc(Default::default())
@ -1410,7 +1406,7 @@ impl<'a> Resolver<'a> {
misc2: AmbiguityErrorMisc::None, 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, // 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. // but not introduce it, as used if they are accessed from lexical scope.
if is_lexical_scope { if is_lexical_scope {
@ -1423,17 +1419,17 @@ impl<'a> Resolver<'a> {
} }
} }
used.set(true); used.set(true);
directive.used.set(true); import.used.set(true);
self.used_imports.insert((directive.id, ns)); self.used_imports.insert((import.id, ns));
self.add_to_glob_map(&directive, ident); self.add_to_glob_map(&import, ident);
self.record_use(ident, ns, binding, false); self.record_use(ident, ns, binding, false);
} }
} }
#[inline] #[inline]
fn add_to_glob_map(&mut self, directive: &ImportDirective<'_>, ident: Ident) { fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) {
if directive.is_glob() { if import.is_glob() {
self.glob_map.entry(directive.id).or_default().insert(ident.name); 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 // `ExternCrate` (also used for `crate::...`) then no need to issue a
// warning, this looks all good! // warning, this looks all good!
if let Some(binding) = second_binding { if let Some(binding) = second_binding {
if let NameBindingKind::Import { directive: d, .. } = binding.kind { if let NameBindingKind::Import { import, .. } = binding.kind {
// Careful: we still want to rewrite paths from // Careful: we still want to rewrite paths from renamed extern crates.
// renamed extern crates. if let ImportKind::ExternCrate { source: None, .. } = import.kind {
if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass {
return; return;
} }
} }
@ -2564,10 +2559,10 @@ impl<'a> Resolver<'a> {
// See https://github.com/rust-lang/rust/issues/32354 // See https://github.com/rust-lang/rust/issues/32354
use NameBindingKind::Import; 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 // If there are two imports where one or both have attributes then prefer removing the
// import without attributes. // import without attributes.
(Import { directive: new, .. }, Import { directive: old, .. }) (Import { import: new, .. }, Import { import: old, .. })
if { if {
!new_binding.span.is_dummy() !new_binding.span.is_dummy()
&& !old_binding.span.is_dummy() && !old_binding.span.is_dummy()
@ -2581,11 +2576,11 @@ impl<'a> Resolver<'a> {
} }
} }
// Otherwise prioritize the new binding. // Otherwise prioritize the new binding.
(Import { directive, .. }, other) if !new_binding.span.is_dummy() => { (Import { import, .. }, other) if !new_binding.span.is_dummy() => {
Some((directive, new_binding.span, other.is_import())) Some((import, new_binding.span, other.is_import()))
} }
(other, Import { directive, .. }) if !old_binding.span.is_dummy() => { (other, Import { import, .. }) if !old_binding.span.is_dummy() => {
Some((directive, old_binding.span, other.is_import())) Some((import, old_binding.span, other.is_import()))
} }
_ => None, _ => None,
}; };
@ -2602,22 +2597,22 @@ impl<'a> Resolver<'a> {
&& !has_dummy_span && !has_dummy_span
&& ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item); && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
match directive { match import {
Some((directive, span, true)) if should_remove_import && directive.is_nested() => { Some((import, span, true)) if should_remove_import && import.is_nested() => {
self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span) 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 // Simple case - remove the entire import. Due to the above match arm, this can
// only be a single use so just remove it entirely. // only be a single use so just remove it entirely.
err.tool_only_span_suggestion( err.tool_only_span_suggestion(
directive.use_span_with_attributes, import.use_span_with_attributes,
"remove unnecessary import", "remove unnecessary import",
String::new(), String::new(),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
); );
} }
Some((directive, span, _)) => { Some((import, span, _)) => {
self.add_suggestion_for_rename_of_use(&mut err, name, directive, span) self.add_suggestion_for_rename_of_use(&mut err, name, import, span)
} }
_ => {} _ => {}
} }
@ -2639,7 +2634,7 @@ impl<'a> Resolver<'a> {
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
name: Name, name: Name,
directive: &ImportDirective<'_>, import: &Import<'_>,
binding_span: Span, binding_span: Span,
) { ) {
let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
@ -2649,11 +2644,11 @@ impl<'a> Resolver<'a> {
}; };
let mut suggestion = None; let mut suggestion = None;
match directive.subclass { match import.kind {
ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => { ImportKind::Single { type_ns_only: true, .. } => {
suggestion = Some(format!("self as {}", suggested_name)) suggestion = Some(format!("self as {}", suggested_name))
} }
ImportDirectiveSubclass::SingleImport { source, .. } => { ImportKind::Single { source, .. } => {
if let Some(pos) = if let Some(pos) =
source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize) 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!( suggestion = Some(format!(
"extern crate {} as {};", "extern crate {} as {};",
source.unwrap_or(target.name), 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 /// If the nested use contains only one import then the suggestion will remove the entire
/// line. /// 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 /// function. If this invariant is not upheld, this function's behaviour will be unexpected
/// as characters expected by span manipulations won't be present. /// as characters expected by span manipulations won't be present.
fn add_suggestion_for_duplicate_nested_use( fn add_suggestion_for_duplicate_nested_use(
&self, &self,
err: &mut DiagnosticBuilder<'_>, err: &mut DiagnosticBuilder<'_>,
directive: &ImportDirective<'_>, import: &Import<'_>,
binding_span: Span, binding_span: Span,
) { ) {
assert!(directive.is_nested()); assert!(import.is_nested());
let message = "remove unnecessary import"; let message = "remove unnecessary import";
// Two examples will be used to illustrate the span manipulations we're doing: // 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 // - 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 // - 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) = 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 // If there was a closing brace then identify the span to remove any trailing commas from
// previous imports. // previous imports.
@ -2747,7 +2742,7 @@ impl<'a> Resolver<'a> {
// Remove the entire line if we cannot extend the span back, this indicates a // Remove the entire line if we cannot extend the span back, this indicates a
// `issue_52891::{self}` case. // `issue_52891::{self}` case.
err.span_suggestion( err.span_suggestion(
directive.use_span_with_attributes, import.use_span_with_attributes,
message, message,
String::new(), String::new(),
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,

View file

@ -4,7 +4,7 @@
#![warn(macro_use_extern_crate, unused)] #![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; extern crate macro_use_warned_against;
#[macro_use] //~ WARN unused `#[macro_use]` #[macro_use] //~ WARN unused `#[macro_use]`
extern crate macro_use_warned_against2; 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 --> $DIR/macro-use-warned-against.rs:7:1
| |
LL | #[macro_use] LL | #[macro_use]