2019-08-13 02:46:42 +03:00
|
|
|
//! A bunch of methods and structures more or less related to resolving imports.
|
|
|
|
|
2024-07-29 08:13:50 +10:00
|
|
|
use std::cell::Cell;
|
|
|
|
use std::mem;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2020-04-27 23:26:11 +05:30
|
|
|
use rustc_ast::NodeId;
|
2025-03-17 01:34:46 +03:00
|
|
|
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
|
2022-02-04 14:26:29 +11:00
|
|
|
use rustc_data_structures::intern::Interned;
|
2024-07-29 08:13:50 +10:00
|
|
|
use rustc_errors::codes::*;
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
|
2022-06-14 14:58:46 +09:00
|
|
|
use rustc_hir::def::{self, DefKind, PartialRes};
|
2024-03-20 17:06:58 +08:00
|
|
|
use rustc_hir::def_id::DefId;
|
2024-07-29 08:13:50 +10:00
|
|
|
use rustc_middle::metadata::{ModChild, Reexport};
|
|
|
|
use rustc_middle::{span_bug, ty};
|
2024-09-22 19:05:04 -04:00
|
|
|
use rustc_session::lint::BuiltinLintDiag;
|
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,
|
2024-04-11 14:10:34 -04:00
|
|
|
REDUNDANT_IMPORTS, UNUSED_IMPORTS,
|
2023-03-20 03:11:28 +08:00
|
|
|
};
|
2024-12-25 14:54:49 +08:00
|
|
|
use rustc_session::parse::feature_err;
|
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;
|
2024-12-25 14:54:49 +08:00
|
|
|
use rustc_span::{Ident, Span, Symbol, kw, sym};
|
2023-03-22 17:57:39 +04:00
|
|
|
use smallvec::SmallVec;
|
2024-05-10 13:46:24 +10:00
|
|
|
use tracing::debug;
|
2015-03-16 10:44:19 +13:00
|
|
|
|
2024-09-22 19:05:04 -04:00
|
|
|
use crate::Determinacy::{self, *};
|
|
|
|
use crate::Namespace::*;
|
|
|
|
use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
|
2024-07-29 08:13:50 +10:00
|
|
|
use crate::errors::{
|
|
|
|
CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
|
|
|
|
CannotBeReexportedPrivateNS, CannotDetermineImportResolution, CannotGlobImportAllCrates,
|
|
|
|
ConsiderAddingMacroExport, ConsiderMarkingAsPub, IsNotDirectlyImportable,
|
|
|
|
ItemsInTraitsAreNotImportable,
|
|
|
|
};
|
|
|
|
use crate::{
|
2024-09-22 19:05:04 -04:00
|
|
|
AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module,
|
|
|
|
ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
|
|
|
|
PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
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)]
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) enum ImportKind<'ra> {
|
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`.
|
2024-08-04 15:38:11 +08:00
|
|
|
/// It will directly use `source` when the format is `use prefix::source`.
|
2018-11-30 21:16:21 +03:00
|
|
|
target: Ident,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// Bindings to which `source` refers to.
|
2024-09-10 16:19:40 +10:00
|
|
|
source_bindings: PerNS<Cell<Result<NameBinding<'ra>, Determinacy>>>,
|
2018-12-01 22:14:37 +03:00
|
|
|
/// Bindings introduced by `target`.
|
2024-09-10 16:19:40 +10:00
|
|
|
target_bindings: PerNS<Cell<Option<NameBinding<'ra>>>>,
|
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.
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra> std::fmt::Debug for ImportKind<'ra> {
|
2022-08-15 18:29:43 +02:00
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
use ImportKind::*;
|
|
|
|
match self {
|
|
|
|
Single {
|
2025-02-20 18:28:48 +00:00
|
|
|
source,
|
|
|
|
target,
|
|
|
|
source_bindings,
|
|
|
|
target_bindings,
|
|
|
|
type_ns_only,
|
|
|
|
nested,
|
|
|
|
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(),
|
2025-02-20 18:28:48 +00:00
|
|
|
Glob { is_prelude, max_vis, 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(),
|
2025-02-20 18:28:48 +00:00
|
|
|
ExternCrate { source, target, 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)]
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) struct ImportData<'ra> {
|
|
|
|
pub kind: ImportKind<'ra>,
|
2020-03-07 18:49:13 +03:00
|
|
|
|
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,
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub parent_scope: ParentScope<'ra>,
|
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`.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub imported_module: Cell<Option<ModuleOrUniformRoot<'ra>>>,
|
2024-08-06 19:27:15 +08:00
|
|
|
pub vis: ty::Visibility,
|
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.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>;
|
2023-07-04 18:51:35 +03:00
|
|
|
|
2025-02-17 21:16:08 -05:00
|
|
|
// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
|
|
|
|
// contained data.
|
|
|
|
// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
|
|
|
|
// are upheld.
|
|
|
|
impl std::hash::Hash for ImportData<'_> {
|
|
|
|
fn hash<H>(&self, _: &mut H)
|
|
|
|
where
|
|
|
|
H: std::hash::Hasher,
|
|
|
|
{
|
|
|
|
unreachable!()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra> ImportData<'ra> {
|
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
|
|
|
|
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)]
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) struct NameResolution<'ra> {
|
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.
|
2025-03-17 01:34:46 +03:00
|
|
|
pub single_imports: FxIndexSet<Import<'ra>>,
|
2016-02-07 23:58:14 +00:00
|
|
|
/// The least shadowable known binding for this name, or None if there are no known bindings.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub binding: Option<NameBinding<'ra>>,
|
|
|
|
pub shadowed_glob: Option<NameBinding<'ra>>,
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra> NameResolution<'ra> {
|
2022-11-27 11:15:06 +00:00
|
|
|
/// Returns the binding for the name if it is known or None if it not known.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn binding(&self) -> Option<NameBinding<'ra>> {
|
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>>,
|
2024-03-20 17:06:58 +08:00
|
|
|
segment: Option<Symbol>,
|
|
|
|
/// comes from `PathRes::Failed { module }`
|
|
|
|
module: Option<DefId>,
|
2023-02-22 21:20:54 +04:00
|
|
|
}
|
|
|
|
|
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.
|
2024-06-03 07:17:19 +02:00
|
|
|
fn pub_use_of_private_extern_crate_hack(
|
|
|
|
import: Import<'_>,
|
|
|
|
binding: NameBinding<'_>,
|
|
|
|
) -> Option<NodeId> {
|
2021-01-29 00:59:20 +03:00
|
|
|
match (&import.kind, &binding.kind) {
|
2024-06-03 07:17:19 +02:00
|
|
|
(ImportKind::Single { .. }, NameBindingKind::Import { import: binding_import, .. })
|
|
|
|
if let ImportKind::ExternCrate { id, .. } = binding_import.kind
|
2024-08-06 19:27:15 +08:00
|
|
|
&& import.vis.is_public() =>
|
2024-06-03 07:17:19 +02:00
|
|
|
{
|
|
|
|
Some(id)
|
2023-07-04 18:51:35 +03:00
|
|
|
}
|
2024-06-03 07:17:19 +02:00
|
|
|
_ => None,
|
2021-01-29 00:59:20 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
impl<'ra, 'tcx> Resolver<'ra, '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.
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn import(
|
|
|
|
&self,
|
|
|
|
binding: NameBinding<'ra>,
|
|
|
|
import: Import<'ra>,
|
|
|
|
) -> NameBinding<'ra> {
|
2024-08-06 19:27:15 +08:00
|
|
|
let import_vis = import.vis.to_def_id();
|
2023-02-22 19:51:17 +04:00
|
|
|
let vis = if binding.vis.is_at_least(import_vis, self.tcx)
|
2024-06-03 07:17:19 +02:00
|
|
|
|| pub_use_of_private_extern_crate_hack(import, binding).is_some()
|
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
|
|
|
};
|
|
|
|
|
2025-01-20 17:41:03 +00:00
|
|
|
if let ImportKind::Glob { ref max_vis, .. } = import.kind
|
|
|
|
&& (vis == import_vis
|
|
|
|
|| max_vis.get().is_none_or(|max_vis| vis.is_at_least(max_vis, self.tcx)))
|
|
|
|
{
|
|
|
|
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,
|
2024-09-10 16:19:40 +10:00
|
|
|
module: Module<'ra>,
|
2019-09-09 21:04:26 +01:00
|
|
|
key: BindingKey,
|
2024-09-10 16:19:40 +10:00
|
|
|
binding: NameBinding<'ra>,
|
2023-07-26 22:46:49 +08:00
|
|
|
warn_ambiguity: bool,
|
2024-09-10 16:19:40 +10:00
|
|
|
) -> Result<(), NameBinding<'ra>> {
|
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) => {
|
2024-06-25 19:03:39 +03:00
|
|
|
// FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity.
|
|
|
|
if !binding.is_ambiguity_recursive()
|
2023-10-13 08:58:33 +00:00
|
|
|
&& let NameBindingKind::Import { import: old_import, .. } =
|
|
|
|
old_binding.kind
|
2023-07-26 22:46:49 +08:00
|
|
|
&& let NameBindingKind::Import { import, .. } = binding.kind
|
2023-10-13 08:58:33 +00:00
|
|
|
&& old_import == import
|
|
|
|
{
|
2023-07-26 22:46:49 +08:00
|
|
|
// 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() {
|
2024-06-25 19:03:39 +03:00
|
|
|
resolution.binding = Some(this.new_ambiguity_binding(
|
|
|
|
AmbiguityKind::GlobVsGlob,
|
|
|
|
old_binding,
|
|
|
|
binding,
|
|
|
|
warn_ambiguity,
|
|
|
|
));
|
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);
|
2024-06-25 19:03:39 +03:00
|
|
|
} else if binding.is_ambiguity_recursive() {
|
|
|
|
resolution.binding = Some(this.new_warn_ambiguity_binding(binding));
|
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) };
|
2024-06-04 12:40:41 +08:00
|
|
|
if key.ns == MacroNS
|
2021-06-25 20:43:04 +02:00
|
|
|
&& nonglob_binding.expansion != LocalExpnId::ROOT
|
2024-06-04 12:40:41 +08:00
|
|
|
&& glob_binding.res() != nonglob_binding.res()
|
2019-09-09 21:04:26 +01:00
|
|
|
{
|
2024-06-25 19:03:39 +03:00
|
|
|
resolution.binding = Some(this.new_ambiguity_binding(
|
2019-09-01 00:01:25 -07:00
|
|
|
AmbiguityKind::GlobVsExpanded,
|
|
|
|
nonglob_binding,
|
|
|
|
glob_binding,
|
2024-06-25 19:03:39 +03:00
|
|
|
false,
|
2019-09-01 00:01:25 -07:00
|
|
|
));
|
2018-11-05 01:11:59 +03:00
|
|
|
} else {
|
|
|
|
resolution.binding = Some(nonglob_binding);
|
|
|
|
}
|
2023-06-14 00:55:36 +08:00
|
|
|
|
2024-06-25 19:03:39 +03:00
|
|
|
if let Some(old_shadowed_glob) = resolution.shadowed_glob {
|
|
|
|
assert!(old_shadowed_glob.is_glob_import());
|
|
|
|
if glob_binding.res() != old_shadowed_glob.res() {
|
|
|
|
resolution.shadowed_glob = Some(this.new_ambiguity_binding(
|
2023-06-14 00:55:36 +08:00
|
|
|
AmbiguityKind::GlobVsGlob,
|
2024-06-25 19:03:39 +03:00
|
|
|
old_shadowed_glob,
|
2023-06-14 00:55:36 +08:00
|
|
|
glob_binding,
|
2024-06-25 19:03:39 +03:00
|
|
|
false,
|
2023-06-14 00:55:36 +08:00
|
|
|
));
|
2024-06-25 19:03:39 +03:00
|
|
|
} else if !old_shadowed_glob.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(())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-06-25 19:03:39 +03:00
|
|
|
fn new_ambiguity_binding(
|
2023-06-20 22:47:50 +08:00
|
|
|
&self,
|
2024-06-25 19:03:39 +03:00
|
|
|
ambiguity_kind: AmbiguityKind,
|
2024-09-10 16:19:40 +10:00
|
|
|
primary_binding: NameBinding<'ra>,
|
|
|
|
secondary_binding: NameBinding<'ra>,
|
2024-06-25 19:03:39 +03:00
|
|
|
warn_ambiguity: bool,
|
2024-09-10 16:19:40 +10:00
|
|
|
) -> NameBinding<'ra> {
|
2024-06-25 19:03:39 +03:00
|
|
|
let ambiguity = Some((secondary_binding, ambiguity_kind));
|
|
|
|
let data = NameBindingData { ambiguity, warn_ambiguity, ..*primary_binding };
|
|
|
|
self.arenas.alloc_name_binding(data)
|
2023-06-20 22:47:50 +08:00
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn new_warn_ambiguity_binding(&self, binding: NameBinding<'ra>) -> NameBinding<'ra> {
|
2024-06-25 19:03:39 +03:00
|
|
|
assert!(binding.is_ambiguity_recursive());
|
|
|
|
self.arenas.alloc_name_binding(NameBindingData { warn_ambiguity: true, ..*binding })
|
2023-07-26 22:46:49 +08:00
|
|
|
}
|
|
|
|
|
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,
|
2024-09-10 16:19:40 +10:00
|
|
|
module: Module<'ra>,
|
2023-07-26 22:46:49 +08:00
|
|
|
key: BindingKey,
|
|
|
|
warn_ambiguity: bool,
|
|
|
|
f: F,
|
|
|
|
) -> T
|
2023-06-20 22:47:50 +08:00
|
|
|
where
|
2024-09-10 16:19:40 +10:00
|
|
|
F: FnOnce(&mut Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T,
|
2023-06-20 22:47:50 +08:00
|
|
|
{
|
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-10-13 08:58:33 +00:00
|
|
|
if let Some(binding) = resolution.binding()
|
|
|
|
&& old_binding != Some(binding)
|
|
|
|
{
|
2023-07-26 22:46:49 +08:00
|
|
|
(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.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn import_dummy_binding(&mut self, import: Import<'ra>, 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| {
|
2025-03-17 01:34:46 +03:00
|
|
|
resolution.single_imports.swap_remove(&import);
|
2023-12-06 21:48:19 +08:00
|
|
|
})
|
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() {
|
2024-08-09 18:33:20 +08:00
|
|
|
self.import_use_map.insert(import, 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![];
|
2024-04-03 17:49:59 +03:00
|
|
|
let mut prev_root_id: NodeId = NodeId::ZERO;
|
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
|
|
|
|
2024-05-21 19:12:05 +00:00
|
|
|
let mut glob_error = false;
|
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
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
let Some(err) = unresolved_import_error else { continue };
|
2024-05-21 19:12:05 +00:00
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
glob_error |= import.is_glob();
|
2017-06-10 10:55:19 +01:00
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
if let ImportKind::Single { source, ref source_bindings, .. } = import.kind
|
|
|
|
&& source.name == kw::SelfLower
|
|
|
|
// Silence `unresolved import` error if E0429 is already emitted
|
|
|
|
&& let Err(Determined) = source_bindings.value_ns.get()
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if prev_root_id != NodeId::ZERO && prev_root_id != import.root_id && !errors.is_empty()
|
|
|
|
{
|
|
|
|
// In the case of a new import line, throw a diagnostic message
|
|
|
|
// for the previous line.
|
|
|
|
self.throw_unresolved_import_error(errors, glob_error);
|
|
|
|
errors = vec![];
|
|
|
|
}
|
|
|
|
if seen_spans.insert(err.span) {
|
|
|
|
errors.push((*import, err));
|
|
|
|
prev_root_id = import.root_id;
|
2023-07-29 00:14:38 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !errors.is_empty() {
|
2024-05-21 19:12:05 +00:00
|
|
|
self.throw_unresolved_import_error(errors, glob_error);
|
2023-07-29 00:14:38 +08:00
|
|
|
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,
|
|
|
|
);
|
|
|
|
// FIXME: there should be a better way of doing this than
|
|
|
|
// formatting this as a string then checking for `::`
|
|
|
|
if path.contains("::") {
|
2024-03-20 17:06:58 +08:00
|
|
|
let err = UnresolvedImportError {
|
|
|
|
span: import.span,
|
|
|
|
label: None,
|
|
|
|
note: None,
|
|
|
|
suggestion: None,
|
|
|
|
candidates: None,
|
|
|
|
segment: None,
|
|
|
|
module: None,
|
|
|
|
};
|
2023-07-29 00:14:38 +08:00
|
|
|
errors.push((*import, err))
|
2016-08-15 08:19:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-21 19:12:05 +00:00
|
|
|
self.throw_unresolved_import_error(errors, glob_error);
|
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,
|
2024-09-10 16:19:40 +10:00
|
|
|
exported_ambiguities: FxHashSet<NameBinding<'ra>>,
|
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();
|
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
let Some(binding) = resolution.binding else { continue };
|
|
|
|
|
|
|
|
if let NameBindingKind::Import { import, .. } = binding.kind
|
|
|
|
&& let Some((amb_binding, _)) = binding.ambiguity
|
|
|
|
&& binding.res() != Res::Err
|
|
|
|
&& exported_ambiguities.contains(&binding)
|
|
|
|
{
|
|
|
|
self.lint_buffer.buffer_lint(
|
|
|
|
AMBIGUOUS_GLOB_REEXPORTS,
|
|
|
|
import.root_id,
|
|
|
|
import.root_span,
|
|
|
|
BuiltinLintDiag::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()
|
2023-05-09 07:15:46 +08:00
|
|
|
{
|
2024-05-20 17:47:54 +00:00
|
|
|
self.lint_buffer.buffer_lint(
|
2025-01-20 20:35:45 +00:00
|
|
|
HIDDEN_GLOB_REEXPORTS,
|
|
|
|
binding_id,
|
|
|
|
binding.span,
|
|
|
|
BuiltinLintDiag::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-05-09 07:15:46 +08:00
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2023-03-20 03:11:28 +08:00
|
|
|
}
|
2023-05-09 07:15:46 +08:00
|
|
|
}
|
2023-03-20 03:11:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-21 19:12:05 +00:00
|
|
|
fn throw_unresolved_import_error(
|
|
|
|
&mut self,
|
2024-12-05 21:47:06 +00:00
|
|
|
mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
|
2024-05-21 19:12:05 +00:00
|
|
|
glob_error: bool,
|
|
|
|
) {
|
2024-12-05 21:47:06 +00:00
|
|
|
errors.retain(|(_import, err)| match err.module {
|
|
|
|
// Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
|
|
|
|
Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
|
|
|
|
_ => true,
|
|
|
|
});
|
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-07-19 11:51:21 -04: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-17 00:55:35 +08:00
|
|
|
DiagMode::Import { append: false },
|
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
|
|
|
|
2024-03-20 17:06:58 +08:00
|
|
|
if matches!(import.kind, ImportKind::Single { .. })
|
|
|
|
&& let Some(segment) = err.segment
|
|
|
|
&& let Some(module) = err.module
|
|
|
|
{
|
|
|
|
self.find_cfg_stripped(&mut diag, &segment, module)
|
2023-06-21 02:20:55 +08:00
|
|
|
}
|
2018-10-18 19:09:49 +02:00
|
|
|
}
|
2019-01-16 15:30:41 -05:00
|
|
|
|
2024-05-21 19:12:05 +00:00
|
|
|
let guar = diag.emit();
|
|
|
|
if glob_error {
|
|
|
|
self.glob_error = Some(guar);
|
|
|
|
}
|
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.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn resolve_import(&mut self, import: Import<'ra>) -> 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 {
|
2024-08-06 19:27:15 +08:00
|
|
|
let path_res = self.maybe_resolve_path(
|
|
|
|
&import.module_path,
|
|
|
|
None,
|
|
|
|
&import.parent_scope,
|
|
|
|
Some(import),
|
|
|
|
);
|
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() {
|
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,
|
2024-08-06 19:27:15 +08:00
|
|
|
Some(import),
|
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() => {
|
2024-12-25 14:54:49 +08:00
|
|
|
if binding.is_assoc_const_or_fn()
|
|
|
|
&& !this.tcx.features().import_trait_associated_functions()
|
|
|
|
{
|
|
|
|
feature_err(
|
|
|
|
this.tcx.sess,
|
|
|
|
sym::import_trait_associated_functions,
|
|
|
|
import.span,
|
|
|
|
"`use` associated items of traits is unstable",
|
|
|
|
)
|
|
|
|
.emit();
|
|
|
|
}
|
2022-04-10 17:21:58 +03:00
|
|
|
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| {
|
2025-03-17 01:34:46 +03:00
|
|
|
resolution.single_imports.swap_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.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportError> {
|
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,
|
|
|
|
};
|
2024-03-01 19:39:07 +08:00
|
|
|
let ambiguity_errors_len =
|
|
|
|
|errors: &Vec<AmbiguityError<'_>>| errors.iter().filter(|error| !error.warning).count();
|
|
|
|
let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);
|
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,
|
2024-08-06 19:27:15 +08:00
|
|
|
Some(import),
|
2022-04-08 22:50:56 +02:00
|
|
|
);
|
2022-10-10 11:14:32 +08:00
|
|
|
|
2024-03-01 19:39:07 +08:00
|
|
|
let no_ambiguity =
|
|
|
|
ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;
|
2024-08-06 19:27:15 +08:00
|
|
|
|
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,
|
2024-12-05 21:19:08 +00:00
|
|
|
error_implied_by_parse_error: _,
|
2023-03-10 22:39:14 +01:00
|
|
|
} => {
|
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());
|
2025-02-08 22:12:13 +00:00
|
|
|
self.report_error(
|
|
|
|
span,
|
|
|
|
ResolutionError::FailedToResolve {
|
|
|
|
segment: Some(segment_name),
|
|
|
|
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,
|
2024-03-20 17:06:58 +08:00
|
|
|
module,
|
|
|
|
segment_name,
|
2023-03-10 22:39:14 +01:00
|
|
|
..
|
|
|
|
} => {
|
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());
|
2024-03-20 17:06:58 +08:00
|
|
|
let module = if let Some(ModuleOrUniformRoot::Module(m)) = module {
|
|
|
|
m.opt_def_id()
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2025-02-24 12:19:52 +03:00
|
|
|
let err = match self
|
|
|
|
.make_path_suggestion(import.module_path.clone(), &import.parent_scope)
|
|
|
|
{
|
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,
|
2024-03-20 17:06:58 +08:00
|
|
|
segment: Some(segment_name),
|
|
|
|
module,
|
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,
|
2024-03-20 17:06:58 +08:00
|
|
|
segment: Some(segment_name),
|
|
|
|
module,
|
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
|
|
|
|
2025-01-20 17:41:03 +00:00
|
|
|
if let ModuleOrUniformRoot::Module(module) = module
|
|
|
|
&& module == import.parent_scope.module
|
|
|
|
{
|
|
|
|
// Importing a module into itself is not allowed.
|
|
|
|
return Some(UnresolvedImportError {
|
|
|
|
span: import.span,
|
|
|
|
label: Some(String::from("cannot glob-import a module into itself")),
|
|
|
|
note: None,
|
|
|
|
suggestion: None,
|
|
|
|
candidates: None,
|
|
|
|
segment: None,
|
|
|
|
module: None,
|
|
|
|
});
|
2018-08-09 16:29:22 +03:00
|
|
|
}
|
2022-10-30 13:35:31 +04:00
|
|
|
if !is_prelude
|
2023-10-13 08:58:33 +00:00
|
|
|
&& let Some(max_vis) = max_vis.get()
|
2024-08-06 19:27:15 +08:00
|
|
|
&& !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);
|
2024-05-20 17:47:54 +00:00
|
|
|
self.lint_buffer.buffer_lint(
|
2023-10-13 08:58:33 +00:00
|
|
|
UNUSED_IMPORTS,
|
|
|
|
id,
|
|
|
|
import.span,
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::RedundantImportVisibility {
|
2023-12-01 10:25:40 +08:00
|
|
|
max_vis: max_vis.to_string(def_id, self.tcx),
|
2024-08-06 19:27:15 +08:00
|
|
|
import_vis: import.vis.to_string(def_id, self.tcx),
|
2023-12-01 10:25:40 +08:00
|
|
|
span: import.span,
|
|
|
|
},
|
2023-10-13 08:58:33 +00:00
|
|
|
);
|
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));
|
2024-08-06 19:27:15 +08:00
|
|
|
if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.resolve_path(
|
|
|
|
&path,
|
|
|
|
None,
|
|
|
|
&import.parent_scope,
|
|
|
|
Some(finalize),
|
|
|
|
ignore_binding,
|
|
|
|
None,
|
|
|
|
) {
|
2023-06-16 19:44:06 +00:00
|
|
|
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 {
|
|
|
|
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(),
|
2024-08-06 19:27:15 +08:00
|
|
|
Some(import),
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
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;
|
2025-01-20 17:41:03 +00:00
|
|
|
if let Some(target_binding) = target_bindings[ns].get()
|
|
|
|
&& target.name == kw::Underscore
|
|
|
|
&& initial_binding.is_extern_crate()
|
|
|
|
&& !initial_binding.is_import()
|
|
|
|
{
|
|
|
|
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,
|
2024-08-06 19:27:15 +08: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
|
|
|
|
},
|
2024-03-20 17:06:58 +08:00
|
|
|
module: import.imported_module.get().and_then(|module| {
|
|
|
|
if let ModuleOrUniformRoot::Module(m) = module {
|
|
|
|
m.opt_def_id()
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
segment: Some(ident.name),
|
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| {
|
2025-01-20 20:35:45 +00:00
|
|
|
let Ok(binding) = source_bindings[ns].get() else {
|
|
|
|
return;
|
|
|
|
};
|
|
|
|
|
|
|
|
if !binding.vis.is_at_least(import.vis, this.tcx) {
|
|
|
|
reexport_error = Some((ns, binding));
|
|
|
|
if let ty::Visibility::Restricted(binding_def_id) = binding.vis
|
|
|
|
&& binding_def_id.is_top_level_module()
|
|
|
|
{
|
|
|
|
crate_private_reexport = true;
|
2015-03-16 10:44:19 +13:00
|
|
|
}
|
2025-01-20 20:35:45 +00:00
|
|
|
} else {
|
|
|
|
any_successful_reexport = true;
|
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();
|
2024-06-03 07:17:19 +02:00
|
|
|
if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import, binding) {
|
2024-05-20 17:47:54 +00: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,
|
2024-06-03 07:17:19 +02:00
|
|
|
BuiltinLintDiag::PrivateExternCrateReexport {
|
|
|
|
source: ident,
|
|
|
|
extern_crate_span: self.tcx.source_span(self.local_def_id(extern_crate_id)),
|
|
|
|
},
|
2019-12-24 17:38:22 -05:00
|
|
|
);
|
2024-09-11 17:23:56 -04:00
|
|
|
} else if ns == TypeNS {
|
|
|
|
let err = if crate_private_reexport {
|
|
|
|
self.dcx()
|
|
|
|
.create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })
|
|
|
|
} else {
|
|
|
|
self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })
|
|
|
|
};
|
|
|
|
err.emit();
|
2016-11-10 06:19:54 +00:00
|
|
|
} else {
|
2024-09-11 17:23:56 -04:00
|
|
|
let mut err = if crate_private_reexport {
|
|
|
|
self.dcx()
|
|
|
|
.create_err(CannotBeReexportedCratePublic { span: import.span, ident })
|
2021-11-06 04:43:55 +09:00
|
|
|
} else {
|
2024-09-11 17:23:56 -04:00
|
|
|
self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })
|
|
|
|
};
|
2023-06-21 20:51:24 +01:00
|
|
|
|
2024-09-11 17:23:56 -04: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-06-18 11:10:18 +00:00
|
|
|
err.subdiagnostic( ConsiderAddingMacroExport {
|
2023-06-21 20:51:24 +01:00
|
|
|
span: binding.span,
|
|
|
|
});
|
2022-06-14 14:58:46 +09:00
|
|
|
}
|
|
|
|
_ => {
|
2024-06-18 11:10:18 +00:00
|
|
|
err.subdiagnostic( ConsiderMarkingAsPub {
|
2023-06-21 20:51:24 +01:00
|
|
|
span: import.span,
|
|
|
|
ident,
|
|
|
|
});
|
2022-06-14 14:58:46 +09:00
|
|
|
}
|
|
|
|
}
|
2024-09-11 17:23:56 -04:00
|
|
|
err.emit();
|
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
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {
|
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 {
|
2024-03-11 22:39:02 +08:00
|
|
|
return false;
|
2023-11-10 10:11:24 +08:00
|
|
|
}
|
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 {
|
2024-03-11 22:39:02 +08:00
|
|
|
return false;
|
2019-02-22 15:07:18 +01:00
|
|
|
}
|
|
|
|
|
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.
|
2024-08-09 18:33:20 +08:00
|
|
|
if self.import_use_map.get(&import) == Some(&Used::Other)
|
2023-11-10 10:11:24 +08:00
|
|
|
|| self.effective_visibilities.is_exported(self.local_def_id(id))
|
|
|
|
{
|
2024-03-11 22:39:02 +08:00
|
|
|
return false;
|
2019-02-22 15:07:18 +01:00
|
|
|
}
|
|
|
|
|
2023-11-10 10:11:24 +08:00
|
|
|
let mut is_redundant = true;
|
2019-12-24 17:38:22 -05:00
|
|
|
let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
|
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(),
|
2024-08-06 19:27:15 +08:00
|
|
|
None,
|
2019-12-24 17:38:22 -05:00
|
|
|
) {
|
|
|
|
Ok(other_binding) => {
|
2024-06-25 19:03:39 +03:00
|
|
|
is_redundant = binding.res() == other_binding.res()
|
|
|
|
&& !other_binding.is_ambiguity_recursive();
|
2023-11-10 10:11:24 +08:00
|
|
|
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();
|
2024-04-11 14:10:34 -04:00
|
|
|
self.lint_buffer.buffer_lint(
|
|
|
|
REDUNDANT_IMPORTS,
|
2022-10-30 13:35:31 +04:00
|
|
|
id,
|
2020-03-07 19:02:32 +03:00
|
|
|
import.span,
|
2024-02-29 16:40:44 +11:00
|
|
|
BuiltinLintDiag::RedundantImport(redundant_spans, source),
|
2019-02-22 15:07:18 +01:00
|
|
|
);
|
2024-03-11 22:39:02 +08:00
|
|
|
return true;
|
2019-02-22 15:07:18 +01:00
|
|
|
}
|
2024-03-11 22:39:02 +08:00
|
|
|
|
|
|
|
false
|
2019-02-22 15:07:18 +01:00
|
|
|
}
|
|
|
|
|
2024-09-10 16:19:40 +10:00
|
|
|
fn resolve_glob_import(&mut self, import: Import<'ra>) {
|
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()
|
2024-06-25 19:03:39 +03:00
|
|
|
.is_some_and(|binding| binding.warn_ambiguity_recursive());
|
2023-07-26 22:46:49 +08:00
|
|
|
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.
|
2024-09-10 16:19:40 +10:00
|
|
|
fn finalize_resolutions_in(&mut self, module: Module<'ra>) {
|
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
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
let Some(def_id) = module.opt_def_id() else { return };
|
|
|
|
|
|
|
|
let mut children = Vec::new();
|
2023-03-22 17:57:39 +04:00
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
module.for_each_child(self, |this, ident, _, binding| {
|
|
|
|
let res = binding.res().expect_non_local();
|
|
|
|
let error_ambiguity = binding.is_ambiguity_recursive() && !binding.warn_ambiguity;
|
|
|
|
if res != def::Res::Err && !error_ambiguity {
|
|
|
|
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;
|
2016-08-20 05:23:19 +00:00
|
|
|
}
|
2016-02-16 03:54:14 +00:00
|
|
|
|
2025-01-20 20:35:45 +00:00
|
|
|
children.push(ModChild { ident, res, vis: binding.vis, reexport_chain });
|
2016-02-16 03:54:14 +00:00
|
|
|
}
|
2025-01-20 20:35:45 +00: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] };
|
2025-02-08 10:46:05 +01:00
|
|
|
names_to_string(names.iter().map(|ident| ident.name))
|
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!(
|
|
|
|
"{}::{}",
|
2025-02-08 10:46:05 +01:00
|
|
|
names_to_string(names.iter().map(|ident| ident.name)),
|
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
|
|
|
}
|
|
|
|
}
|