2019-08-13 02:46:42 +03:00
|
|
|
//! A bunch of methods and structures more or less related to resolving imports.
|
|
|
|
|
2024-02-29 16:32:35 +11:00
|
|
|
use crate::diagnostics::{import_candidates, DiagMode, Suggestion};
|
2023-06-21 20:51:24 +01:00
|
|
|
use crate::errors::{
|
|
|
|
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
|
|
|
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
|
|
|
|
ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
|
|
|
|
ItemsInTraitsAreNotImportable,
|
|
|
|
};
|
2019-12-24 17:38:22 -05:00
|
|
|
use crate::Determinacy::{self, *};
|
2023-12-01 10:25:40 +08:00
|
|
|
use crate::Namespace::*;
|
2022-10-10 11:14:32 +08:00
|
|
|
use crate::{module_to_string, names_to_string, ImportSuggestion};
|
2023-11-10 10:11:24 +08:00
|
|
|
use crate::{AmbiguityKind, BindingKey, ResolutionError, Resolver, Segment};
|
2022-03-26 20:59:09 +01:00
|
|
|
use crate::{Finalize, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet};
|
2023-11-10 10:11:24 +08:00
|
|
|
use crate::{NameBinding, NameBindingData, NameBindingKind, PathResult, Used};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast::NodeId;
|
2019-12-24 05:02:53 +01:00
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
2022-02-04 14:26:29 +11:00
|
|
|
use rustc_data_structures::intern::Interned;
|
Stop using `String` for error codes.
Error codes are integers, but `String` is used everywhere to represent
them. Gross!
This commit introduces `ErrCode`, an integral newtype for error codes,
replacing `String`. It also introduces a constant for every error code,
e.g. `E0123`, and removes the `error_code!` macro. The constants are
imported wherever used with `use rustc_errors::codes::*`.
With the old code, we have three different ways to specify an error code
at a use point:
```
error_code!(E0123) // macro call
struct_span_code_err!(dcx, span, E0123, "msg"); // bare ident arg to macro call
\#[diag(name, code = "E0123")] // string
struct Diag;
```
With the new code, they all use the `E0123` constant.
```
E0123 // constant
struct_span_code_err!(dcx, span, E0123, "msg"); // constant
\#[diag(name, code = E0123)] // constant
struct Diag;
```
The commit also changes the structure of the error code definitions:
- `rustc_error_codes` now just defines a higher-order macro listing the
used error codes and nothing else.
- Because that's now the only thing in the `rustc_error_codes` crate, I
moved it into the `lib.rs` file and removed the `error_codes.rs` file.
- `rustc_errors` uses that macro to define everything, e.g. the error
code constants and the `DIAGNOSTIC_TABLES`. This is in its new
`codes.rs` file.
2024-01-14 10:57:07 +11:00
|
|
|
use rustc_errors::{codes::*, pluralize, struct_span_code_err, Applicability, MultiSpan};
|
2022-06-14 14:58:46 +09:00
|
|
|
use rustc_hir::def::{self, DefKind, PartialRes};
|
2021-12-21 11:24:43 +08:00
|
|
|
use rustc_middle::metadata::ModChild;
|
2023-03-22 17:57:39 +04:00
|
|
|
use rustc_middle::metadata::Reexport;
|
2021-01-06 18:07:47 +03:00
|
|
|
use rustc_middle::span_bug;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_middle::ty;
|
2023-03-20 03:11:28 +08:00
|
|
|
use rustc_session::lint::builtin::{
|
2023-05-09 07:15:46 +08:00
|
|
|
AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
|
|
|
UNUSED_IMPORTS,
|
2023-03-20 03:11:28 +08:00
|
|
|
};
|
2020-01-05 13:05:49 +01:00
|
|
|
use rustc_session::lint::BuiltinLintDiagnostics;
|
2023-02-19 04:03:56 +00:00
|
|
|
use rustc_span::edit_distance::find_best_match_for_name;
|
2021-06-25 20:43:04 +02:00
|
|
|
use rustc_span::hygiene::LocalExpnId;
|
2020-04-19 13:00:18 +02:00
|
|
|
use rustc_span::symbol::{kw, Ident, Symbol};
|
2022-03-24 02:03:04 +00:00
|
|
|
use rustc_span::Span;
|
2023-03-22 17:57:39 +04:00
|
|
|
use smallvec::SmallVec;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2019-08-16 01:18:14 +03:00
|
|
|
use std::cell::Cell;
|
2023-07-04 20:00:42 +03:00
|
|
|
use std::mem;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
type Res = def::Res<NodeId>;
|
2019-04-03 09:07:45 +02:00
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
/// Contains data for specific kinds of imports.
|
2022-08-15 18:29:43 +02:00
|
|
|
#[derive(Clone)]
|
2023-02-05 23:05:46 +04:00
|
|
|
pub(crate) enum ImportKind<'a> {
|
2020-03-07 18:49:13 +03:00
|
|
|
Single {
|
2018-12-01 22:14:37 +03:00
|
|
|
/// `source` in `use prefix::source as target`.
|
2016-11-29 02:07:12 +00:00
|
|
|
source: Ident,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// `target` in `use prefix::source as target`.
|
2018-11-30 21:16:21 +03:00
|
|
|
target: Ident,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// Bindings to which `source` refers to.
|
2023-07-04 17:28:57 +03:00
|
|
|
source_bindings: PerNS<Cell<Result<NameBinding<'a>, Determinacy>>>,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// Bindings introduced by `target`.
|
2023-07-04 17:28:57 +03:00
|
|
|
target_bindings: PerNS<Cell<Option<NameBinding<'a>>>>,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// `true` for `...::{self [as target]}` imports, `false` otherwise.
|
2016-12-12 03:35:48 +00:00
|
|
|
type_ns_only: bool,
|
2019-01-29 13:34:40 +01:00
|
|
|
/// Did this import result from a nested import? ie. `use foo::{bar, baz};`
|
|
|
|
nested: bool,
|
2022-10-30 13:35:31 +04:00
|
|
|
/// The ID of the `UseTree` that imported this `Import`.
|
|
|
|
///
|
|
|
|
/// In the case where the `Import` was expanded from a "nested" use tree,
|
|
|
|
/// this id is the ID of the leaf tree. For example:
|
|
|
|
///
|
|
|
|
/// ```ignore (pacify the merciless tidy)
|
|
|
|
/// use foo::bar::{a, b}
|
|
|
|
/// ```
|
|
|
|
///
|
|
|
|
/// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`
|
|
|
|
/// for `a` in this field.
|
|
|
|
id: NodeId,
|
2016-02-13 21:49:16 +00:00
|
|
|
},
|
2020-03-07 18:49:13 +03:00
|
|
|
Glob {
|
2016-08-20 00:23:32 +00:00
|
|
|
is_prelude: bool,
|
2022-10-30 13:35:31 +04:00
|
|
|
// The visibility of the greatest re-export.
|
|
|
|
// n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
|
|
|
|
max_vis: Cell<Option<ty::Visibility>>,
|
|
|
|
id: NodeId,
|
2016-08-20 00:23:32 +00:00
|
|
|
},
|
2018-10-21 00:23:29 +02:00
|
|
|
ExternCrate {
|
2020-04-19 13:00:18 +02:00
|
|
|
source: Option<Symbol>,
|
2018-10-21 00:23:29 +02:00
|
|
|
target: Ident,
|
2022-10-30 13:35:31 +04:00
|
|
|
id: NodeId,
|
2018-10-21 00:23:29 +02:00
|
|
|
},
|
2023-12-28 15:18:49 +08:00
|
|
|
MacroUse {
|
|
|
|
/// A field has been added indicating whether it should be reported as a lint,
|
|
|
|
/// addressing issue#119301.
|
|
|
|
warn_private: bool,
|
|
|
|
},
|
2022-10-30 15:55:58 +04:00
|
|
|
MacroExport,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2022-08-15 18:29:43 +02:00
|
|
|
/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings`
|
|
|
|
/// contain `Cell`s which can introduce infinite loops while printing.
|
|
|
|
impl<'a> std::fmt::Debug for ImportKind<'a> {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
use ImportKind::*;
|
|
|
|
match self {
|
|
|
|
Single {
|
|
|
|
ref source,
|
|
|
|
ref target,
|
2023-03-17 13:34:15 +04:00
|
|
|
ref source_bindings,
|
|
|
|
ref target_bindings,
|
2022-08-15 18:29:43 +02:00
|
|
|
ref type_ns_only,
|
|
|
|
ref nested,
|
2022-10-30 13:35:31 +04:00
|
|
|
ref id,
|
2022-08-15 18:29:43 +02:00
|
|
|
} => f
|
|
|
|
.debug_struct("Single")
|
|
|
|
.field("source", source)
|
|
|
|
.field("target", target)
|
2023-03-17 13:34:15 +04:00
|
|
|
// Ignore the nested bindings to avoid an infinite loop while printing.
|
|
|
|
.field(
|
|
|
|
"source_bindings",
|
|
|
|
&source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
|
|
|
|
)
|
|
|
|
.field(
|
|
|
|
"target_bindings",
|
|
|
|
&target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
|
|
|
|
)
|
2022-08-15 18:29:43 +02:00
|
|
|
.field("type_ns_only", type_ns_only)
|
|
|
|
.field("nested", nested)
|
2022-10-30 13:35:31 +04:00
|
|
|
.field("id", id)
|
2023-03-17 13:34:15 +04:00
|
|
|
.finish(),
|
2022-10-30 13:35:31 +04:00
|
|
|
Glob { ref is_prelude, ref max_vis, ref id } => f
|
2022-08-15 18:29:43 +02:00
|
|
|
.debug_struct("Glob")
|
|
|
|
.field("is_prelude", is_prelude)
|
|
|
|
.field("max_vis", max_vis)
|
2022-10-30 13:35:31 +04:00
|
|
|
.field("id", id)
|
2022-08-15 18:29:43 +02:00
|
|
|
.finish(),
|
2022-10-30 13:35:31 +04:00
|
|
|
ExternCrate { ref source, ref target, ref id } => f
|
2022-08-15 18:29:43 +02:00
|
|
|
.debug_struct("ExternCrate")
|
|
|
|
.field("source", source)
|
|
|
|
.field("target", target)
|
2022-10-30 13:35:31 +04:00
|
|
|
.field("id", id)
|
2022-08-15 18:29:43 +02:00
|
|
|
.finish(),
|
2023-12-28 15:18:49 +08:00
|
|
|
MacroUse { .. } => f.debug_struct("MacroUse").finish(),
|
2022-10-30 15:55:58 +04:00
|
|
|
MacroExport => f.debug_struct("MacroExport").finish(),
|
2022-08-15 18:29:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
/// One import.
|
2019-09-01 00:01:25 -07:00
|
|
|
#[derive(Debug, Clone)]
|
2023-07-04 18:51:35 +03:00
|
|
|
pub(crate) struct ImportData<'a> {
|
2020-03-07 18:49:13 +03:00
|
|
|
pub kind: ImportKind<'a>,
|
|
|
|
|
2022-10-30 13:35:31 +04:00
|
|
|
/// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`
|
|
|
|
/// (if it exists) except in the case of "nested" use trees, in which case
|
|
|
|
/// it will be the ID of the root use tree. e.g., in the example
|
|
|
|
/// ```ignore (incomplete code)
|
2018-05-18 17:18:04 -04:00
|
|
|
/// use foo::bar::{a, b}
|
|
|
|
/// ```
|
2022-10-30 13:35:31 +04:00
|
|
|
/// this would be the ID of the `use foo::bar` `UseTree` node.
|
|
|
|
/// In case of imports without their own node ID it's the closest node that can be used,
|
|
|
|
/// for example, for reporting lints.
|
2018-05-18 17:18:04 -04:00
|
|
|
pub root_id: NodeId,
|
|
|
|
|
2019-01-29 13:34:40 +01:00
|
|
|
/// Span of the entire use statement.
|
|
|
|
pub use_span: Span,
|
|
|
|
|
|
|
|
/// Span of the entire use statement with attributes.
|
|
|
|
pub use_span_with_attributes: Span,
|
|
|
|
|
|
|
|
/// Did the use statement have any attributes?
|
|
|
|
pub has_attributes: bool,
|
|
|
|
|
2018-05-18 17:18:04 -04:00
|
|
|
/// Span of this use tree.
|
|
|
|
pub span: Span,
|
|
|
|
|
|
|
|
/// Span of the *root* use tree (see `root_id`).
|
|
|
|
pub root_span: Span,
|
|
|
|
|
2018-10-22 01:28:59 +03:00
|
|
|
pub parent_scope: ParentScope<'a>,
|
2018-09-12 15:21:50 +12:00
|
|
|
pub module_path: Vec<Segment>,
|
2018-08-09 16:29:22 +03:00
|
|
|
/// The resolution of `module_path`.
|
|
|
|
pub imported_module: Cell<Option<ModuleOrUniformRoot<'a>>>,
|
2022-08-27 18:36:57 +03:00
|
|
|
pub vis: Cell<Option<ty::Visibility>>,
|
2023-11-10 10:11:24 +08:00
|
|
|
pub used: Cell<Option<Used>>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2023-07-05 13:46:42 +03:00
|
|
|
/// All imports are unique and allocated on a same arena,
|
|
|
|
/// so we can use referential equality to compare them.
|
2023-07-04 18:51:35 +03:00
|
|
|
pub(crate) type Import<'a> = Interned<'a, ImportData<'a>>;
|
|
|
|
|
|
|
|
impl<'a> ImportData<'a> {
|
2023-02-05 23:05:46 +04:00
|
|
|
pub(crate) fn is_glob(&self) -> bool {
|
2020-10-26 21:02:48 -04:00
|
|
|
matches!(self.kind, ImportKind::Glob { .. })
|
2016-04-17 01:57:09 +00:00
|
|
|
}
|
2018-05-22 11:10:17 -04:00
|
|
|
|
2023-02-05 23:05:46 +04:00
|
|
|
pub(crate) fn is_nested(&self) -> bool {
|
2020-03-07 18:49:13 +03:00
|
|
|
match self.kind {
|
|
|
|
ImportKind::Single { nested, .. } => nested,
|
2019-12-24 17:38:22 -05:00
|
|
|
_ => false,
|
2019-01-29 13:34:40 +01:00
|
|
|
}
|
|
|
|
}
|
2022-08-27 18:36:57 +03:00
|
|
|
|
|
|
|
pub(crate) fn expect_vis(&self) -> ty::Visibility {
|
|
|
|
self.vis.get().expect("encountered cleared import visibility")
|
|
|
|
}
|
2022-10-30 13:35:31 +04:00
|
|
|
|
|
|
|
pub(crate) fn id(&self) -> Option<NodeId> {
|
|
|
|
match self.kind {
|
|
|
|
ImportKind::Single { id, .. }
|
|
|
|
| ImportKind::Glob { id, .. }
|
|
|
|
| ImportKind::ExternCrate { id, .. } => Some(id),
|
2023-12-28 15:18:49 +08:00
|
|
|
ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,
|
2022-10-30 13:35:31 +04:00
|
|
|
}
|
|
|
|
}
|
2023-03-22 17:57:39 +04:00
|
|
|
|
|
|
|
fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport {
|
|
|
|
let to_def_id = |id| r.local_def_id(id).to_def_id();
|
|
|
|
match self.kind {
|
|
|
|
ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),
|
|
|
|
ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)),
|
|
|
|
ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)),
|
2023-12-28 15:18:49 +08:00
|
|
|
ImportKind::MacroUse { .. } => Reexport::MacroUse,
|
2023-03-22 17:57:39 +04:00
|
|
|
ImportKind::MacroExport => Reexport::MacroExport,
|
|
|
|
}
|
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-03-17 08:43:17 +00:00
|
|
|
/// Records information about the resolution of a name in a namespace of a module.
|
2022-03-26 20:59:09 +01:00
|
|
|
#[derive(Clone, Default, Debug)]
|
2022-05-20 19:51:09 -04:00
|
|
|
pub(crate) struct NameResolution<'a> {
|
2018-07-17 04:12:48 +03:00
|
|
|
/// Single imports that may define the name in the namespace.
|
2020-03-07 19:02:32 +03:00
|
|
|
/// Imports are arena-allocated, so it's ok to use pointers as keys.
|
2023-07-04 18:51:35 +03:00
|
|
|
pub single_imports: FxHashSet<Import<'a>>,
|
2016-02-07 23:58:14 +00:00
|
|
|
/// The least shadowable known binding for this name, or None if there are no known bindings.
|
2023-07-04 17:28:57 +03:00
|
|
|
pub binding: Option<NameBinding<'a>>,
|
|
|
|
pub shadowed_glob: Option<NameBinding<'a>>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2016-02-07 22:28:54 +00:00
|
|
|
impl<'a> NameResolution<'a> {
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Returns the binding for the name if it is known or None if it not known.
|
2023-07-04 17:28:57 +03:00
|
|
|
pub(crate) fn binding(&self) -> Option<NameBinding<'a>> {
|
2018-07-17 04:12:48 +03:00
|
|
|
self.binding.and_then(|binding| {
|
2019-12-24 17:38:22 -05:00
|
|
|
if !binding.is_glob_import() || self.single_imports.is_empty() {
|
|
|
|
Some(binding)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2016-03-17 08:43:17 +00:00
|
|
|
})
|
|
|
|
}
|
2016-08-01 20:43:48 +00:00
|
|
|
}
|
|
|
|
|
2023-02-22 21:20:54 +04:00
|
|
|
/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
|
|
|
|
/// import errors within the same use tree into a single diagnostic.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
struct UnresolvedImportError {
|
|
|
|
span: Span,
|
|
|
|
label: Option<String>,
|
|
|
|
note: Option<String>,
|
|
|
|
suggestion: Option<Suggestion>,
|
|
|
|
candidates: Option<Vec<ImportSuggestion>>,
|
|
|
|
}
|
|
|
|
|
2021-01-29 00:59:20 +03:00
|
|
|
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
|
|
|
|
// are permitted for backward-compatibility under a deprecation lint.
|
2023-07-04 18:51:35 +03:00
|
|
|
fn pub_use_of_private_extern_crate_hack(import: Import<'_>, binding: NameBinding<'_>) -> bool {
|
2021-01-29 00:59:20 +03:00
|
|
|
match (&import.kind, &binding.kind) {
|
2023-07-04 18:51:35 +03:00
|
|
|
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. }) => {
|
|
|
|
matches!(binding_import.kind, ImportKind::ExternCrate { .. })
|
|
|
|
&& import.expect_vis().is_public()
|
|
|
|
}
|
2021-01-29 00:59:20 +03:00
|
|
|
_ => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-08 12:59:02 +00:00
|
|
|
impl<'a, 'tcx> Resolver<'a, 'tcx> {
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Given a binding and an import that resolves to it,
|
|
|
|
/// return the corresponding binding defined by the import.
|
2023-07-04 18:51:35 +03:00
|
|
|
pub(crate) fn import(&self, binding: NameBinding<'a>, import: Import<'a>) -> NameBinding<'a> {
|
2022-08-28 00:10:06 +03:00
|
|
|
let import_vis = import.expect_vis().to_def_id();
|
2023-02-22 19:51:17 +04:00
|
|
|
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|
2021-01-29 00:59:20 +03:00
|
|
|
|| pub_use_of_private_extern_crate_hack(import, binding)
|
2019-12-24 17:38:22 -05:00
|
|
|
{
|
2022-08-27 18:36:57 +03:00
|
|
|
import_vis
|
2016-08-19 22:52:26 +00:00
|
|
|
} else {
|
2021-01-06 18:07:47 +03:00
|
|
|
binding.vis
|
2016-08-19 22:52:26 +00:00
|
|
|
};
|
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
if let ImportKind::Glob { ref max_vis, .. } = import.kind {
|
2022-08-27 18:36:57 +03:00
|
|
|
if vis == import_vis
|
2023-02-22 19:51:17 +04:00
|
|
|
|| max_vis.get().map_or(true, |max_vis| vis.is_at_least(max_vis, self.tcx))
|
2022-08-27 18:36:57 +03:00
|
|
|
{
|
2022-08-28 00:10:06 +03:00
|
|
|
max_vis.set(Some(vis.expect_local()))
|
2016-08-20 00:23:32 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-04 17:28:57 +03:00
|
|
|
self.arenas.alloc_name_binding(NameBindingData {
|
2023-11-10 10:11:24 +08:00
|
|
|
kind: NameBindingKind::Import { binding, import },
|
2018-12-29 18:15:29 +03:00
|
|
|
ambiguity: None,
|
2023-07-26 22:46:49 +08:00
|
|
|
warn_ambiguity: false,
|
2020-03-07 19:02:32 +03:00
|
|
|
span: import.span,
|
2017-08-06 22:54:09 -07:00
|
|
|
vis,
|
2020-03-07 19:02:32 +03:00
|
|
|
expansion: import.parent_scope.expansion,
|
2016-11-29 02:53:00 +00:00
|
|
|
})
|
2016-07-31 04:53:04 +00:00
|
|
|
}
|
|
|
|
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Define the name or return the existing binding if there is a collision.
|
2023-07-26 22:46:49 +08:00
|
|
|
/// `update` indicates if the definition is a redefinition of an existing binding.
|
2022-05-20 19:51:09 -04:00
|
|
|
pub(crate) fn try_define(
|
2019-09-01 00:01:25 -07:00
|
|
|
&mut self,
|
|
|
|
module: Module<'a>,
|
2019-09-09 21:04:26 +01:00
|
|
|
key: BindingKey,
|
2023-07-04 17:28:57 +03:00
|
|
|
binding: NameBinding<'a>,
|
2023-07-26 22:46:49 +08:00
|
|
|
warn_ambiguity: bool,
|
2023-07-04 17:28:57 +03:00
|
|
|
) -> Result<(), NameBinding<'a>> {
|
2019-06-30 01:24:34 +03:00
|
|
|
let res = binding.res();
|
2019-09-09 21:04:26 +01:00
|
|
|
self.check_reserved_macro_name(key.ident, res);
|
2018-09-27 04:49:40 +03:00
|
|
|
self.set_binding_parent_module(binding, module);
|
2023-07-26 22:46:49 +08:00
|
|
|
self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
|
2023-06-20 22:47:50 +08:00
|
|
|
if let Some(old_binding) = resolution.binding {
|
|
|
|
if res == Res::Err && old_binding.res() != Res::Err {
|
|
|
|
// Do not override real bindings with `Res::Err`s from error recovery.
|
|
|
|
return Ok(());
|
|
|
|
}
|
2018-11-05 01:11:59 +03:00
|
|
|
match (old_binding.is_glob_import(), binding.is_glob_import()) {
|
|
|
|
(true, true) => {
|
2023-07-26 22:46:49 +08:00
|
|
|
// FIXME: remove `!binding.is_ambiguity()` after delete the warning ambiguity.
|
|
|
|
if !binding.is_ambiguity()
|
|
|
|
&& let NameBindingKind::Import { import: old_import, .. } =
|
|
|
|
old_binding.kind
|
|
|
|
&& let NameBindingKind::Import { import, .. } = binding.kind
|
|
|
|
&& old_import == import
|
|
|
|
{
|
|
|
|
// We should replace the `old_binding` with `binding` regardless
|
|
|
|
// of whether they has same resolution or not when they are
|
|
|
|
// imported from the same glob-import statement.
|
2023-09-04 20:14:40 +08:00
|
|
|
resolution.binding = Some(binding);
|
2023-07-26 22:46:49 +08:00
|
|
|
} else if res != old_binding.res() {
|
|
|
|
let binding = if warn_ambiguity {
|
|
|
|
this.warn_ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
|
|
|
|
} else {
|
|
|
|
this.ambiguity(AmbiguityKind::GlobVsGlob, old_binding, binding)
|
|
|
|
};
|
|
|
|
resolution.binding = Some(binding);
|
2023-06-20 22:47:50 +08:00
|
|
|
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
|
2018-11-05 01:11:59 +03:00
|
|
|
// We are glob-importing the same item but with greater visibility.
|
|
|
|
resolution.binding = Some(binding);
|
2023-07-26 22:46:49 +08:00
|
|
|
} else if binding.is_ambiguity() {
|
|
|
|
resolution.binding =
|
|
|
|
Some(self.arenas.alloc_name_binding(NameBindingData {
|
|
|
|
warn_ambiguity: true,
|
|
|
|
..(*binding).clone()
|
|
|
|
}));
|
2018-11-05 01:11:59 +03:00
|
|
|
}
|
2016-08-20 03:28:35 +00:00
|
|
|
}
|
2018-11-05 01:11:59 +03:00
|
|
|
(old_glob @ true, false) | (old_glob @ false, true) => {
|
2019-12-24 17:38:22 -05:00
|
|
|
let (glob_binding, nonglob_binding) =
|
|
|
|
if old_glob { (old_binding, binding) } else { (binding, old_binding) };
|
2019-09-09 21:04:26 +01:00
|
|
|
if glob_binding.res() != nonglob_binding.res()
|
2019-12-24 17:38:22 -05:00
|
|
|
&& key.ns == MacroNS
|
2021-06-25 20:43:04 +02:00
|
|
|
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
2019-09-09 21:04:26 +01:00
|
|
|
{
|
2023-06-20 22:47:50 +08:00
|
|
|
resolution.binding = Some(this.ambiguity(
|
2019-09-01 00:01:25 -07:00
|
|
|
AmbiguityKind::GlobVsExpanded,
|
|
|
|
nonglob_binding,
|
|
|
|
glob_binding,
|
|
|
|
));
|
2018-11-05 01:11:59 +03:00
|
|
|
} else {
|
|
|
|
resolution.binding = Some(nonglob_binding);
|
|
|
|
}
|
2023-06-14 00:55:36 +08:00
|
|
|
|
|
|
|
if let Some(old_binding) = resolution.shadowed_glob {
|
|
|
|
assert!(old_binding.is_glob_import());
|
|
|
|
if glob_binding.res() != old_binding.res() {
|
2023-06-20 22:47:50 +08:00
|
|
|
resolution.shadowed_glob = Some(this.ambiguity(
|
2023-06-14 00:55:36 +08:00
|
|
|
AmbiguityKind::GlobVsGlob,
|
|
|
|
old_binding,
|
|
|
|
glob_binding,
|
|
|
|
));
|
2023-06-20 22:47:50 +08:00
|
|
|
} else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
|
2023-06-14 00:55:36 +08:00
|
|
|
resolution.shadowed_glob = Some(glob_binding);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
resolution.shadowed_glob = Some(glob_binding);
|
|
|
|
}
|
2018-11-05 01:11:59 +03:00
|
|
|
}
|
|
|
|
(false, false) => {
|
2023-06-20 22:47:50 +08:00
|
|
|
return Err(old_binding);
|
2016-11-10 10:29:36 +00:00
|
|
|
}
|
2016-07-28 02:34:01 +00:00
|
|
|
}
|
2023-06-20 22:47:50 +08:00
|
|
|
} else {
|
|
|
|
resolution.binding = Some(binding);
|
2016-07-28 02:34:01 +00:00
|
|
|
}
|
|
|
|
|
2023-06-20 22:47:50 +08:00
|
|
|
Ok(())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn ambiguity(
|
|
|
|
&self,
|
|
|
|
kind: AmbiguityKind,
|
2023-07-04 17:28:57 +03:00
|
|
|
primary_binding: NameBinding<'a>,
|
|
|
|
secondary_binding: NameBinding<'a>,
|
|
|
|
) -> NameBinding<'a> {
|
|
|
|
self.arenas.alloc_name_binding(NameBindingData {
|
2023-06-20 22:47:50 +08:00
|
|
|
ambiguity: Some((secondary_binding, kind)),
|
2023-07-04 17:28:57 +03:00
|
|
|
..(*primary_binding).clone()
|
2023-06-20 22:47:50 +08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-07-26 22:46:49 +08:00
|
|
|
fn warn_ambiguity(
|
|
|
|
&self,
|
|
|
|
kind: AmbiguityKind,
|
|
|
|
primary_binding: NameBinding<'a>,
|
|
|
|
secondary_binding: NameBinding<'a>,
|
|
|
|
) -> NameBinding<'a> {
|
|
|
|
self.arenas.alloc_name_binding(NameBindingData {
|
|
|
|
ambiguity: Some((secondary_binding, kind)),
|
|
|
|
warn_ambiguity: true,
|
|
|
|
..(*primary_binding).clone()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-06-20 22:47:50 +08:00
|
|
|
// Use `f` to mutate the resolution of the name in the module.
|
|
|
|
// If the resolution becomes a success, define it in the module's glob importers.
|
2023-07-26 22:46:49 +08:00
|
|
|
fn update_resolution<T, F>(
|
|
|
|
&mut self,
|
|
|
|
module: Module<'a>,
|
|
|
|
key: BindingKey,
|
|
|
|
warn_ambiguity: bool,
|
|
|
|
f: F,
|
|
|
|
) -> T
|
2023-06-20 22:47:50 +08:00
|
|
|
where
|
|
|
|
F: FnOnce(&mut Resolver<'a, 'tcx>, &mut NameResolution<'a>) -> T,
|
|
|
|
{
|
2016-07-28 02:34:01 +00:00
|
|
|
// Ensure that `resolution` isn't borrowed when defining in the module's glob importers,
|
|
|
|
// during which the resolution might end up getting re-defined via a glob cycle.
|
2023-07-26 22:46:49 +08:00
|
|
|
let (binding, t, warn_ambiguity) = {
|
2023-06-20 22:47:50 +08:00
|
|
|
let resolution = &mut *self.resolution(module, key).borrow_mut();
|
|
|
|
let old_binding = resolution.binding();
|
|
|
|
|
|
|
|
let t = f(self, resolution);
|
|
|
|
|
2023-07-26 22:46:49 +08:00
|
|
|
if let Some(binding) = resolution.binding()
|
|
|
|
&& old_binding != Some(binding)
|
|
|
|
{
|
|
|
|
(binding, t, warn_ambiguity || old_binding.is_some())
|
2023-07-04 17:28:57 +03:00
|
|
|
} else {
|
|
|
|
return t;
|
2023-06-20 22:47:50 +08:00
|
|
|
}
|
2016-04-07 22:14:44 +00:00
|
|
|
};
|
|
|
|
|
2023-07-26 22:46:49 +08:00
|
|
|
let Ok(glob_importers) = module.glob_importers.try_borrow_mut() else {
|
|
|
|
return t;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Define or update `binding` in `module`s glob importers.
|
|
|
|
for import in glob_importers.iter() {
|
2019-09-09 21:04:26 +01:00
|
|
|
let mut ident = key.ident;
|
2020-03-07 19:02:32 +03:00
|
|
|
let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) {
|
2021-09-12 01:47:46 +03:00
|
|
|
Some(Some(def)) => self.expn_def_scope(def),
|
2020-03-07 19:02:32 +03:00
|
|
|
Some(None) => import.parent_scope.module,
|
2017-03-22 08:39:51 +00:00
|
|
|
None => continue,
|
|
|
|
};
|
|
|
|
if self.is_accessible_from(binding.vis, scope) {
|
2023-07-04 18:51:35 +03:00
|
|
|
let imported_binding = self.import(binding, *import);
|
2019-09-09 21:04:26 +01:00
|
|
|
let key = BindingKey { ident, ..key };
|
2023-07-26 22:46:49 +08:00
|
|
|
let _ = self.try_define(
|
|
|
|
import.parent_scope.module,
|
|
|
|
key,
|
|
|
|
imported_binding,
|
|
|
|
warn_ambiguity,
|
|
|
|
);
|
2016-07-28 02:34:01 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2016-07-28 02:34:01 +00:00
|
|
|
|
|
|
|
t
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
|
2023-05-12 02:09:46 +08:00
|
|
|
// Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
|
|
|
|
// or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
|
2023-07-04 18:51:35 +03:00
|
|
|
fn import_dummy_binding(&mut self, import: Import<'a>, is_indeterminate: bool) {
|
2022-04-10 17:21:58 +03:00
|
|
|
if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
|
2023-05-12 02:09:46 +08:00
|
|
|
if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
|
|
|
|
{
|
2022-04-10 17:21:58 +03:00
|
|
|
return; // Has resolution, do not create the dummy binding
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
let dummy_binding = self.dummy_binding;
|
2020-03-07 19:02:32 +03:00
|
|
|
let dummy_binding = self.import(dummy_binding, import);
|
2016-11-10 06:19:54 +00:00
|
|
|
self.per_ns(|this, ns| {
|
2023-04-18 22:46:51 +08:00
|
|
|
let key = BindingKey::new(target, ns);
|
2023-07-26 22:46:49 +08:00
|
|
|
let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
|
2023-12-06 21:48:19 +08:00
|
|
|
this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
|
|
|
|
resolution.single_imports.remove(&import);
|
|
|
|
})
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2023-11-10 10:11:24 +08:00
|
|
|
self.record_use(target, dummy_binding, Used::Other);
|
2022-04-10 17:21:58 +03:00
|
|
|
} else if import.imported_module.get().is_none() {
|
2023-11-10 10:11:24 +08:00
|
|
|
import.used.set(Some(Used::Other));
|
2022-10-30 13:35:31 +04:00
|
|
|
if let Some(id) = import.id() {
|
|
|
|
self.used_imports.insert(id);
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-28 16:17:01 +00:00
|
|
|
|
2015-03-16 10:44:19 +13:00
|
|
|
// Import resolution
|
|
|
|
//
|
|
|
|
// This is a fixed-point algorithm. We resolve imports until our efforts
|
|
|
|
// are stymied by an unresolved import; then we bail out of the current
|
|
|
|
// module and continue. We terminate successfully once no more imports
|
|
|
|
// remain or unsuccessfully when no forward progress in resolving imports
|
|
|
|
// is made.
|
|
|
|
|
|
|
|
/// Resolves all imports for the crate. This method performs the fixed-
|
|
|
|
/// point iteration.
|
2023-02-05 23:05:46 +04:00
|
|
|
pub(crate) fn resolve_imports(&mut self) {
|
2023-03-19 20:12:57 +08:00
|
|
|
let mut prev_indeterminate_count = usize::MAX;
|
|
|
|
let mut indeterminate_count = self.indeterminate_imports.len() * 3;
|
|
|
|
while indeterminate_count < prev_indeterminate_count {
|
|
|
|
prev_indeterminate_count = indeterminate_count;
|
|
|
|
indeterminate_count = 0;
|
2023-02-22 21:20:54 +04:00
|
|
|
for import in mem::take(&mut self.indeterminate_imports) {
|
2023-07-04 18:51:35 +03:00
|
|
|
let import_indeterminate_count = self.resolve_import(import);
|
2023-03-19 20:12:57 +08:00
|
|
|
indeterminate_count += import_indeterminate_count;
|
|
|
|
match import_indeterminate_count {
|
|
|
|
0 => self.determined_imports.push(import),
|
|
|
|
_ => self.indeterminate_imports.push(import),
|
2016-04-17 20:23:10 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-08-17 00:52:18 +00:00
|
|
|
}
|
2016-11-10 10:11:25 +00:00
|
|
|
}
|
2016-08-17 00:52:18 +00:00
|
|
|
|
2023-02-05 23:05:46 +04:00
|
|
|
pub(crate) fn finalize_imports(&mut self) {
|
2023-02-22 21:20:54 +04:00
|
|
|
for module in self.arenas.local_modules().iter() {
|
2023-07-04 20:00:42 +03:00
|
|
|
self.finalize_resolutions_in(*module);
|
2016-08-17 00:52:18 +00:00
|
|
|
}
|
|
|
|
|
2018-10-16 10:44:26 +02:00
|
|
|
let mut seen_spans = FxHashSet::default();
|
2019-01-16 15:30:41 -05:00
|
|
|
let mut errors = vec![];
|
2018-11-07 10:08:41 +01:00
|
|
|
let mut prev_root_id: NodeId = NodeId::from_u32(0);
|
2023-02-22 21:20:54 +04:00
|
|
|
let determined_imports = mem::take(&mut self.determined_imports);
|
|
|
|
let indeterminate_imports = mem::take(&mut self.indeterminate_imports);
|
2019-09-01 00:01:25 -07:00
|
|
|
|
|
|
|
for (is_indeterminate, import) in determined_imports
|
2023-07-29 00:14:38 +08:00
|
|
|
.iter()
|
2019-09-01 00:01:25 -07:00
|
|
|
.map(|i| (false, i))
|
2023-07-29 00:14:38 +08:00
|
|
|
.chain(indeterminate_imports.iter().map(|i| (true, i)))
|
2019-09-01 00:01:25 -07:00
|
|
|
{
|
2023-07-29 00:14:38 +08:00
|
|
|
let unresolved_import_error = self.finalize_import(*import);
|
2022-04-10 17:21:58 +03:00
|
|
|
|
|
|
|
// If this import is unresolved then create a dummy import
|
|
|
|
// resolution for it so that later resolve stages won't complain.
|
2023-07-29 00:14:38 +08:00
|
|
|
self.import_dummy_binding(*import, is_indeterminate);
|
2022-04-10 17:21:58 +03:00
|
|
|
|
|
|
|
if let Some(err) = unresolved_import_error {
|
2020-03-07 18:49:13 +03:00
|
|
|
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind {
|
2019-05-13 22:46:20 +03:00
|
|
|
if source.name == kw::SelfLower {
|
2017-06-10 10:55:19 +01:00
|
|
|
// Silence `unresolved import` error if E0429 is already emitted
|
2018-11-30 21:16:21 +03:00
|
|
|
if let Err(Determined) = source_bindings.value_ns.get() {
|
2018-10-17 11:13:44 +02:00
|
|
|
continue;
|
2017-06-10 10:55:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:30:41 -05:00
|
|
|
if prev_root_id.as_u32() != 0
|
2019-12-24 17:38:22 -05:00
|
|
|
&& prev_root_id.as_u32() != import.root_id.as_u32()
|
|
|
|
&& !errors.is_empty()
|
|
|
|
{
|
2019-01-16 15:30:41 -05:00
|
|
|
// In the case of a new import line, throw a diagnostic message
|
|
|
|
// for the previous line.
|
2022-11-04 13:59:04 +09:00
|
|
|
self.throw_unresolved_import_error(errors);
|
2019-01-16 15:30:41 -05:00
|
|
|
errors = vec![];
|
2018-09-03 17:27:14 +00:00
|
|
|
}
|
2019-10-16 13:48:20 +09:00
|
|
|
if seen_spans.insert(err.span) {
|
2023-07-29 00:14:38 +08:00
|
|
|
errors.push((*import, err));
|
2018-09-03 17:27:14 +00:00
|
|
|
prev_root_id = import.root_id;
|
2017-07-23 15:15:45 -07:00
|
|
|
}
|
2023-07-29 00:14:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !errors.is_empty() {
|
|
|
|
self.throw_unresolved_import_error(errors);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for import in &indeterminate_imports {
|
|
|
|
let path = import_path_to_string(
|
|
|
|
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
|
|
|
&import.kind,
|
|
|
|
import.span,
|
|
|
|
);
|
|
|
|
let err = UnresolvedImportError {
|
|
|
|
span: import.span,
|
|
|
|
label: None,
|
|
|
|
note: None,
|
|
|
|
suggestion: None,
|
|
|
|
candidates: None,
|
|
|
|
};
|
|
|
|
// FIXME: there should be a better way of doing this than
|
|
|
|
// formatting this as a string then checking for `::`
|
|
|
|
if path.contains("::") {
|
|
|
|
errors.push((*import, err))
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:30:41 -05:00
|
|
|
if !errors.is_empty() {
|
2022-11-04 13:59:04 +09:00
|
|
|
self.throw_unresolved_import_error(errors);
|
2018-09-03 17:27:14 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2023-05-09 07:15:46 +08:00
|
|
|
pub(crate) fn check_hidden_glob_reexports(
|
2023-03-20 03:11:28 +08:00
|
|
|
&mut self,
|
2023-07-04 17:28:57 +03:00
|
|
|
exported_ambiguities: FxHashSet<NameBinding<'a>>,
|
2023-03-20 03:11:28 +08:00
|
|
|
) {
|
|
|
|
for module in self.arenas.local_modules().iter() {
|
2023-07-04 20:00:42 +03:00
|
|
|
for (key, resolution) in self.resolutions(*module).borrow().iter() {
|
2023-05-09 07:15:46 +08:00
|
|
|
let resolution = resolution.borrow();
|
|
|
|
|
|
|
|
if let Some(binding) = resolution.binding {
|
|
|
|
if let NameBindingKind::Import { import, .. } = binding.kind
|
|
|
|
&& let Some((amb_binding, _)) = binding.ambiguity
|
|
|
|
&& binding.res() != Res::Err
|
2023-07-04 17:28:57 +03:00
|
|
|
&& exported_ambiguities.contains(&binding)
|
2023-05-09 07:15:46 +08:00
|
|
|
{
|
|
|
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
|
|
|
AMBIGUOUS_GLOB_REEXPORTS,
|
|
|
|
import.root_id,
|
|
|
|
import.root_span,
|
|
|
|
"ambiguous glob re-exports",
|
|
|
|
BuiltinLintDiagnostics::AmbiguousGlobReexports {
|
|
|
|
name: key.ident.to_string(),
|
|
|
|
namespace: key.ns.descr().to_string(),
|
|
|
|
first_reexport_span: import.root_span,
|
|
|
|
duplicate_reexport_span: amb_binding.span,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Some(glob_binding) = resolution.shadowed_glob {
|
|
|
|
let binding_id = match binding.kind {
|
|
|
|
NameBindingKind::Res(res) => {
|
|
|
|
Some(self.def_id_to_node_id[res.def_id().expect_local()])
|
|
|
|
}
|
|
|
|
NameBindingKind::Module(module) => {
|
|
|
|
Some(self.def_id_to_node_id[module.def_id().expect_local()])
|
|
|
|
}
|
|
|
|
NameBindingKind::Import { import, .. } => import.id(),
|
|
|
|
};
|
|
|
|
|
|
|
|
if binding.res() != Res::Err
|
|
|
|
&& glob_binding.res() != Res::Err
|
|
|
|
&& let NameBindingKind::Import { import: glob_import, .. } =
|
|
|
|
glob_binding.kind
|
|
|
|
&& let Some(binding_id) = binding_id
|
|
|
|
&& let Some(glob_import_id) = glob_import.id()
|
|
|
|
&& let glob_import_def_id = self.local_def_id(glob_import_id)
|
|
|
|
&& self.effective_visibilities.is_exported(glob_import_def_id)
|
|
|
|
&& glob_binding.vis.is_public()
|
|
|
|
&& !binding.vis.is_public()
|
|
|
|
{
|
|
|
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
|
|
|
HIDDEN_GLOB_REEXPORTS,
|
|
|
|
binding_id,
|
|
|
|
binding.span,
|
|
|
|
"private item shadows public glob re-export",
|
|
|
|
BuiltinLintDiagnostics::HiddenGlobReexports {
|
|
|
|
name: key.ident.name.to_string(),
|
|
|
|
namespace: key.ns.descr().to_owned(),
|
|
|
|
glob_reexport_span: glob_binding.span,
|
|
|
|
private_item_span: binding.span,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2023-03-20 03:11:28 +08:00
|
|
|
}
|
2023-05-09 07:15:46 +08:00
|
|
|
}
|
2023-03-20 03:11:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-04 18:51:35 +03:00
|
|
|
fn throw_unresolved_import_error(&mut self, errors: Vec<(Import<'_>, UnresolvedImportError)>) {
|
2022-11-04 13:59:04 +09:00
|
|
|
if errors.is_empty() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-16 15:30:41 -05:00
|
|
|
/// Upper limit on the number of `span_label` messages.
|
|
|
|
const MAX_LABEL_COUNT: usize = 10;
|
|
|
|
|
2022-11-04 13:59:04 +09:00
|
|
|
let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
|
2022-12-27 04:28:02 +00:00
|
|
|
let paths = errors
|
|
|
|
.iter()
|
|
|
|
.map(|(import, err)| {
|
|
|
|
let path = import_path_to_string(
|
|
|
|
&import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
|
|
|
|
&import.kind,
|
|
|
|
err.span,
|
|
|
|
);
|
|
|
|
format!("`{path}`")
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
2022-11-04 13:59:04 +09:00
|
|
|
let msg = format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
|
2018-10-18 19:09:49 +02:00
|
|
|
|
2024-01-04 09:08:36 +11:00
|
|
|
let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{}", &msg);
|
2019-01-16 15:30:41 -05:00
|
|
|
|
2022-07-28 18:17:55 +09:00
|
|
|
if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.iter().last() {
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
diag.note(note.clone());
|
2018-09-03 17:27:14 +00:00
|
|
|
}
|
2019-01-16 15:30:41 -05:00
|
|
|
|
2022-12-27 04:28:02 +00:00
|
|
|
for (import, err) in errors.into_iter().take(MAX_LABEL_COUNT) {
|
2019-01-16 15:30:41 -05:00
|
|
|
if let Some(label) = err.label {
|
|
|
|
diag.span_label(err.span, label);
|
|
|
|
}
|
|
|
|
|
2019-04-12 01:53:32 +02:00
|
|
|
if let Some((suggestions, msg, applicability)) = err.suggestion {
|
2022-05-22 11:48:35 +09:00
|
|
|
if suggestions.is_empty() {
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
diag.help(msg);
|
2022-05-22 11:48:35 +09:00
|
|
|
continue;
|
|
|
|
}
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
diag.multipart_suggestion(msg, suggestions, applicability);
|
2019-01-16 15:30:41 -05:00
|
|
|
}
|
2022-10-10 11:14:32 +08:00
|
|
|
|
2022-12-27 05:09:33 +00:00
|
|
|
if let Some(candidates) = &err.candidates {
|
2022-12-27 04:28:02 +00:00
|
|
|
match &import.kind {
|
2022-12-27 07:05:45 +00:00
|
|
|
ImportKind::Single { nested: false, source, target, .. } => import_candidates(
|
2023-02-22 21:20:54 +04:00
|
|
|
self.tcx,
|
2022-12-27 04:28:02 +00:00
|
|
|
&mut diag,
|
|
|
|
Some(err.span),
|
2023-11-21 20:07:32 +01:00
|
|
|
candidates,
|
2024-02-29 16:32:35 +11:00
|
|
|
DiagMode::Import,
|
2023-01-09 18:07:34 +00:00
|
|
|
(source != target)
|
|
|
|
.then(|| format!(" as {target}"))
|
|
|
|
.as_deref()
|
|
|
|
.unwrap_or(""),
|
2022-12-27 04:28:02 +00:00
|
|
|
),
|
2022-12-27 07:05:45 +00:00
|
|
|
ImportKind::Single { nested: true, source, target, .. } => {
|
2022-12-27 05:09:33 +00:00
|
|
|
import_candidates(
|
2023-02-22 21:20:54 +04:00
|
|
|
self.tcx,
|
2022-12-27 05:09:33 +00:00
|
|
|
&mut diag,
|
|
|
|
None,
|
2023-11-21 20:07:32 +01:00
|
|
|
candidates,
|
2024-02-29 16:32:35 +11:00
|
|
|
DiagMode::Normal,
|
2023-01-09 18:07:34 +00:00
|
|
|
(source != target)
|
|
|
|
.then(|| format!(" as {target}"))
|
|
|
|
.as_deref()
|
|
|
|
.unwrap_or(""),
|
2022-12-27 05:09:33 +00:00
|
|
|
);
|
|
|
|
}
|
2022-12-27 04:28:02 +00:00
|
|
|
_ => {}
|
|
|
|
}
|
2022-10-10 11:14:32 +08:00
|
|
|
}
|
2023-06-21 02:20:55 +08:00
|
|
|
|
|
|
|
match &import.kind {
|
|
|
|
ImportKind::Single { source, .. } => {
|
|
|
|
if let Some(ModuleOrUniformRoot::Module(module)) = import.imported_module.get()
|
|
|
|
&& let Some(module) = module.opt_def_id()
|
|
|
|
{
|
|
|
|
self.find_cfg_stripped(&mut diag, &source.name, module)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2018-10-18 19:09:49 +02:00
|
|
|
}
|
2019-01-16 15:30:41 -05:00
|
|
|
|
|
|
|
diag.emit();
|
2018-09-03 17:27:14 +00:00
|
|
|
}
|
|
|
|
|
2023-03-19 20:12:57 +08:00
|
|
|
/// Attempts to resolve the given import, returning:
|
|
|
|
/// - `0` means its resolution is determined.
|
|
|
|
/// - Other values mean that indeterminate exists under certain namespaces.
|
|
|
|
///
|
|
|
|
/// Meanwhile, if resolve successful, the resolved bindings are written
|
|
|
|
/// into the module.
|
2023-07-04 18:51:35 +03:00
|
|
|
fn resolve_import(&mut self, import: Import<'a>) -> usize {
|
2019-08-05 21:18:50 +03:00
|
|
|
debug!(
|
|
|
|
"(resolving import for module) resolving import `{}::...` in `{}`",
|
2020-03-07 19:02:32 +03:00
|
|
|
Segment::names_to_string(&import.module_path),
|
|
|
|
module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),
|
2019-08-05 21:18:50 +03:00
|
|
|
);
|
2020-03-07 19:02:32 +03:00
|
|
|
let module = if let Some(module) = import.imported_module.get() {
|
2016-08-18 00:11:56 +00:00
|
|
|
module
|
|
|
|
} else {
|
2018-11-09 01:29:07 +03:00
|
|
|
// For better failure detection, pretend that the import will
|
|
|
|
// not define any names while resolving its module path.
|
2022-08-27 18:36:57 +03:00
|
|
|
let orig_vis = import.vis.take();
|
2023-02-22 21:20:54 +04:00
|
|
|
let path_res = self.maybe_resolve_path(&import.module_path, None, &import.parent_scope);
|
2020-03-07 19:02:32 +03:00
|
|
|
import.vis.set(orig_vis);
|
2016-08-18 00:11:56 +00:00
|
|
|
|
2018-11-10 18:58:37 +03:00
|
|
|
match path_res {
|
2016-11-25 06:07:21 +00:00
|
|
|
PathResult::Module(module) => module,
|
2023-03-19 20:12:57 +08:00
|
|
|
PathResult::Indeterminate => return 3,
|
|
|
|
PathResult::NonModule(..) | PathResult::Failed { .. } => return 0,
|
2016-08-18 00:11:56 +00:00
|
|
|
}
|
2016-03-13 02:53:22 +00:00
|
|
|
};
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
import.imported_module.set(Some(module));
|
|
|
|
let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
|
2020-03-07 18:49:13 +03:00
|
|
|
ImportKind::Single {
|
|
|
|
source,
|
|
|
|
target,
|
|
|
|
ref source_bindings,
|
|
|
|
ref target_bindings,
|
|
|
|
type_ns_only,
|
|
|
|
..
|
|
|
|
} => (source, target, source_bindings, target_bindings, type_ns_only),
|
|
|
|
ImportKind::Glob { .. } => {
|
2020-03-07 19:02:32 +03:00
|
|
|
self.resolve_glob_import(import);
|
2023-03-19 20:12:57 +08:00
|
|
|
return 0;
|
2020-03-07 18:49:13 +03:00
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2016-02-07 23:58:14 +00:00
|
|
|
|
2023-03-19 20:12:57 +08:00
|
|
|
let mut indeterminate_count = 0;
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2019-12-24 17:38:22 -05:00
|
|
|
if !type_ns_only || ns == TypeNS {
|
|
|
|
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.
|
2022-08-27 18:36:57 +03:00
|
|
|
let orig_vis = import.vis.take();
|
2023-09-04 20:14:40 +08:00
|
|
|
let binding = this.maybe_resolve_ident_in_module(
|
2019-12-24 17:38:22 -05:00
|
|
|
module,
|
|
|
|
source,
|
|
|
|
ns,
|
2020-03-07 19:02:32 +03:00
|
|
|
&import.parent_scope,
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2020-03-07 19:02:32 +03:00
|
|
|
import.vis.set(orig_vis);
|
2019-12-24 17:38:22 -05:00
|
|
|
source_bindings[ns].set(binding);
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
};
|
2016-08-17 20:48:53 +00:00
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
let parent = import.parent_scope.module;
|
2019-12-24 17:38:22 -05:00
|
|
|
match source_bindings[ns].get() {
|
2023-03-19 20:12:57 +08:00
|
|
|
Err(Undetermined) => indeterminate_count += 1,
|
2019-12-24 17:38:22 -05:00
|
|
|
// Don't update the resolution, because it was never added.
|
|
|
|
Err(Determined) if target.name == kw::Underscore => {}
|
2022-04-10 17:21:58 +03:00
|
|
|
Ok(binding) if binding.is_importable() => {
|
|
|
|
let imported_binding = this.import(binding, import);
|
|
|
|
target_bindings[ns].set(Some(imported_binding));
|
|
|
|
this.define(parent, target, ns, imported_binding);
|
|
|
|
}
|
|
|
|
source_binding @ (Ok(..) | Err(Determined)) => {
|
|
|
|
if source_binding.is_ok() {
|
2023-12-18 22:21:37 +11:00
|
|
|
this.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(IsNotDirectlyImportable { span: import.span, target })
|
2022-04-10 17:21:58 +03:00
|
|
|
.emit();
|
|
|
|
}
|
2023-04-18 22:46:51 +08:00
|
|
|
let key = BindingKey::new(target, ns);
|
2023-07-26 22:46:49 +08:00
|
|
|
this.update_resolution(parent, key, false, |_, resolution| {
|
2023-07-04 18:51:35 +03:00
|
|
|
resolution.single_imports.remove(&import);
|
2023-06-20 22:47:50 +08:00
|
|
|
});
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2016-02-16 13:14:32 +00:00
|
|
|
}
|
2016-02-13 21:49:16 +00:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2023-03-19 20:12:57 +08:00
|
|
|
indeterminate_count
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
|
2019-01-16 15:30:41 -05:00
|
|
|
/// Performs final import resolution, consistency checks and error reporting.
|
|
|
|
///
|
|
|
|
/// Optionally returns an unresolved import error. This error is buffered and used to
|
|
|
|
/// consolidate multiple unresolved import errors into a single diagnostic.
|
2023-07-04 18:51:35 +03:00
|
|
|
fn finalize_import(&mut self, import: Import<'a>) -> Option<UnresolvedImportError> {
|
2022-08-27 18:36:57 +03:00
|
|
|
let orig_vis = import.vis.take();
|
2022-04-30 18:01:01 +03:00
|
|
|
let ignore_binding = match &import.kind {
|
2022-04-08 22:50:56 +02:00
|
|
|
ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
|
2020-11-05 15:16:12 -05:00
|
|
|
_ => None,
|
|
|
|
};
|
2023-02-22 21:20:54 +04:00
|
|
|
let prev_ambiguity_errors_len = self.ambiguity_errors.len();
|
2022-04-30 17:31:44 +03:00
|
|
|
let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);
|
2023-06-16 19:44:06 +00:00
|
|
|
|
|
|
|
// We'll provide more context to the privacy errors later, up to `len`.
|
|
|
|
let privacy_errors_len = self.privacy_errors.len();
|
|
|
|
|
2023-02-22 21:20:54 +04:00
|
|
|
let path_res = self.resolve_path(
|
2022-04-08 22:50:56 +02:00
|
|
|
&import.module_path,
|
|
|
|
None,
|
|
|
|
&import.parent_scope,
|
2022-04-30 17:31:44 +03:00
|
|
|
Some(finalize),
|
2022-04-30 18:01:01 +03:00
|
|
|
ignore_binding,
|
2022-04-08 22:50:56 +02:00
|
|
|
);
|
2022-10-10 11:14:32 +08:00
|
|
|
|
2023-02-22 21:20:54 +04:00
|
|
|
let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
|
2020-03-07 19:02:32 +03:00
|
|
|
import.vis.set(orig_vis);
|
2018-11-10 18:58:37 +03:00
|
|
|
let module = match path_res {
|
|
|
|
PathResult::Module(module) => {
|
2019-08-12 21:52:37 +03:00
|
|
|
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
2020-03-07 19:02:32 +03:00
|
|
|
if let Some(initial_module) = import.imported_module.get() {
|
2023-07-04 20:00:42 +03:00
|
|
|
if module != initial_module && no_ambiguity {
|
2020-11-05 15:16:12 -05:00
|
|
|
span_bug!(import.span, "inconsistent resolution for an import");
|
2018-11-10 18:58:37 +03:00
|
|
|
}
|
2023-02-22 21:20:54 +04:00
|
|
|
} else if self.privacy_errors.is_empty() {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(CannotDetermineImportResolution { span: import.span })
|
|
|
|
.emit();
|
2018-11-10 18:58:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
module
|
|
|
|
}
|
2023-03-10 22:39:14 +01:00
|
|
|
PathResult::Failed {
|
|
|
|
is_error_from_last_segment: false,
|
|
|
|
span,
|
2024-01-13 21:05:41 +08:00
|
|
|
segment_name,
|
2023-03-10 22:39:14 +01:00
|
|
|
label,
|
|
|
|
suggestion,
|
|
|
|
module,
|
|
|
|
} => {
|
2018-12-08 04:19:29 +03:00
|
|
|
if no_ambiguity {
|
2020-03-07 19:02:32 +03:00
|
|
|
assert!(import.imported_module.get().is_none());
|
2023-03-10 22:39:14 +01:00
|
|
|
self.report_error(
|
|
|
|
span,
|
|
|
|
ResolutionError::FailedToResolve {
|
2024-01-13 21:05:41 +08:00
|
|
|
segment: Some(segment_name),
|
2023-03-10 22:39:14 +01:00
|
|
|
label,
|
|
|
|
suggestion,
|
|
|
|
module,
|
|
|
|
},
|
|
|
|
);
|
2018-12-08 04:19:29 +03:00
|
|
|
}
|
2017-11-19 17:05:29 +03:00
|
|
|
return None;
|
|
|
|
}
|
2023-03-10 22:39:14 +01:00
|
|
|
PathResult::Failed {
|
|
|
|
is_error_from_last_segment: true,
|
|
|
|
span,
|
|
|
|
label,
|
|
|
|
suggestion,
|
|
|
|
..
|
|
|
|
} => {
|
2018-12-08 04:19:29 +03:00
|
|
|
if no_ambiguity {
|
2020-11-05 15:16:12 -05:00
|
|
|
assert!(import.imported_module.get().is_none());
|
2019-01-16 15:30:41 -05:00
|
|
|
let err = match self.make_path_suggestion(
|
|
|
|
span,
|
2020-03-07 19:02:32 +03:00
|
|
|
import.module_path.clone(),
|
|
|
|
&import.parent_scope,
|
2019-01-16 15:30:41 -05:00
|
|
|
) {
|
2019-12-24 17:38:22 -05:00
|
|
|
Some((suggestion, note)) => UnresolvedImportError {
|
|
|
|
span,
|
|
|
|
label: None,
|
|
|
|
note,
|
|
|
|
suggestion: Some((
|
|
|
|
vec![(span, Segment::names_to_string(&suggestion))],
|
|
|
|
String::from("a similar path exists"),
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
)),
|
2022-12-27 05:09:33 +00:00
|
|
|
candidates: None,
|
2019-12-24 17:38:22 -05:00
|
|
|
},
|
|
|
|
None => UnresolvedImportError {
|
|
|
|
span,
|
|
|
|
label: Some(label),
|
2022-07-28 18:17:55 +09:00
|
|
|
note: None,
|
2019-12-24 17:38:22 -05:00
|
|
|
suggestion,
|
2022-12-27 05:09:33 +00:00
|
|
|
candidates: None,
|
2019-12-24 17:38:22 -05:00
|
|
|
},
|
2019-01-16 15:30:41 -05:00
|
|
|
};
|
|
|
|
return Some(err);
|
2018-12-08 04:19:29 +03:00
|
|
|
}
|
|
|
|
return None;
|
2018-11-10 18:58:37 +03:00
|
|
|
}
|
2023-07-01 11:53:31 +08:00
|
|
|
PathResult::NonModule(partial_res) => {
|
|
|
|
if no_ambiguity && partial_res.full_res() != Some(Res::Err) {
|
|
|
|
// Check if there are no ambiguities and the result is not dummy.
|
2020-03-07 19:02:32 +03:00
|
|
|
assert!(import.imported_module.get().is_none());
|
2018-12-08 04:19:29 +03:00
|
|
|
}
|
2018-11-10 18:58:37 +03:00
|
|
|
// The error was already reported earlier.
|
|
|
|
return None;
|
|
|
|
}
|
2021-03-20 20:00:25 -07:00
|
|
|
PathResult::Indeterminate => unreachable!(),
|
2016-08-15 08:19:09 +00:00
|
|
|
};
|
|
|
|
|
2022-10-30 13:35:31 +04:00
|
|
|
let (ident, target, source_bindings, target_bindings, type_ns_only, import_id) =
|
|
|
|
match import.kind {
|
|
|
|
ImportKind::Single {
|
|
|
|
source,
|
|
|
|
target,
|
|
|
|
ref source_bindings,
|
|
|
|
ref target_bindings,
|
|
|
|
type_ns_only,
|
|
|
|
id,
|
|
|
|
..
|
|
|
|
} => (source, target, source_bindings, target_bindings, type_ns_only, id),
|
|
|
|
ImportKind::Glob { is_prelude, ref max_vis, id } => {
|
|
|
|
if import.module_path.len() <= 1 {
|
|
|
|
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
|
|
|
// 2 segments, so the `resolve_path` above won't trigger it.
|
|
|
|
let mut full_path = import.module_path.clone();
|
|
|
|
full_path.push(Segment::from_ident(Ident::empty()));
|
2023-02-22 21:20:54 +04:00
|
|
|
self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
|
2022-10-30 13:35:31 +04:00
|
|
|
}
|
2018-08-09 16:29:22 +03:00
|
|
|
|
2022-10-30 13:35:31 +04:00
|
|
|
if let ModuleOrUniformRoot::Module(module) = module {
|
2023-07-04 20:00:42 +03:00
|
|
|
if module == import.parent_scope.module {
|
2022-10-30 13:35:31 +04:00
|
|
|
// Importing a module into itself is not allowed.
|
|
|
|
return Some(UnresolvedImportError {
|
|
|
|
span: import.span,
|
|
|
|
label: Some(String::from(
|
|
|
|
"cannot glob-import a module into itself",
|
|
|
|
)),
|
|
|
|
note: None,
|
|
|
|
suggestion: None,
|
2022-12-27 05:09:33 +00:00
|
|
|
candidates: None,
|
2022-10-30 13:35:31 +04:00
|
|
|
});
|
|
|
|
}
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
2022-10-30 13:35:31 +04:00
|
|
|
if !is_prelude
|
2022-08-27 18:36:57 +03:00
|
|
|
&& let Some(max_vis) = max_vis.get()
|
2023-12-01 10:25:40 +08:00
|
|
|
&& let import_vis = import.expect_vis()
|
|
|
|
&& !max_vis.is_at_least(import_vis, self.tcx)
|
2023-09-19 21:21:01 +01:00
|
|
|
{
|
2023-12-01 10:25:40 +08:00
|
|
|
let def_id = self.local_def_id(id);
|
|
|
|
let msg = format!(
|
|
|
|
"glob import doesn't reexport anything with visibility `{}` because no imported item is public enough",
|
|
|
|
import_vis.to_string(def_id, self.tcx)
|
|
|
|
);
|
|
|
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
2023-09-19 21:21:01 +01:00
|
|
|
UNUSED_IMPORTS,
|
|
|
|
id,
|
|
|
|
import.span,
|
2023-12-11 21:54:36 +01:00
|
|
|
msg,
|
2023-12-01 10:25:40 +08:00
|
|
|
BuiltinLintDiagnostics::RedundantImportVisibility {
|
|
|
|
max_vis: max_vis.to_string(def_id, self.tcx),
|
|
|
|
span: import.span,
|
|
|
|
},
|
2023-09-19 21:21:01 +01:00
|
|
|
);
|
|
|
|
}
|
2022-10-30 13:35:31 +04:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2023-06-16 19:44:06 +00:00
|
|
|
if self.privacy_errors.len() != privacy_errors_len {
|
|
|
|
// Get the Res for the last element, so that we can point to alternative ways of
|
|
|
|
// importing it if available.
|
|
|
|
let mut path = import.module_path.clone();
|
|
|
|
path.push(Segment::from_ident(ident));
|
|
|
|
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
|
|
|
|
self.resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_binding)
|
|
|
|
{
|
|
|
|
let res = module.res().map(|r| (r, ident));
|
|
|
|
for error in &mut self.privacy_errors[privacy_errors_len..] {
|
|
|
|
error.outermost_res = res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
let mut all_ns_err = true;
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2019-12-24 17:38:22 -05:00
|
|
|
if !type_ns_only || ns == TypeNS {
|
2022-08-27 18:36:57 +03:00
|
|
|
let orig_vis = import.vis.take();
|
2019-12-24 17:38:22 -05:00
|
|
|
let binding = this.resolve_ident_in_module(
|
|
|
|
module,
|
|
|
|
ident,
|
|
|
|
ns,
|
2020-03-07 19:02:32 +03:00
|
|
|
&import.parent_scope,
|
2022-04-30 17:31:44 +03:00
|
|
|
Some(Finalize { report_private: false, ..finalize }),
|
2022-04-08 22:50:56 +02:00
|
|
|
target_bindings[ns].get(),
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2020-03-07 19:02:32 +03:00
|
|
|
import.vis.set(orig_vis);
|
2018-11-10 18:58:37 +03:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
match binding {
|
|
|
|
Ok(binding) => {
|
|
|
|
// Consistency checks, analogous to `finalize_macro_resolutions`.
|
2023-05-29 23:36:06 +03:00
|
|
|
let initial_res = source_bindings[ns].get().map(|initial_binding| {
|
2019-12-24 17:38:22 -05:00
|
|
|
all_ns_err = false;
|
|
|
|
if let Some(target_binding) = target_bindings[ns].get() {
|
2020-07-08 11:04:10 +10:00
|
|
|
if target.name == kw::Underscore
|
2019-12-24 17:38:22 -05:00
|
|
|
&& initial_binding.is_extern_crate()
|
|
|
|
&& !initial_binding.is_import()
|
|
|
|
{
|
2023-11-10 10:11:24 +08:00
|
|
|
let used = if import.module_path.is_empty() {
|
|
|
|
Used::Scope
|
|
|
|
} else {
|
|
|
|
Used::Other
|
|
|
|
};
|
|
|
|
this.record_use(ident, target_binding, used);
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
|
|
|
}
|
2023-05-29 23:36:06 +03:00
|
|
|
initial_binding.res()
|
2019-12-24 17:38:22 -05:00
|
|
|
});
|
|
|
|
let res = binding.res();
|
2023-12-12 20:41:51 +01:00
|
|
|
let has_ambiguity_error =
|
|
|
|
this.ambiguity_errors.iter().any(|error| !error.warning);
|
2023-07-26 22:46:49 +08:00
|
|
|
if res == Res::Err || has_ambiguity_error {
|
2023-12-18 22:21:37 +11:00
|
|
|
this.dcx()
|
2023-11-30 15:01:11 +11:00
|
|
|
.span_delayed_bug(import.span, "some error happened for an import");
|
2023-07-25 01:57:12 +08:00
|
|
|
return;
|
|
|
|
}
|
2023-05-29 23:36:06 +03:00
|
|
|
if let Ok(initial_res) = initial_res {
|
2023-07-25 01:57:12 +08:00
|
|
|
if res != initial_res {
|
2023-05-29 23:36:06 +03:00
|
|
|
span_bug!(import.span, "inconsistent resolution for an import");
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2023-07-25 01:57:12 +08:00
|
|
|
} else if this.privacy_errors.is_empty() {
|
2023-12-18 22:21:37 +11:00
|
|
|
this.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(CannotDetermineImportResolution { span: import.span })
|
|
|
|
.emit();
|
2018-11-10 18:58:37 +03:00
|
|
|
}
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
Err(..) => {
|
|
|
|
// FIXME: This assert may fire if public glob is later shadowed by a private
|
|
|
|
// single import (see test `issue-55884-2.rs`). In theory single imports should
|
|
|
|
// always block globs, even if they are not yet resolved, so that this kind of
|
|
|
|
// self-inconsistent resolution never happens.
|
2020-03-06 12:13:55 +01:00
|
|
|
// Re-enable the assert when the issue is fixed.
|
2019-12-24 17:38:22 -05:00
|
|
|
// assert!(result[ns].get().is_err());
|
|
|
|
}
|
2018-10-20 20:26:24 +03:00
|
|
|
}
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
if all_ns_err {
|
|
|
|
let mut all_ns_failed = true;
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2019-12-24 17:38:22 -05:00
|
|
|
if !type_ns_only || ns == TypeNS {
|
|
|
|
let binding = this.resolve_ident_in_module(
|
|
|
|
module,
|
|
|
|
ident,
|
|
|
|
ns,
|
2020-03-07 19:02:32 +03:00
|
|
|
&import.parent_scope,
|
2022-04-30 17:31:44 +03:00
|
|
|
Some(finalize),
|
2022-04-08 22:50:56 +02:00
|
|
|
None,
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
|
|
|
if binding.is_ok() {
|
|
|
|
all_ns_failed = false;
|
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
}
|
|
|
|
});
|
2016-08-15 08:19:09 +00:00
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
return if all_ns_failed {
|
2018-08-09 16:29:22 +03:00
|
|
|
let resolutions = match module {
|
2023-02-22 21:20:54 +04:00
|
|
|
ModuleOrUniformRoot::Module(module) => Some(self.resolutions(module).borrow()),
|
2018-11-24 19:14:05 +03:00
|
|
|
_ => None,
|
2018-08-09 16:29:22 +03:00
|
|
|
};
|
|
|
|
let resolutions = resolutions.as_ref().into_iter().flat_map(|r| r.iter());
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
let names = resolutions
|
|
|
|
.filter_map(|(BindingKey { ident: i, .. }, resolution)| {
|
2022-12-27 07:17:22 +00:00
|
|
|
if i.name == ident.name {
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
return None;
|
|
|
|
} // Never suggest the same name
|
|
|
|
match *resolution.borrow() {
|
|
|
|
NameResolution { binding: Some(name_binding), .. } => {
|
|
|
|
match name_binding.kind {
|
|
|
|
NameBindingKind::Import { binding, .. } => {
|
|
|
|
match binding.kind {
|
|
|
|
// Never suggest the name that has binding error
|
|
|
|
// i.e., the name that cannot be previously resolved
|
2022-10-30 15:55:58 +04:00
|
|
|
NameBindingKind::Res(Res::Err) => None,
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
_ => Some(i.name),
|
|
|
|
}
|
2017-02-02 22:05:49 +11:00
|
|
|
}
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
_ => Some(i.name),
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2017-02-02 22:05:49 +11:00
|
|
|
}
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
NameResolution { ref single_imports, .. }
|
|
|
|
if single_imports.is_empty() =>
|
|
|
|
{
|
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => Some(i.name),
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
})
|
|
|
|
.collect::<Vec<Symbol>>();
|
2019-01-16 15:30:41 -05:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let lev_suggestion =
|
Move lev_distance to rustc_ast, make non-generic
rustc_ast currently has a few dependencies on rustc_lexer. Ideally, an AST
would not have any dependency its lexer, for minimizing unnecessarily
design-time dependencies. Breaking this dependency would also have practical
benefits, since modifying rustc_lexer would not trigger a rebuild of rustc_ast.
This commit does not remove the rustc_ast --> rustc_lexer dependency,
but it does remove one of the sources of this dependency, which is the
code that handles fuzzy matching between symbol names for making suggestions
in diagnostics. Since that code depends only on Symbol, it is easy to move
it to rustc_span. It might even be best to move it to a separate crate,
since other tools such as Cargo use the same algorithm, and have simply
contain a duplicate of the code.
This changes the signature of find_best_match_for_name so that it is no
longer generic over its input. I checked the optimized binaries, and this
function was duplicated at nearly every call site, because most call sites
used short-lived iterator chains, generic over Map and such. But there's
no good reason for a function like this to be generic, since all it does
is immediately convert the generic input (the Iterator impl) to a concrete
Vec<Symbol>. This has all of the costs of generics (duplicated method bodies)
with no benefit.
Changing find_best_match_for_name to be non-generic removed about 10KB of
code from the optimized binary. I know it's a drop in the bucket, but we have
to start reducing binary size, and beginning to tame over-use of generics
is part of that.
2020-11-12 11:24:10 -08:00
|
|
|
find_best_match_for_name(&names, ident.name, None).map(|suggestion| {
|
2019-12-24 17:38:22 -05:00
|
|
|
(
|
|
|
|
vec![(ident.span, suggestion.to_string())],
|
|
|
|
String::from("a similar name exists in the module"),
|
|
|
|
Applicability::MaybeIncorrect,
|
|
|
|
)
|
|
|
|
});
|
2019-04-07 20:34:21 +02:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let (suggestion, note) =
|
2020-03-07 19:02:32 +03:00
|
|
|
match self.check_for_module_export_macro(import, module, ident) {
|
2019-12-24 17:38:22 -05:00
|
|
|
Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),
|
2022-07-28 18:17:55 +09:00
|
|
|
_ => (lev_suggestion, None),
|
2019-12-24 17:38:22 -05:00
|
|
|
};
|
2019-01-16 15:30:41 -05:00
|
|
|
|
|
|
|
let label = match module {
|
2018-08-09 16:29:22 +03:00
|
|
|
ModuleOrUniformRoot::Module(module) => {
|
|
|
|
let module_str = module_to_string(module);
|
|
|
|
if let Some(module_str) = module_str {
|
2023-07-25 23:04:01 +02:00
|
|
|
format!("no `{ident}` in `{module_str}`")
|
2018-08-09 16:29:22 +03:00
|
|
|
} else {
|
2023-07-25 23:04:01 +02:00
|
|
|
format!("no `{ident}` in the root")
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
|
|
|
}
|
2018-11-24 19:14:05 +03:00
|
|
|
_ => {
|
2018-08-09 16:29:22 +03:00
|
|
|
if !ident.is_path_segment_keyword() {
|
2023-07-25 23:04:01 +02:00
|
|
|
format!("no external crate `{ident}`")
|
2018-08-09 16:29:22 +03:00
|
|
|
} else {
|
|
|
|
// HACK(eddyb) this shows up for `self` & `super`, which
|
|
|
|
// should work instead - for now keep the same error message.
|
2023-07-25 23:04:01 +02:00
|
|
|
format!("no `{ident}` in the root")
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
|
|
|
}
|
2016-04-09 01:06:57 +00:00
|
|
|
};
|
2019-04-07 19:56:41 +02:00
|
|
|
|
2022-10-10 11:14:32 +08:00
|
|
|
let parent_suggestion =
|
2023-02-22 21:20:54 +04:00
|
|
|
self.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);
|
2022-10-10 11:14:32 +08:00
|
|
|
|
2019-01-16 15:30:41 -05:00
|
|
|
Some(UnresolvedImportError {
|
2020-03-07 19:02:32 +03:00
|
|
|
span: import.span,
|
2019-01-16 15:30:41 -05:00
|
|
|
label: Some(label),
|
2019-04-07 19:56:41 +02:00
|
|
|
note,
|
|
|
|
suggestion,
|
2022-12-27 05:09:33 +00:00
|
|
|
candidates: if !parent_suggestion.is_empty() {
|
2022-10-10 11:14:32 +08:00
|
|
|
Some(parent_suggestion)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
},
|
2019-01-16 15:30:41 -05:00
|
|
|
})
|
2016-08-15 08:19:09 +00:00
|
|
|
} else {
|
2016-11-29 02:07:12 +00:00
|
|
|
// `resolve_ident_in_module` reported a privacy error.
|
2016-11-26 12:21:47 +00:00
|
|
|
None
|
2019-12-24 17:38:22 -05:00
|
|
|
};
|
2016-07-25 23:04:42 +00:00
|
|
|
}
|
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
let mut reexport_error = None;
|
|
|
|
let mut any_successful_reexport = false;
|
2021-11-06 04:43:55 +09:00
|
|
|
let mut crate_private_reexport = false;
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2018-11-30 21:16:21 +03:00
|
|
|
if let Ok(binding) = source_bindings[ns].get() {
|
2023-02-22 19:51:17 +04:00
|
|
|
if !binding.vis.is_at_least(import.expect_vis(), this.tcx) {
|
2016-11-10 06:19:54 +00:00
|
|
|
reexport_error = Some((ns, binding));
|
2021-11-06 04:43:55 +09:00
|
|
|
if let ty::Visibility::Restricted(binding_def_id) = binding.vis {
|
|
|
|
if binding_def_id.is_top_level_module() {
|
|
|
|
crate_private_reexport = true;
|
|
|
|
}
|
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
} else {
|
2016-11-10 06:19:54 +00:00
|
|
|
any_successful_reexport = true;
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2015-12-14 22:36:31 +05:30
|
|
|
|
2016-11-10 06:19:54 +00:00
|
|
|
// All namespaces must be re-exported with extra visibility for an error to occur.
|
|
|
|
if !any_successful_reexport {
|
2017-05-21 15:50:38 +03:00
|
|
|
let (ns, binding) = reexport_error.unwrap();
|
2021-01-29 00:59:20 +03:00
|
|
|
if pub_use_of_private_extern_crate_hack(import, binding) {
|
2019-12-24 17:38:22 -05:00
|
|
|
let msg = format!(
|
2023-07-25 23:04:01 +02:00
|
|
|
"extern crate `{ident}` is private, and cannot be \
|
2018-01-12 16:41:45 -05:00
|
|
|
re-exported (error E0365), consider declaring with \
|
2023-07-25 23:04:01 +02:00
|
|
|
`pub`"
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2023-02-22 21:20:54 +04:00
|
|
|
self.lint_buffer.buffer_lint(
|
2019-12-24 17:38:22 -05:00
|
|
|
PUB_USE_OF_PRIVATE_EXTERN_CRATE,
|
2022-10-30 13:35:31 +04:00
|
|
|
import_id,
|
2020-03-07 19:02:32 +03:00
|
|
|
import.span,
|
Restrict `From<S>` for `{D,Subd}iagnosticMessage`.
Currently a `{D,Subd}iagnosticMessage` can be created from any type that
impls `Into<String>`. That includes `&str`, `String`, and `Cow<'static,
str>`, which are reasonable. It also includes `&String`, which is pretty
weird, and results in many places making unnecessary allocations for
patterns like this:
```
self.fatal(&format!(...))
```
This creates a string with `format!`, takes a reference, passes the
reference to `fatal`, which does an `into()`, which clones the
reference, doing a second allocation. Two allocations for a single
string, bleh.
This commit changes the `From` impls so that you can only create a
`{D,Subd}iagnosticMessage` from `&str`, `String`, or `Cow<'static,
str>`. This requires changing all the places that currently create one
from a `&String`. Most of these are of the `&format!(...)` form
described above; each one removes an unnecessary static `&`, plus an
allocation when executed. There are also a few places where the existing
use of `&String` was more reasonable; these now just use `clone()` at
the call site.
As well as making the code nicer and more efficient, this is a step
towards possibly using `Cow<'static, str>` in
`{D,Subd}iagnosticMessage::{Str,Eager}`. That would require changing
the `From<&'a str>` impls to `From<&'static str>`, which is doable, but
I'm not yet sure if it's worthwhile.
2023-04-20 13:26:58 +10:00
|
|
|
msg,
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2016-11-10 06:19:54 +00:00
|
|
|
} else {
|
2021-11-06 04:43:55 +09:00
|
|
|
if ns == TypeNS {
|
Make `DiagnosticBuilder::emit` consuming.
This works for most of its call sites. This is nice, because `emit` very
much makes sense as a consuming operation -- indeed,
`DiagnosticBuilderState` exists to ensure no diagnostic is emitted
twice, but it uses runtime checks.
For the small number of call sites where a consuming emit doesn't work,
the commit adds `DiagnosticBuilder::emit_without_consuming`. (This will
be removed in subsequent commits.)
Likewise, `emit_unless` becomes consuming. And `delay_as_bug` becomes
consuming, while `delay_as_bug_without_consuming` is added (which will
also be removed in subsequent commits.)
All this requires significant changes to `DiagnosticBuilder`'s chaining
methods. Currently `DiagnosticBuilder` method chaining uses a
non-consuming `&mut self -> &mut Self` style, which allows chaining to
be used when the chain ends in `emit()`, like so:
```
struct_err(msg).span(span).emit();
```
But it doesn't work when producing a `DiagnosticBuilder` value,
requiring this:
```
let mut err = self.struct_err(msg);
err.span(span);
err
```
This style of chaining won't work with consuming `emit` though. For
that, we need to use to a `self -> Self` style. That also would allow
`DiagnosticBuilder` production to be chained, e.g.:
```
self.struct_err(msg).span(span)
```
However, removing the `&mut self -> &mut Self` style would require that
individual modifications of a `DiagnosticBuilder` go from this:
```
err.span(span);
```
to this:
```
err = err.span(span);
```
There are *many* such places. I have a high tolerance for tedious
refactorings, but even I gave up after a long time trying to convert
them all.
Instead, this commit has it both ways: the existing `&mut self -> Self`
chaining methods are kept, and new `self -> Self` chaining methods are
added, all of which have a `_mv` suffix (short for "move"). Changes to
the existing `forward!` macro lets this happen with very little
additional boilerplate code. I chose to add the suffix to the new
chaining methods rather than the existing ones, because the number of
changes required is much smaller that way.
This doubled chainging is a bit clumsy, but I think it is worthwhile
because it allows a *lot* of good things to subsequently happen. In this
commit, there are many `mut` qualifiers removed in places where
diagnostics are emitted without being modified. In subsequent commits:
- chaining can be used more, making the code more concise;
- more use of chaining also permits the removal of redundant diagnostic
APIs like `struct_err_with_code`, which can be replaced easily with
`struct_err` + `code_mv`;
- `emit_without_diagnostic` can be removed, which simplifies a lot of
machinery, removing the need for `DiagnosticBuilderState`.
2024-01-03 12:17:35 +11:00
|
|
|
let err = if crate_private_reexport {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx().create_err(CannotBeReexportedCratePublicNS {
|
2023-06-21 20:51:24 +01:00
|
|
|
span: import.span,
|
|
|
|
ident,
|
|
|
|
})
|
2021-11-06 04:43:55 +09:00
|
|
|
} else {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
|
2021-11-06 04:43:55 +09:00
|
|
|
};
|
2023-06-21 20:51:24 +01:00
|
|
|
err.emit();
|
2021-11-06 04:43:55 +09:00
|
|
|
} else {
|
2023-06-21 20:51:24 +01:00
|
|
|
let mut err = if crate_private_reexport {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
|
|
|
|
} else {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.dcx()
|
2023-06-21 20:51:24 +01:00
|
|
|
.create_err(CannotBeReexportedPrivate { span: import.span, ident })
|
|
|
|
};
|
|
|
|
|
2022-06-14 14:58:46 +09:00
|
|
|
match binding.kind {
|
2022-10-30 15:55:58 +04:00
|
|
|
NameBindingKind::Res(Res::Def(DefKind::Macro(_), def_id))
|
2022-06-14 14:58:46 +09:00
|
|
|
// exclude decl_macro
|
2023-02-22 21:20:54 +04:00
|
|
|
if self.get_macro_by_def_id(def_id).macro_rules =>
|
2022-06-14 14:58:46 +09:00
|
|
|
{
|
2024-02-14 14:17:27 +00:00
|
|
|
err.subdiagnostic(self.dcx(), ConsiderAddingMacroExport {
|
2023-06-21 20:51:24 +01:00
|
|
|
span: binding.span,
|
|
|
|
});
|
2022-06-14 14:58:46 +09:00
|
|
|
}
|
|
|
|
_ => {
|
2024-02-14 14:17:27 +00:00
|
|
|
err.subdiagnostic(self.dcx(), ConsiderMarkingAsPub {
|
2023-06-21 20:51:24 +01:00
|
|
|
span: import.span,
|
|
|
|
ident,
|
|
|
|
});
|
2022-06-14 14:58:46 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
err.emit();
|
2021-11-06 04:43:55 +09:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
}
|
2016-01-14 01:42:45 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
if import.module_path.len() <= 1 {
|
2018-08-09 16:29:22 +03:00
|
|
|
// HACK(eddyb) `lint_if_path_starts_with_module` needs at least
|
|
|
|
// 2 segments, so the `resolve_path` above won't trigger it.
|
2020-03-07 19:02:32 +03:00
|
|
|
let mut full_path = import.module_path.clone();
|
2018-09-12 15:21:50 +12:00
|
|
|
full_path.push(Segment::from_ident(ident));
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2018-11-30 21:16:21 +03:00
|
|
|
if let Ok(binding) = source_bindings[ns].get() {
|
2022-04-30 17:31:44 +03:00
|
|
|
this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding));
|
2018-05-11 10:02:17 -07:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2016-02-07 23:06:10 +00:00
|
|
|
// Record what this import resolves to for later uses in documentation,
|
|
|
|
// this may resolve to either a value or a type, but for documentation
|
|
|
|
// purposes it's good enough to just favor one over the other.
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2020-03-02 00:09:17 +01:00
|
|
|
if let Ok(binding) = source_bindings[ns].get() {
|
2022-10-30 13:35:31 +04:00
|
|
|
this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2016-11-10 06:19:54 +00:00
|
|
|
});
|
2015-03-16 10:44:19 +13:00
|
|
|
|
|
|
|
debug!("(resolving single import) successfully resolved import");
|
2016-11-26 12:21:47 +00:00
|
|
|
None
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) {
|
2022-10-30 13:35:31 +04:00
|
|
|
// This function is only called for single imports.
|
2023-11-10 10:11:24 +08:00
|
|
|
let ImportKind::Single {
|
|
|
|
source, target, ref source_bindings, ref target_bindings, id, ..
|
|
|
|
} = import.kind
|
|
|
|
else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
|
|
|
|
|
|
|
// Skip if the import is of the form `use source as target` and source != target.
|
|
|
|
if source != target {
|
|
|
|
return;
|
|
|
|
}
|
2022-10-30 13:35:31 +04:00
|
|
|
|
2019-03-16 16:49:13 +01:00
|
|
|
// Skip if the import was produced by a macro.
|
2021-06-25 20:43:04 +02:00
|
|
|
if import.parent_scope.expansion != LocalExpnId::ROOT {
|
2019-02-22 15:07:18 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-16 16:49:13 +01:00
|
|
|
// Skip if we are inside a named module (in contrast to an anonymous
|
|
|
|
// module defined by a block).
|
2023-11-10 10:11:24 +08:00
|
|
|
// Skip if the import is public or was used through non scope-based resolution,
|
|
|
|
// e.g. through a module-relative path.
|
|
|
|
if import.used.get() == Some(Used::Other)
|
|
|
|
|| self.effective_visibilities.is_exported(self.local_def_id(id))
|
|
|
|
{
|
2019-02-22 15:07:18 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
let mut is_redundant = true;
|
2019-02-22 15:07:18 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
|
2019-02-22 15:07:18 +01:00
|
|
|
|
2023-02-22 21:20:54 +04:00
|
|
|
self.per_ns(|this, ns| {
|
2023-11-10 10:11:24 +08:00
|
|
|
if is_redundant && let Ok(binding) = source_bindings[ns].get() {
|
2019-12-24 17:38:22 -05:00
|
|
|
if binding.res() == Res::Err {
|
|
|
|
return;
|
|
|
|
}
|
2019-02-22 15:07:18 +01:00
|
|
|
|
2019-12-24 17:38:22 -05:00
|
|
|
match this.early_resolve_ident_in_lexical_scope(
|
|
|
|
target,
|
2023-05-29 23:36:06 +03:00
|
|
|
ScopeSet::All(ns),
|
2020-03-07 19:02:32 +03:00
|
|
|
&import.parent_scope,
|
2022-03-24 00:32:00 +03:00
|
|
|
None,
|
2019-12-24 17:38:22 -05:00
|
|
|
false,
|
2022-04-08 22:50:56 +02:00
|
|
|
target_bindings[ns].get(),
|
2019-12-24 17:38:22 -05:00
|
|
|
) {
|
|
|
|
Ok(other_binding) => {
|
2023-11-10 10:11:24 +08:00
|
|
|
is_redundant =
|
|
|
|
binding.res() == other_binding.res() && !other_binding.is_ambiguity();
|
|
|
|
if is_redundant {
|
|
|
|
redundant_span[ns] =
|
|
|
|
Some((other_binding.span, other_binding.is_import()));
|
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2023-11-10 10:11:24 +08:00
|
|
|
Err(_) => is_redundant = false,
|
2019-02-22 15:07:18 +01:00
|
|
|
}
|
2019-12-24 17:38:22 -05:00
|
|
|
}
|
2019-02-22 15:07:18 +01:00
|
|
|
});
|
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
if is_redundant && !redundant_span.is_empty() {
|
2019-04-11 16:15:48 -07:00
|
|
|
let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();
|
2019-04-12 11:42:52 -07:00
|
|
|
redundant_spans.sort();
|
2019-04-11 16:15:48 -07:00
|
|
|
redundant_spans.dedup();
|
2023-02-22 21:20:54 +04:00
|
|
|
self.lint_buffer.buffer_lint_with_diagnostic(
|
2019-03-17 09:49:31 +01:00
|
|
|
UNUSED_IMPORTS,
|
2022-10-30 13:35:31 +04:00
|
|
|
id,
|
2020-03-07 19:02:32 +03:00
|
|
|
import.span,
|
2023-11-10 10:11:24 +08:00
|
|
|
format!("the item `{source}` is imported redundantly"),
|
|
|
|
BuiltinLintDiagnostics::RedundantImport(redundant_spans, source),
|
2019-02-22 15:07:18 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-04 18:51:35 +03:00
|
|
|
fn resolve_glob_import(&mut self, import: Import<'a>) {
|
2022-10-30 13:35:31 +04:00
|
|
|
// This function is only called for glob imports.
|
|
|
|
let ImportKind::Glob { id, is_prelude, .. } = import.kind else { unreachable!() };
|
|
|
|
|
2022-02-19 00:48:49 +01:00
|
|
|
let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {
|
2024-01-04 10:38:10 +11:00
|
|
|
self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });
|
2022-02-19 00:48:49 +01:00
|
|
|
return;
|
2018-08-09 16:29:22 +03:00
|
|
|
};
|
|
|
|
|
2019-03-15 14:55:04 -07:00
|
|
|
if module.is_trait() {
|
2024-01-04 10:38:10 +11:00
|
|
|
self.dcx().emit_err(ItemsInTraitsAreNotImportable { span: import.span });
|
2016-08-19 21:46:28 +00:00
|
|
|
return;
|
2023-07-04 20:00:42 +03:00
|
|
|
} else if module == import.parent_scope.module {
|
2016-08-15 08:19:09 +00:00
|
|
|
return;
|
2022-10-30 13:35:31 +04:00
|
|
|
} else if is_prelude {
|
2023-02-22 21:20:54 +04:00
|
|
|
self.prelude = Some(module);
|
2016-08-15 08:19:09 +00:00
|
|
|
return;
|
2016-03-09 01:46:46 +00:00
|
|
|
}
|
|
|
|
|
2016-08-18 01:43:26 +00:00
|
|
|
// Add to module's glob_importers
|
2020-03-07 19:02:32 +03:00
|
|
|
module.glob_importers.borrow_mut().push(import);
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2016-07-28 02:34:01 +00:00
|
|
|
// Ensure that `resolutions` isn't borrowed during `try_define`,
|
2016-04-11 18:30:48 +00:00
|
|
|
// since it might get updated via a glob cycle.
|
2019-12-24 17:38:22 -05:00
|
|
|
let bindings = self
|
|
|
|
.resolutions(module)
|
|
|
|
.borrow()
|
|
|
|
.iter()
|
|
|
|
.filter_map(|(key, resolution)| {
|
|
|
|
resolution.borrow().binding().map(|binding| (*key, binding))
|
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
2019-09-09 21:04:26 +01:00
|
|
|
for (mut key, binding) in bindings {
|
2020-03-07 19:02:32 +03:00
|
|
|
let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) {
|
2023-02-22 21:20:54 +04:00
|
|
|
Some(Some(def)) => self.expn_def_scope(def),
|
2020-03-07 19:02:32 +03:00
|
|
|
Some(None) => import.parent_scope.module,
|
2017-03-22 08:39:51 +00:00
|
|
|
None => continue,
|
|
|
|
};
|
2023-02-22 21:20:54 +04:00
|
|
|
if self.is_accessible_from(binding.vis, scope) {
|
|
|
|
let imported_binding = self.import(binding, import);
|
2023-07-26 22:46:49 +08:00
|
|
|
let warn_ambiguity = self
|
|
|
|
.resolution(import.parent_scope.module, key)
|
|
|
|
.borrow()
|
|
|
|
.binding()
|
|
|
|
.is_some_and(|binding| binding.is_warn_ambiguity());
|
|
|
|
let _ = self.try_define(
|
|
|
|
import.parent_scope.module,
|
|
|
|
key,
|
|
|
|
imported_binding,
|
|
|
|
warn_ambiguity,
|
|
|
|
);
|
2016-02-07 23:58:14 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
|
|
|
|
// Record the destination of this import
|
2023-02-22 21:20:54 +04:00
|
|
|
self.record_partial_res(id, PartialRes::new(module.res().unwrap()));
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2018-01-12 16:41:25 -05:00
|
|
|
// Miscellaneous post-processing, including recording re-exports,
|
2017-05-21 14:11:08 +03:00
|
|
|
// reporting conflicts, and reporting unresolved imports.
|
2023-02-22 21:20:54 +04:00
|
|
|
fn finalize_resolutions_in(&mut self, module: Module<'a>) {
|
2016-02-16 03:54:14 +00:00
|
|
|
// Since import resolution is finished, globs will not define any more names.
|
2016-03-17 11:05:09 +00:00
|
|
|
*module.globs.borrow_mut() = Vec::new();
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2022-06-27 16:29:56 +10:00
|
|
|
if let Some(def_id) = module.opt_def_id() {
|
2023-04-27 18:34:43 +03:00
|
|
|
let mut children = Vec::new();
|
2022-06-27 16:29:56 +10:00
|
|
|
|
2023-02-22 21:20:54 +04:00
|
|
|
module.for_each_child(self, |this, ident, _, binding| {
|
2023-04-10 19:07:57 +03:00
|
|
|
let res = binding.res().expect_non_local();
|
2023-07-26 22:46:49 +08:00
|
|
|
let error_ambiguity = binding.is_ambiguity() && !binding.warn_ambiguity;
|
|
|
|
if res != def::Res::Err && !error_ambiguity {
|
2023-03-22 17:57:39 +04:00
|
|
|
let mut reexport_chain = SmallVec::new();
|
|
|
|
let mut next_binding = binding;
|
|
|
|
while let NameBindingKind::Import { binding, import, .. } = next_binding.kind {
|
|
|
|
reexport_chain.push(import.simplify(this));
|
|
|
|
next_binding = binding;
|
|
|
|
}
|
|
|
|
|
2023-04-27 18:34:43 +03:00
|
|
|
children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2022-06-27 16:29:56 +10:00
|
|
|
});
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2023-04-27 18:34:43 +03:00
|
|
|
if !children.is_empty() {
|
|
|
|
// Should be fine because this code is only called for local modules.
|
|
|
|
self.module_children.insert(def_id.expect_local(), children);
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2020-03-07 18:49:13 +03:00
|
|
|
fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {
|
2019-12-24 17:38:22 -05:00
|
|
|
let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);
|
2019-05-11 17:41:37 +03:00
|
|
|
let global = !names.is_empty() && names[0].name == kw::PathRoot;
|
2017-07-23 15:15:45 -07:00
|
|
|
if let Some(pos) = pos {
|
|
|
|
let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };
|
2019-09-14 21:10:12 +01:00
|
|
|
names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>())
|
2015-03-16 10:44:19 +13:00
|
|
|
} else {
|
2017-07-23 15:15:45 -07:00
|
|
|
let names = if global { &names[1..] } else { names };
|
|
|
|
if names.is_empty() {
|
2020-03-07 19:02:32 +03:00
|
|
|
import_kind_to_string(import_kind)
|
2017-07-23 15:15:45 -07:00
|
|
|
} else {
|
2019-09-14 21:10:12 +01:00
|
|
|
format!(
|
|
|
|
"{}::{}",
|
|
|
|
names_to_string(&names.iter().map(|ident| ident.name).collect::<Vec<_>>()),
|
2020-03-07 19:02:32 +03:00
|
|
|
import_kind_to_string(import_kind),
|
2019-09-14 21:10:12 +01:00
|
|
|
)
|
2017-07-23 15:15:45 -07:00
|
|
|
}
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-07 19:02:32 +03:00
|
|
|
fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
|
2020-03-07 18:49:13 +03:00
|
|
|
match import_kind {
|
|
|
|
ImportKind::Single { source, .. } => source.to_string(),
|
|
|
|
ImportKind::Glob { .. } => "*".to_string(),
|
|
|
|
ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),
|
2023-12-28 15:18:49 +08:00
|
|
|
ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),
|
2022-10-30 15:55:58 +04:00
|
|
|
ImportKind::MacroExport => "#[macro_export]".to_string(),
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
}
|