Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
unsafe { self.speculative_flag.set(true) };
1//! A bunch of methods and structures more or less related to resolving imports.23use std::cmp::Ordering;4use std::mem;56use rustc_ast::NodeId;7use rustc_data_structures::fx::{FxHashSet, FxIndexSet};8use rustc_data_structures::intern::Interned;9use rustc_errors::{Applicability, BufferedEarlyLint, Diagnostic};10use rustc_expand::base::SyntaxExtensionKind;11use rustc_hir::def::{self, DefKind, PartialRes};12use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap};13use rustc_lint_defs::LintId;14use rustc_lint_defs::builtin::{15 AMBIGUOUS_GLOB_REEXPORTS, EXPORTED_PRIVATE_DEPENDENCIES, HIDDEN_GLOB_REEXPORTS,16 PUB_USE_OF_PRIVATE_EXTERN_CRATE, REDUNDANT_IMPORTS, UNUSED_IMPORTS,17};18use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};19use rustc_middle::span_bug;20use rustc_middle::ty::Visibility;21use rustc_session::diagnostics::feature_err;22use rustc_span::edit_distance::find_best_match_for_name;23use rustc_span::hygiene::LocalExpnId;24use rustc_span::{Ident, Span, Symbol, kw, sym};25use tracing::debug;2627use crate::Namespace::{self, *};28use crate::diagnostics::impls::{OnUnknownData, Suggestion};29use crate::diagnostics::{30 self, CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS,31 CannotBeReexportedPrivate, CannotBeReexportedPrivateNS, CannotDetermineImportResolution,32 CannotGlobImportAllCrates, ConsiderAddingMacroExport, ConsiderMarkingAsPub,33 ConsiderMarkingAsPubCrate,34};35use crate::ref_mut::{CmCell, CmRefCell};36use crate::{37 AmbiguityError, BindingKey, Decl, DeclData, DeclKind, Determinacy, Finalize, IdentKey,38 ImportSuggestion, ImportSummary, LocalModule, ModuleOrUniformRoot, ParentScope, PathResult,39 PerNS, Res, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string,40 names_to_string,41};4243/// A potential import declaration in the process of being planted into a module.44/// Also used for lazily planting names from `--extern` flags to extern prelude.45#[derive(Clone, Copy, Default, PartialEq, Debug)]46pub(crate) enum PendingDecl<'ra> {47 Ready(Option<Decl<'ra>>),48 #[default]49 Pending,50}5152enum ImportResolutionKind<'ra> {53 // these are the decls the import imports, not the import declarations themselves54 Single(PerNS<PendingDecl<'ra>>),55 Glob(Vec<(Decl<'ra>, BindingKey, Span /* orig_ident_span */)>),56}5758pub(crate) struct ImportResolution<'ra> {59 kind: ImportResolutionKind<'ra>,60 imported_module: ModuleOrUniformRoot<'ra>,61}6263impl<'ra> PendingDecl<'ra> {64 pub(crate) fn decl(self) -> Option<Decl<'ra>> {65 match self {66 PendingDecl::Ready(decl) => decl,67 PendingDecl::Pending => None,68 }69 }70}7172/// Contains data for specific kinds of imports.73pub(crate) enum ImportKind<'ra> {74 Single {75 /// `source` in `use prefix::source as target`.76 source: Ident,77 /// `target` in `use prefix::source as target`.78 /// It will directly use `source` when the format is `use prefix::source`.79 target: Ident,80 /// Name declarations introduced by the import.81 decls: PerNS<CmCell<PendingDecl<'ra>>>,82 /// Did this import result from a nested import? i.e. `use foo::{bar, baz};`83 nested: bool,84 /// The ID of the `UseTree` that imported this `Import`.85 ///86 /// In the case where the `Import` was expanded from a "nested" use tree,87 /// this id is the ID of the leaf tree. For example:88 ///89 /// ```ignore (pacify the merciless tidy)90 /// use foo::bar::{a, b}91 /// ```92 ///93 /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree`94 /// for `a` in this field.95 id: NodeId,96 def_id: LocalDefId,97 },98 Glob {99 // The visibility of the greatest re-export.100 // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.101 max_vis: CmCell<Option<Visibility>>,102 id: NodeId,103 def_id: LocalDefId,104 },105 ExternCrate {106 source: Option<Symbol>,107 target: Ident,108 id: NodeId,109 def_id: LocalDefId,110 },111 MacroUse {112 /// A field has been added indicating whether it should be reported as a lint,113 /// addressing issue#119301.114 warn_private: bool,115 },116 MacroExport,117}118119/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings`120/// contain `Cell`s which can introduce infinite loops while printing.121impl<'ra> std::fmt::Debug for ImportKind<'ra> {122 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {123 use ImportKind::*;124 match self {125 Single { source, target, decls, nested, id, def_id } => f126 .debug_struct("Single")127 .field("source", source)128 .field("target", target)129 // Ignore the nested bindings to avoid an infinite loop while printing.130 .field(131 "decls",132 &decls.clone().map(|b| b.into_inner().decl().map(|_| format_args!(".."))),133 )134 .field("nested", nested)135 .field("id", id)136 .field("def_id", def_id)137 .finish(),138 Glob { max_vis, id, def_id } => f139 .debug_struct("Glob")140 .field("max_vis", max_vis)141 .field("id", id)142 .field("def_id", def_id)143 .finish(),144 ExternCrate { source, target, id, def_id } => f145 .debug_struct("ExternCrate")146 .field("source", source)147 .field("target", target)148 .field("id", id)149 .field("def_id", def_id)150 .finish(),151 MacroUse { warn_private } => {152 f.debug_struct("MacroUse").field("warn_private", warn_private).finish()153 }154 MacroExport => f.debug_struct("MacroExport").finish(),155 }156 }157}158159/// One import.160#[derive(Debug)]161pub(crate) struct ImportData<'ra> {162 pub kind: ImportKind<'ra>,163164 /// Node ID of the "root" use item -- this is always the same as `ImportKind`'s `id`165 /// (if it exists) except in the case of "nested" use trees, in which case166 /// it will be the ID of the root use tree. e.g., in the example167 /// ```ignore (incomplete code)168 /// use foo::bar::{a, b}169 /// ```170 /// this would be the ID of the `use foo::bar` `UseTree` node.171 /// In case of imports without their own node ID it's the closest node that can be used,172 /// for example, for reporting lints.173 pub root_id: NodeId,174175 /// Span of the entire use statement.176 pub use_span: Span,177178 /// Span of the entire use statement with attributes.179 pub use_span_with_attributes: Span,180181 /// Did the use statement have any attributes?182 pub has_attributes: bool,183184 /// Span of this use tree.185 pub span: Span,186187 /// Span of the *root* use tree (see `root_id`).188 pub root_span: Span,189190 pub parent_scope: ParentScope<'ra>,191 pub module_path: Vec<Segment>,192 /// The resolution of `module_path`:193 ///194 /// | `module_path` | `imported_module` | remark |195 /// |-|-|-|196 /// |`use prefix::foo`| `ModuleOrUniformRoot::Module(prefix)` | - |197 /// |`use ::foo` | `ModuleOrUniformRoot::ExternPrelude` | 2018+ editions |198 /// |`use ::foo` | `ModuleOrUniformRoot::ModuleAndExternPrelude` | a special case in 2015 edition |199 /// |`use foo` | `ModuleOrUniformRoot::CurrentScope` | - |200 pub imported_module: CmCell<Option<ModuleOrUniformRoot<'ra>>>,201 pub vis: Visibility,202203 /// Span of the visibility.204 pub vis_span: Span,205206 /// A `#[diagnostic::on_unknown]` attribute applied207 /// to the given import. This allows crates to specify208 /// custom error messages for a specific import209 ///210 /// This is `None` if the feature flag for `diagnostic::on_unknown` is disabled.211 pub on_unknown_attr: Option<OnUnknownData>,212}213214/// `Interned` is used because values of this type have "identity" and compare as unequal even if215/// they have the same contents.216pub(crate) type Import<'ra> = Interned<'ra, ImportData<'ra>>;217218impl<'ra> ImportData<'ra> {219 pub(crate) fn is_glob(&self) -> bool {220 matches!(self.kind, ImportKind::Glob { .. })221 }222223 pub(crate) fn is_nested(&self) -> bool {224 match self.kind {225 ImportKind::Single { nested, .. } => nested,226 _ => false,227 }228 }229230 pub(crate) fn id(&self) -> Option<NodeId> {231 match self.kind {232 ImportKind::Single { id, .. }233 | ImportKind::Glob { id, .. }234 | ImportKind::ExternCrate { id, .. } => Some(id),235 ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,236 }237 }238239 pub(crate) fn def_id(&self) -> Option<LocalDefId> {240 match self.kind {241 ImportKind::Single { def_id, .. }242 | ImportKind::Glob { def_id, .. }243 | ImportKind::ExternCrate { def_id, .. } => Some(def_id),244 ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,245 }246 }247248 pub(crate) fn simplify(&self) -> Reexport {249 match self.kind {250 ImportKind::Single { def_id, .. } => Reexport::Single(def_id.to_def_id()),251 ImportKind::Glob { def_id, .. } => Reexport::Glob(def_id.to_def_id()),252 ImportKind::ExternCrate { def_id, .. } => Reexport::ExternCrate(def_id.to_def_id()),253 ImportKind::MacroUse { .. } => Reexport::MacroUse,254 ImportKind::MacroExport => Reexport::MacroExport,255 }256 }257258 fn summary(&self) -> ImportSummary {259 ImportSummary {260 vis: self.vis,261 nearest_parent_mod: self.parent_scope.module.nearest_parent_mod().expect_local(),262 is_single: matches!(self.kind, ImportKind::Single { .. }),263 priv_macro_use: matches!(self.kind, ImportKind::MacroUse { warn_private: true }),264 span: self.span,265 }266 }267}268269/// Records information about the resolution of a name in a namespace of a module.270#[derive(Debug)]271pub(crate) struct NameResolution<'ra> {272 /// Single imports that may define the name in the namespace.273 /// Imports are arena-allocated, so it's ok to use pointers as keys.274 pub single_imports: FxIndexSet<Import<'ra>>,275 /// The non-glob declaration for this name, if it is known to exist.276 pub non_glob_decl: Option<Decl<'ra>> = None,277 /// The glob declaration for this name, if it is known to exist.278 pub glob_decl: Option<Decl<'ra>> = None,279 pub orig_ident_span: Span,280}281282/// `Interned` is used because values of this type have "identity" and compare as unequal even if283/// they have the same contents.284pub(crate) type NameResolutionRef<'ra> = Interned<'ra, CmRefCell<NameResolution<'ra>>>;285286impl<'ra> NameResolution<'ra> {287 pub(crate) fn new(orig_ident_span: Span) -> Self {288 NameResolution { single_imports: FxIndexSet::default(), orig_ident_span, .. }289 }290291 /// Returns the best declaration if it is not going to change, and `None` if the best292 /// declaration may still change to something else.293 /// FIXME: this function considers `single_imports`, but not `unexpanded_invocations`, so294 /// the returned declaration may actually change after expanding macros in the same module,295 /// because of this fact we have glob overwriting (`select_glob_decl`). Consider using296 /// `unexpanded_invocations` here and avoiding glob overwriting entirely, if it doesn't cause297 /// code breakage in practice.298 /// FIXME: relationship between this function and similar `DeclData::determined` is unclear.299 pub(crate) fn determined_decl(&self) -> Option<Decl<'ra>> {300 if self.non_glob_decl.is_some() {301 self.non_glob_decl302 } else if self.glob_decl.is_some() && self.single_imports.is_empty() {303 self.glob_decl304 } else {305 None306 }307 }308309 pub(crate) fn best_decl(&self) -> Option<Decl<'ra>> {310 self.non_glob_decl.or(self.glob_decl)311 }312}313314// module to keep the TLS private and only accessible through the function `enter_cycle_detector`.315pub(crate) mod cycle_detection {316 use std::cell::RefCell;317 use std::ptr;318319 use crate::{BindingKey, LocalModule};320321 thread_local!(322 /// During import resolution, recursive imports can form cycles.323 /// This set stores the active resolution stack for the current thread.324 /// By keeping track of the module and `BindingKey` pair that identifies325 /// the specific resolution.326 ///327 /// The pointer is the interned address of a `Interned<'ra, ModuleData>` allocated328 /// in the `Resolver Arenas` (lifetime `'ra`), it is thus stable and allows casting329 /// to a `*const ()` for comparison. This is done because we can't use lifetimes330 /// other than `'static` in thread local storage.331 static ACTIVE_RESOLUTIONS: RefCell<Vec<(*const (), BindingKey)>> = Default::default();332 );333334 pub(crate) struct ActiveResolutionGuard {335 key: (*const (), BindingKey),336 }337338 impl Drop for ActiveResolutionGuard {339 fn drop(&mut self) {340 ACTIVE_RESOLUTIONS.with_borrow_mut(|ar| {341 // Only this guard is allowed to remove this key.342 assert!(343 Some(self.key) == ar.pop(),344 "This guard should be the only one removing this key"345 );346 });347 }348 }349350 /// Returns `Err(())` if a cycle is detected, otherwise this returns a351 /// guard that will remove the resolution when dropped.352 pub(crate) fn enter_cycle_detector<'ra>(353 module: LocalModule<'ra>,354 binding_key: BindingKey,355 ) -> Result<ActiveResolutionGuard, ()> {356 let module_key = ptr::from_ref(module.0.0).cast();357 let key = (module_key, binding_key);358 ACTIVE_RESOLUTIONS.with_borrow_mut(|ar| {359 if ar.contains(&key) {360 return Err(());361 }362 ar.push(key);363 Ok(ActiveResolutionGuard { key })364 })365 }366}367368/// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved369/// import errors within the same use tree into a single diagnostic.370#[derive(Debug)]371pub(crate) struct UnresolvedImportError {372 pub(crate) span: Span,373 pub(crate) label: Option<String>,374 pub(crate) note: Option<String>,375 pub(crate) suggestion: Option<Suggestion>,376 pub(crate) candidates: Option<Vec<ImportSuggestion>>,377 pub(crate) segment: Option<Ident>,378 /// comes from `PathRes::Failed { module }`379 pub(crate) module: Option<DefId>,380 pub(crate) on_unknown_attr: Option<OnUnknownData>,381}382383// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`384// are permitted for backward-compatibility under a deprecation lint.385fn pub_use_of_private_extern_crate_hack(386 import: ImportSummary,387 decl: Decl<'_>,388) -> Option<LocalDefId> {389 match (import.is_single, &decl.kind) {390 (true, DeclKind::Import { import: decl_import, .. })391 if let ImportKind::ExternCrate { def_id, .. } = decl_import.kind392 && import.vis.is_public() =>393 {394 Some(def_id)395 }396 _ => None,397 }398}399400/// Removes identical import layers from two declarations.401fn remove_same_import<'ra>(d1: Decl<'ra>, d2: Decl<'ra>) -> (Decl<'ra>, Decl<'ra>) {402 if let DeclKind::Import { import: import1, source_decl: d1_next } = d1.kind403 && let DeclKind::Import { import: import2, source_decl: d2_next } = d2.kind404 && import1 == import2405 {406 assert_eq!(d1.expansion, d2.expansion);407 assert_eq!(d1.span, d2.span);408 if d1.ambiguity.get() != d2.ambiguity.get() {409 assert!(d1.ambiguity.get().is_some());410 }411 // Visibility of the new import declaration may be different,412 // because it already incorporates the visibility of the source binding.413 remove_same_import(d1_next, d2_next)414 } else {415 (d1, d2)416 }417}418419impl<'ra, 'tcx> Resolver<'ra, 'tcx> {420 pub(crate) fn import_decl_vis(&self, decl: Decl<'ra>, import: ImportSummary) -> Visibility {421 self.import_decl_vis_ext(decl, import, false)422 }423424 pub(crate) fn import_decl_vis_ext(425 &self,426 decl: Decl<'ra>,427 import: ImportSummary,428 min: bool,429 ) -> Visibility {430 assert!(import.vis.is_accessible_from(import.nearest_parent_mod, self.tcx));431 let decl_vis = if min { decl.min_vis() } else { decl.vis() };432 let ord = decl_vis.partial_cmp(import.vis, self.tcx);433 let extern_crate_hack = pub_use_of_private_extern_crate_hack(import, decl).is_some();434 if ord == Some(Ordering::Less)435 && decl_vis.is_accessible_from(import.nearest_parent_mod, self.tcx)436 && !extern_crate_hack437 {438 // Imported declaration is less visible than the import, but is still visible439 // from the current module, use the declaration's visibility.440 decl_vis.expect_local()441 } else {442 // Good case - imported declaration is more visible than the import, or the same,443 // use the import's visibility.444 //445 // Bad case - imported declaration is too private for the current module.446 // It doesn't matter what visibility we choose here (except in the `PRIVATE_MACRO_USE`447 // and `PUB_USE_OF_PRIVATE_EXTERN_CRATE` cases), because an error will be reported.448 // Use import visibility to keep the all declaration visibilities in a module ordered.449 if !min450 && matches!(ord, None | Some(Ordering::Less))451 && !extern_crate_hack452 && !import.priv_macro_use453 {454 let msg = format!("cannot extend visibility from {decl_vis:?} to {:?}", import.vis);455 self.dcx().span_delayed_bug(import.span, msg);456 }457 import.vis458 }459 }460461 /// Given an import and the declaration that it points to,462 /// create the corresponding import declaration.463 pub(crate) fn new_import_decl(&self, decl: Decl<'ra>, import: Import<'ra>) -> Decl<'ra> {464 let vis = self.import_decl_vis(decl, import.summary());465466 if let ImportKind::Glob { ref max_vis, .. } = import.kind467 && (vis == import.vis468 || max_vis.get().is_none_or(|max_vis| vis.greater_than(max_vis, self.tcx)))469 {470 // `set` can't fail because this can only happen during "write_import_resolutions"471 max_vis.set_checked(Some(vis), self)472 }473474 self.arenas.alloc_decl(DeclData {475 kind: DeclKind::Import { source_decl: decl, import },476 ambiguity: CmCell::new(None),477 span: import.span,478 initial_vis: vis.to_mod_id(),479 ambiguity_vis_max: CmCell::new(None),480 ambiguity_vis_min: CmCell::new(None),481 expansion: import.parent_scope.expansion,482 parent_module: Some(import.parent_scope.module),483 })484 }485486 fn is_noise_0_7_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {487 let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };488 let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };489 let [seg1, seg2] = &i1.module_path[..] else { return false };490 if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin_surflet" {491 return false;492 }493 let [seg1, seg2] = &i2.module_path[..] else { return false };494 if seg1.ident.name != kw::SelfLower || seg2.ident.name.as_str() != "perlin" {495 return false;496 }497 let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };498 let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };499 self.def_path_str(def_id1).ends_with("noise_fns::generators::perlin_surflet::Perlin")500 && self.def_path_str(def_id2).ends_with("noise_fns::generators::perlin::Perlin")501 }502503 fn is_rustybuzz_0_4_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {504 let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };505 let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };506 let [seg1, seg2] = &i1.module_path[..] else { return false };507 if seg1.ident.name != kw::Super || seg2.ident.name.as_str() != "gsubgpos" {508 return false;509 }510 let [seg1] = &i2.module_path[..] else { return false };511 if seg1.ident.name != kw::Super {512 return false;513 }514 let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };515 let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };516 self.def_path_str(def_id1).ends_with("tables::gsubgpos::Class")517 && self.def_path_str(def_id2).ends_with("ggg::Class")518 }519520 fn is_pdf_0_9_0(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {521 let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };522 let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };523 let [seg1, seg2] = &i1.module_path[..] else { return false };524 if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "content" {525 return false;526 }527 let [seg1, seg2] = &i2.module_path[..] else { return false };528 if seg1.ident.name != kw::Crate || seg2.ident.name.as_str() != "object" {529 return false;530 }531 let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };532 let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };533 self.def_path_str(def_id1).ends_with("crate::content::Rect")534 && self.def_path_str(def_id2).ends_with("crate::object::types::Rect")535 }536537 fn is_net2_0_2_39(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> bool {538 let DeclKind::Import { import: i1, .. } = glob_decl.kind else { unreachable!() };539 let DeclKind::Import { import: i2, .. } = old_glob_decl.kind else { unreachable!() };540 let [seg1, seg2, seg3, seg4] = &i1.module_path[..] else { return false };541 if seg1.ident.name != kw::PathRoot542 || seg2.ident.name.as_str() != "winapi"543 || seg3.ident.name.as_str() != "shared"544 || seg4.ident.name.as_str() != "ws2def"545 {546 return false;547 }548 let [seg1, seg2, seg3, seg4] = &i2.module_path[..] else { return false };549 if seg1.ident.name != kw::PathRoot550 || seg2.ident.name.as_str() != "winapi"551 || seg3.ident.name.as_str() != "um"552 || seg4.ident.name.as_str() != "winsock2"553 {554 return false;555 }556 let Some(def_id1) = glob_decl.res().opt_def_id() else { return false };557 let Some(def_id2) = old_glob_decl.res().opt_def_id() else { return false };558 self.def_path_str(def_id1).starts_with("winapi::shared::ws2def::")559 && self.def_path_str(def_id2).starts_with("winapi::um::winsock2::")560 }561562 /// If `glob_decl` attempts to overwrite `old_glob_decl` in a module,563 /// decide which one to keep.564 fn select_glob_decl(&self, old_glob_decl: Decl<'ra>, glob_decl: Decl<'ra>) -> Decl<'ra> {565 assert!(glob_decl.is_glob_import());566 assert!(old_glob_decl.is_glob_import());567 assert_ne!(glob_decl, old_glob_decl);568 // `best_decl` with a given key in a module may be overwritten in a569 // number of cases (all of them can be seen below in the `match` in `try_define_local`),570 // all these overwrites will be re-fetched by glob imports importing571 // from that module without generating new ambiguities.572 // - A glob decl is overwritten by a non-glob decl arriving later.573 // - A glob decl is overwritten by a glob decl re-fetching an574 // overwritten decl from other module (the recursive case).575 // Here we are detecting all such re-fetches and overwrite old decls576 // with the re-fetched decls.577 // This is probably incorrect in corner cases, and the outdated decls still get578 // propagated to other places and get stuck there, but that's what we have at the moment.579 let (old_deep_decl, deep_decl) = remove_same_import(old_glob_decl, glob_decl);580 if deep_decl != glob_decl {581 // Some import layers have been removed, need to overwrite.582 assert_ne!(old_deep_decl, old_glob_decl);583 assert!(!deep_decl.is_glob_import());584 if let Some((old_ambig, _)) = old_glob_decl.ambiguity.get()585 && glob_decl.ambiguity.get().is_none()586 {587 // Do not lose glob ambiguities when re-fetching the glob.588 glob_decl.ambiguity.set_checked(Some((old_ambig, true)), self);589 }590 glob_decl591 } else if glob_decl.res() != old_glob_decl.res() {592 let warning = self.is_noise_0_7_0(old_glob_decl, glob_decl)593 || self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl)594 || self.is_pdf_0_9_0(old_glob_decl, glob_decl)595 || self.is_net2_0_2_39(old_glob_decl, glob_decl);596 old_glob_decl.ambiguity.set_checked(Some((glob_decl, warning)), self);597 old_glob_decl598 } else if let old_vis = old_glob_decl.vis()599 && let vis = glob_decl.vis()600 && old_vis != vis601 {602 // We are glob-importing the same item but with a different visibility.603 // All visibilities here are ordered because all of them are ancestors of `module`.604 if vis.greater_than(old_vis, self.tcx) {605 old_glob_decl.ambiguity_vis_max.set_checked(Some(glob_decl), self);606 } else if let old_min_vis = old_glob_decl.min_vis()607 && old_min_vis != vis608 && old_min_vis.greater_than(vis, self.tcx)609 {610 old_glob_decl.ambiguity_vis_min.set_checked(Some(glob_decl), self);611 }612 old_glob_decl613 } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() {614 // Overwriting a non-ambiguous glob import with an ambiguous glob import.615 old_glob_decl.ambiguity.set_checked(Some((glob_decl, true)), self);616 old_glob_decl617 } else {618 old_glob_decl619 }620 }621622 /// Attempt to put the declaration with the given name and namespace into the module,623 /// and return existing declaration if there is a collision.624 pub(crate) fn try_plant_decl_into_local_module(625 &mut self,626 ident: IdentKey,627 orig_ident_span: Span,628 ns: Namespace,629 decl: Decl<'ra>,630 ) -> Result<(), Decl<'ra>> {631 assert!(decl.ambiguity.get().is_none());632 assert!(decl.ambiguity_vis_max.get().is_none());633 assert!(decl.ambiguity_vis_min.get().is_none());634 let module = decl.parent_module.unwrap().expect_local();635 assert!(self.is_accessible_from(decl.vis(), module.to_module()));636 let res = decl.res();637 self.check_reserved_macro_name(ident.name, orig_ident_span, res);638 // Even if underscore names cannot be looked up, we still need to add them to modules,639 // because they can be fetched by glob imports from those modules, and bring traits640 // into scope both directly and through glob imports.641 let key = BindingKey::new_disambiguated(ident, ns, || {642 module.underscore_disambiguator.update(self, |d| d + 1);643 module.underscore_disambiguator.get()644 });645 self.update_local_resolution(module, key, orig_ident_span, |this, resolution| {646 if res == Res::Err647 && let Some(old_decl) = resolution.best_decl()648 && old_decl.res() != Res::Err649 {650 // Do not override real declarations with `Res::Err`s from error recovery.651 // FIXME: this special case shouldn't be necessary, but removing it triggers an ICE652 // due to some other issues (#157406, tests/ui/imports/dummy-import-ice.rs).653 return Ok(());654 }655 if decl.is_glob_import() {656 resolution.glob_decl = Some(match resolution.glob_decl {657 Some(old_decl) => this.select_glob_decl(old_decl, decl),658 None => decl,659 });660 } else {661 resolution.non_glob_decl = Some(match resolution.non_glob_decl {662 Some(old_decl) => return Err(old_decl),663 None => decl,664 })665 }666667 Ok(())668 })669 }670671 // Use `f` to mutate the resolution of the name in the module.672 // If the resolution becomes a success, define it in the module's glob importers.673 fn update_local_resolution<T, F>(674 &mut self,675 module: LocalModule<'ra>,676 key: BindingKey,677 orig_ident_span: Span,678 f: F,679 ) -> T680 where681 F: FnOnce(&Resolver<'ra, 'tcx>, &mut NameResolution<'ra>) -> T,682 {683 // Ensure that `resolution` isn't borrowed when defining in the module's glob importers,684 // during which the resolution might end up getting re-defined via a glob cycle.685 let (binding, t) = {686 let resolution = &mut *self687 .resolution_or_default(module.to_module(), key, orig_ident_span)688 .0689 .borrow_mut(self);690 let old_decl = resolution.determined_decl();691 let old_vis = old_decl.map(|d| d.vis());692693 let t = f(self, resolution);694695 if let Some(binding) = resolution.determined_decl()696 && (old_decl != Some(binding) || old_vis != Some(binding.vis()))697 {698 (binding, t)699 } else {700 return t;701 }702 };703704 let Ok(glob_importers) = module.glob_importers.try_borrow_mut(self) else {705 return t;706 };707708 // Define or update `binding` in `module`s glob importers.709 for import in glob_importers.iter() {710 let mut ident = key.ident;711 let scope = match ident712 .ctxt713 .update_unchecked(|ctxt| ctxt.reverse_glob_adjust(module.expansion, import.span))714 {715 Some(Some(def)) => self.expn_def_scope(def),716 Some(None) => import.parent_scope.module,717 None => continue,718 };719 if self.is_accessible_from(binding.vis(), scope) {720 let import_decl = self.new_import_decl(binding, *import);721 self.try_plant_decl_into_local_module(ident, orig_ident_span, key.ns, import_decl)722 .expect("planting a glob cannot fail");723 }724 }725726 t727 }728729 // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed730 // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.731 fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) {732 if let ImportKind::Single { target, ref decls, .. } = import.kind {733 if !(is_indeterminate || decls.iter().all(|d| d.get().decl().is_none())) {734 return; // Has resolution, do not create the dummy binding735 }736 let dummy_decl = self.dummy_decl;737 let dummy_decl = self.new_import_decl(dummy_decl, import);738 self.per_ns_mut(|this, ns| {739 let ident = IdentKey::new(target);740 // This can fail, dummies are inserted only in non-occupied slots.741 let _ = this.try_plant_decl_into_local_module(ident, target.span, ns, dummy_decl);742 // Don't remove underscores from `single_imports`, they were never added.743 if target.name != kw::Underscore {744 let key = BindingKey::new(ident, ns);745 this.update_local_resolution(746 import.parent_scope.module.expect_local(),747 key,748 target.span,749 |_, resolution| {750 resolution.single_imports.swap_remove(&import);751 },752 )753 }754 });755 self.record_use(target, dummy_decl, Used::Other);756 } else if import.imported_module.get().is_none() {757 self.import_use_map.insert(import, Used::Other);758 if let Some(id) = import.id() {759 self.used_imports.insert(id);760 }761 }762 }763764 // Import resolution765 //766 // This is a batched fixed-point algorithm. Each import is resolved in767 // isolation, with any resolutions collected for later.768 // After a full pass over the current set of `indeterminate_imports`,769 // the collected resolutions are committed together. The process770 // repeats until either no imports remain or no further progress can771 // be made.772773 /// Resolves all imports for the crate. This method performs the fixed-774 /// point iteration.775 pub(crate) fn resolve_imports(&mut self) {776 let mut prev_indeterminate_count = usize::MAX;777 let mut indeterminate_count = self.indeterminate_imports.len() * 3;778 while indeterminate_count < prev_indeterminate_count {779 prev_indeterminate_count = indeterminate_count;780 indeterminate_count = 0;781782 let mut imports_to_resolve = mem::take(&mut self.indeterminate_imports);783784 // SAFETY: This is a "top-level" function used by the macro expansion code, unless some785 // weird thing is done, all `tracked` borrows done in the previous call of786 // `resolve_imports` are dropped when that call ended.787 unsafe { self.speculative_flag.set(true) };788 rustc_data_structures::sync::par_for_each_slice(789 &mut imports_to_resolve,790 |(import, resolution, indeterminate_count)| {791 (*resolution, *indeterminate_count) = self.resolve_import(*import);792 },793 );794 // SAFETY: All `untracked` borrows are dropped after the `par_for_each_slice` call,795 // as they cannot escape since they are tied to the `CmRefCell` they borrowed from.796 //797 // Note: Some `CmRefCell`s are arena allocated and thus have the `'ra` lifetime,798 // allowing these borrows to escape, but that does not and should not happen.799 unsafe { self.speculative_flag.set(false) };800801 self.write_import_resolutions(&imports_to_resolve);802803 self.indeterminate_imports = imports_to_resolve804 .extract_if(.., |(_, _, count)| {805 indeterminate_count += *count;806 *count > 0807 })808 .collect();809 self.determined_imports.extend(imports_to_resolve.into_iter().map(|(i, _, _)| i));810 }811 }812813 fn write_import_resolutions(814 &mut self,815 import_resolutions: &[(Import<'ra>, Option<ImportResolution<'ra>>, usize)],816 ) {817 for &(import, ref resolution, _) in import_resolutions {818 let Some(ImportResolution { imported_module, .. }) = resolution else {819 continue;820 };821 import.imported_module.set(Some(*imported_module), self);822823 if import.is_glob()824 && let ModuleOrUniformRoot::Module(module) = imported_module825 && import.parent_scope.module != *module826 && module.is_local()827 {828 module.glob_importers.borrow_mut(self).push(import);829 }830 }831832 for &(import, ref resolution, _) in import_resolutions {833 let Some(ImportResolution { imported_module, kind: resolution_kind }) = resolution834 else {835 continue;836 };837838 match (&import.kind, resolution_kind) {839 (840 ImportKind::Single { target, decls, .. },841 ImportResolutionKind::Single(import_decls),842 ) => {843 self.per_ns_mut(|this, ns| {844 match import_decls[ns] {845 PendingDecl::Ready(Some(decl)) => {846 // We need the `target`, `source` can be extracted.847 let import_decl = this.new_import_decl(decl, import);848 if import_decl.is_assoc_item()849 && !this.features.import_trait_associated_functions()850 {851 feature_err(852 this.tcx.sess,853 sym::import_trait_associated_functions,854 import.span,855 "`use` associated items of traits is unstable",856 )857 .emit();858 }859 this.plant_decl_into_local_module(860 IdentKey::new(*target),861 target.span,862 ns,863 import_decl,864 );865 decls[ns].set(PendingDecl::Ready(Some(import_decl)), this);866 }867 PendingDecl::Ready(None) => {868 // Don't remove underscores from `single_imports`, they were never added.869 if target.name != kw::Underscore {870 let key = BindingKey::new(IdentKey::new(*target), ns);871 this.update_local_resolution(872 import.parent_scope.module.expect_local(),873 key,874 target.span,875 |_, resolution| {876 resolution.single_imports.swap_remove(&import);877 },878 );879 }880 decls[ns].set(PendingDecl::Ready(None), this);881 }882 PendingDecl::Pending => {}883 }884 });885 }886 (ImportKind::Glob { id, .. }, ImportResolutionKind::Glob(imported_decls)) => {887 let ModuleOrUniformRoot::Module(module) = imported_module else {888 self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span });889 continue;890 };891892 if module.is_trait() && !self.features.import_trait_associated_functions() {893 feature_err(894 self.tcx.sess,895 sym::import_trait_associated_functions,896 import.span,897 "`use` associated items of traits is unstable",898 )899 .emit();900 }901902 for (binding, key, orig_ident_span) in imported_decls {903 let import_decl = self.new_import_decl(*binding, import);904 let _ = self905 .try_plant_decl_into_local_module(906 key.ident,907 *orig_ident_span,908 key.ns,909 import_decl,910 )911 .expect("planting a glob cannot fail");912 }913914 self.record_partial_res(*id, PartialRes::new(module.res().unwrap()));915 }916917 // Something weird happened, which shouldn't have happened.918 _ => unreachable!("mismatched import and resolution kind"),919 }920 }921 }922923 pub(crate) fn finalize_imports(&mut self) {924 let mut module_children = Default::default();925 let mut ambig_module_children = Default::default();926 for module in &self.local_modules {927 self.finalize_resolutions_in(*module, &mut module_children, &mut ambig_module_children);928 }929 self.module_children = module_children;930 self.ambig_module_children = ambig_module_children;931932 let mut seen_spans = FxHashSet::default();933 let mut errors = vec![];934 let mut prev_root_id: NodeId = NodeId::ZERO;935 let determined_imports = mem::take(&mut self.determined_imports);936 let indeterminate_imports = mem::take(&mut self.indeterminate_imports);937938 let mut glob_error = false;939 for (is_indeterminate, import) in determined_imports940 .iter()941 .map(|i| (false, i))942 .chain(indeterminate_imports.iter().map(|(i, _, _)| (true, i)))943 {944 let unresolved_import_error = self.finalize_import(*import);945 // If this import is unresolved then create a dummy import946 // resolution for it so that later resolve stages won't complain.947 self.import_dummy_binding(*import, is_indeterminate);948949 let Some(err) = unresolved_import_error else { continue };950951 glob_error |= import.is_glob();952953 if let ImportKind::Single { source, ref decls, .. } = import.kind954 && source.name == kw::SelfLower955 // Silence `unresolved import` error if E0429 is already emitted956 && let PendingDecl::Ready(None) = decls.value_ns.get()957 {958 continue;959 }960961 if prev_root_id != NodeId::ZERO && prev_root_id != import.root_id && !errors.is_empty()962 {963 // In the case of a new import line, throw a diagnostic message964 // for the previous line.965 self.throw_unresolved_import_error(errors, glob_error);966 errors = vec![];967 }968 if seen_spans.insert(err.span) {969 errors.push((*import, err));970 prev_root_id = import.root_id;971 }972 }973974 if self.cstore().had_extern_crate_load_failure() {975 self.tcx.sess.dcx().abort_if_errors();976 }977978 if !errors.is_empty() {979 self.throw_unresolved_import_error(errors, glob_error);980 return;981 }982983 for (import, _, _) in &indeterminate_imports {984 let path = import_path_to_string(985 &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),986 &import.kind,987 import.span,988 );989 // FIXME: there should be a better way of doing this than990 // formatting this as a string then checking for `::`991 if path.contains("::") {992 let err = UnresolvedImportError {993 span: import.span,994 label: None,995 note: None,996 suggestion: None,997 candidates: None,998 segment: None,999 module: None,1000 on_unknown_attr: import.on_unknown_attr.clone(),1001 };1002 errors.push((*import, err))1003 }1004 }10051006 if !errors.is_empty() {1007 self.throw_unresolved_import_error(errors, glob_error);1008 }1009 }10101011 pub(crate) fn lint_reexports(&mut self, exported_ambiguities: FxHashSet<Decl<'ra>>) {1012 for module in &self.local_modules {1013 for (key, resolution) in self.resolutions(module.to_module()).iter() {1014 let resolution = resolution.borrow_checked(self);1015 let Some(binding) = resolution.best_decl() else { continue };10161017 // Report "cannot reexport" errors for exotic cases involving macros 2.01018 // privacy bending or invariant-breaking code under deprecation lints.1019 for decl in [resolution.non_glob_decl, resolution.glob_decl] {1020 if let Some(decl) = decl1021 && let DeclKind::Import { source_decl, import } = decl.kind1022 // FIXME: Do not check visibility-ambiguous imports for now. To check them1023 // properly we need to preserve all imports in ambiguous glob sets and1024 // check them all individually.1025 && decl.ambiguity_vis_max.get().is_none()1026 {1027 // The source entity is too private to be reexported1028 // with the given import declaration's visibility.1029 let ord = source_decl.vis().partial_cmp(decl.vis(), self.tcx);1030 if matches!(ord, None | Some(Ordering::Less)) {1031 let ident = match import.kind {1032 ImportKind::Single { source, .. } => source,1033 _ => key.ident.orig(resolution.orig_ident_span),1034 };1035 if let Some(lint) =1036 self.report_cannot_reexport(import, source_decl, ident, key.ns)1037 {1038 self.lint_buffer.add_early_lint(lint);1039 }1040 }1041 }1042 }10431044 if let DeclKind::Import { import, .. } = binding.kind1045 && let Some((amb_binding, _)) = binding.ambiguity.get()1046 && binding.res() != Res::Err1047 && exported_ambiguities.contains(&binding)1048 {1049 self.lint_buffer.buffer_lint(1050 AMBIGUOUS_GLOB_REEXPORTS,1051 import.root_id,1052 import.root_span,1053 diagnostics::AmbiguousGlobReexports {1054 name: key.ident.name.to_string(),1055 namespace: key.ns.descr().to_string(),1056 first_reexport: import.root_span,1057 duplicate_reexport: amb_binding.span,1058 },1059 );1060 }10611062 if let Some(glob_decl) = resolution.glob_decl1063 && resolution.non_glob_decl.is_some()1064 {1065 if binding.res() != Res::Err1066 && glob_decl.res() != Res::Err1067 && let DeclKind::Import { import: glob_import, .. } = glob_decl.kind1068 && let Some(glob_import_def_id) = glob_import.def_id()1069 && self.effective_visibilities.is_exported(glob_import_def_id)1070 && glob_decl.vis().is_public()1071 && !binding.vis().is_public()1072 {1073 let binding_id = match binding.kind {1074 DeclKind::Def(res) => {1075 Some(self.def_id_to_node_id(res.def_id().expect_local()))1076 }1077 DeclKind::Import { import, .. } => import.id(),1078 };1079 if let Some(binding_id) = binding_id {1080 self.lint_buffer.buffer_lint(1081 HIDDEN_GLOB_REEXPORTS,1082 binding_id,1083 binding.span,1084 diagnostics::HiddenGlobReexports {1085 name: key.ident.name.to_string(),1086 namespace: key.ns.descr().to_owned(),1087 glob_reexport: glob_decl.span,1088 private_item: binding.span,1089 },1090 );1091 }1092 }1093 }10941095 if let DeclKind::Import { import, .. } = binding.kind1096 && let Some(binding_id) = import.id()1097 && let import_def_id = import.def_id().unwrap()1098 && self.effective_visibilities.is_exported(import_def_id)1099 && let Res::Def(reexported_kind, reexported_def_id) = binding.res()1100 && !matches!(reexported_kind, DefKind::Ctor(..))1101 && !reexported_def_id.is_local()1102 && self.tcx.is_private_dep(reexported_def_id.krate)1103 {1104 self.lint_buffer.buffer_lint(1105 EXPORTED_PRIVATE_DEPENDENCIES,1106 binding_id,1107 binding.span,1108 crate::diagnostics::ReexportPrivateDependency {1109 name: key.ident.name,1110 kind: binding.res().descr(),1111 krate: self.tcx.crate_name(reexported_def_id.krate),1112 },1113 );1114 }1115 }1116 }1117 }11181119 /// Attempts to resolve the given import, returning:1120 /// - `0` means its resolution is determined.1121 /// - Other values mean that indeterminate exists under certain namespaces.1122 ///1123 /// Meanwhile, if resolution is successful, its result is returned.1124 fn resolve_import(&self, import: Import<'ra>) -> (Option<ImportResolution<'ra>>, usize) {1125 debug!(1126 "(resolving import for module) resolving import `{}::{}` in `{}`",1127 Segment::names_to_string(&import.module_path),1128 import_kind_to_string(&import.kind),1129 module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()),1130 );1131 let module = if let Some(module) = import.imported_module.get() {1132 module1133 } else {1134 let path_res = self.cm().maybe_resolve_path(1135 &import.module_path,1136 None,1137 &import.parent_scope,1138 Some(import),1139 );11401141 match path_res {1142 PathResult::Module(module) => module,1143 PathResult::Indeterminate => return (None, 3),1144 PathResult::NonModule(..) | PathResult::Failed { .. } => return (None, 0),1145 }1146 };11471148 let (source, bindings) = match import.kind {1149 ImportKind::Single { source, ref decls, .. } => (source, decls),1150 ImportKind::Glob { .. } => {1151 let import_resolution = ImportResolution {1152 imported_module: module,1153 kind: self.resolve_glob_import(import, module),1154 };1155 return (Some(import_resolution), 0);1156 }1157 _ => unreachable!(),1158 };11591160 let mut decls = PerNS::default();1161 let mut indeterminate_count = 0;1162 self.per_ns(|this, ns| {1163 if bindings[ns].get() != PendingDecl::Pending {1164 return;1165 };1166 let binding_result = this.cm().maybe_resolve_ident_in_module(1167 module,1168 source,1169 ns,1170 &import.parent_scope,1171 Some(import),1172 );1173 let pending_decl = match binding_result {1174 Ok(binding) => PendingDecl::Ready(Some(binding)),1175 Err(Determinacy::Determined) => PendingDecl::Ready(None),1176 Err(Determinacy::Undetermined) => {1177 indeterminate_count += 1;1178 PendingDecl::Pending1179 }1180 };1181 decls[ns] = pending_decl;1182 });1183 let import_resolution =1184 ImportResolution { imported_module: module, kind: ImportResolutionKind::Single(decls) };11851186 (Some(import_resolution), indeterminate_count)1187 }11881189 /// Performs final import resolution, consistency checks and error reporting.1190 ///1191 /// Optionally returns an unresolved import error. This error is buffered and used to1192 /// consolidate multiple unresolved import errors into a single diagnostic.1193 fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportError> {1194 let ignore_decl = match &import.kind {1195 ImportKind::Single { decls, .. } => decls[TypeNS].get().decl(),1196 _ => None,1197 };1198 let ambiguity_errors_len = |errors: &Vec<AmbiguityError<'_>>| {1199 errors.iter().filter(|error| error.warning.is_none()).count()1200 };1201 let prev_ambiguity_errors_len = ambiguity_errors_len(&self.ambiguity_errors);1202 let finalize = Finalize::with_root_span(import.root_id, import.span, import.root_span);12031204 // We'll provide more context to the privacy errors later, up to `len`.1205 let privacy_errors_len = self.privacy_errors.len();12061207 let path_res = self.cm_mut().resolve_path(1208 &import.module_path,1209 None,1210 &import.parent_scope,1211 Some(finalize),1212 ignore_decl,1213 Some(import),1214 );12151216 let no_ambiguity =1217 ambiguity_errors_len(&self.ambiguity_errors) == prev_ambiguity_errors_len;12181219 let module = match path_res {1220 PathResult::Module(module) => {1221 // Consistency checks, analogous to `finalize_macro_resolutions`.1222 if let Some(initial_module) = import.imported_module.get() {1223 if module != initial_module && no_ambiguity && !self.issue_145575_hack_applied {1224 span_bug!(import.span, "inconsistent resolution for an import");1225 }1226 } else if self.privacy_errors.is_empty() {1227 self.dcx()1228 .create_err(CannotDetermineImportResolution { span: import.span })1229 .emit();1230 }12311232 module1233 }1234 PathResult::Failed {1235 is_error_from_last_segment: false,1236 span,1237 segment,1238 label,1239 suggestion,1240 module,1241 error_implied_by_parse_error: _,1242 message,1243 note: _,1244 } => {1245 if no_ambiguity {1246 if !self.issue_145575_hack_applied {1247 assert!(import.imported_module.get().is_none());1248 }1249 self.report_error(1250 span,1251 ResolutionError::FailedToResolve {1252 segment: segment.name,1253 label,1254 suggestion,1255 module,1256 message,1257 },1258 );1259 }1260 return None;1261 }1262 PathResult::Failed {1263 is_error_from_last_segment: true,1264 span,1265 label,1266 suggestion,1267 module,1268 segment,1269 note,1270 ..1271 } => {1272 if no_ambiguity {1273 if !self.issue_145575_hack_applied {1274 assert!(import.imported_module.get().is_none());1275 }1276 let module = if let Some(ModuleOrUniformRoot::Module(m)) = module {1277 m.opt_def_id()1278 } else {1279 None1280 };1281 let err = match self1282 .make_path_suggestion(import.module_path.clone(), &import.parent_scope)1283 {1284 Some((suggestion, note)) => UnresolvedImportError {1285 span,1286 label: None,1287 note,1288 suggestion: Some((1289 vec![(span, Segment::names_to_string(&suggestion))],1290 String::from("a similar path exists"),1291 Applicability::MaybeIncorrect,1292 )),1293 candidates: None,1294 segment: Some(segment),1295 module,1296 on_unknown_attr: import.on_unknown_attr.clone(),1297 },1298 None => UnresolvedImportError {1299 span,1300 label: Some(label),1301 note,1302 suggestion,1303 candidates: None,1304 segment: Some(segment),1305 module,1306 on_unknown_attr: import.on_unknown_attr.clone(),1307 },1308 };1309 return Some(err);1310 }1311 return None;1312 }1313 PathResult::NonModule(partial_res) => {1314 if no_ambiguity && partial_res.full_res() != Some(Res::Err) {1315 // Check if there are no ambiguities and the result is not dummy.1316 assert!(import.imported_module.get().is_none());1317 }1318 // The error was already reported earlier.1319 return None;1320 }1321 PathResult::Indeterminate => unreachable!(),1322 };13231324 let (ident, target, bindings, import_id) = match import.kind {1325 ImportKind::Single { source, target, ref decls, id, .. } => (source, target, decls, id),1326 ImportKind::Glob { ref max_vis, id, def_id } => {1327 if import.module_path.len() <= 1 {1328 // HACK(eddyb) `lint_if_path_starts_with_module` needs at least1329 // 2 segments, so the `resolve_path` above won't trigger it.1330 let mut full_path = import.module_path.clone();1331 full_path.push(Segment::from_ident(Ident::dummy()));1332 self.lint_if_path_starts_with_module(finalize, &full_path, None);1333 }13341335 if let ModuleOrUniformRoot::Module(module) = module1336 && module == import.parent_scope.module1337 {1338 // Importing a module into itself is not allowed.1339 return Some(UnresolvedImportError {1340 span: import.span,1341 label: Some(String::from("cannot glob-import a module into itself")),1342 note: None,1343 suggestion: None,1344 candidates: None,1345 segment: None,1346 module: None,1347 on_unknown_attr: None,1348 });1349 }1350 if let Some(max_vis) = max_vis.get()1351 && import.vis.greater_than(max_vis, self.tcx)1352 {1353 self.lint_buffer.buffer_lint(1354 UNUSED_IMPORTS,1355 id,1356 import.span,1357 crate::diagnostics::RedundantImportVisibility {1358 span: import.span,1359 help: (),1360 max_vis: max_vis.to_string(def_id, self.tcx),1361 import_vis: import.vis.to_string(def_id, self.tcx),1362 },1363 );1364 }1365 return None;1366 }1367 _ => unreachable!(),1368 };13691370 if self.privacy_errors.len() != privacy_errors_len {1371 // Get the Res for the last element, so that we can point to alternative ways of1372 // importing it if available.1373 let mut path = import.module_path.clone();1374 path.push(Segment::from_ident(ident));1375 if let PathResult::Module(ModuleOrUniformRoot::Module(module)) = self1376 .cm_mut()1377 .resolve_path(&path, None, &import.parent_scope, Some(finalize), ignore_decl, None)1378 {1379 let res = module.res().map(|r| (r, ident));1380 for error in &mut self.privacy_errors[privacy_errors_len..] {1381 error.outermost_res = res;1382 }1383 } else {1384 // The final item is not a module (e.g., a struct, function, or macro).1385 // Resolve it directly in the parent module to get its Res, so1386 // `report_privacy_error()` can search for public re-export paths.1387 for ns in [TypeNS, ValueNS, MacroNS] {1388 if let Ok(binding) = self.cm().resolve_ident_in_module(1389 module,1390 ident,1391 ns,1392 &import.parent_scope,1393 None,1394 ignore_decl,1395 None,1396 ) {1397 let res = binding.res();1398 for error in &mut self.privacy_errors[privacy_errors_len..] {1399 error.outermost_res = Some((res, ident));1400 }1401 break;1402 }1403 }1404 }1405 }14061407 let mut all_ns_err = true;1408 self.per_ns_mut(|this, ns| {1409 let binding = this.cm_mut().resolve_ident_in_module(1410 module,1411 ident,1412 ns,1413 &import.parent_scope,1414 Some(Finalize {1415 report_private: false,1416 import: Some(import.summary()),1417 ..finalize1418 }),1419 bindings[ns].get().decl(),1420 Some(import),1421 );14221423 match binding {1424 Ok(binding) => {1425 // Consistency checks, analogous to `finalize_macro_resolutions`.1426 let initial_res = bindings[ns].get().decl().map(|binding| {1427 let initial_binding = binding.import_source();1428 all_ns_err = false;1429 if target.name == kw::Underscore1430 && initial_binding.is_extern_crate()1431 && !initial_binding.is_import()1432 {1433 let used = if import.module_path.is_empty() {1434 Used::Scope1435 } else {1436 Used::Other1437 };1438 this.record_use(ident, binding, used);1439 }1440 initial_binding.res()1441 });1442 let res = binding.res();1443 let has_ambiguity_error =1444 this.ambiguity_errors.iter().any(|error| error.warning.is_none());1445 if res == Res::Err || has_ambiguity_error {1446 this.dcx()1447 .span_delayed_bug(import.span, "some error happened for an import");1448 return;1449 }1450 if let Some(initial_res) = initial_res {1451 if res != initial_res && !this.issue_145575_hack_applied {1452 span_bug!(import.span, "inconsistent resolution for an import");1453 }1454 } else if this.privacy_errors.is_empty() {1455 this.dcx()1456 .create_err(CannotDetermineImportResolution { span: import.span })1457 .emit();1458 }1459 }1460 Err(..) => {1461 // FIXME: This assert may fire if public glob is later shadowed by a private1462 // single import (see test `issue-55884-2.rs`). In theory single imports should1463 // always block globs, even if they are not yet resolved, so that this kind of1464 // self-inconsistent resolution never happens.1465 // Re-enable the assert when the issue is fixed.1466 // assert!(result[ns].get().is_err());1467 }1468 }1469 });14701471 if all_ns_err {1472 let mut all_ns_failed = true;1473 self.per_ns_mut(|this, ns| {1474 let binding = this.cm_mut().resolve_ident_in_module(1475 module,1476 ident,1477 ns,1478 &import.parent_scope,1479 Some(finalize),1480 None,1481 None,1482 );1483 if binding.is_ok() {1484 all_ns_failed = false;1485 }1486 });14871488 return if all_ns_failed {1489 let names = match module {1490 ModuleOrUniformRoot::Module(module) => {1491 self.resolutions(module)1492 .iter()1493 .filter_map(|(BindingKey { ident: i, .. }, resolution)| {1494 if i.name == ident.name {1495 return None;1496 } // Never suggest the same name1497 if i.name == kw::Underscore {1498 return None;1499 } // `use _` is never valid15001501 let resolution = resolution.borrow(self);1502 if let Some(name_binding) = resolution.best_decl() {1503 match name_binding.kind {1504 DeclKind::Import { source_decl, .. } => {1505 match source_decl.kind {1506 // Never suggest names that previously could not1507 // be resolved.1508 DeclKind::Def(Res::Err) => None,1509 _ => Some(i.name),1510 }1511 }1512 _ => Some(i.name),1513 }1514 } else if resolution.single_imports.is_empty() {1515 None1516 } else {1517 Some(i.name)1518 }1519 })1520 .collect()1521 }1522 _ => Vec::new(),1523 };15241525 let lev_suggestion =1526 find_best_match_for_name(&names, ident.name, None).map(|suggestion| {1527 (1528 vec![(ident.span, suggestion.to_string())],1529 String::from("a similar name exists in the module"),1530 Applicability::MaybeIncorrect,1531 )1532 });15331534 let (suggestion, note) =1535 match self.check_for_module_export_macro(import, module, ident) {1536 Some((suggestion, note)) => (suggestion.or(lev_suggestion), note),1537 _ => (lev_suggestion, None),1538 };15391540 // If importing of trait asscoiated items is enabled, an also find an1541 // `Enum`, then note that inherent associated items cannot be imported.1542 let note = if self.features.import_trait_associated_functions()1543 && let PathResult::Module(ModuleOrUniformRoot::Module(m)) = path_res1544 && let Some(Res::Def(DefKind::Enum, _)) = m.res()1545 {1546 note.or(Some(1547 "cannot import inherent associated items, only trait associated items"1548 .to_string(),1549 ))1550 } else {1551 note1552 };15531554 let label = match module {1555 ModuleOrUniformRoot::Module(module) => {1556 let module_str = module_to_string(module);1557 if let Some(module_str) = module_str {1558 format!("no `{ident}` in `{module_str}`")1559 } else {1560 format!("no `{ident}` in the root")1561 }1562 }1563 _ => {1564 if !ident.is_path_segment_keyword() {1565 format!("no external crate `{ident}`")1566 } else {1567 // HACK(eddyb) this shows up for `self` & `super`, which1568 // should work instead - for now keep the same error message.1569 format!("no `{ident}` in the root")1570 }1571 }1572 };15731574 let parent_suggestion =1575 self.lookup_import_candidates(ident, TypeNS, &import.parent_scope, |_| true);15761577 Some(UnresolvedImportError {1578 span: import.span,1579 label: Some(label),1580 note,1581 suggestion,1582 candidates: if !parent_suggestion.is_empty() {1583 Some(parent_suggestion)1584 } else {1585 None1586 },1587 module: import.imported_module.get().and_then(|module| {1588 if let ModuleOrUniformRoot::Module(m) = module {1589 m.opt_def_id()1590 } else {1591 None1592 }1593 }),1594 segment: Some(ident),1595 on_unknown_attr: import.on_unknown_attr.clone(),1596 })1597 } else {1598 // `resolve_ident_in_module` reported a privacy error.1599 None1600 };1601 }16021603 let mut reexport_error = None;1604 let mut any_successful_reexport = false;1605 self.per_ns(|this, ns| {1606 let Some(binding) = bindings[ns].get().decl() else {1607 return;1608 };16091610 if import.vis.greater_than(binding.vis(), this.tcx) {1611 // In isolation, a declaration like this is not an error, but if *all* 1-31612 // declarations introduced by the import are more private than the import item's1613 // nominal visibility, then it's an error.1614 reexport_error = Some((ns, binding.import_source()));1615 } else {1616 any_successful_reexport = true;1617 }1618 });16191620 if !any_successful_reexport {1621 let (ns, binding) = reexport_error.unwrap();1622 if let Some(lint) = self.report_cannot_reexport(import, binding, ident, ns) {1623 self.lint_buffer.add_early_lint(lint);1624 }1625 }16261627 if import.module_path.len() <= 1 {1628 // HACK(eddyb) `lint_if_path_starts_with_module` needs at least1629 // 2 segments, so the `resolve_path` above won't trigger it.1630 let mut full_path = import.module_path.clone();1631 full_path.push(Segment::from_ident(ident));1632 self.per_ns_mut(|this, ns| {1633 if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {1634 this.lint_if_path_starts_with_module(finalize, &full_path, Some(binding));1635 }1636 });1637 }16381639 // Record what this import resolves to for later uses in documentation,1640 // this may resolve to either a value or a type, but for documentation1641 // purposes it's good enough to just favor one over the other.1642 self.per_ns_mut(|this, ns| {1643 if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) {1644 this.owners.get_mut(&import_id).unwrap().import_res[ns] = Some(binding.res());1645 }1646 });16471648 debug!("(resolving single import) successfully resolved import");1649 None1650 }16511652 fn report_cannot_reexport(1653 &self,1654 import: Import<'ra>,1655 decl: Decl<'ra>,1656 ident: Ident,1657 ns: Namespace,1658 ) -> Option<BufferedEarlyLint> {1659 let crate_private_reexport = match decl.vis() {1660 Visibility::Restricted(mod_id) if mod_id.is_top_level_module() => true,1661 _ => false,1662 };16631664 if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl)1665 {1666 let ImportKind::Single { id, .. } = import.kind else { unreachable!() };1667 let sugg = self.tcx.source_span(extern_crate_id).shrink_to_lo();1668 let diagnostic = crate::diagnostics::PrivateExternCrateReexport { ident, sugg };1669 return Some(BufferedEarlyLint {1670 lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE),1671 node_id: id,1672 span: Some(import.span.into()),1673 diagnostic: diagnostic.into(),1674 });1675 } else if ns == TypeNS {1676 let err = if crate_private_reexport {1677 self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident })1678 } else {1679 self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident })1680 };1681 err.emit();1682 } else {1683 let mut err = if crate_private_reexport {1684 self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident })1685 } else {1686 self.dcx().create_err(CannotBeReexportedPrivate { span: import.span, ident })1687 };16881689 match decl.kind {1690 // exclude decl_macro1691 DeclKind::Def(Res::Def(DefKind::Macro(_), def_id))1692 if let SyntaxExtensionKind::MacroRules(mr) =1693 &self.get_macro_by_def_id(def_id).kind1694 && mr.is_macro_rules() =>1695 {1696 err.subdiagnostic(ConsiderAddingMacroExport { span: decl.span });1697 err.subdiagnostic(ConsiderMarkingAsPubCrate { vis_span: import.vis_span });1698 }1699 _ => {1700 err.subdiagnostic(ConsiderMarkingAsPub { span: import.span, ident });1701 }1702 }1703 err.emit();1704 }17051706 None1707 }17081709 pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {1710 // This function is only called for single imports.1711 let ImportKind::Single { source, target, ref decls, id, def_id, .. } = import.kind else {1712 unreachable!()1713 };17141715 // Skip if the import is of the form `use source as target` and source != target.1716 if source != target {1717 return false;1718 }17191720 // Skip if the import was produced by a macro.1721 if import.parent_scope.expansion != LocalExpnId::ROOT {1722 return false;1723 }17241725 // Skip if we are inside a named module (in contrast to an anonymous1726 // module defined by a block).1727 // Skip if the import is public or was used through non scope-based resolution,1728 // e.g. through a module-relative path.1729 if self.import_use_map.get(&import) == Some(&Used::Other)1730 || self.effective_visibilities.is_exported(def_id)1731 {1732 return false;1733 }17341735 let mut is_redundant = true;1736 let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };1737 self.per_ns(|this, ns| {1738 let binding = decls[ns].get().decl().map(|b| b.import_source());1739 if is_redundant && let Some(binding) = binding {1740 if binding.res() == Res::Err {1741 return;1742 }17431744 match this.cm().resolve_ident_in_scope_set(1745 target,1746 ScopeSet::All(ns),1747 &import.parent_scope,1748 None,1749 decls[ns].get().decl(),1750 None,1751 ) {1752 Ok(other_binding) => {1753 is_redundant = binding.res() == other_binding.res()1754 && !other_binding.is_ambiguity_recursive();1755 if is_redundant {1756 redundant_span[ns] =1757 Some((other_binding.span, other_binding.is_import()));1758 }1759 }1760 Err(_) => is_redundant = false,1761 }1762 }1763 });17641765 if is_redundant && !redundant_span.is_empty() {1766 let mut redundant_spans: Vec<_> = redundant_span.present_items().collect();1767 redundant_spans.sort();1768 redundant_spans.dedup();1769 self.lint_buffer.dyn_buffer_lint(1770 REDUNDANT_IMPORTS,1771 id,1772 import.span,1773 move |dcx, level| {1774 let ident = source;1775 let subs = redundant_spans1776 .into_iter()1777 .map(|(span, is_imported)| match (span.is_dummy(), is_imported) {1778 (false, true) => {1779 diagnostics::RedundantImportSub::ImportedHere { span, ident }1780 }1781 (false, false) => {1782 diagnostics::RedundantImportSub::DefinedHere { span, ident }1783 }1784 (true, true) => {1785 diagnostics::RedundantImportSub::ImportedPrelude { span, ident }1786 }1787 (true, false) => {1788 diagnostics::RedundantImportSub::DefinedPrelude { span, ident }1789 }1790 })1791 .collect();1792 diagnostics::RedundantImport { subs, ident }.into_diag(dcx, level)1793 },1794 );1795 return true;1796 }17971798 false1799 }18001801 fn resolve_glob_import(1802 &self,1803 import: Import<'ra>,1804 imported_module: ModuleOrUniformRoot<'ra>,1805 ) -> ImportResolutionKind<'ra> {1806 let import_bindings = match imported_module {1807 ModuleOrUniformRoot::Module(module) if module != import.parent_scope.module => self1808 .resolutions(module)1809 .iter()1810 .filter_map(|(key, resolution)| {1811 let res = resolution.borrow_checked(self);1812 let decl = res.determined_decl()?;1813 let mut key = *key;1814 let scope = match key.ident.ctxt.update_unchecked(|ctxt| {1815 ctxt.reverse_glob_adjust(module.expansion, import.span)1816 }) {1817 Some(Some(def)) => self.expn_def_scope(def),1818 Some(None) => import.parent_scope.module,1819 None => return None,1820 };1821 self.is_accessible_from(decl.vis(), scope).then_some((1822 decl,1823 key,1824 res.orig_ident_span,1825 ))1826 })1827 .collect::<Vec<_>>(),18281829 // Errors are reported in `write_imports_resolutions`1830 _ => vec![],1831 };18321833 ImportResolutionKind::Glob(import_bindings)1834 }18351836 // Hack for the `rust_embed` regression observed in the crater run of #145108.1837 fn rust_embed_hack(&self, module: LocalModule<'ra>, decl: Decl<'ra>) -> bool {1838 // We are looking for this pattern:1839 // ```rust1840 // #[macro_use]1841 // extern crate rust_embed_impl;1842 // pub use rust_embed_impl::*;1843 //1844 // pub use RustEmbed as Embed;1845 // ```1846 if let DeclKind::Import { source_decl, import } = decl.kind1847 // Check that `decl` is the re-export: "pub use RustEmbed as Embed;"1848 && let ImportKind::Single { source, .. } = import.kind1849 && source.name == sym::RustEmbed1850 // make sure that the import points to the #[macro_use] import1851 && let DeclKind::Import { import, .. } = source_decl.kind1852 && matches!(import.kind, ImportKind::MacroUse { .. })1853 && self.macro_use_prelude.contains_key(&source.name) // and that the name actually exists in the macro_use_prelude1854 // Then check that `RustEmbed` exists in the modules Macro namespace.1855 && let Some(y_decl) = self1856 .resolution(module.to_module(), BindingKey::new(IdentKey::new(source), MacroNS))1857 .and_then(|res| res.best_decl())1858 // which comes from "pub use rust_embed_impl::*"1859 && y_decl.is_glob_import()1860 && y_decl.vis().is_public()1861 {1862 return true;1863 }18641865 false1866 }18671868 // Miscellaneous post-processing, including recording re-exports,1869 // reporting conflicts, and reporting unresolved imports.1870 fn finalize_resolutions_in(1871 &self,1872 module: LocalModule<'ra>,1873 module_children: &mut LocalDefIdMap<Vec<ModChild>>,1874 ambig_module_children: &mut LocalDefIdMap<Vec<AmbigModChild>>,1875 ) {1876 // Since import resolution is finished, globs will not define any more names.1877 *module.globs.borrow_mut_checked(self) = Vec::new();18781879 let Some(def_id) = module.opt_def_id() else { return };18801881 let mut children = Vec::new();1882 let mut ambig_children = Vec::new();18831884 module.to_module().for_each_child(self, |this, ident, orig_ident_span, _, decl| {1885 let res = decl.res().expect_non_local();1886 if res != def::Res::Err {1887 let vis = if this.rust_embed_hack(module, decl) {1888 Visibility::Public1889 } else {1890 decl.vis()1891 };1892 let ident = ident.orig(orig_ident_span);1893 let child = |reexport_chain| ModChild { ident, res, vis, reexport_chain };1894 if let Some((ambig_binding1, ambig_binding2)) = decl.descent_to_ambiguity() {1895 let main = child(ambig_binding1.reexport_chain());1896 let second = ModChild {1897 ident,1898 res: ambig_binding2.res().expect_non_local(),1899 vis: ambig_binding2.vis(),1900 reexport_chain: ambig_binding2.reexport_chain(),1901 };1902 ambig_children.push(AmbigModChild { main, second })1903 } else {1904 children.push(child(decl.reexport_chain()));1905 }1906 }1907 });19081909 if !children.is_empty() {1910 module_children.insert(def_id.expect_local(), children);1911 }1912 if !ambig_children.is_empty() {1913 ambig_module_children.insert(def_id.expect_local(), ambig_children);1914 }1915 }1916}19171918pub(crate) fn import_path_to_string(1919 names: &[Ident],1920 import_kind: &ImportKind<'_>,1921 span: Span,1922) -> String {1923 let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot);1924 let global = !names.is_empty() && names[0].name == kw::PathRoot;1925 if let Some(pos) = pos {1926 let names = if global { &names[1..pos + 1] } else { &names[..pos + 1] };1927 names_to_string(names.iter().map(|ident| ident.name))1928 } else {1929 let names = if global { &names[1..] } else { names };1930 if names.is_empty() {1931 import_kind_to_string(import_kind)1932 } else {1933 format!(1934 "{}::{}",1935 names_to_string(names.iter().map(|ident| ident.name)),1936 import_kind_to_string(import_kind),1937 )1938 }1939 }1940}19411942fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {1943 match import_kind {1944 ImportKind::Single { source, .. } => source.to_string(),1945 ImportKind::Glob { .. } => "*".to_string(),1946 ImportKind::ExternCrate { .. } => "<extern crate>".to_string(),1947 ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),1948 ImportKind::MacroExport => "#[macro_export]".to_string(),1949 }1950}
Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.