1//! A bunch of methods and structures more or less related to resolving imports.23use std::cmp::Ordering;4use std::mem;56use itertools::Itertools;7use rustc_ast::{Item, NodeId};8use rustc_attr_parsing::AttributeParser;9use rustc_data_structures::fx::{FxHashSet, FxIndexSet};10use rustc_data_structures::intern::Interned;11use rustc_errors::codes::*;12use rustc_errors::{13 Applicability, BufferedEarlyLint, Diagnostic, MultiSpan, pluralize, struct_span_code_err,14};15use rustc_hir::Attribute;16use rustc_hir::attrs::AttributeKind;17use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};18use rustc_hir::def::{self, DefKind, PartialRes};19use rustc_hir::def_id::{DefId, LocalDefIdMap};20use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};21use rustc_middle::span_bug;22use rustc_middle::ty::{TyCtxt, Visibility};23use rustc_session::errors::feature_err;24use rustc_session::lint::LintId;25use rustc_session::lint::builtin::{26 AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,27 PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,28};29use rustc_span::edit_distance::find_best_match_for_name;30use rustc_span::hygiene::LocalExpnId;31use rustc_span::{Ident, Span, Symbol, kw, sym};32use tracing::debug;3334use crate::Namespace::{self, *};35use crate::diagnostics::{DiagMode, Suggestion, import_candidates};36use crate::errors::{37 self, CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS,38 CannotBeReexportedPrivate, CannotBeReexportedPrivateNS, CannotDetermineImportResolution,39 CannotGlobImportAllCrates, ConsiderAddingMacroExport, ConsiderMarkingAsPub,40 ConsiderMarkingAsPubCrate,41};42use crate::ref_mut::CmCell;43use crate::{44 AmbiguityError, BindingKey, CmResolver, Decl, DeclData, DeclKind, Determinacy, Finalize,45 IdentKey, ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope,46 PathResult, PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string,47 names_to_string,48};4950/// A potential import declaration in the process of being planted into a module.51/// Also used for lazily planting names from `--extern` flags to extern prelude.52#[derive(Clone, Copy, Default, PartialEq, Debug)]53pub(crate) enum PendingDecl<'ra> {54 Ready(Option<Decl<'ra>>),55 #[default]56 Pending,57}5859impl<'ra> PendingDecl<'ra> {60 pub(crate) fn decl(self) -> Option<Decl<'ra>> {61 match self {62 PendingDecl::Ready(decl) => decl,63 PendingDecl::Pending => None,64 }65 }66}6768/// Contains data for specific kinds of imports.69#[derive(Clone)]70pub(crate) enum ImportKind<'ra> {71 Single {72 /// `source` in `use prefix::source as target`.73 source: Ident,74 /// `target` in `use prefix::source as target`.75 /// It will directly use `source` when the format is `use prefix::source`.76 target: Ident,77 /// Name declarations introduced by the import.78 decls: PerNS<CmCell<PendingDecl<'ra>>>,79 /// Did this import result from a nested import? i.e. `use foo::{bar, baz};`80 nested: bool,81 /// The ID of the `UseTree` that imported this `Import`.82 ///83 /// In the case where the `Import` was expanded from a "nested" use tree,84 /// this id is the ID of the leaf tree. For example:85 ///86 /// ```ignore (pacify the merciless tidy)87 /// use foo::bar::{a, b}88 /// ```89 ///90 /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`91 /// for `a` in this field.92 id: NodeId,93 },94 Glob {95 // The visibility of the greatest re-export.96 // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.97 max_vis: CmCell<Option<Visibility>>,98 id: NodeId,99 },100 ExternCrate {101 source: Option<Symbol>,102 target: Ident,103 id: NodeId,104 },105 MacroUse {106 /// A field has been added indicating whether it should be reported as a lint,107 /// addressing issue#119301.108 warn_private: bool,109 },110 MacroExport,111}112113/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings`114/// contain `Cell`s which can introduce infinite loops while printing.115impl<'ra> std::fmt::Debug for ImportKind<'ra> {116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {117 use ImportKind::*;118 match self {119 Single { source, target, decls, nested, id, .. } => f120 .debug_struct("Single")121 .field("source", source)122 .field("target", target)123 // Ignore the nested bindings to avoid an infinite loop while printing.124 .field(125 "decls",126 &decls.clone().map(|b| b.into_inner().decl().map(|_| format_args!(".."))),127 )128 .field("nested", nested)129 .field("id", id)130 .finish(),131 Glob { max_vis, id } => {132 f.debug_struct("Glob").field("max_vis", max_vis).field("id", id).finish()133 }134 ExternCrate { source, target, id } => f135 .debug_struct("ExternCrate")136 .field("source", source)137 .field("target", target)138 .field("id", id)139 .finish(),140 MacroUse { warn_private } => {141 f.debug_struct("MacroUse").field("warn_private", warn_private).finish()142 }143 MacroExport => f.debug_struct("MacroExport").finish(),144 }145 }146}147148#[derive(Debug, Clone, Default)]149pub(crate) struct OnUnknownData {150 directive: Box<Directive>,151}152153impl OnUnknownData {154 pub(crate) fn from_attrs<'tcx>(tcx: TyCtxt<'tcx>, item: &Item) -> Option<OnUnknownData> {155 if tcx.features().diagnostic_on_unknown()156 && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) =157 AttributeParser::parse_limited(158 tcx.sess,159 &item.attrs,160 &[sym::diagnostic, sym::on_unknown],161 )162 {163 Some(Self { directive: directive? })164 } else {165 None166 }167 }168}169170/// One import.171#[derive(Debug, Clone)]172pub(crate) struct ImportData<'ra> {173 pub kind: ImportKind<'ra>,174175 /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`176 /// (if it exists) except in the case of "nested" use trees, in which case177 /// it will be the ID of the root use tree. e.g., in the example178 /// ```ignore (incomplete code)179 /// use foo::bar::{a, b}180 /// ```181 /// this would be the ID of the `use foo::bar` `UseTree` node.182 /// In case of imports without their own node ID it's the closest node that can be used,183 /// for example, for reporting lints.184 pub root_id: NodeId,185186 /// Span of the entire use statement.187 pub use_span: Span,188189 /// Span of the entire use statement with attributes.190 pub use_span_with_attributes: Span,191192 /// Did the use statement have any attributes?193 pub has_attributes: bool,194195 /// Span of this use tree.196 pub span: Span,197198 /// Span of the *root* use tree (see `root_id`).199 pub root_span: Span,200201 pub parent_scope: ParentScope<'ra>,202 pub module_path: Vec<Segment>,203 /// The resolution of `module_path`:204 ///205 /// | `module_path` | `imported_module` | remark |206 /// |-|-|-|207 /// |`use prefix::foo`| `ModuleOrUniformRoot::Module(prefix)` | - |208 /// |`use ::foo` | `ModuleOrUniformRoot::ExternPrelude` | 2018+ editions |209 /// |`use ::foo` | `ModuleOrUniformRoot::ModuleAndExternPrelude` | a special case in 2015 edition |210 /// |`use foo` | `ModuleOrUniformRoot::CurrentScope` | - |211 pub imported_module: CmCell<Option<ModuleOrUniformRoot<'ra>>>,212 pub vis: Visibility,213214 /// Span of the visibility.215 pub vis_span: Span,216217 /// A `#[diagnostic::on_unknown]` attribute applied218 /// to the given import. This allows crates to specify219 /// custom error messages for a specific import220 ///221 /// This is `None` if the feature flag for `diagnostic::on_unknown` is disabled.222 pub on_unknown_attr: Option<OnUnknownData>,223}224225/// All imports are unique and allocated on a same arena,226/// so we can use referential equality to compare them.227pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>;228229// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the230// contained data.231// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees232// are upheld.233impl std::hash::Hash for ImportData<'_> {234 fn hash<H>(&self, _: &mut H)235 where236 H: std::hash::Hasher,237 {238 unreachable!()239 }240}241242impl<'ra> ImportData<'ra> {243 pub(crate) fn is_glob(&self) -> bool {244 matches!(self.kind, ImportKind::Glob { .. })245 }246247 pub(crate) fn is_nested(&self) -> bool {248 match self.kind {249 ImportKind::Single { nested, .. } => nested,250 _ => false,251 }252 }253254 pub(crate) fn id(&self) -> Option<NodeId> {255 match self.kind {256 ImportKind::Single { id, .. }257 | ImportKind::Glob { id, .. }258 | ImportKind::ExternCrate { id, .. } => Some(id),259 ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,260 }261 }262263 pub(crate) fn simplify(&self, r: &Resolver<'_, '_>) -> Reexport {264 let to_def_id = |id| r.local_def_id(id).to_def_id();265 match self.kind {266 ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),267 ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)),268 ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)),269 ImportKind::MacroUse { .. } => Reexport::MacroUse,270 ImportKind::MacroExport => Reexport::MacroExport,271 }272 }273274 fn summary(&self) -> ImportSummary {275 ImportSummary {276 vis: self.vis,277 nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(),278 is_single: matches!(self.kind, ImportKind::Single { .. }),279 priv_macro_use: matches!(self.kind, ImportKind::MacroUse { warn_private: true }),280 span: self.span,281 }282 }283}284285/// Records information about the resolution of a name in a namespace of a module.286#[derive(Clone, Debug)]287pub(crate) struct NameResolution<'ra> {288 /// Single imports that may define the name in the namespace.289 /// Imports are arena-allocated, so it's ok to use pointers as keys.290 pub single_imports: FxIndexSet<Import<'ra>>,291 /// The non-glob declaration for this name, if it is known to exist.292 pub non_glob_decl: Option<Decl<'ra>> = None,293 /// The glob declaration for this name, if it is known to exist.294 pub glob_decl: Option<Decl<'ra>> = None,295 pub orig_ident_span: Span,296}297298impl<'ra> NameResolution<'ra> {299 pub(crate) fn new(orig_ident_span: Span) -> Self {300 NameResolution { single_imports: FxIndexSet::default(), orig_ident_span, .. }301 }302303 /// Returns the best declaration if it is not going to change, and `None` if the best304 /// declaration may still change to something else.305 /// FIXME: this function considers `single_imports`, but not `unexpanded_invocations`, so306 /// the returned declaration may actually change after expanding macros in the same module,307 /// because of this fact we have glob overwriting (`select_glob_decl`). Consider using308 /// `unexpanded_invocations` here and avoiding glob overwriting entirely, if it doesn't cause309 /// code breakage in practice.310 /// FIXME: relationship between this function and similar `DeclData::determined` is unclear.311 pub(crate) fn determined_decl(&self) -> Option<Decl<'ra>> {312 if self.non_glob_decl.is_some() {313 self.non_glob_decl314 } else if self.glob_decl.is_some() && self.single_imports.is_empty() {315 self.glob_decl316 } else {317 None318 }319 }320321 pub(crate) fn best_decl(&self) -> Option<Decl<'ra>> {322 self.non_glob_decl.or(self.glob_decl)323 }324}325326/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved327/// import errors within the same use tree into a single diagnostic.328#[derive(Debug, Clone)]329struct UnresolvedImportError {330 span: Span,331 label: Option<String>,332 note: Option<String>,333 suggestion: Option<Suggestion>,334 candidates: Option<Vec<ImportSuggestion>>,335 segment: Option<Symbol>,336 /// comes from `PathRes::Failed { module }`337 module: Option<DefId>,338 on_unknown_attr: Option<OnUnknownData>,339}340341// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`342// are permitted for backward-compatibility under a deprecation lint.343fn pub_use_of_private_extern_crate_hack(import: ImportSummary, decl: Decl<'_>) -> Option<NodeId> {344 match (import.is_single, decl.kind) {345 (true, DeclKind::Import { import: decl_import, .. })346 if let ImportKind::ExternCrate { id, .. } = decl_import.kind347 && import.vis.is_public() =>348 {349 Some(id)350 }351 _ => None,352 }353}354355/// Removes identical import layers from two declarations.356fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra>) {357 if let DeclKind::Import { import: import1, source_decl: d1_next } = d1.kind358 && let DeclKind::Import { import: import2, source_decl: d2_next } = d2.kind359 && import1 == import2360 {361 assert_eq!(d1.expansion, d2.expansion);362 assert_eq!(d1.span, d2.span);363 if d1.ambiguity.get() != d2.ambiguity.get() {364 assert!(d1.ambiguity.get().is_some());365 assert!(d2.ambiguity.get().is_none());366 }367 // Visibility of the new import declaration may be different,368 // because it already incorporates the visibility of the source binding.369 // `warn_ambiguity` of a re-fetched glob can also change in both directions.370 remove_same_import(d1_next, d2_next)371 } else {372 (d1, d2)373 }374}375376impl<'ra, 'tcx> Resolver<'ra, 'tcx> {377 pub(crate) fn import_decl_vis(&self, decl: Decl<'ra>, import: ImportSummary) -> Visibility {378 self.import_decl_vis_ext(decl, import, false)379 }380381 pub(crate) fn import_decl_vis_ext(382 &self,383 decl: Decl<'ra>,384 import: ImportSummary,385 min: bool,386 ) -> Visibility {387 assert!(import.vis.is_accessible_from(import.nearest_parent_mod, self.tcx));388 let decl_vis = if min { decl.min_vis() } else { decl.vis() };389 let ord = decl_vis.partial_cmp(import.vis, self.tcx);390 let extern_crate_hack = pub_use_of_private_extern_crate_hack(import, decl).is_some();391 if ord == Some(Ordering::Less)392 && decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx)393 && !extern_crate_hack394 {395 // Imported declaration is less visible than the import, but is still visible396 // from the current module, use the declaration's visibility.397 decl_vis.expect_local()398 } else {399 // Good case - imported declaration is more visible than the import, or the same,400 // use the import's visibility.401 //402 // Bad case - imported declaration is too private for the current module.403 // It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE`404 // and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because an error will be reported.405 // Use import visibility to keep the all declaration visibilities in a module ordered.406 if !min407 && matches!(ord, None | Some(Ordering::Less))408 && !extern_crate_hack409 && !import.priv_macro_use410 {411 let msg = format!("cannot extend visibility from {decl_vis:?} to {:?}", import.vis);412 self.dcx().span_delayed_bug(import.span, msg);413 }414 import.vis415 }416 }417418 /// Given an import and the declaration that it points to,419 /// create the corresponding import declaration.420 pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> Decl<'ra> {421 let vis = self.import_decl_vis(decl, import.summary());422423 if let ImportKind::Glob { ref max_vis, .. } = import.kind424 && (vis == import.vis425 || max_vis.get().is_none_or(|max_vis| vis.greater_than(max_vis, self.tcx)))426 {427 max_vis.set_unchecked(Some(vis))428 }429430 self.arenas.alloc_decl(DeclData {431 kind: DeclKind::Import { source_decl: decl, import },432 ambiguity: CmCell::new(None),433 warn_ambiguity: CmCell::new(false),434 span: import.span,435 initial_vis: vis.to_def_id(),436 ambiguity_vis_max: CmCell::new(None),437 ambiguity_vis_min: CmCell::new(None),438 expansion: import.parent_scope.expansion,439 parent_module: Some(import.parent_scope.module),440 })441 }442443 /// If `glob_decl` attempts to overwrite `old_glob_decl` in a module,444 /// decide which one to keep.445 fn select_glob_decl(446 &self,447 old_glob_decl: Decl<'ra>,448 glob_decl: Decl<'ra>,449 warn_ambiguity: bool,450 ) -> Decl<'ra> {451 assert!(glob_decl.is_glob_import());452 assert!(old_glob_decl.is_glob_import());453 assert_ne!(glob_decl, old_glob_decl);454 // `best_decl` with a given key in a module may be overwritten in a455 // number of cases (all of them can be seen below in the `match` in `try_define_local`),456 // all these overwrites will be re-fetched by glob imports importing457 // from that module without generating new ambiguities.458 // - A glob decl is overwritten by a non-glob decl arriving later.459 // - A glob decl is overwritten by its clone after setting ambiguity in it.460 // FIXME: avoid this by removing `warn_ambiguity`, or by triggering glob re-fetch461 // with the same decl in some way.462 // - A glob decl is overwritten by a glob decl re-fetching an463 // overwritten decl from other module (the recursive case).464 // Here we are detecting all such re-fetches and overwrite old decls465 // with the re-fetched decls.466 // This is probably incorrect in corner cases, and the outdated decls still get467 // propagated to other places and get stuck there, but that's what we have at the moment.468 let (old_deep_decl, deep_decl) = remove_same_import(old_glob_decl, glob_decl);469 if deep_decl != glob_decl {470 // Some import layers have been removed, need to overwrite.471 assert_ne!(old_deep_decl, old_glob_decl);472 // FIXME: reenable the asserts when `warn_ambiguity` is removed (#149195).473 // assert_ne!(old_deep_decl, deep_decl);474 // assert!(old_deep_decl.is_glob_import());475 assert!(!deep_decl.is_glob_import());476 if old_glob_decl.ambiguity.get().is_some() && glob_decl.ambiguity.get().is_none() {477 // Do not lose glob ambiguities when re-fetching the glob.478 glob_decl.ambiguity.set_unchecked(old_glob_decl.ambiguity.get());479 }480 if glob_decl.is_ambiguity_recursive() {481 glob_decl.warn_ambiguity.set_unchecked(true);482 }483 glob_decl484 } else if glob_decl.res() != old_glob_decl.res() {485 old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));486 old_glob_decl.warn_ambiguity.set_unchecked(warn_ambiguity);487 if warn_ambiguity {488 old_glob_decl489 } else {490 // Need a fresh decl so other glob imports importing it could re-fetch it491 // and set their own `warn_ambiguity` to true.492 // FIXME: remove this when `warn_ambiguity` is removed (#149195).493 self.arenas.alloc_decl((*old_glob_decl).clone())494 }495 } else if let old_vis = old_glob_decl.vis()496 && let vis = glob_decl.vis()497 && old_vis != vis498 {499 // We are glob-importing the same item but with a different visibility.500 // All visibilities here are ordered because all of them are ancestors of `module`.501 if vis.greater_than(old_vis, self.tcx) {502 old_glob_decl.ambiguity_vis_max.set_unchecked(Some(glob_decl));503 } else if let old_min_vis = old_glob_decl.min_vis()504 && old_min_vis != vis505 && old_min_vis.greater_than(vis, self.tcx)506 {507 old_glob_decl.ambiguity_vis_min.set_unchecked(Some(glob_decl));508 }509 old_glob_decl510 } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {511 // Overwriting a non-ambiguous glob import with an ambiguous glob import.512 old_glob_decl.ambiguity.set_unchecked(Some(glob_decl));513 old_glob_decl.warn_ambiguity.set_unchecked(true);514 old_glob_decl515 } else {516 old_glob_decl517 }518 }519520 /// Attempt to put the declaration with the given name and namespace into the module,521 /// and return existing declaration if there is a collision.522 pub(crate) fn try_plant_decl_into_local_module(523 &mut self,524 ident: IdentKey,525 orig_ident_span: Span,526 ns: Namespace,527 decl: Decl<'ra>,528 warn_ambiguity: bool,529 ) -> Result<(), Decl<'ra>> {530 assert!(!decl.warn_ambiguity.get());531 assert!(decl.ambiguity.get().is_none());532 assert!(decl.ambiguity_vis_max.get().is_none());533 assert!(decl.ambiguity_vis_min.get().is_none());534 let module = decl.parent_module.unwrap().expect_local();535 assert!(self.is_accessible_from(decl.vis(), module.to_module()));536 let res = decl.res();537 self.check_reserved_macro_name(ident.name, orig_ident_span, res);538 // Even if underscore names cannot be looked up, we still need to add them to modules,539 // because they can be fetched by glob imports from those modules, and bring traits540 // into scope both directly and through glob imports.541 let key = BindingKey::new_disambiguated(ident, ns, || {542 module.underscore_disambiguator.update_unchecked(|d| d + 1);543 module.underscore_disambiguator.get()544 });545 self.update_local_resolution(546 module,547 key,548 orig_ident_span,549 warn_ambiguity,550 |this, resolution| {551 if decl.is_glob_import() {552 resolution.glob_decl = Some(match resolution.glob_decl {553 Some(old_decl) => this.select_glob_decl(554 old_decl,555 decl,556 warn_ambiguity && resolution.non_glob_decl.is_none(),557 ),558 None => decl,559 })560 } else {561 resolution.non_glob_decl = Some(match resolution.non_glob_decl {562 Some(old_decl) => return Err(old_decl),563 None => decl,564 })565 }566567 Ok(())568 },569 )570 }571572 // Use `f` to mutate the resolution of the name in the module.573 // If the resolution becomes a success, define it in the module's glob importers.574 fn update_local_resolution<T, F>(575 &mut self,576 module: LocalModule<'ra>,577 key: BindingKey,578 orig_ident_span: Span,579 warn_ambiguity: bool,580 f: F,581 ) -> T582 where583 F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T,584 {585 // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,586 // during which the resolution might end up getting re-defined via a glob cycle.587 let (binding, t, warn_ambiguity) = {588 let resolution = &mut *self589 .resolution_or_default(module.to_module(), key, orig_ident_span)590 .borrow_mut_unchecked();591 let old_decl = resolution.determined_decl();592 let old_vis = old_decl.map(|d| d.vis());593594 let t = f(self, resolution);595596 if let Some(binding) = resolution.determined_decl()597 && (old_decl != Some(binding) || old_vis != Some(binding.vis()))598 {599 (binding, t, warn_ambiguity || old_decl.is_some())600 } else {601 return t;602 }603 };604605 let Ok(glob_importers) = module.glob_importers.try_borrow_mut_unchecked() else {606 return t;607 };608609 // Define or update `binding` in `module`s glob importers.610 for import in glob_importers.iter() {611 let mut ident = key.ident;612 let scope = match ident613 .ctxt614 .update_unchecked(|ctxt| ctxt.reverse_glob_adjust(module.expansion, import.span))615 {616 Some(Some(def)) => self.expn_def_scope(def),617 Some(None) => import.parent_scope.module,618 None => continue,619 };620 if self.is_accessible_from(binding.vis(), scope) {621 let import_decl = self.new_import_decl(binding, *import);622 self.try_plant_decl_into_local_module(623 ident,624 orig_ident_span,625 key.ns,626 import_decl,627 warn_ambiguity,628 )629 .expect("planting a glob cannot fail");630 }631 }632633 t634 }635636 // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed637 // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.638 fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) {639 if let ImportKind::Single { target, ref decls, .. } = import.kind {640 if !(is_indeterminate || decls.iter().all(|d| d.get().decl().is_none())) {641 return; // Has resolution, do not create the dummy binding642 }643 let dummy_decl = self.dummy_decl;644 let dummy_decl = self.new_import_decl(dummy_decl, import);645 self.per_ns(|this, ns| {646 let ident = IdentKey::new(target);647 // This can fail, dummies are inserted only in non-occupied slots.648 let _ = this.try_plant_decl_into_local_module(649 ident,650 target.span,651 ns,652 dummy_decl,653 false,654 );655 // Don't remove underscores from `single_imports`, they were never added.656 if target.name != kw::Underscore {657 let key = BindingKey::new(ident, ns);658 this.update_local_resolution(659 import.parent_scope.module.expect_local(),660 key,661 target.span,662 false,663 |_, resolution| {664 resolution.single_imports.swap_remove(&import);665 },666 )667 }668 });669 self.record_use(target, dummy_decl, Used::Other);670 } else if import.imported_module.get().is_none() {671 self.import_use_map.insert(import, Used::Other);672 if let Some(id) = import.id() {673 self.used_imports.insert(id);674 }675 }676 }677678 // Import resolution679 //680 // This is a fixed-point algorithm. We resolve imports until our efforts681 // are stymied by an unresolved import; then we bail out of the current682 // module and continue. We terminate successfully once no more imports683 // remain or unsuccessfully when no forward progress in resolving imports684 // is made.685686 /// Resolves all imports for the crate. This method performs the fixed-687 /// point iteration.688 pub(crate) fn resolve_imports(&mut self) {689 let mut prev_indeterminate_count = usize::MAX;690 let mut indeterminate_count = self.indeterminate_imports.len() * 3;691 while indeterminate_count < prev_indeterminate_count {692 prev_indeterminate_count = indeterminate_count;693 indeterminate_count = 0;694 self.assert_speculative = true;695 for import in mem::take(&mut self.indeterminate_imports) {696 let import_indeterminate_count = self.cm().resolve_import(import);697 indeterminate_count += import_indeterminate_count;698 match import_indeterminate_count {699 0 => self.determined_imports.push(import),700 _ => self.indeterminate_imports.push(import),701 }702 }703 self.assert_speculative = false;704 }705 }706707 pub(crate) fn finalize_imports(&mut self) {708 let mut module_children = Default::default();709 let mut ambig_module_children = Default::default();710 for module in &self.local_modules {711 self.finalize_resolutions_in(*module, &mut module_children, &mut ambig_module_children);712 }713 self.module_children = module_children;714 self.ambig_module_children = ambig_module_children;715716 let mut seen_spans = FxHashSet::default();717 let mut errors = vec![];718 let mut prev_root_id: NodeId = NodeId::ZERO;719 let determined_imports = mem::take(&mut self.determined_imports);720 let indeterminate_imports = mem::take(&mut self.indeterminate_imports);721722 let mut glob_error = false;723 for (is_indeterminate, import) in determined_imports724 .iter()725 .map(|i| (false, i))726 .chain(indeterminate_imports.iter().map(|i| (true, i)))727 {728 let unresolved_import_error = self.finalize_import(*import);729 // If this import is unresolved then create a dummy import730 // resolution for it so that later resolve stages won't complain.731 self.import_dummy_binding(*import, is_indeterminate);732733 let Some(err) = unresolved_import_error else { continue };734735 glob_error |= import.is_glob();736737 if let ImportKind::Single { source, ref decls, .. } = import.kind738 && source.name == kw::SelfLower739 // Silence `unresolved import` error if E0429 is already emitted740 && let PendingDecl::Ready(None) = decls.value_ns.get()741 {742 continue;743 }744745 if prev_root_id != NodeId::ZERO && prev_root_id != import.root_id && !errors.is_empty()746 {747 // In the case of a new import line, throw a diagnostic message748 // for the previous line.749 self.throw_unresolved_import_error(errors, glob_error);750 errors = vec![];751 }752 if seen_spans.insert(err.span) {753 errors.push((*import, err));754 prev_root_id = import.root_id;755 }756 }757758 if self.cstore().had_extern_crate_load_failure() {759 self.tcx.sess.dcx().abort_if_errors();760 }761762 if !errors.is_empty() {763 self.throw_unresolved_import_error(errors, glob_error);764 return;765 }766767 for import in &indeterminate_imports {768 let path = import_path_to_string(769 &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),770 &import.kind,771 import.span,772 );773 // FIXME: there should be a better way of doing this than774 // formatting this as a string then checking for `::`775 if path.contains("::") {776 let err = UnresolvedImportError {777 span: import.span,778 label: None,779 note: None,780 suggestion: None,781 candidates: None,782 segment: None,783 module: None,784 on_unknown_attr: import.on_unknown_attr.clone(),785 };786 errors.push((*import, err))787 }788 }789790 if !errors.is_empty() {791 self.throw_unresolved_import_error(errors, glob_error);792 }793 }794795 pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {796 for module in &self.local_modules {797 for (key, resolution) in self.resolutions(module.to_module()).borrow().iter() {798 let resolution = resolution.borrow();799 let Some(binding) = resolution.best_decl() else { continue };800801 // Report "cannot reexport" errors for exotic cases involving macros 2.0802 // privacy bending or invariant-breaking code under deprecation lints.803 for decl in [resolution.non_glob_decl, resolution.glob_decl] {804 if let Some(decl) = decl805 && let DeclKind::Import { source_decl, import } = decl.kind806 {807 // The source entity is too private to be reexported808 // with the given import declaration's visibility.809 let ord = source_decl.vis().partial_cmp(decl.vis(), self.tcx);810 if matches!(ord, None | Some(Ordering::Less)) {811 let ident = match import.kind {812 ImportKind::Single { source, .. } => source,813 _ => key.ident.orig(resolution.orig_ident_span),814 };815 if let Some(lint) =816 self.report_cannot_reexport(import, source_decl, ident, key.ns)817 {818 self.lint_buffer.add_early_lint(lint);819 }820 }821 }822 }823824 if let DeclKind::Import { import, .. } = binding.kind825 && let Some(amb_binding) = binding.ambiguity.get()826 && binding.res() != Res::Err827 && exported_ambiguities.contains(&binding)828 {829 self.lint_buffer.buffer_lint(830 AMBIGUOUS_GLOB_REEXPORTS,831 import.root_id,832 import.root_span,833 errors::AmbiguousGlobReexports {834 name: key.ident.name.to_string(),835 namespace: key.ns.descr().to_string(),836 first_reexport: import.root_span,837 duplicate_reexport: amb_binding.span,838 },839 );840 }841842 if let Some(glob_decl) = resolution.glob_decl843 && resolution.non_glob_decl.is_some()844 {845 if binding.res() != Res::Err846 && glob_decl.res() != Res::Err847 && let DeclKind::Import { import: glob_import, .. } = glob_decl.kind848 && let Some(glob_import_id) = glob_import.id()849 && let glob_import_def_id = self.local_def_id(glob_import_id)850 && self.effective_visibilities.is_exported(glob_import_def_id)851 && glob_decl.vis().is_public()852 && !binding.vis().is_public()853 {854 let binding_id = match binding.kind {855 DeclKind::Def(res) => {856 Some(self.def_id_to_node_id(res.def_id().expect_local()))857 }858 DeclKind::Import { import, .. } => import.id(),859 };860 if let Some(binding_id) = binding_id {861 self.lint_buffer.buffer_lint(862 HIDDEN_GLOB_REEXPORTS,863 binding_id,864 binding.span,865 errors::HiddenGlobReexports {866 name: key.ident.name.to_string(),867 namespace: key.ns.descr().to_owned(),868 glob_reexport: glob_decl.span,869 private_item: binding.span,870 },871 );872 }873 }874 }875876 if let DeclKind::Import { import, .. } = binding.kind877 && let Some(binding_id) = import.id()878 && let import_def_id = self.local_def_id(binding_id)879 && self.effective_visibilities.is_exported(import_def_id)880 && let Res::Def(reexported_kind, reexported_def_id) = binding.res()881 && !matches!(reexported_kind, DefKind::Ctor(..))882 && !reexported_def_id.is_local()883 && self.tcx.is_private_dep(reexported_def_id.krate)884 {885 self.lint_buffer.buffer_lint(886 EXPORTED_PRIVATE_DEPENDENCIES,887 binding_id,888 binding.span,889 crate::errors::ReexportPrivateDependency {890 name: key.ident.name,891 kind: binding.res().descr(),892 krate: self.tcx.crate_name(reexported_def_id.krate),893 },894 );895 }896 }897 }898 }899900 fn throw_unresolved_import_error(901 &mut self,902 mut errors: Vec<(Import<'_>, UnresolvedImportError)>,903 glob_error: bool,904 ) {905 errors.retain(|(_import, err)| match err.module {906 // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.907 Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,908 // If we've encountered something like `use _;`, we've already emitted an error stating909 // that `_` is not a valid identifier, so we ignore that resolve error.910 _ => err.segment != Some(kw::Underscore),911 });912 if errors.is_empty() {913 self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");914 return;915 }916917 let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());918919 let paths = errors920 .iter()921 .map(|(import, err)| {922 let path = import_path_to_string(923 &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),924 &import.kind,925 err.span,926 );927 format!("`{path}`")928 })929 .collect::<Vec<_>>();930 let default_message =931 format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);932 let (message, label, notes) =933 // Feature gating for `on_unknown_attr` happens initialization of the field934 if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) {935 let this = errors.iter().map(|(_import, err)| {936937 // Is this unwrap_or reachable?938 err.segment.unwrap_or(kw::Underscore)939 }).join(", ");940941 let args = FormatArgs {942 this,943 ..944 };945 let CustomDiagnostic { message, label, notes, .. } = directive.eval(None, &args);946947 (message, label, notes)948 } else {949 (None, None, Vec::new())950 };951 let has_custom_message = message.is_some();952 let message = message.as_deref().unwrap_or(default_message.as_str());953954 let mut diag = struct_span_code_err!(self.dcx(), span, E0432, "{message}");955 if has_custom_message {956 diag.note(default_message);957 }958959 if !notes.is_empty() {960 for note in notes {961 diag.note(note);962 }963 } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) =964 errors.iter().last()965 {966 diag.note(note.clone());967 }968969 /// Upper limit on the number of `span_label` messages.970 const MAX_LABEL_COUNT: usize = 10;971972 for (import, err) in errors.into_iter().take(MAX_LABEL_COUNT) {973 if let Some(label) = &label {974 diag.span_label(err.span, label.clone());975 } else if let Some(label) = &err.label {976 diag.span_label(err.span, label.clone());977 }978979 if let Some((suggestions, msg, applicability)) = err.suggestion {980 if suggestions.is_empty() {981 diag.help(msg);982 continue;983 }984 diag.multipart_suggestion(msg, suggestions, applicability);985 }986987 if let Some(candidates) = &err.candidates {988 match &import.kind {989 ImportKind::Single { nested: false, source, target, .. } => import_candidates(990 self.tcx,991 &mut diag,992 Some(err.span),993 candidates,994 DiagMode::Import { append: false, unresolved_import: true },995 (source != target)996 .then(|| format!(" as {target}"))997 .as_deref()998 .unwrap_or(""),999 ),1000 ImportKind::Single { nested: true, source, target, .. } => {1001 import_candidates(1002 self.tcx,1003 &mut diag,1004 None,1005 candidates,1006 DiagMode::Normal,1007 (source != target)1008 .then(|| format!(" as {target}"))1009 .as_deref()1010 .unwrap_or(""),1011 );1012 }1013 _ => {}1014 }1015 }10161017 if matches!(import.kind, ImportKind::Single { .. })1018 && let Some(segment) = err.segment1019 && let Some(module) = err.module1020 {1021 self.find_cfg_stripped(&mut diag, &segment, module)1022 }1023 }10241025 let guar = diag.emit();1026 if glob_error {1027 self.glob_error = Some(guar);1028 }1029 }10301031 /// Attempts to resolve the given import, returning:1032 /// - `0` means its resolution is determined.1033 /// - Other values mean that indeterminate exists under certain namespaces.1034 ///1035 /// Meanwhile, if resolve successful, the resolved bindings are written1036 /// into the module.1037 fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize {1038 debug!(1039 "(resolving import for module) resolving import `{}::...` in `{}`",1040 Segment::names_to_string(&import.module_path),1041 module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),1042 );1043 let module = if let Some(module) = import.imported_module.get() {1044 module1045 } else {1046 let path_res = self.reborrow().maybe_resolve_path(1047 &import.module_path,1048 None,1049 &import.parent_scope,1050 Some(import),1051 );10521053 match path_res {1054 PathResult::Module(module) => module,1055 PathResult::Indeterminate => return 3,1056 PathResult::NonModule(..) | PathResult::Failed { .. } => return 0,1057 }1058 };10591060 import.imported_module.set_unchecked(Some(module));1061 let (source, target, bindings) = match import.kind {1062 ImportKind::Single { source, target, ref decls, .. } => (source, target, decls),1063 ImportKind::Glob { .. } => {1064 self.get_mut_unchecked().resolve_glob_import(import);1065 return 0;1066 }1067 _ => unreachable!(),1068 };10691070 let mut indeterminate_count = 0;1071 self.per_ns_cm(|mut this, ns| {1072 if bindings[ns].get() != PendingDecl::Pending {1073 return;1074 };1075 let binding_result = this.reborrow().maybe_resolve_ident_in_module(1076 module,1077 source,1078 ns,1079 &import.parent_scope,1080 Some(import),1081 );1082 let parent = import.parent_scope.module;1083 let binding = match binding_result {1084 Ok(binding) => {1085 if binding.is_assoc_item()1086 && !this.tcx.features().import_trait_associated_functions()1087 {1088 feature_err(1089 this.tcx.sess,1090 sym::import_trait_associated_functions,1091 import.span,1092 "`use` associated items of traits is unstable",1093 )1094 .emit();1095 }1096 // We need the `target`, `source` can be extracted.1097 let import_decl = this.new_import_decl(binding, import);1098 this.get_mut_unchecked().plant_decl_into_local_module(1099 IdentKey::new(target),1100 target.span,1101 ns,1102 import_decl,1103 );1104 PendingDecl::Ready(Some(import_decl))1105 }1106 Err(Determinacy::Determined) => {1107 // Don't remove underscores from `single_imports`, they were never added.1108 if target.name != kw::Underscore {1109 let key = BindingKey::new(IdentKey::new(target), ns);1110 this.get_mut_unchecked().update_local_resolution(1111 parent.expect_local(),1112 key,1113 target.span,1114 false,1115 |_, resolution| {1116 resolution.single_imports.swap_remove(&import);1117 },1118 );1119 }1120 PendingDecl::Ready(None)1121 }1122 Err(Determinacy::Undetermined) => {1123 indeterminate_count += 1;1124 PendingDecl::Pending1125 }1126 };1127 bindings[ns].set_unchecked(binding);1128 });11291130 indeterminate_count1131 }11321133 /// Performs final import resolution, consistency checks and error reporting.1134 ///1135 /// Optionally returns an unresolved import error. This error is buffered and used to1136 /// consolidate multiple unresolved import errors into a single diagnostic.1137 fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportError> {1138 let ignore_decl = match &import.kind {1139 ImportKind::Single { decls, .. } => decls[TypeNS].get().decl(),1140 _ => None,1141 };1142 let ambiguity_errors_len = |errors: &Vec<AmbiguityError<'_>>| {1143 errors.iter().filter(|error| error.warning.is_none()).count()1144 };1145 let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);1146 let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);11471148 // We'll provide more context to the privacy errors later, up to `len`.1149 let privacy_errors_len = self.privacy_errors.len();11501151 let path_res = self.cm().resolve_path(1152 &import.module_path,1153 None,1154 &import.parent_scope,1155 Some(finalize),1156 ignore_decl,1157 Some(import),1158 );11591160 let no_ambiguity =1161 ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;11621163 let module = match path_res {1164 PathResult::Module(module) => {1165 // Consistency checks, analogous to `finalize_macro_resolutions`.1166 if let Some(initial_module) = import.imported_module.get() {1167 if module != initial_module && no_ambiguity && !self.issue_145575_hack_applied {1168 span_bug!(import.span, "inconsistent resolution for an import");1169 }1170 } else if self.privacy_errors.is_empty() {1171 self.dcx()1172 .create_err(CannotDetermineImportResolution { span: import.span })1173 .emit();1174 }11751176 module1177 }1178 PathResult::Failed {1179 is_error_from_last_segment: false,1180 span,1181 segment_name,1182 label,1183 suggestion,1184 module,1185 error_implied_by_parse_error: _,1186 message,1187 note: _,1188 } => {1189 if no_ambiguity {1190 if !self.issue_145575_hack_applied {1191 assert!(import.imported_module.get().is_none());1192 }1193 self.report_error(1194 span,1195 ResolutionError::FailedToResolve {1196 segment: segment_name,1197 label,1198 suggestion,1199 module,1200 message,1201 },1202 );1203 }1204 return None;1205 }1206 PathResult::Failed {1207 is_error_from_last_segment: true,1208 span,1209 label,1210 suggestion,1211 module,1212 segment_name,1213 note,1214 ..1215 } => {1216 if no_ambiguity {1217 if !self.issue_145575_hack_applied {1218 assert!(import.imported_module.get().is_none());1219 }1220 let module = if let Some(ModuleOrUniformRoot::Module(m)) = module {1221 m.opt_def_id()1222 } else {1223 None1224 };1225 let err = match self1226 .make_path_suggestion(import.module_path.clone(), &import.parent_scope)1227 {1228 Some((suggestion, note)) => UnresolvedImportError {1229 span,1230 label: None,1231 note,1232 suggestion: Some((1233 vec![(span, Segment::names_to_string(&suggestion))],1234 String::from("a similar path exists"),1235 Applicability::MaybeIncorrect,1236 )),1237 candidates: None,1238 segment: Some(segment_name),1239 module,1240 on_unknown_attr: import.on_unknown_attr.clone(),1241 },1242 None => UnresolvedImportError {1243 span,1244 label: Some(label),1245 note,1246 suggestion,1247 candidates: None,1248 segment: Some(segment_name),1249 module,1250 on_unknown_attr: import.on_unknown_attr.clone(),1251 },1252 };1253 return Some(err);1254 }1255 return None;1256 }1257 PathResult::NonModule(partial_res) => {1258 if no_ambiguity && partial_res.full_res() != Some(Res::Err) {1259 // Check if there are no ambiguities and the result is not dummy.1260 assert!(import.imported_module.get().is_none());1261 }1262 // The error was already reported earlier.1263 return None;1264 }1265 PathResult::Indeterminate => unreachable!(),1266 };12671268 let (ident, target, bindings, import_id) = match import.kind {1269 ImportKind::Single { source, target, ref decls, id, .. } => (source, target, decls, id),1270 ImportKind::Glob { ref max_vis, id } => {1271 if import.module_path.len() <= 1 {1272 // HACK(eddyb) `lint_if_path_starts_with_module` needs at least1273 // 2 segments, so the `resolve_path` above won't trigger it.1274 let mut full_path = import.module_path.clone();1275 full_path.push(Segment::from_ident(Ident::dummy()));1276 self.lint_if_path_starts_with_module(finalize, &full_path, None);1277 }12781279 if let ModuleOrUniformRoot::Module(module) = module1280 && module == import.parent_scope.module1281 {1282 // Importing a module into itself is not allowed.1283 return Some(UnresolvedImportError {1284 span: import.span,1285 label: Some(String::from("cannot glob-import a module into itself")),1286 note: None,1287 suggestion: None,1288 candidates: None,1289 segment: None,1290 module: None,1291 on_unknown_attr: None,1292 });1293 }1294 if let Some(max_vis) = max_vis.get()1295 && import.vis.greater_than(max_vis, self.tcx)1296 {1297 let def_id = self.local_def_id(id);1298 self.lint_buffer.buffer_lint(1299 UNUSED_IMPORTS,1300 id,1301 import.span,1302 crate::errors::RedundantImportVisibility {1303 span: import.span,1304 help: (),1305 max_vis: max_vis.to_string(def_id, self.tcx),1306 import_vis: import.vis.to_string(def_id, self.tcx),1307 },1308 );1309 }1310 return None;1311 }1312 _ => unreachable!(),1313 };13141315 if self.privacy_errors.len() != privacy_errors_len {1316 // Get the Res for the last element, so that we can point to alternative ways of1317 // importing it if available.1318 let mut path = import.module_path.clone();1319 path.push(Segment::from_ident(ident));1320 if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self.cm().resolve_path(1321 &path,1322 None,1323 &import.parent_scope,1324 Some(finalize),1325 ignore_decl,1326 None,1327 ) {1328 let res = module.res().map(|r| (r, ident));1329 for error in &mut self.privacy_errors[privacy_errors_len..] {1330 error.outermost_res = res;1331 }1332 } else {1333 // The final item is not a module (e.g., a struct, function, or macro).1334 // Resolve it directly in the parent module to get its Res, so1335 // `report_privacy_error()` can search for public re-export paths.1336 for ns in [TypeNS, ValueNS, MacroNS] {1337 if let Ok(binding) = self.cm().resolve_ident_in_module(1338 module,1339 ident,1340 ns,1341 &import.parent_scope,1342 None,1343 ignore_decl,1344 None,1345 ) {1346 let res = binding.res();1347 for error in &mut self.privacy_errors[privacy_errors_len..] {1348 error.outermost_res = Some((res, ident));1349 }1350 break;1351 }1352 }1353 }1354 }13551356 let mut all_ns_err = true;1357 self.per_ns(|this, ns| {1358 let binding = this.cm().resolve_ident_in_module(1359 module,1360 ident,1361 ns,1362 &import.parent_scope,1363 Some(Finalize {1364 report_private: false,1365 import: Some(import.summary()),1366 ..finalize1367 }),1368 bindings[ns].get().decl(),1369 Some(import),1370 );13711372 match binding {1373 Ok(binding) => {1374 // Consistency checks, analogous to `finalize_macro_resolutions`.1375 let initial_res = bindings[ns].get().decl().map(|binding| {1376 let initial_binding = binding.import_source();1377 all_ns_err = false;1378 if target.name == kw::Underscore1379 && initial_binding.is_extern_crate()1380 && !initial_binding.is_import()1381 {1382 let used = if import.module_path.is_empty() {1383 Used::Scope1384 } else {1385 Used::Other1386 };1387 this.record_use(ident, binding, used);1388 }1389 initial_binding.res()1390 });1391 let res = binding.res();1392 let has_ambiguity_error =1393 this.ambiguity_errors.iter().any(|error| error.warning.is_none());1394 if res == Res::Err || has_ambiguity_error {1395 this.dcx()1396 .span_delayed_bug(import.span, "some error happened for an import");1397 return;1398 }1399 if let Some(initial_res) = initial_res {1400 if res != initial_res && !this.issue_145575_hack_applied {1401 span_bug!(import.span, "inconsistent resolution for an import");1402 }1403 } else if this.privacy_errors.is_empty() {1404 this.dcx()1405 .create_err(CannotDetermineImportResolution { span: import.span })1406 .emit();1407 }1408 }1409 Err(..) => {1410 // FIXME: This assert may fire if public glob is later shadowed by a private1411 // single import (see test `issue-55884-2.rs`). In theory single imports should1412 // always block globs, even if they are not yet resolved, so that this kind of1413 // self-inconsistent resolution never happens.1414 // Re-enable the assert when the issue is fixed.1415 // assert!(result[ns].get().is_err());1416 }1417 }1418 });14191420 if all_ns_err {1421 let mut all_ns_failed = true;1422 self.per_ns(|this, ns| {1423 let binding = this.cm().resolve_ident_in_module(1424 module,1425 ident,1426 ns,1427 &import.parent_scope,1428 Some(finalize),1429 None,1430 None,1431 );1432 if binding.is_ok() {1433 all_ns_failed = false;1434 }1435 });14361437 return if all_ns_failed {1438 let names = match module {1439 ModuleOrUniformRoot::Module(module) => {1440 self.resolutions(module)1441 .borrow()1442 .iter()1443 .filter_map(|(BindingKey { ident: i, .. }, resolution)| {1444 if i.name == ident.name {1445 return None;1446 } // Never suggest the same name1447 if i.name == kw::Underscore {1448 return None;1449 } // `use _` is never valid14501451 let resolution = resolution.borrow();1452 if let Some(name_binding) = resolution.best_decl() {1453 match name_binding.kind {1454 DeclKind::Import { source_decl, .. } => {1455 match source_decl.kind {1456 // Never suggest names that previously could not1457 // be resolved.1458 DeclKind::Def(Res::Err) => None,1459 _ => Some(i.name),1460 }1461 }1462 _ => Some(i.name),1463 }1464 } else if resolution.single_imports.is_empty() {1465 None1466 } else {1467 Some(i.name)1468 }1469 })1470 .collect()1471 }1472 _ => Vec::new(),1473 };14741475 let lev_suggestion =1476 find_best_match_for_name(&names, ident.name, None).map(|suggestion| {1477 (1478 vec![(ident.span, suggestion.to_string())],1479 String::from("a similar name exists in the module"),1480 Applicability::MaybeIncorrect,1481 )1482 });14831484 let (suggestion, note) =1485 match self.check_for_module_export_macro(import, module, ident) {1486 Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),1487 _ => (lev_suggestion, None),1488 };14891490 // If importing of trait asscoiated items is enabled, an also find an1491 // `Enum`, then note that inherent associated items cannot be imported.1492 let note = if self.tcx.features().import_trait_associated_functions()1493 && let PathResult::Module(ModuleOrUniformRoot::Module(m)) = path_res1494 && let Some(Res::Def(DefKind::Enum, _)) = m.res()1495 {1496 note.or(Some(1497 "cannot import inherent associated items, only trait associated items"1498 .to_string(),1499 ))1500 } else {1501 note1502 };15031504 let label = match module {1505 ModuleOrUniformRoot::Module(module) => {1506 let module_str = module_to_string(module);1507 if let Some(module_str) = module_str {1508 format!("no `{ident}` in `{module_str}`")1509 } else {1510 format!("no `{ident}` in the root")1511 }1512 }1513 _ => {1514 if !ident.is_path_segment_keyword() {1515 format!("no external crate `{ident}`")1516 } else {1517 // HACK(eddyb) this shows up for `self` & `super`, which1518 // should work instead - for now keep the same error message.1519 format!("no `{ident}` in the root")1520 }1521 }1522 };15231524 let parent_suggestion =1525 self.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);15261527 Some(UnresolvedImportError {1528 span: import.span,1529 label: Some(label),1530 note,1531 suggestion,1532 candidates: if !parent_suggestion.is_empty() {1533 Some(parent_suggestion)1534 } else {1535 None1536 },1537 module: import.imported_module.get().and_then(|module| {1538 if let ModuleOrUniformRoot::Module(m) = module {1539 m.opt_def_id()1540 } else {1541 None1542 }1543 }),1544 segment: Some(ident.name),1545 on_unknown_attr: import.on_unknown_attr.clone(),1546 })1547 } else {1548 // `resolve_ident_in_module` reported a privacy error.1549 None1550 };1551 }15521553 let mut reexport_error = None;1554 let mut any_successful_reexport = false;1555 self.per_ns(|this, ns| {1556 let Some(binding) = bindings[ns].get().decl() else {1557 return;1558 };15591560 if import.vis.greater_than(binding.vis(), this.tcx) {1561 // In isolation, a declaration like this is not an error, but if *all* 1-31562 // declarations introduced by the import are more private than the import item's1563 // nominal visibility, then it's an error.1564 reexport_error = Some((ns, binding.import_source()));1565 } else {1566 any_successful_reexport = true;1567 }1568 });15691570 if !any_successful_reexport {1571 let (ns, binding) = reexport_error.unwrap();1572 if let Some(lint) = self.report_cannot_reexport(import, binding, ident, ns) {1573 self.lint_buffer.add_early_lint(lint);1574 }1575 }15761577 if import.module_path.len() <= 1 {1578 // HACK(eddyb) `lint_if_path_starts_with_module` needs at least1579 // 2 segments, so the `resolve_path` above won't trigger it.1580 let mut full_path = import.module_path.clone();1581 full_path.push(Segment::from_ident(ident));1582 self.per_ns(|this, ns| {1583 if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {1584 this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding));1585 }1586 });1587 }15881589 // Record what this import resolves to for later uses in documentation,1590 // this may resolve to either a value or a type, but for documentation1591 // purposes it's good enough to just favor one over the other.1592 self.per_ns(|this, ns| {1593 if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {1594 this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());1595 }1596 });15971598 debug!("(resolving single import) successfully resolved import");1599 None1600 }16011602 fn report_cannot_reexport(1603 &self,1604 import: Import<'ra>,1605 decl: Decl<'ra>,1606 ident: Ident,1607 ns: Namespace,1608 ) -> Option<BufferedEarlyLint> {1609 let crate_private_reexport = match decl.vis() {1610 Visibility::Restricted(def_id) if def_id.is_top_level_module() => true,1611 _ => false,1612 };16131614 if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl)1615 {1616 let ImportKind::Single { id, .. } = import.kind else { unreachable!() };1617 let sugg = self.tcx.source_span(self.local_def_id(extern_crate_id)).shrink_to_lo();1618 let diagnostic = crate::errors::PrivateExternCrateReexport { ident, sugg };1619 return Some(BufferedEarlyLint {1620 lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),1621 node_id: id,1622 span: Some(import.span.into()),1623 diagnostic: diagnostic.into(),1624 });1625 } else if ns == TypeNS {1626 let err = if crate_private_reexport {1627 self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })1628 } else {1629 self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })1630 };1631 err.emit();1632 } else {1633 let mut err = if crate_private_reexport {1634 self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident })1635 } else {1636 self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })1637 };16381639 match decl.kind {1640 // exclude decl_macro1641 DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))1642 if self.get_macro_by_def_id(def_id).macro_rules =>1643 {1644 err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span });1645 err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span });1646 }1647 _ => {1648 err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident });1649 }1650 }1651 err.emit();1652 }16531654 None1655 }16561657 pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {1658 // This function is only called for single imports.1659 let ImportKind::Single { source, target, ref decls, id, .. } = import.kind else {1660 unreachable!()1661 };16621663 // Skip if the import is of the form `use source as target` and source != target.1664 if source != target {1665 return false;1666 }16671668 // Skip if the import was produced by a macro.1669 if import.parent_scope.expansion != LocalExpnId::ROOT {1670 return false;1671 }16721673 // Skip if we are inside a named module (in contrast to an anonymous1674 // module defined by a block).1675 // Skip if the import is public or was used through non scope-based resolution,1676 // e.g. through a module-relative path.1677 if self.import_use_map.get(&import) == Some(&Used::Other)1678 || self.effective_visibilities.is_exported(self.local_def_id(id))1679 {1680 return false;1681 }16821683 let mut is_redundant = true;1684 let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };1685 self.per_ns(|this, ns| {1686 let binding = decls[ns].get().decl().map(|b| b.import_source());1687 if is_redundant && let Some(binding) = binding {1688 if binding.res() == Res::Err {1689 return;1690 }16911692 match this.cm().resolve_ident_in_scope_set(1693 target,1694 ScopeSet::All(ns),1695 &import.parent_scope,1696 None,1697 decls[ns].get().decl(),1698 None,1699 ) {1700 Ok(other_binding) => {1701 is_redundant = binding.res() == other_binding.res()1702 && !other_binding.is_ambiguity_recursive();1703 if is_redundant {1704 redundant_span[ns] =1705 Some((other_binding.span, other_binding.is_import()));1706 }1707 }1708 Err(_) => is_redundant = false,1709 }1710 }1711 });17121713 if is_redundant && !redundant_span.is_empty() {1714 let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();1715 redundant_spans.sort();1716 redundant_spans.dedup();1717 self.lint_buffer.dyn_buffer_lint(1718 REDUNDANT_IMPORTS,1719 id,1720 import.span,1721 move |dcx, level| {1722 let ident = source;1723 let subs = redundant_spans1724 .into_iter()1725 .map(|(span, is_imported)| match (span.is_dummy(), is_imported) {1726 (false, true) => {1727 errors::RedundantImportSub::ImportedHere { span, ident }1728 }1729 (false, false) => {1730 errors::RedundantImportSub::DefinedHere { span, ident }1731 }1732 (true, true) => {1733 errors::RedundantImportSub::ImportedPrelude { span, ident }1734 }1735 (true, false) => {1736 errors::RedundantImportSub::DefinedPrelude { span, ident }1737 }1738 })1739 .collect();1740 errors::RedundantImport { subs, ident }.into_diag(dcx, level)1741 },1742 );1743 return true;1744 }17451746 false1747 }17481749 fn resolve_glob_import(&mut self, import: Import<'ra>) {1750 // This function is only called for glob imports.1751 let ImportKind::Glob { id, .. } = import.kind else { unreachable!() };17521753 let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else {1754 self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });1755 return;1756 };17571758 if module.is_trait() && !self.tcx.features().import_trait_associated_functions() {1759 feature_err(1760 self.tcx.sess,1761 sym::import_trait_associated_functions,1762 import.span,1763 "`use` associated items of traits is unstable",1764 )1765 .emit();1766 }17671768 if module == import.parent_scope.module {1769 return;1770 }17711772 // Add to module's glob_importers1773 module.glob_importers.borrow_mut_unchecked().push(import);17741775 // Ensure that `resolutions` isn't borrowed during `try_define`,1776 // since it might get updated via a glob cycle.1777 let bindings = self1778 .resolutions(module)1779 .borrow()1780 .iter()1781 .filter_map(|(key, resolution)| {1782 let resolution = resolution.borrow();1783 resolution.determined_decl().map(|decl| (*key, decl, resolution.orig_ident_span))1784 })1785 .collect::<Vec<_>>();1786 for (mut key, binding, orig_ident_span) in bindings {1787 let scope =1788 match key.ident.ctxt.update_unchecked(|ctxt| {1789 ctxt.reverse_glob_adjust(module.expansion, import.span)1790 }) {1791 Some(Some(def)) => self.expn_def_scope(def),1792 Some(None) => import.parent_scope.module,1793 None => continue,1794 };1795 if self.is_accessible_from(binding.vis(), scope) {1796 let import_decl = self.new_import_decl(binding, import);1797 let warn_ambiguity = self1798 .resolution(import.parent_scope.module, key)1799 .and_then(|r| r.determined_decl())1800 .is_some_and(|binding| binding.warn_ambiguity_recursive());1801 self.try_plant_decl_into_local_module(1802 key.ident,1803 orig_ident_span,1804 key.ns,1805 import_decl,1806 warn_ambiguity,1807 )1808 .expect("planting a glob cannot fail");1809 }1810 }18111812 // Record the destination of this import1813 self.record_partial_res(id, PartialRes::new(module.res().unwrap()));1814 }18151816 // Miscellaneous post-processing, including recording re-exports,1817 // reporting conflicts, and reporting unresolved imports.1818 fn finalize_resolutions_in(1819 &self,1820 module: LocalModule<'ra>,1821 module_children: &mut LocalDefIdMap<Vec<ModChild>>,1822 ambig_module_children: &mut LocalDefIdMap<Vec<AmbigModChild>>,1823 ) {1824 // Since import resolution is finished, globs will not define any more names.1825 *module.globs.borrow_mut(self) = Vec::new();18261827 let Some(def_id) = module.opt_def_id() else { return };18281829 let mut children = Vec::new();1830 let mut ambig_children = Vec::new();18311832 module.to_module().for_each_child(self, |this, ident, orig_ident_span, _, binding| {1833 let res = binding.res().expect_non_local();1834 if res != def::Res::Err {1835 let ident = ident.orig(orig_ident_span);1836 let child =1837 |reexport_chain| ModChild { ident, res, vis: binding.vis(), reexport_chain };1838 if let Some((ambig_binding1, ambig_binding2)) = binding.descent_to_ambiguity() {1839 let main = child(ambig_binding1.reexport_chain(this));1840 let second = ModChild {1841 ident,1842 res: ambig_binding2.res().expect_non_local(),1843 vis: ambig_binding2.vis(),1844 reexport_chain: ambig_binding2.reexport_chain(this),1845 };1846 ambig_children.push(AmbigModChild { main, second })1847 } else {1848 children.push(child(binding.reexport_chain(this)));1849 }1850 }1851 });18521853 if !children.is_empty() {1854 module_children.insert(def_id.expect_local(), children);1855 }1856 if !ambig_children.is_empty() {1857 ambig_module_children.insert(def_id.expect_local(), ambig_children);1858 }1859 }1860}18611862fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String {1863 let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);1864 let global = !names.is_empty() && names[0].name == kw::PathRoot;1865 if let Some(pos) = pos {1866 let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };1867 names_to_string(names.iter().map(|ident| ident.name))1868 } else {1869 let names = if global { &names[1..] } else { names };1870 if names.is_empty() {1871 import_kind_to_string(import_kind)1872 } else {1873 format!(1874 "{}::{}",1875 names_to_string(names.iter().map(|ident| ident.name)),1876 import_kind_to_string(import_kind),1877 )1878 }1879 }1880}18811882fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {1883 match import_kind {1884 ImportKind::Single { source, .. } => source.to_string(),1885 ImportKind::Glob { .. } => "*".to_string(),1886 ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),1887 ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),1888 ImportKind::MacroExport => "#[macro_export]".to_string(),1889 }1890}