mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
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:
commit
17b77913f9
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -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)
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -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, ¬e_msg)
|
||||
struct_span_err!(self.r.session, import.span, E0364, "{}", &msg)
|
||||
.span_note(import.span, ¬e_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(),
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user