Skip to main content

rustc_resolve/
diagnostics.rs

1// ignore-tidy-filelength
2use std::ops::ControlFlow;
3
4use itertools::Itertools as _;
5use rustc_ast::visit::{self, Visitor};
6use rustc_ast::{
7    self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents,
8};
9use rustc_ast_pretty::pprust;
10use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11use rustc_data_structures::unord::{UnordMap, UnordSet};
12use rustc_errors::codes::*;
13use rustc_errors::{
14    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
15    struct_span_code_err,
16};
17use rustc_feature::BUILTIN_ATTRIBUTES;
18use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
19use rustc_hir::def::Namespace::{self, *};
20use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
21use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
22use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr};
23use rustc_middle::bug;
24use rustc_middle::ty::{TyCtxt, Visibility};
25use rustc_session::Session;
26use rustc_session::lint::builtin::{
27    ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
28    AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
29};
30use rustc_session::utils::was_invoked_from_cargo;
31use rustc_span::edit_distance::find_best_match_for_name;
32use rustc_span::edition::Edition;
33use rustc_span::hygiene::MacroKind;
34use rustc_span::source_map::SourceMap;
35use rustc_span::{
36    BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,
37};
38use thin_vec::{ThinVec, thin_vec};
39use tracing::{debug, instrument};
40
41use crate::errors::{
42    self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
43    ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
44    MaybeMissingMacroRulesName,
45};
46use crate::hygiene::Macros20NormalizedSyntaxContext;
47use crate::imports::{Import, ImportKind};
48use crate::late::{DiagMetadata, PatternSource, Rib};
49use crate::{
50    AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
51    Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, LateDecl, MacroRulesScope,
52    Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res,
53    ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, VisResolutionError,
54    errors as errs, path_names_to_string,
55};
56
57/// A vector of spans and replacements, a message and applicability.
58pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
59
60/// Potential candidate for an undeclared or out-of-scope label - contains the ident of a
61/// similarly named label and whether or not it is reachable.
62pub(crate) type LabelSuggestion = (Ident, bool);
63
64#[derive(#[automatically_derived]
impl ::core::clone::Clone for StructCtor {
    #[inline]
    fn clone(&self) -> StructCtor {
        StructCtor {
            res: ::core::clone::Clone::clone(&self.res),
            vis: ::core::clone::Clone::clone(&self.vis),
            field_visibilities: ::core::clone::Clone::clone(&self.field_visibilities),
        }
    }
}Clone)]
65pub(crate) struct StructCtor {
66    pub res: Res,
67    pub vis: Visibility<DefId>,
68    pub field_visibilities: Vec<Visibility<DefId>>,
69}
70
71impl StructCtor {
72    pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
73        self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
74    }
75}
76
77#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SuggestionTarget {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                SuggestionTarget::SimilarlyNamed => "SimilarlyNamed",
                SuggestionTarget::SingleItem => "SingleItem",
            })
    }
}Debug)]
78pub(crate) enum SuggestionTarget {
79    /// The target has a similar name as the name used by the programmer (probably a typo)
80    SimilarlyNamed,
81    /// The target is the only valid item that can be used in the corresponding context
82    SingleItem,
83}
84
85#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TypoSuggestion {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field4_finish(f,
            "TypoSuggestion", "candidate", &self.candidate, "span",
            &self.span, "res", &self.res, "target", &&self.target)
    }
}Debug)]
86pub(crate) struct TypoSuggestion {
87    pub candidate: Symbol,
88    /// The source location where the name is defined; None if the name is not defined
89    /// in source e.g. primitives
90    pub span: Option<Span>,
91    pub res: Res,
92    pub target: SuggestionTarget,
93}
94
95impl TypoSuggestion {
96    pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
97        Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
98    }
99    pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
100        Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
101    }
102    pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
103        Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
104    }
105}
106
107/// A free importable items suggested in case of resolution failure.
108#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ImportSuggestion {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            &["did", "descr", "path", "accessible", "doc_visible",
                        "via_import", "note", "is_stable"];
        let values: &[&dyn ::core::fmt::Debug] =
            &[&self.did, &self.descr, &self.path, &self.accessible,
                        &self.doc_visible, &self.via_import, &self.note,
                        &&self.is_stable];
        ::core::fmt::Formatter::debug_struct_fields_finish(f,
            "ImportSuggestion", names, values)
    }
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ImportSuggestion {
    #[inline]
    fn clone(&self) -> ImportSuggestion {
        ImportSuggestion {
            did: ::core::clone::Clone::clone(&self.did),
            descr: ::core::clone::Clone::clone(&self.descr),
            path: ::core::clone::Clone::clone(&self.path),
            accessible: ::core::clone::Clone::clone(&self.accessible),
            doc_visible: ::core::clone::Clone::clone(&self.doc_visible),
            via_import: ::core::clone::Clone::clone(&self.via_import),
            note: ::core::clone::Clone::clone(&self.note),
            is_stable: ::core::clone::Clone::clone(&self.is_stable),
        }
    }
}Clone)]
109pub(crate) struct ImportSuggestion {
110    pub did: Option<DefId>,
111    pub descr: &'static str,
112    pub path: Path,
113    pub accessible: bool,
114    // false if the path traverses a foreign `#[doc(hidden)]` item.
115    pub doc_visible: bool,
116    pub via_import: bool,
117    /// An extra note that should be issued if this item is suggested
118    pub note: Option<String>,
119    pub is_stable: bool,
120}
121
122/// Adjust the impl span so that just the `impl` keyword is taken by removing
123/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
124/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
125///
126/// *Attention*: the method used is very fragile since it essentially duplicates the work of the
127/// parser. If you need to use this function or something similar, please consider updating the
128/// `source_map` functions and this function to something more robust.
129fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
130    let impl_span = sm.span_until_char(impl_span, '<');
131    sm.span_until_whitespace(impl_span)
132}
133
134impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
135    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
136        self.tcx.dcx()
137    }
138
139    pub(crate) fn report_errors(&mut self, krate: &Crate) {
140        self.report_with_use_injections(krate);
141
142        for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
143            self.lint_buffer.buffer_lint(
144                MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
145                CRATE_NODE_ID,
146                span_use,
147                errors::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
148            );
149        }
150
151        for ambiguity_error in &self.ambiguity_errors {
152            let mut diag = self.ambiguity_diagnostic(ambiguity_error);
153
154            if let Some(ambiguity_warning) = ambiguity_error.warning {
155                let node_id = match ambiguity_error.b1.0.kind {
156                    DeclKind::Import { import, .. } => import.root_id,
157                    DeclKind::Def(_) => CRATE_NODE_ID,
158                };
159
160                let lint = match ambiguity_warning {
161                    _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
162                    AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
163                    AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
164                };
165
166                self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
167            } else {
168                diag.is_error = true;
169                self.dcx().emit_err(diag);
170            }
171        }
172
173        let mut reported_spans = FxHashSet::default();
174        for error in std::mem::take(&mut self.privacy_errors) {
175            if reported_spans.insert(error.dedup_span) {
176                self.report_privacy_error(&error);
177            }
178        }
179    }
180
181    fn report_with_use_injections(&mut self, krate: &Crate) {
182        for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
183            std::mem::take(&mut self.use_injections)
184        {
185            let (span, found_use) = if let Some(def_id) = def_id.as_local() {
186                UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id))
187            } else {
188                (None, FoundUse::No)
189            };
190
191            if !candidates.is_empty() {
192                show_candidates(
193                    self.tcx,
194                    &mut err,
195                    span,
196                    &candidates,
197                    if instead { Instead::Yes } else { Instead::No },
198                    found_use,
199                    DiagMode::Normal,
200                    path,
201                    "",
202                );
203                err.emit();
204            } else if let Some((span, msg, sugg, appl)) = suggestion {
205                err.span_suggestion_verbose(span, msg, sugg, appl);
206                err.emit();
207            } else if let [segment] = path.as_slice()
208                && is_call
209            {
210                err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
211            } else {
212                err.emit();
213            }
214        }
215    }
216
217    pub(crate) fn report_conflict(
218        &mut self,
219        ident: IdentKey,
220        ns: Namespace,
221        old_binding: Decl<'ra>,
222        new_binding: Decl<'ra>,
223    ) {
224        // Error on the second of two conflicting names
225        if old_binding.span.lo() > new_binding.span.lo() {
226            return self.report_conflict(ident, ns, new_binding, old_binding);
227        }
228
229        let container = match old_binding.parent_module.unwrap().kind {
230            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
231            // indirectly *calls* the resolver, and would cause a query cycle.
232            ModuleKind::Def(kind, def_id, _) => kind.descr(def_id),
233            ModuleKind::Block => "block",
234        };
235
236        let (name, span) =
237            (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
238
239        if self.name_already_seen.get(&name) == Some(&span) {
240            return;
241        }
242
243        let old_kind = match (ns, old_binding.res()) {
244            (ValueNS, _) => "value",
245            (MacroNS, _) => "macro",
246            (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
247            (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
248            (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
249            (TypeNS, _) => "type",
250        };
251
252        let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
253            (true, true) => E0259,
254            (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
255                true => E0254,
256                false => E0260,
257            },
258            _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
259                (false, false) => E0428,
260                (true, true) => E0252,
261                _ => E0255,
262            },
263        };
264
265        let label = match new_binding.is_import_user_facing() {
266            true => errors::NameDefinedMultipleTimeLabel::Reimported { span, name },
267            false => errors::NameDefinedMultipleTimeLabel::Redefined { span, name },
268        };
269
270        let old_binding_label =
271            (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
272                let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
273                match old_binding.is_import_user_facing() {
274                    true => errors::NameDefinedMultipleTimeOldBindingLabel::Import {
275                        span,
276                        old_kind,
277                        name,
278                    },
279                    false => errors::NameDefinedMultipleTimeOldBindingLabel::Definition {
280                        span,
281                        old_kind,
282                        name,
283                    },
284                }
285            });
286
287        let mut err = self
288            .dcx()
289            .create_err(errors::NameDefinedMultipleTime {
290                span,
291                name,
292                descr: ns.descr(),
293                container,
294                label,
295                old_binding_label,
296            })
297            .with_code(code);
298
299        // See https://github.com/rust-lang/rust/issues/32354
300        use DeclKind::Import;
301        let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
302            !binding.span.is_dummy()
303                && !#[allow(non_exhaustive_omitted_patterns)] match import.kind {
    ImportKind::MacroUse { .. } | ImportKind::MacroExport => true,
    _ => false,
}matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
304        };
305        let import = match (&new_binding.kind, &old_binding.kind) {
306            // If there are two imports where one or both have attributes then prefer removing the
307            // import without attributes.
308            (Import { import: new, .. }, Import { import: old, .. })
309                if {
310                    (new.has_attributes || old.has_attributes)
311                        && can_suggest(old_binding, *old)
312                        && can_suggest(new_binding, *new)
313                } =>
314            {
315                if old.has_attributes {
316                    Some((*new, new_binding.span, true))
317                } else {
318                    Some((*old, old_binding.span, true))
319                }
320            }
321            // Otherwise prioritize the new binding.
322            (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
323                Some((*import, new_binding.span, other.is_import()))
324            }
325            (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
326                Some((*import, old_binding.span, other.is_import()))
327            }
328            _ => None,
329        };
330
331        // Check if the target of the use for both bindings is the same.
332        let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
333        let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
334        let from_item =
335            self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
336        // Only suggest removing an import if both bindings are to the same def, if both spans
337        // aren't dummy spans. Further, if both bindings are imports, then the ident must have
338        // been introduced by an item.
339        let should_remove_import = duplicate
340            && !has_dummy_span
341            && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
342
343        match import {
344            Some((import, span, true)) if should_remove_import && import.is_nested() => {
345                self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
346            }
347            Some((import, _, true)) if should_remove_import && !import.is_glob() => {
348                // Simple case - remove the entire import. Due to the above match arm, this can
349                // only be a single use so just remove it entirely.
350                err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport {
351                    span: import.use_span_with_attributes,
352                });
353            }
354            Some((import, span, _)) => {
355                self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
356            }
357            _ => {}
358        }
359
360        err.emit();
361        self.name_already_seen.insert(name, span);
362    }
363
364    /// This function adds a suggestion to change the binding name of a new import that conflicts
365    /// with an existing import.
366    ///
367    /// ```text,ignore (diagnostic)
368    /// help: you can use `as` to change the binding name of the import
369    ///    |
370    /// LL | use foo::bar as other_bar;
371    ///    |     ^^^^^^^^^^^^^^^^^^^^^
372    /// ```
373    fn add_suggestion_for_rename_of_use(
374        &self,
375        err: &mut Diag<'_>,
376        name: Symbol,
377        import: Import<'_>,
378        binding_span: Span,
379    ) {
380        let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
381            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Other{0}", name))
    })format!("Other{name}")
382        } else {
383            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("other_{0}", name))
    })format!("other_{name}")
384        };
385
386        let mut suggestion = None;
387        let mut span = binding_span;
388        match import.kind {
389            ImportKind::Single { type_ns_only: true, .. } => {
390                suggestion = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("self as {0}", suggested_name))
    })format!("self as {suggested_name}"))
391            }
392            ImportKind::Single { source, .. } => {
393                if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
394                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
395                    && pos as usize <= snippet.len()
396                {
397                    span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
398                        binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
399                    );
400                    suggestion = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" as {0}", suggested_name))
    })format!(" as {suggested_name}"));
401                }
402            }
403            ImportKind::ExternCrate { source, target, .. } => {
404                suggestion = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("extern crate {0} as {1};",
                source.unwrap_or(target.name), suggested_name))
    })format!(
405                    "extern crate {} as {};",
406                    source.unwrap_or(target.name),
407                    suggested_name,
408                ))
409            }
410            _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
411        }
412
413        if let Some(suggestion) = suggestion {
414            err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
415        } else {
416            err.subdiagnostic(ChangeImportBinding { span });
417        }
418    }
419
420    /// This function adds a suggestion to remove an unnecessary binding from an import that is
421    /// nested. In the following example, this function will be invoked to remove the `a` binding
422    /// in the second use statement:
423    ///
424    /// ```ignore (diagnostic)
425    /// use issue_52891::a;
426    /// use issue_52891::{d, a, e};
427    /// ```
428    ///
429    /// The following suggestion will be added:
430    ///
431    /// ```ignore (diagnostic)
432    /// use issue_52891::{d, a, e};
433    ///                      ^-- help: remove unnecessary import
434    /// ```
435    ///
436    /// If the nested use contains only one import then the suggestion will remove the entire
437    /// line.
438    ///
439    /// It is expected that the provided import is nested - this isn't checked by the
440    /// function. If this invariant is not upheld, this function's behaviour will be unexpected
441    /// as characters expected by span manipulations won't be present.
442    fn add_suggestion_for_duplicate_nested_use(
443        &self,
444        err: &mut Diag<'_>,
445        import: Import<'_>,
446        binding_span: Span,
447    ) {
448        if !import.is_nested() {
    ::core::panicking::panic("assertion failed: import.is_nested()")
};assert!(import.is_nested());
449
450        // Two examples will be used to illustrate the span manipulations we're doing:
451        //
452        // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
453        //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.
454        // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
455        //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.
456
457        let (found_closing_brace, span) =
458            find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
459
460        // If there was a closing brace then identify the span to remove any trailing commas from
461        // previous imports.
462        if found_closing_brace {
463            if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
464                err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport { span });
465            } else {
466                // Remove the entire line if we cannot extend the span back, this indicates an
467                // `issue_52891::{self}` case.
468                err.subdiagnostic(errors::RemoveUnnecessaryImport {
469                    span: import.use_span_with_attributes,
470                });
471            }
472
473            return;
474        }
475
476        err.subdiagnostic(errors::RemoveUnnecessaryImport { span });
477    }
478
479    pub(crate) fn lint_if_path_starts_with_module(
480        &mut self,
481        finalize: Finalize,
482        path: &[Segment],
483        second_binding: Option<Decl<'_>>,
484    ) {
485        let Finalize { node_id, root_span, .. } = finalize;
486
487        let first_name = match path.get(0) {
488            // In the 2018 edition this lint is a hard error, so nothing to do
489            Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
490                seg.ident.name
491            }
492            _ => return,
493        };
494
495        // We're only interested in `use` paths which should start with
496        // `{{root}}` currently.
497        if first_name != kw::PathRoot {
498            return;
499        }
500
501        match path.get(1) {
502            // If this import looks like `crate::...` it's already good
503            Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
504            // Otherwise go below to see if it's an extern crate
505            Some(_) => {}
506            // If the path has length one (and it's `PathRoot` most likely)
507            // then we don't know whether we're gonna be importing a crate or an
508            // item in our crate. Defer this lint to elsewhere
509            None => return,
510        }
511
512        // If the first element of our path was actually resolved to an
513        // `ExternCrate` (also used for `crate::...`) then no need to issue a
514        // warning, this looks all good!
515        if let Some(binding) = second_binding
516            && let DeclKind::Import { import, .. } = binding.kind
517            // Careful: we still want to rewrite paths from renamed extern crates.
518            && let ImportKind::ExternCrate { source: None, .. } = import.kind
519        {
520            return;
521        }
522
523        self.lint_buffer.dyn_buffer_lint_any(
524            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
525            node_id,
526            root_span,
527            move |dcx, level, sess| {
528                let (replacement, applicability) = match sess
529                    .downcast_ref::<Session>()
530                    .expect("expected a `Session`")
531                    .source_map()
532                    .span_to_snippet(root_span)
533                {
534                    Ok(ref s) => {
535                        // FIXME(Manishearth) ideally the emitting code
536                        // can tell us whether or not this is global
537                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
538
539                        (::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
    })format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
540                    }
541                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
542                };
543                errors::AbsPathWithModule {
544                    sugg: errors::AbsPathWithModuleSugg {
545                        span: root_span,
546                        applicability,
547                        replacement,
548                    },
549                }
550                .into_diag(dcx, level)
551            },
552        );
553    }
554
555    pub(crate) fn add_module_candidates(
556        &self,
557        module: Module<'ra>,
558        names: &mut Vec<TypoSuggestion>,
559        filter_fn: &impl Fn(Res) -> bool,
560        ctxt: Option<SyntaxContext>,
561    ) {
562        module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
563            let res = binding.res();
564            if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
565                names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
566            }
567        });
568    }
569
570    /// Combines an error with provided span and emits it.
571    ///
572    /// This takes the error provided, combines it with the span and any additional spans inside the
573    /// error and emits it.
574    pub(crate) fn report_error(
575        &mut self,
576        span: Span,
577        resolution_error: ResolutionError<'ra>,
578    ) -> ErrorGuaranteed {
579        self.into_struct_error(span, resolution_error).emit()
580    }
581
582    pub(crate) fn into_struct_error(
583        &mut self,
584        span: Span,
585        resolution_error: ResolutionError<'ra>,
586    ) -> Diag<'_> {
587        match resolution_error {
588            ResolutionError::GenericParamsFromOuterItem {
589                outer_res,
590                has_generic_params,
591                def_kind,
592                inner_item,
593                current_self_ty,
594            } => {
595                use errs::GenericParamsFromOuterItemLabel as Label;
596                let static_or_const = match def_kind {
597                    DefKind::Static { .. } => {
598                        Some(errs::GenericParamsFromOuterItemStaticOrConst::Static)
599                    }
600                    DefKind::Const { .. } => {
601                        Some(errs::GenericParamsFromOuterItemStaticOrConst::Const)
602                    }
603                    _ => None,
604                };
605                let is_self =
606                    #[allow(non_exhaustive_omitted_patterns)] match outer_res {
    Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => true,
    _ => false,
}matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
607                let mut err = errs::GenericParamsFromOuterItem {
608                    span,
609                    label: None,
610                    refer_to_type_directly: None,
611                    sugg: None,
612                    static_or_const,
613                    is_self,
614                    item: inner_item.as_ref().map(|(span, kind)| {
615                        errs::GenericParamsFromOuterItemInnerItem {
616                            span: *span,
617                            descr: kind.descr().to_string(),
618                            is_self,
619                        }
620                    }),
621                };
622
623                let sm = self.tcx.sess.source_map();
624                let def_id = match outer_res {
625                    Res::SelfTyParam { .. } => {
626                        err.label = Some(Label::SelfTyParam(span));
627                        return self.dcx().create_err(err);
628                    }
629                    Res::SelfTyAlias { alias_to: def_id, .. } => {
630                        err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
631                            sm,
632                            self.def_span(def_id),
633                        )));
634                        err.refer_to_type_directly =
635                            current_self_ty.map(|snippet| errs::UseTypeDirectly { span, snippet });
636                        return self.dcx().create_err(err);
637                    }
638                    Res::Def(DefKind::TyParam, def_id) => {
639                        err.label = Some(Label::TyParam(self.def_span(def_id)));
640                        def_id
641                    }
642                    Res::Def(DefKind::ConstParam, def_id) => {
643                        err.label = Some(Label::ConstParam(self.def_span(def_id)));
644                        def_id
645                    }
646                    _ => {
647                        ::rustc_middle::util::bug::bug_fmt(format_args!("GenericParamsFromOuterItem should only be used with Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or DefKind::ConstParam"));bug!(
648                            "GenericParamsFromOuterItem should only be used with \
649                            Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
650                            DefKind::ConstParam"
651                        );
652                    }
653                };
654
655                if let HasGenericParams::Yes(span) = has_generic_params
656                    && !#[allow(non_exhaustive_omitted_patterns)] match inner_item {
    Some((_, ItemKind::Delegation(..))) => true,
    _ => false,
}matches!(inner_item, Some((_, ItemKind::Delegation(..))))
657                {
658                    let name = self.tcx.item_name(def_id);
659                    let (span, snippet) = if span.is_empty() {
660                        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", name))
    })format!("<{name}>");
661                        (span, snippet)
662                    } else {
663                        let span = sm.span_through_char(span, '<').shrink_to_hi();
664                        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", name))
    })format!("{name}, ");
665                        (span, snippet)
666                    };
667                    err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
668                }
669
670                self.dcx().create_err(err)
671            }
672            ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
673                .dcx()
674                .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
675            ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
676                self.dcx().create_err(errs::MethodNotMemberOfTrait {
677                    span,
678                    method,
679                    trait_,
680                    sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
681                        span: method.span,
682                        candidate: c,
683                    }),
684                })
685            }
686            ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
687                self.dcx().create_err(errs::TypeNotMemberOfTrait {
688                    span,
689                    type_,
690                    trait_,
691                    sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
692                        span: type_.span,
693                        candidate: c,
694                    }),
695                })
696            }
697            ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
698                self.dcx().create_err(errs::ConstNotMemberOfTrait {
699                    span,
700                    const_,
701                    trait_,
702                    sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
703                        span: const_.span,
704                        candidate: c,
705                    }),
706                })
707            }
708            ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
709                let BindingError { name, target, origin, could_be_path } = binding_error;
710
711                let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
712                target_sp.sort();
713                target_sp.dedup();
714                let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
715                origin_sp.sort();
716                origin_sp.dedup();
717
718                let msp = MultiSpan::from_spans(target_sp.clone());
719                let mut err = self
720                    .dcx()
721                    .create_err(errors::VariableIsNotBoundInAllPatterns { multispan: msp, name });
722                for sp in target_sp {
723                    err.subdiagnostic(errors::PatternDoesntBindName { span: sp, name });
724                }
725                for sp in &origin_sp {
726                    err.subdiagnostic(errors::VariableNotInAllPatterns { span: *sp });
727                }
728                let mut suggested_typo = false;
729                if !target.iter().all(|pat| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
    ast::PatKind::Ident(..) => true,
    _ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
730                    && !origin.iter().all(|(_, pat)| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
    ast::PatKind::Ident(..) => true,
    _ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
731                {
732                    // The check above is so that when we encounter `match foo { (a | b) => {} }`,
733                    // we don't suggest `(a | a) => {}`, which would never be what the user wants.
734                    let mut target_visitor = BindingVisitor::default();
735                    for pat in &target {
736                        target_visitor.visit_pat(pat);
737                    }
738                    target_visitor.identifiers.sort();
739                    target_visitor.identifiers.dedup();
740                    let mut origin_visitor = BindingVisitor::default();
741                    for (_, pat) in &origin {
742                        origin_visitor.visit_pat(pat);
743                    }
744                    origin_visitor.identifiers.sort();
745                    origin_visitor.identifiers.dedup();
746                    // Find if the binding could have been a typo
747                    if let Some(typo) =
748                        find_best_match_for_name(&target_visitor.identifiers, name.name, None)
749                        && !origin_visitor.identifiers.contains(&typo)
750                    {
751                        err.subdiagnostic(errors::PatternBindingTypo { spans: origin_sp, typo });
752                        suggested_typo = true;
753                    }
754                }
755                if could_be_path {
756                    let import_suggestions = self.lookup_import_candidates(
757                        name,
758                        Namespace::ValueNS,
759                        &parent_scope,
760                        &|res: Res| {
761                            #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const) |
        DefKind::Ctor(CtorOf::Struct, CtorKind::Const) | DefKind::Const { .. }
        | DefKind::AssocConst { .. }, _) => true,
    _ => false,
}matches!(
762                                res,
763                                Res::Def(
764                                    DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
765                                        | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
766                                        | DefKind::Const { .. }
767                                        | DefKind::AssocConst { .. },
768                                    _,
769                                )
770                            )
771                        },
772                    );
773
774                    if import_suggestions.is_empty() && !suggested_typo {
775                        let kind_matches: [fn(DefKind) -> bool; 4] = [
776                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => true,
    _ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
777                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => true,
    _ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
778                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Const { .. } => true,
    _ => false,
}matches!(kind, DefKind::Const { .. }),
779                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::AssocConst { .. } => true,
    _ => false,
}matches!(kind, DefKind::AssocConst { .. }),
780                        ];
781                        let mut local_names = ::alloc::vec::Vec::new()vec![];
782                        self.add_module_candidates(
783                            parent_scope.module,
784                            &mut local_names,
785                            &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(_, _) => true,
    _ => false,
}matches!(res, Res::Def(_, _)),
786                            None,
787                        );
788                        let local_names: FxHashSet<_> = local_names
789                            .into_iter()
790                            .filter_map(|s| match s.res {
791                                Res::Def(_, def_id) => Some(def_id),
792                                _ => None,
793                            })
794                            .collect();
795
796                        let mut local_suggestions = ::alloc::vec::Vec::new()vec![];
797                        let mut suggestions = ::alloc::vec::Vec::new()vec![];
798                        for matches_kind in kind_matches {
799                            if let Some(suggestion) = self.early_lookup_typo_candidate(
800                                ScopeSet::All(Namespace::ValueNS),
801                                &parent_scope,
802                                name,
803                                &|res: Res| match res {
804                                    Res::Def(k, _) => matches_kind(k),
805                                    _ => false,
806                                },
807                            ) && let Res::Def(kind, mut def_id) = suggestion.res
808                            {
809                                if let DefKind::Ctor(_, _) = kind {
810                                    def_id = self.tcx.parent(def_id);
811                                }
812                                let kind = kind.descr(def_id);
813                                if local_names.contains(&def_id) {
814                                    // The item is available in the current scope. Very likely to
815                                    // be a typo. Don't use the full path.
816                                    local_suggestions.push((
817                                        suggestion.candidate,
818                                        suggestion.candidate.to_string(),
819                                        kind,
820                                    ));
821                                } else {
822                                    suggestions.push((
823                                        suggestion.candidate,
824                                        self.def_path_str(def_id),
825                                        kind,
826                                    ));
827                                }
828                            }
829                        }
830                        let suggestions = if !local_suggestions.is_empty() {
831                            // There is at least one item available in the current scope that is a
832                            // likely typo. We only show those.
833                            local_suggestions
834                        } else {
835                            suggestions
836                        };
837                        for (name, sugg, kind) in suggestions {
838                            err.span_suggestion_verbose(
839                                span,
840                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might have meant to use the similarly named {0} `{1}`",
                kind, name))
    })format!(
841                                    "you might have meant to use the similarly named {kind} `{name}`",
842                                ),
843                                sugg,
844                                Applicability::MaybeIncorrect,
845                            );
846                            suggested_typo = true;
847                        }
848                    }
849                    if import_suggestions.is_empty() && !suggested_typo {
850                        let help_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you meant to match on a unit struct, unit variant or a `const` item, consider making the path in the pattern qualified: `path::to::ModOrType::{0}`",
                name))
    })format!(
851                            "if you meant to match on a unit struct, unit variant or a `const` \
852                             item, consider making the path in the pattern qualified: \
853                             `path::to::ModOrType::{name}`",
854                        );
855                        err.span_help(span, help_msg);
856                    }
857                    show_candidates(
858                        self.tcx,
859                        &mut err,
860                        Some(span),
861                        &import_suggestions,
862                        Instead::No,
863                        FoundUse::Yes,
864                        DiagMode::Pattern,
865                        ::alloc::vec::Vec::new()vec![],
866                        "",
867                    );
868                }
869                err
870            }
871            ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
872                self.dcx().create_err(errs::VariableBoundWithDifferentMode {
873                    span,
874                    first_binding_span,
875                    variable_name,
876                })
877            }
878            ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
879                .dcx()
880                .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
881            ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
882                .dcx()
883                .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
884            ResolutionError::UndeclaredLabel { name, suggestion } => {
885                let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
886                {
887                    // A reachable label with a similar name exists.
888                    Some((ident, true)) => (
889                        (
890                            Some(errs::LabelWithSimilarNameReachable(ident.span)),
891                            Some(errs::TryUsingSimilarlyNamedLabel {
892                                span,
893                                ident_name: ident.name,
894                            }),
895                        ),
896                        None,
897                    ),
898                    // An unreachable label with a similar name exists.
899                    Some((ident, false)) => (
900                        (None, None),
901                        Some(errs::UnreachableLabelWithSimilarNameExists {
902                            ident_span: ident.span,
903                        }),
904                    ),
905                    // No similarly-named labels exist.
906                    None => ((None, None), None),
907                };
908                self.dcx().create_err(errs::UndeclaredLabel {
909                    span,
910                    name,
911                    sub_reachable,
912                    sub_reachable_suggestion,
913                    sub_unreachable,
914                })
915            }
916            ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
917                // None of the suggestions below would help with a case like `use self`.
918                let (suggestion, mpart_suggestion) = if root {
919                    (None, None)
920                } else {
921                    // use foo::bar::self        -> foo::bar
922                    // use foo::bar::self as abc -> foo::bar as abc
923                    let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
924
925                    // use foo::bar::self        -> foo::bar::{self}
926                    // use foo::bar::self as abc -> foo::bar::{self as abc}
927                    let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
928                        multipart_start: span_with_rename.shrink_to_lo(),
929                        multipart_end: span_with_rename.shrink_to_hi(),
930                    };
931                    (Some(suggestion), Some(mpart_suggestion))
932                };
933                self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin {
934                    span,
935                    suggestion,
936                    mpart_suggestion,
937                })
938            }
939            ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
940                let mut err = {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", message))
                })).with_code(E0433)
}struct_span_code_err!(self.dcx(), span, E0433, "{message}");
941                err.span_label(span, label);
942
943                if let Some((suggestions, msg, applicability)) = suggestion {
944                    if suggestions.is_empty() {
945                        err.help(msg);
946                        return err;
947                    }
948                    err.multipart_suggestion(msg, suggestions, applicability);
949                }
950
951                let module = match module {
952                    Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
953                    _ => CRATE_DEF_ID.to_def_id(),
954                };
955                self.find_cfg_stripped(&mut err, &segment, module);
956
957                err
958            }
959            ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
960                self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
961            }
962            ResolutionError::AttemptToUseNonConstantValueInConstant {
963                ident,
964                suggestion,
965                current,
966                type_span,
967            } => {
968                // let foo =...
969                //     ^^^ given this Span
970                // ------- get this Span to have an applicable suggestion
971
972                // edit:
973                // only do this if the const and usage of the non-constant value are on the same line
974                // the further the two are apart, the higher the chance of the suggestion being wrong
975
976                let sp = self
977                    .tcx
978                    .sess
979                    .source_map()
980                    .span_extend_to_prev_str(ident.span, current, true, false);
981
982                let (with, with_label, without) = match sp {
983                    Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
984                        let sp = sp
985                            .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
986                            .until(ident.span);
987
988                        // Only suggest replacing the binding keyword if this is a simple
989                        // binding.
990                        //
991                        // Note: this approach still incorrectly suggests for irrefutable
992                        // patterns like `if let x = 1 { const { x } }`, since the text
993                        // between `let` and the identifier is just whitespace.
994                        // See tests/ui/consts/non-const-value-in-const-irrefutable-pat-binding.rs
995                        let is_simple_binding =
996                            self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {
997                                let after_keyword = snippet[current.len()..].trim();
998                                after_keyword.is_empty() || after_keyword == "mut"
999                            });
1000
1001                        if is_simple_binding {
1002                            (
1003                                Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
1004                                    span: sp,
1005                                    suggestion,
1006                                    current,
1007                                    type_span,
1008                                }),
1009                                Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1010                                None,
1011                            )
1012                        } else {
1013                            (
1014                                None,
1015                                Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1016                                None,
1017                            )
1018                        }
1019                    }
1020                    _ => (
1021                        None,
1022                        None,
1023                        Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
1024                            ident_span: ident.span,
1025                            suggestion,
1026                        }),
1027                    ),
1028                };
1029
1030                self.dcx().create_err(errs::AttemptToUseNonConstantValueInConstant {
1031                    span,
1032                    with,
1033                    with_label,
1034                    without,
1035                })
1036            }
1037            ResolutionError::BindingShadowsSomethingUnacceptable {
1038                shadowing_binding,
1039                name,
1040                participle,
1041                article,
1042                shadowed_binding,
1043                shadowed_binding_span,
1044            } => self.dcx().create_err(errs::BindingShadowsSomethingUnacceptable {
1045                span,
1046                shadowing_binding,
1047                shadowed_binding,
1048                article,
1049                sub_suggestion: match (shadowing_binding, shadowed_binding) {
1050                    (
1051                        PatternSource::Match,
1052                        Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
1053                    ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
1054                    _ => None,
1055                },
1056                shadowed_binding_span,
1057                participle,
1058                name,
1059            }),
1060            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
1061                ForwardGenericParamBanReason::Default => {
1062                    self.dcx().create_err(errs::ForwardDeclaredGenericParam { param, span })
1063                }
1064                ForwardGenericParamBanReason::ConstParamTy => self
1065                    .dcx()
1066                    .create_err(errs::ForwardDeclaredGenericInConstParamTy { param, span }),
1067            },
1068            ResolutionError::ParamInTyOfConstParam { name } => {
1069                self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
1070            }
1071            ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {
1072                self.dcx().create_err(errs::ParamInNonTrivialAnonConst {
1073                    span,
1074                    name,
1075                    param_kind: is_type,
1076                    help: self.tcx.sess.is_nightly_build(),
1077                    is_gca,
1078                    help_gca: is_gca,
1079                })
1080            }
1081            ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
1082                .dcx()
1083                .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
1084            ResolutionError::ForwardDeclaredSelf(reason) => match reason {
1085                ForwardGenericParamBanReason::Default => {
1086                    self.dcx().create_err(errs::SelfInGenericParamDefault { span })
1087                }
1088                ForwardGenericParamBanReason::ConstParamTy => {
1089                    self.dcx().create_err(errs::SelfInConstGenericTy { span })
1090                }
1091            },
1092            ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
1093                let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
1094                    match suggestion {
1095                        // A reachable label with a similar name exists.
1096                        Some((ident, true)) => (
1097                            (
1098                                Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
1099                                Some(errs::UnreachableLabelSubSuggestion {
1100                                    span,
1101                                    // intentionally taking 'ident.name' instead of 'ident' itself, as this
1102                                    // could be used in suggestion context
1103                                    ident_name: ident.name,
1104                                }),
1105                            ),
1106                            None,
1107                        ),
1108                        // An unreachable label with a similar name exists.
1109                        Some((ident, false)) => (
1110                            (None, None),
1111                            Some(errs::UnreachableLabelSubLabelUnreachable {
1112                                ident_span: ident.span,
1113                            }),
1114                        ),
1115                        // No similarly-named labels exist.
1116                        None => ((None, None), None),
1117                    };
1118                self.dcx().create_err(errs::UnreachableLabel {
1119                    span,
1120                    name,
1121                    definition_span,
1122                    sub_suggestion,
1123                    sub_suggestion_label,
1124                    sub_unreachable_label,
1125                })
1126            }
1127            ResolutionError::TraitImplMismatch {
1128                name,
1129                kind,
1130                code,
1131                trait_item_span,
1132                trait_path,
1133            } => self
1134                .dcx()
1135                .create_err(errors::TraitImplMismatch {
1136                    span,
1137                    name,
1138                    kind,
1139                    trait_path,
1140                    trait_item_span,
1141                })
1142                .with_code(code),
1143            ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
1144                .dcx()
1145                .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
1146            ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
1147            ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
1148            ResolutionError::BindingInNeverPattern => {
1149                self.dcx().create_err(errs::BindingInNeverPattern { span })
1150            }
1151        }
1152    }
1153
1154    pub(crate) fn report_vis_error(
1155        &mut self,
1156        vis_resolution_error: VisResolutionError<'_>,
1157    ) -> ErrorGuaranteed {
1158        match vis_resolution_error {
1159            VisResolutionError::Relative2018(span, path) => {
1160                self.dcx().create_err(errs::Relative2018 {
1161                    span,
1162                    path_span: path.span,
1163                    // intentionally converting to String, as the text would also be used as
1164                    // in suggestion context
1165                    path_str: pprust::path_to_string(path),
1166                })
1167            }
1168            VisResolutionError::AncestorOnly(span) => {
1169                self.dcx().create_err(errs::AncestorOnly(span))
1170            }
1171            VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self
1172                .into_struct_error(
1173                    span,
1174                    ResolutionError::FailedToResolve {
1175                        segment,
1176                        label,
1177                        suggestion,
1178                        module: None,
1179                        message,
1180                    },
1181                ),
1182            VisResolutionError::ExpectedFound(span, path_str, res) => {
1183                self.dcx().create_err(errs::ExpectedModuleFound { span, res, path_str })
1184            }
1185            VisResolutionError::Indeterminate(span) => {
1186                self.dcx().create_err(errs::Indeterminate(span))
1187            }
1188            VisResolutionError::ModuleOnly(span) => self.dcx().create_err(errs::ModuleOnly(span)),
1189        }
1190        .emit()
1191    }
1192
1193    fn def_path_str(&self, mut def_id: DefId) -> String {
1194        // We can't use `def_path_str` in resolve.
1195        let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [def_id]))vec![def_id];
1196        while let Some(parent) = self.tcx.opt_parent(def_id) {
1197            def_id = parent;
1198            path.push(def_id);
1199            if def_id.is_top_level_module() {
1200                break;
1201            }
1202        }
1203        // We will only suggest importing directly if it is accessible through that path.
1204        path.into_iter()
1205            .rev()
1206            .map(|def_id| {
1207                self.tcx
1208                    .opt_item_name(def_id)
1209                    .map(|name| {
1210                        match (
1211                            def_id.is_top_level_module(),
1212                            def_id.is_local(),
1213                            self.tcx.sess.edition(),
1214                        ) {
1215                            (true, true, Edition::Edition2015) => String::new(),
1216                            (true, true, _) => kw::Crate.to_string(),
1217                            (true, false, _) | (false, _, _) => name.to_string(),
1218                        }
1219                    })
1220                    .unwrap_or_else(|| "_".to_string())
1221            })
1222            .collect::<Vec<String>>()
1223            .join("::")
1224    }
1225
1226    pub(crate) fn add_scope_set_candidates(
1227        &mut self,
1228        suggestions: &mut Vec<TypoSuggestion>,
1229        scope_set: ScopeSet<'ra>,
1230        ps: &ParentScope<'ra>,
1231        sp: Span,
1232        filter_fn: &impl Fn(Res) -> bool,
1233    ) {
1234        let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
1235        self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
1236            match scope {
1237                Scope::DeriveHelpers(expn_id) => {
1238                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
1239                    if filter_fn(res) {
1240                        suggestions.extend(
1241                            this.helper_attrs.get(&expn_id).into_iter().flatten().map(
1242                                |&(ident, orig_ident_span, _)| {
1243                                    TypoSuggestion::new(ident.name, orig_ident_span, res)
1244                                },
1245                            ),
1246                        );
1247                    }
1248                }
1249                Scope::DeriveHelpersCompat => {
1250                    // Never recommend deprecated helper attributes.
1251                }
1252                Scope::MacroRules(macro_rules_scope) => {
1253                    if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
1254                        let res = macro_rules_def.decl.res();
1255                        if filter_fn(res) {
1256                            suggestions.push(TypoSuggestion::new(
1257                                macro_rules_def.ident.name,
1258                                macro_rules_def.orig_ident_span,
1259                                res,
1260                            ))
1261                        }
1262                    }
1263                }
1264                Scope::ModuleNonGlobs(module, _) => {
1265                    this.add_module_candidates(module, suggestions, filter_fn, None);
1266                }
1267                Scope::ModuleGlobs(..) => {
1268                    // Already handled in `ModuleNonGlobs`.
1269                }
1270                Scope::MacroUsePrelude => {
1271                    suggestions.extend(this.macro_use_prelude.iter().filter_map(
1272                        |(name, binding)| {
1273                            let res = binding.res();
1274                            filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1275                        },
1276                    ));
1277                }
1278                Scope::BuiltinAttrs => {
1279                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
1280                    if filter_fn(res) {
1281                        suggestions.extend(
1282                            BUILTIN_ATTRIBUTES
1283                                .iter()
1284                                // These trace attributes are compiler-generated and have
1285                                // deliberately invalid names.
1286                                .filter(|attr| {
1287                                    !#[allow(non_exhaustive_omitted_patterns)] match attr.name {
    sym::cfg_trace | sym::cfg_attr_trace => true,
    _ => false,
}matches!(attr.name, sym::cfg_trace | sym::cfg_attr_trace)
1288                                })
1289                                .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
1290                        );
1291                    }
1292                }
1293                Scope::ExternPreludeItems => {
1294                    // Add idents from both item and flag scopes.
1295                    suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
1296                        let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1297                        filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
1298                    }));
1299                }
1300                Scope::ExternPreludeFlags => {}
1301                Scope::ToolPrelude => {
1302                    let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1303                    suggestions.extend(
1304                        this.registered_tools
1305                            .iter()
1306                            .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
1307                    );
1308                }
1309                Scope::StdLibPrelude => {
1310                    if let Some(prelude) = this.prelude {
1311                        let mut tmp_suggestions = Vec::new();
1312                        this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1313                        suggestions.extend(
1314                            tmp_suggestions
1315                                .into_iter()
1316                                .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
1317                        );
1318                    }
1319                }
1320                Scope::BuiltinTypes => {
1321                    suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1322                        let res = Res::PrimTy(*prim_ty);
1323                        filter_fn(res)
1324                            .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1325                    }))
1326                }
1327            }
1328
1329            ControlFlow::<()>::Continue(())
1330        });
1331    }
1332
1333    /// Lookup typo candidate in scope for a macro or import.
1334    fn early_lookup_typo_candidate(
1335        &mut self,
1336        scope_set: ScopeSet<'ra>,
1337        parent_scope: &ParentScope<'ra>,
1338        ident: Ident,
1339        filter_fn: &impl Fn(Res) -> bool,
1340    ) -> Option<TypoSuggestion> {
1341        let mut suggestions = Vec::new();
1342        self.add_scope_set_candidates(
1343            &mut suggestions,
1344            scope_set,
1345            parent_scope,
1346            ident.span,
1347            filter_fn,
1348        );
1349
1350        // Make sure error reporting is deterministic.
1351        suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
1352
1353        match find_best_match_for_name(
1354            &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1355            ident.name,
1356            None,
1357        ) {
1358            Some(found) if found != ident.name => {
1359                suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1360            }
1361            _ => None,
1362        }
1363    }
1364
1365    fn lookup_import_candidates_from_module<FilterFn>(
1366        &self,
1367        lookup_ident: Ident,
1368        namespace: Namespace,
1369        parent_scope: &ParentScope<'ra>,
1370        start_module: Module<'ra>,
1371        crate_path: ThinVec<ast::PathSegment>,
1372        filter_fn: FilterFn,
1373    ) -> Vec<ImportSuggestion>
1374    where
1375        FilterFn: Fn(Res) -> bool,
1376    {
1377        let mut candidates = Vec::new();
1378        let mut seen_modules = FxHashSet::default();
1379        let start_did = start_module.def_id();
1380        let mut worklist = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(start_module, ThinVec::<ast::PathSegment>::new(), true,
                    start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
                    true)]))vec![(
1381            start_module,
1382            ThinVec::<ast::PathSegment>::new(),
1383            true,
1384            start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1385            true,
1386        )];
1387        let mut worklist_via_import = ::alloc::vec::Vec::new()vec![];
1388
1389        while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1390            match worklist.pop() {
1391                None => worklist_via_import.pop(),
1392                Some(x) => Some(x),
1393            }
1394        {
1395            let in_module_is_extern = !in_module.def_id().is_local();
1396            in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
1397                // Avoid non-importable candidates.
1398                if name_binding.is_assoc_item()
1399                    && !this.tcx.features().import_trait_associated_functions()
1400                {
1401                    return;
1402                }
1403
1404                if ident.name == kw::Underscore {
1405                    return;
1406                }
1407
1408                let child_accessible =
1409                    accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);
1410
1411                // do not venture inside inaccessible items of other crates
1412                if in_module_is_extern && !child_accessible {
1413                    return;
1414                }
1415
1416                let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1417
1418                // There is an assumption elsewhere that paths of variants are in the enum's
1419                // declaration and not imported. With this assumption, the variant component is
1420                // chopped and the rest of the path is assumed to be the enum's own path. For
1421                // errors where a variant is used as the type instead of the enum, this causes
1422                // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
1423                if via_import && name_binding.is_possibly_imported_variant() {
1424                    return;
1425                }
1426
1427                // #90113: Do not count an inaccessible reexported item as a candidate.
1428                if let DeclKind::Import { source_decl, .. } = name_binding.kind
1429                    && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1430                    && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
1431                {
1432                    return;
1433                }
1434
1435                let res = name_binding.res();
1436                let did = match res {
1437                    Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
1438                    _ => res.opt_def_id(),
1439                };
1440                let child_doc_visible = doc_visible
1441                    && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));
1442
1443                // collect results based on the filter function
1444                // avoid suggesting anything from the same module in which we are resolving
1445                // avoid suggesting anything with a hygienic name
1446                if ident.name == lookup_ident.name
1447                    && ns == namespace
1448                    && in_module != parent_scope.module
1449                    && ident.ctxt.is_root()
1450                    && filter_fn(res)
1451                {
1452                    // create the path
1453                    let mut segms = if lookup_ident.span.at_least_rust_2018() {
1454                        // crate-local absolute paths start with `crate::` in edition 2018
1455                        // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
1456                        crate_path.clone()
1457                    } else {
1458                        ThinVec::new()
1459                    };
1460                    segms.append(&mut path_segments.clone());
1461
1462                    segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1463                    let path = Path { span: name_binding.span, segments: segms, tokens: None };
1464
1465                    if child_accessible
1466                        // Remove invisible match if exists
1467                        && let Some(idx) = candidates
1468                            .iter()
1469                            .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1470                    {
1471                        candidates.remove(idx);
1472                    }
1473
1474                    let is_stable = if is_stable
1475                        && let Some(did) = did
1476                        && this.is_stable(did, path.span)
1477                    {
1478                        true
1479                    } else {
1480                        false
1481                    };
1482
1483                    // Rreplace unstable suggestions if we meet a new stable one,
1484                    // and do nothing if any other situation. For example, if we
1485                    // meet `std::ops::Range` after `std::range::legacy::Range`,
1486                    // we will remove the latter and then insert the former.
1487                    if is_stable
1488                        && let Some(idx) = candidates
1489                            .iter()
1490                            .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1491                    {
1492                        candidates.remove(idx);
1493                    }
1494
1495                    if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1496                        // See if we're recommending TryFrom, TryInto, or FromIterator and add
1497                        // a note about editions
1498                        let note = if let Some(did) = did {
1499                            let requires_note = !did.is_local()
1500                                && {
        {
            'done:
                {
                for i in
                    ::rustc_hir::attrs::HasAttrs::get_attrs(did, &this.tcx) {
                    #[allow(unused_imports)]
                    use rustc_hir::attrs::AttributeKind::*;
                    let i: &rustc_hir::Attribute = i;
                    match i {
                        rustc_hir::Attribute::Parsed(RustcDiagnosticItem(sym::TryInto
                            | sym::TryFrom | sym::FromIterator)) => {
                            break 'done Some(());
                        }
                        rustc_hir::Attribute::Unparsed(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(
1501                                    this.tcx,
1502                                    did,
1503                                    RustcDiagnosticItem(
1504                                        sym::TryInto | sym::TryFrom | sym::FromIterator
1505                                    )
1506                                );
1507                            requires_note.then(|| {
1508                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("\'{0}\' is included in the prelude starting in Edition 2021",
                path_names_to_string(&path)))
    })format!(
1509                                    "'{}' is included in the prelude starting in Edition 2021",
1510                                    path_names_to_string(&path)
1511                                )
1512                            })
1513                        } else {
1514                            None
1515                        };
1516
1517                        candidates.push(ImportSuggestion {
1518                            did,
1519                            descr: res.descr(),
1520                            path,
1521                            accessible: child_accessible,
1522                            doc_visible: child_doc_visible,
1523                            note,
1524                            via_import,
1525                            is_stable,
1526                        });
1527                    }
1528                }
1529
1530                // collect submodules to explore
1531                if let Some(def_id) = name_binding.res().module_like_def_id() {
1532                    // form the path
1533                    let mut path_segments = path_segments.clone();
1534                    path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1535
1536                    let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
1537                        && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
1538                        && import.parent_scope.expansion == parent_scope.expansion
1539                    {
1540                        true
1541                    } else {
1542                        false
1543                    };
1544
1545                    let is_extern_crate_that_also_appears_in_prelude =
1546                        name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
1547
1548                    if !is_extern_crate_that_also_appears_in_prelude || alias_import {
1549                        // add the module to the lookup
1550                        if seen_modules.insert(def_id) {
1551                            if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1552                                (
1553                                    this.expect_module(def_id),
1554                                    path_segments,
1555                                    child_accessible,
1556                                    child_doc_visible,
1557                                    is_stable && this.is_stable(def_id, name_binding.span),
1558                                ),
1559                            );
1560                        }
1561                    }
1562                }
1563            })
1564        }
1565
1566        candidates
1567    }
1568
1569    fn is_stable(&self, did: DefId, span: Span) -> bool {
1570        if did.is_local() {
1571            return true;
1572        }
1573
1574        match self.tcx.lookup_stability(did) {
1575            Some(Stability {
1576                level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
1577            }) => {
1578                if span.allows_unstable(feature) {
1579                    true
1580                } else if self.tcx.features().enabled(feature) {
1581                    true
1582                } else if let Some(implied_by) = implied_by
1583                    && self.tcx.features().enabled(implied_by)
1584                {
1585                    true
1586                } else {
1587                    false
1588                }
1589            }
1590            Some(_) => true,
1591            None => false,
1592        }
1593    }
1594
1595    /// When name resolution fails, this method can be used to look up candidate
1596    /// entities with the expected name. It allows filtering them using the
1597    /// supplied predicate (which should be used to only accept the types of
1598    /// definitions expected, e.g., traits). The lookup spans across all crates.
1599    ///
1600    /// N.B., the method does not look into imports, but this is not a problem,
1601    /// since we report the definitions (thus, the de-aliased imports).
1602    pub(crate) fn lookup_import_candidates<FilterFn>(
1603        &mut self,
1604        lookup_ident: Ident,
1605        namespace: Namespace,
1606        parent_scope: &ParentScope<'ra>,
1607        filter_fn: FilterFn,
1608    ) -> Vec<ImportSuggestion>
1609    where
1610        FilterFn: Fn(Res) -> bool,
1611    {
1612        let crate_path = {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate)));
    vec
}thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];
1613        let mut suggestions = self.lookup_import_candidates_from_module(
1614            lookup_ident,
1615            namespace,
1616            parent_scope,
1617            self.graph_root.to_module(),
1618            crate_path,
1619            &filter_fn,
1620        );
1621
1622        if lookup_ident.span.at_least_rust_2018() {
1623            for (ident, entry) in &self.extern_prelude {
1624                if entry.span().from_expansion() {
1625                    // Idents are adjusted to the root context before being
1626                    // resolved in the extern prelude, so reporting this to the
1627                    // user is no help. This skips the injected
1628                    // `extern crate std` in the 2018 edition, which would
1629                    // otherwise cause duplicate suggestions.
1630                    continue;
1631                }
1632                let Some(crate_id) =
1633                    self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
1634                else {
1635                    continue;
1636                };
1637
1638                let crate_def_id = crate_id.as_def_id();
1639                let crate_root = self.expect_module(crate_def_id);
1640
1641                // Check if there's already an item in scope with the same name as the crate.
1642                // If so, we have to disambiguate the potential import suggestions by making
1643                // the paths *global* (i.e., by prefixing them with `::`).
1644                let needs_disambiguation =
1645                    self.resolutions(parent_scope.module).borrow().iter().any(
1646                        |(key, name_resolution)| {
1647                            if key.ns == TypeNS
1648                                && key.ident == *ident
1649                                && let Some(decl) = name_resolution.borrow().best_decl()
1650                            {
1651                                match decl.res() {
1652                                    // No disambiguation needed if the identically named item we
1653                                    // found in scope actually refers to the crate in question.
1654                                    Res::Def(_, def_id) => def_id != crate_def_id,
1655                                    Res::PrimTy(_) => true,
1656                                    _ => false,
1657                                }
1658                            } else {
1659                                false
1660                            }
1661                        },
1662                    );
1663                let mut crate_path = ThinVec::new();
1664                if needs_disambiguation {
1665                    crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
1666                }
1667                crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
1668
1669                suggestions.extend(self.lookup_import_candidates_from_module(
1670                    lookup_ident,
1671                    namespace,
1672                    parent_scope,
1673                    crate_root,
1674                    crate_path,
1675                    &filter_fn,
1676                ));
1677            }
1678        }
1679
1680        suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
1681        suggestions
1682    }
1683
1684    pub(crate) fn unresolved_macro_suggestions(
1685        &mut self,
1686        err: &mut Diag<'_>,
1687        macro_kind: MacroKind,
1688        parent_scope: &ParentScope<'ra>,
1689        ident: Ident,
1690        krate: &Crate,
1691        sugg_span: Option<Span>,
1692    ) {
1693        // Bring all unused `derive` macros into `macro_map` so we ensure they can be used for
1694        // suggestions.
1695        self.register_macros_for_all_crates();
1696
1697        let is_expected =
1698            &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
1699        let suggestion = self.early_lookup_typo_candidate(
1700            ScopeSet::Macro(macro_kind),
1701            parent_scope,
1702            ident,
1703            is_expected,
1704        );
1705        if !self.add_typo_suggestion(err, suggestion, ident.span) {
1706            self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
1707        }
1708
1709        let import_suggestions =
1710            self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1711        let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() {
1712            Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)),
1713            None => (None, FoundUse::No),
1714        };
1715        show_candidates(
1716            self.tcx,
1717            err,
1718            span,
1719            &import_suggestions,
1720            Instead::No,
1721            found_use,
1722            DiagMode::Normal,
1723            ::alloc::vec::Vec::new()vec![],
1724            "",
1725        );
1726
1727        if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
1728            let label_span = ident.span.shrink_to_hi();
1729            let mut spans = MultiSpan::from_span(label_span);
1730            spans.push_span_label(label_span, "put a macro name here");
1731            err.subdiagnostic(MaybeMissingMacroRulesName { spans });
1732            return;
1733        }
1734
1735        if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1736            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
1737            return;
1738        }
1739
1740        let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
1741            if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
1742        });
1743
1744        if let Some((def_id, unused_ident)) = unused_macro {
1745            let scope = self.local_macro_def_scopes[&def_id];
1746            let parent_nearest = parent_scope.module.nearest_parent_mod();
1747            let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds();
1748            if !unused_macro_kinds.contains(macro_kind.into()) {
1749                match macro_kind {
1750                    MacroKind::Bang => {
1751                        err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
1752                    }
1753                    MacroKind::Attr => {
1754                        err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
1755                    }
1756                    MacroKind::Derive => {
1757                        err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
1758                    }
1759                }
1760                return;
1761            }
1762            if Some(parent_nearest) == scope.opt_def_id() {
1763                err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1764                err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1765                return;
1766            }
1767        }
1768
1769        if ident.name == kw::Default
1770            && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
1771        {
1772            let span = self.def_span(def_id);
1773            let source_map = self.tcx.sess.source_map();
1774            let head_span = source_map.guess_head_span(span);
1775            err.subdiagnostic(ConsiderAddingADerive {
1776                span: head_span.shrink_to_lo(),
1777                suggestion: "#[derive(Default)]\n".to_string(),
1778            });
1779        }
1780        for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
1781            let Ok(binding) = self.cm().resolve_ident_in_scope_set(
1782                ident,
1783                ScopeSet::All(ns),
1784                parent_scope,
1785                None,
1786                None,
1787                None,
1788            ) else {
1789                continue;
1790            };
1791
1792            let desc = match binding.res() {
1793                Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
1794                    "a function-like macro".to_string()
1795                }
1796                Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
1797                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
    })format!("an attribute: `#[{ident}]`")
1798                }
1799                Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
1800                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
                ident))
    })format!("a derive macro: `#[derive({ident})]`")
1801                }
1802                Res::Def(DefKind::Macro(kinds), _) => {
1803                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
                kinds.descr()))
    })format!("{} {}", kinds.article(), kinds.descr())
1804                }
1805                Res::ToolMod | Res::OpenMod(..) => {
1806                    // Don't confuse the user with tool modules or open modules.
1807                    continue;
1808                }
1809                Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
1810                    "only a trait, without a derive macro".to_string()
1811                }
1812                res => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}, not {2} {3}",
                res.article(), res.descr(), macro_kind.article(),
                macro_kind.descr_expected()))
    })format!(
1813                    "{} {}, not {} {}",
1814                    res.article(),
1815                    res.descr(),
1816                    macro_kind.article(),
1817                    macro_kind.descr_expected(),
1818                ),
1819            };
1820            if let crate::DeclKind::Import { import, .. } = binding.kind
1821                && !import.span.is_dummy()
1822            {
1823                let note = errors::IdentImporterHereButItIsDesc {
1824                    span: import.span,
1825                    imported_ident: ident,
1826                    imported_ident_desc: &desc,
1827                };
1828                err.subdiagnostic(note);
1829                // Silence the 'unused import' warning we might get,
1830                // since this diagnostic already covers that import.
1831                self.record_use(ident, binding, Used::Other);
1832                return;
1833            }
1834            let note = errors::IdentInScopeButItIsDesc {
1835                imported_ident: ident,
1836                imported_ident_desc: &desc,
1837            };
1838            err.subdiagnostic(note);
1839            return;
1840        }
1841
1842        if self.macro_names.contains(&IdentKey::new(ident)) {
1843            err.subdiagnostic(AddedMacroUse);
1844            return;
1845        }
1846    }
1847
1848    /// Given an attribute macro that failed to be resolved, look for `derive` macros that could
1849    /// provide it, either as-is or with small typos.
1850    fn detect_derive_attribute(
1851        &self,
1852        err: &mut Diag<'_>,
1853        ident: Ident,
1854        parent_scope: &ParentScope<'ra>,
1855        sugg_span: Option<Span>,
1856    ) {
1857        // Find all of the `derive`s in scope and collect their corresponding declared
1858        // attributes.
1859        // FIXME: this only works if the crate that owns the macro that has the helper_attr
1860        // has already been imported.
1861        let mut derives = ::alloc::vec::Vec::new()vec![];
1862        let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
1863        // We're collecting these in a hashmap, and handle ordering the output further down.
1864        #[allow(rustc::potential_query_instability)]
1865        for (def_id, data) in self
1866            .local_macro_map
1867            .iter()
1868            .map(|(local_id, data)| (local_id.to_def_id(), data))
1869            .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
1870        {
1871            for helper_attr in &data.ext.helper_attrs {
1872                let item_name = self.tcx.item_name(def_id);
1873                all_attrs.entry(*helper_attr).or_default().push(item_name);
1874                if helper_attr == &ident.name {
1875                    derives.push(item_name);
1876                }
1877            }
1878        }
1879        let kind = MacroKind::Derive.descr();
1880        if !derives.is_empty() {
1881            // We found an exact match for the missing attribute in a `derive` macro. Suggest it.
1882            let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
1883            derives.sort();
1884            derives.dedup();
1885            let msg = match &derives[..] {
1886                [derive] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", derive))
    })format!(" `{derive}`"),
1887                [start @ .., last] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("s {0} and `{1}`",
                start.iter().map(|d|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("`{0}`", d))
                                    })).collect::<Vec<_>>().join(", "), last))
    })format!(
1888                    "s {} and `{last}`",
1889                    start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
1890                ),
1891                [] => {
    ::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
            format_args!("we checked for this to be non-empty 10 lines above!?")));
}unreachable!("we checked for this to be non-empty 10 lines above!?"),
1892            };
1893            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is an attribute that can be used by the {1}{2}, you might be missing a `derive` attribute",
                ident.name, kind, msg))
    })format!(
1894                "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
1895                     missing a `derive` attribute",
1896                ident.name,
1897            );
1898            let sugg_span = if let ModuleKind::Def(DefKind::Enum, id, _) = parent_scope.module.kind
1899            {
1900                let span = self.def_span(id);
1901                if span.from_expansion() {
1902                    None
1903                } else {
1904                    // For enum variants sugg_span is empty but we can get the enum's Span.
1905                    Some(span.shrink_to_lo())
1906                }
1907            } else {
1908                // For items this `Span` will be populated, everything else it'll be None.
1909                sugg_span
1910            };
1911            match sugg_span {
1912                Some(span) => {
1913                    err.span_suggestion_verbose(
1914                        span,
1915                        msg,
1916                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[derive({0})]\n",
                derives.join(", ")))
    })format!("#[derive({})]\n", derives.join(", ")),
1917                        Applicability::MaybeIncorrect,
1918                    );
1919                }
1920                None => {
1921                    err.note(msg);
1922                }
1923            }
1924        } else {
1925            // We didn't find an exact match. Look for close matches. If any, suggest fixing typo.
1926            let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
1927            if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
1928                && let Some(macros) = all_attrs.get(&best_match)
1929            {
1930                let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
1931                macros.sort();
1932                macros.dedup();
1933                let msg = match &macros[..] {
1934                    [] => return,
1935                    [name] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}` accepts", name))
    })format!(" `{name}` accepts"),
1936                    [start @ .., end] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("s {0} and `{1}` accept",
                start.iter().map(|m|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("`{0}`", m))
                                    })).collect::<Vec<_>>().join(", "), end))
    })format!(
1937                        "s {} and `{end}` accept",
1938                        start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
1939                    ),
1940                };
1941                let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the {0}{1} the similarly named `{2}` attribute",
                kind, msg, best_match))
    })format!("the {kind}{msg} the similarly named `{best_match}` attribute");
1942                err.span_suggestion_verbose(
1943                    ident.span,
1944                    msg,
1945                    best_match,
1946                    Applicability::MaybeIncorrect,
1947                );
1948            }
1949        }
1950    }
1951
1952    pub(crate) fn add_typo_suggestion(
1953        &self,
1954        err: &mut Diag<'_>,
1955        suggestion: Option<TypoSuggestion>,
1956        span: Span,
1957    ) -> bool {
1958        let suggestion = match suggestion {
1959            None => return false,
1960            // We shouldn't suggest underscore.
1961            Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
1962            Some(suggestion) => suggestion,
1963        };
1964
1965        let mut did_label_def_span = false;
1966
1967        if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
1968            if span.overlaps(def_span) {
1969                // Don't suggest typo suggestion for itself like in the following:
1970                // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
1971                //   --> $DIR/unicode-string-literal-syntax-error-64792.rs:4:14
1972                //    |
1973                // LL | struct X {}
1974                //    | ----------- `X` defined here
1975                // LL |
1976                // LL | const Y: X = X("ö");
1977                //    | -------------^^^^^^- similarly named constant `Y` defined here
1978                //    |
1979                // help: use struct literal syntax instead
1980                //    |
1981                // LL | const Y: X = X {};
1982                //    |              ^^^^
1983                // help: a constant with a similar name exists
1984                //    |
1985                // LL | const Y: X = Y("ö");
1986                //    |              ^
1987                return false;
1988            }
1989            let span = self.tcx.sess.source_map().guess_head_span(def_span);
1990            let candidate_descr = suggestion.res.descr();
1991            let candidate = suggestion.candidate;
1992            let label = match suggestion.target {
1993                SuggestionTarget::SimilarlyNamed => {
1994                    errors::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
1995                }
1996                SuggestionTarget::SingleItem => {
1997                    errors::DefinedHere::SingleItem { span, candidate_descr, candidate }
1998                }
1999            };
2000            did_label_def_span = true;
2001            err.subdiagnostic(label);
2002        }
2003
2004        let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
2005            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2006            && let Some(span) = suggestion.span
2007            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
2008            && snippet == candidate
2009        {
2010            let candidate = suggestion.candidate;
2011            // When the suggested binding change would be from `x` to `_x`, suggest changing the
2012            // original binding definition instead. (#60164)
2013            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the leading underscore in `{0}` marks it as unused, consider renaming it to `{1}`",
                candidate, snippet))
    })format!(
2014                "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
2015            );
2016            if !did_label_def_span {
2017                err.span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
    })format!("`{candidate}` defined here"));
2018            }
2019            (span, msg, snippet)
2020        } else {
2021            let msg = match suggestion.target {
2022                SuggestionTarget::SimilarlyNamed => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1} with a similar name exists",
                suggestion.res.article(), suggestion.res.descr()))
    })format!(
2023                    "{} {} with a similar name exists",
2024                    suggestion.res.article(),
2025                    suggestion.res.descr()
2026                ),
2027                SuggestionTarget::SingleItem => {
2028                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("maybe you meant this {0}",
                suggestion.res.descr()))
    })format!("maybe you meant this {}", suggestion.res.descr())
2029                }
2030            };
2031            (span, msg, suggestion.candidate.to_ident_string())
2032        };
2033        err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2034        true
2035    }
2036
2037    fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2038        let res = b.res();
2039        if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2040            let (built_in, from) = match scope {
2041                Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2042                Scope::ExternPreludeFlags
2043                    if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2044                        || #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::OpenMod(..) => true,
    _ => false,
}matches!(res, Res::OpenMod(..)) =>
2045                {
2046                    ("", " passed with `--extern`")
2047                }
2048                _ => {
2049                    if #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
    _ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2050                        // These already contain the "built-in" prefix or look bad with it.
2051                        ("", "")
2052                    } else {
2053                        (" built-in", "")
2054                    }
2055                }
2056            };
2057
2058            let a = if built_in.is_empty() { res.article() } else { "a" };
2059            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}{2} {0}{3}", res.descr(), a,
                built_in, from))
    })format!("{a}{built_in} {thing}{from}", thing = res.descr())
2060        } else {
2061            let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2062            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
                introduced))
    })format!("the {thing} {introduced} here", thing = res.descr())
2063        }
2064    }
2065
2066    fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity {
2067        let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2068            *ambiguity_error;
2069        let extern_prelude_ambiguity = || {
2070            // Note: b1 may come from a module scope, as an extern crate item in module.
2071            #[allow(non_exhaustive_omitted_patterns)] match scope2 {
    Scope::ExternPreludeFlags => true,
    _ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2072                && self
2073                    .extern_prelude
2074                    .get(&IdentKey::new(ident))
2075                    .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2076        };
2077        let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2078            // We have to print the span-less alternative first, otherwise formatting looks bad.
2079            (b2, b1, scope2, scope1, true)
2080        } else {
2081            (b1, b2, scope1, scope2, false)
2082        };
2083
2084        let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2085            let what = self.decl_description(b, ident, scope);
2086            let note_msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` could{1} refer to {2}",
                ident, also, what))
    })format!("`{ident}` could{also} refer to {what}");
2087
2088            let thing = b.res().descr();
2089            let mut help_msgs = Vec::new();
2090            if b.is_glob_import()
2091                && (kind == AmbiguityKind::GlobVsGlob
2092                    || kind == AmbiguityKind::GlobVsExpanded
2093                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2094            {
2095                help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
                ident))
    })format!(
2096                    "consider adding an explicit import of `{ident}` to disambiguate"
2097                ))
2098            }
2099            if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2100            {
2101                help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use `::{0}` to refer to this {1} unambiguously",
                ident, thing))
    })format!("use `::{ident}` to refer to this {thing} unambiguously"))
2102            }
2103
2104            if kind != AmbiguityKind::GlobVsGlob {
2105                if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2106                    if module == self.graph_root.to_module() {
2107                        help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
                ident, thing))
    })format!(
2108                            "use `crate::{ident}` to refer to this {thing} unambiguously"
2109                        ));
2110                    } else if module.is_normal() {
2111                        help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
                ident, thing))
    })format!(
2112                            "use `self::{ident}` to refer to this {thing} unambiguously"
2113                        ));
2114                    }
2115                }
2116            }
2117
2118            (
2119                Spanned { node: note_msg, span: b.span },
2120                help_msgs
2121                    .iter()
2122                    .enumerate()
2123                    .map(|(i, help_msg)| {
2124                        let or = if i == 0 { "" } else { "or " };
2125                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
    })format!("{or}{help_msg}")
2126                    })
2127                    .collect::<Vec<_>>(),
2128            )
2129        };
2130        let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2131        let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2132        let help = if kind == AmbiguityKind::GlobVsGlob
2133            && b1
2134                .parent_module
2135                .and_then(|m| m.opt_def_id())
2136                .map(|d| !d.is_local())
2137                .unwrap_or_default()
2138        {
2139            Some(&[
2140                "consider updating this dependency to resolve this error",
2141                "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2142            ] as &[_])
2143        } else {
2144            None
2145        };
2146
2147        let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2148            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} or {1}",
                vis1.to_string(CRATE_DEF_ID, self.tcx),
                vis2.to_string(CRATE_DEF_ID, self.tcx)))
    })format!(
2149                "{} or {}",
2150                vis1.to_string(CRATE_DEF_ID, self.tcx),
2151                vis2.to_string(CRATE_DEF_ID, self.tcx)
2152            )
2153        });
2154
2155        errors::Ambiguity {
2156            ident,
2157            help,
2158            ambig_vis,
2159            kind: kind.descr(),
2160            b1_note,
2161            b1_help_msgs,
2162            b2_note,
2163            b2_help_msgs,
2164            is_error: false,
2165        }
2166    }
2167
2168    /// If the binding refers to a tuple struct constructor with fields,
2169    /// returns the span of its fields.
2170    fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2171        let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
2172            decl.kind
2173        else {
2174            return None;
2175        };
2176
2177        let def_id = self.tcx.parent(ctor_def_id);
2178        self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()`
2179    }
2180
2181    fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2182        let PrivacyError {
2183            ident,
2184            decl,
2185            outermost_res,
2186            parent_scope,
2187            single_nested,
2188            dedup_span,
2189            ref source,
2190        } = *privacy_error;
2191
2192        let res = decl.res();
2193        let ctor_fields_span = self.ctor_fields_span(decl);
2194        let plain_descr = res.descr().to_string();
2195        let nonimport_descr =
2196            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2197        let import_descr = nonimport_descr.clone() + " import";
2198        let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2199
2200        // Print the primary message.
2201        let ident_descr = get_descr(decl);
2202        let mut err =
2203            self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident });
2204
2205        self.mention_default_field_values(source, ident, &mut err);
2206
2207        let mut not_publicly_reexported = false;
2208        if let Some((this_res, outer_ident)) = outermost_res {
2209            let import_suggestions = self.lookup_import_candidates(
2210                outer_ident,
2211                this_res.ns().unwrap_or(Namespace::TypeNS),
2212                &parent_scope,
2213                &|res: Res| res == this_res,
2214            );
2215            let point_to_def = !show_candidates(
2216                self.tcx,
2217                &mut err,
2218                Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2219                &import_suggestions,
2220                Instead::Yes,
2221                FoundUse::Yes,
2222                DiagMode::Import { append: single_nested, unresolved_import: false },
2223                ::alloc::vec::Vec::new()vec![],
2224                "",
2225            );
2226            // If we suggest importing a public re-export, don't point at the definition.
2227            if point_to_def && ident.span != outer_ident.span {
2228                not_publicly_reexported = true;
2229                let label = errors::OuterIdentIsNotPubliclyReexported {
2230                    span: outer_ident.span,
2231                    outer_ident_descr: this_res.descr(),
2232                    outer_ident,
2233                };
2234                err.subdiagnostic(label);
2235            }
2236        }
2237
2238        let mut non_exhaustive = None;
2239        // If an ADT is foreign and marked as `non_exhaustive`, then that's
2240        // probably why we have the privacy error.
2241        // Otherwise, point out if the struct has any private fields.
2242        if let Some(def_id) = res.opt_def_id()
2243            && !def_id.is_local()
2244            && let Some(attr_span) = {
    {
        'done:
            {
            for i in
                ::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
                #[allow(unused_imports)]
                use rustc_hir::attrs::AttributeKind::*;
                let i: &rustc_hir::Attribute = i;
                match i {
                    rustc_hir::Attribute::Parsed(NonExhaustive(span)) => {
                        break 'done Some(*span);
                    }
                    rustc_hir::Attribute::Unparsed(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }
}find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
2245        {
2246            non_exhaustive = Some(attr_span);
2247        } else if let Some(span) = ctor_fields_span {
2248            let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
2249            err.subdiagnostic(label);
2250            if let Res::Def(_, d) = res
2251                && let Some(fields) = self.field_visibility_spans.get(&d)
2252            {
2253                let spans = fields.iter().map(|span| *span).collect();
2254                let sugg =
2255                    errors::ConsiderMakingTheFieldPublic { spans, number_of_fields: fields.len() };
2256                err.subdiagnostic(sugg);
2257            }
2258        }
2259
2260        let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2261        if let Some(mut def_id) = res.opt_def_id() {
2262            // We can't use `def_path_str` in resolve.
2263            let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [def_id]))vec![def_id];
2264            while let Some(parent) = self.tcx.opt_parent(def_id) {
2265                def_id = parent;
2266                if !def_id.is_top_level_module() {
2267                    path.push(def_id);
2268                } else {
2269                    break;
2270                }
2271            }
2272            // We will only suggest importing directly if it is accessible through that path.
2273            let path_names: Option<Vec<Ident>> = path
2274                .iter()
2275                .rev()
2276                .map(|def_id| {
2277                    self.tcx.opt_item_name(*def_id).map(|name| {
2278                        Ident::with_dummy_span(if def_id.is_top_level_module() {
2279                            kw::Crate
2280                        } else {
2281                            name
2282                        })
2283                    })
2284                })
2285                .collect();
2286            if let Some(&def_id) = path.get(0)
2287                && let Some(path) = path_names
2288            {
2289                if let Some(def_id) = def_id.as_local() {
2290                    if self.effective_visibilities.is_directly_public(def_id) {
2291                        sugg_paths.push((path, false));
2292                    }
2293                } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2294                {
2295                    sugg_paths.push((path, false));
2296                }
2297            }
2298        }
2299
2300        // Print the whole import chain to make it easier to see what happens.
2301        let first_binding = decl;
2302        let mut next_binding = Some(decl);
2303        let mut next_ident = ident;
2304        let mut path = ::alloc::vec::Vec::new()vec![];
2305        while let Some(binding) = next_binding {
2306            let name = next_ident;
2307            next_binding = match binding.kind {
2308                _ if res == Res::Err => None,
2309                DeclKind::Import { source_decl, import, .. } => match import.kind {
2310                    _ if source_decl.span.is_dummy() => None,
2311                    ImportKind::Single { source, .. } => {
2312                        next_ident = source;
2313                        Some(source_decl)
2314                    }
2315                    ImportKind::Glob { .. }
2316                    | ImportKind::MacroUse { .. }
2317                    | ImportKind::MacroExport => Some(source_decl),
2318                    ImportKind::ExternCrate { .. } => None,
2319                },
2320                _ => None,
2321            };
2322
2323            match binding.kind {
2324                DeclKind::Import { import, .. } => {
2325                    for segment in import.module_path.iter().skip(1) {
2326                        // Don't include `{{root}}` in suggestions - it's an internal symbol
2327                        // that should never be shown to users.
2328                        if segment.ident.name != kw::PathRoot {
2329                            path.push(segment.ident);
2330                        }
2331                    }
2332                    sugg_paths.push((
2333                        path.iter().cloned().chain(std::iter::once(ident)).collect::<Vec<_>>(),
2334                        true, // re-export
2335                    ));
2336                }
2337                DeclKind::Def(_) => {}
2338            }
2339            let first = binding == first_binding;
2340            let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2341            let mut note_span = MultiSpan::from_span(def_span);
2342            if !first && binding.vis().is_public() {
2343                let desc = match binding.kind {
2344                    DeclKind::Import { .. } => "re-export",
2345                    _ => "directly",
2346                };
2347                note_span.push_span_label(def_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you could import this {0}", desc))
    })format!("you could import this {desc}"));
2348            }
2349            // Final step in the import chain, point out if the ADT is `non_exhaustive`
2350            // which is probably why this privacy violation occurred.
2351            if next_binding.is_none()
2352                && let Some(span) = non_exhaustive
2353            {
2354                note_span.push_span_label(
2355                    span,
2356                    "cannot be constructed because it is `#[non_exhaustive]`",
2357                );
2358            }
2359            let note = errors::NoteAndRefersToTheItemDefinedHere {
2360                span: note_span,
2361                binding_descr: get_descr(binding),
2362                binding_name: name,
2363                first,
2364                dots: next_binding.is_some(),
2365            };
2366            err.subdiagnostic(note);
2367        }
2368        // We prioritize shorter paths, non-core imports and direct imports over the alternatives.
2369        sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2370        for (sugg, reexport) in sugg_paths {
2371            if not_publicly_reexported {
2372                break;
2373            }
2374            if sugg.len() <= 1 {
2375                // A single path segment suggestion is wrong. This happens on circular imports.
2376                // `tests/ui/imports/issue-55884-2.rs`
2377                continue;
2378            }
2379            let path = join_path_idents(sugg);
2380            let sugg = if reexport {
2381                errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2382            } else {
2383                errors::ImportIdent::Directly { span: dedup_span, ident, path }
2384            };
2385            err.subdiagnostic(sugg);
2386            break;
2387        }
2388
2389        err.emit();
2390    }
2391
2392    /// When a private field is being set that has a default field value, we suggest using `..` and
2393    /// setting the value of that field implicitly with its default.
2394    ///
2395    /// If we encounter code like
2396    /// ```text
2397    /// struct Priv;
2398    /// pub struct S {
2399    ///     pub field: Priv = Priv,
2400    /// }
2401    /// ```
2402    /// which is used from a place where `Priv` isn't accessible
2403    /// ```text
2404    /// let _ = S { field: m::Priv1 {} };
2405    /// //                    ^^^^^ private struct
2406    /// ```
2407    /// we will suggest instead using the `default_field_values` syntax instead:
2408    /// ```text
2409    /// let _ = S { .. };
2410    /// ```
2411    fn mention_default_field_values(
2412        &self,
2413        source: &Option<ast::Expr>,
2414        ident: Ident,
2415        err: &mut Diag<'_>,
2416    ) {
2417        let Some(expr) = source else { return };
2418        let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2419        // We don't have to handle type-relative paths because they're forbidden in ADT
2420        // expressions, but that would change with `#[feature(more_qualified_paths)]`.
2421        let Some(segment) = struct_expr.path.segments.last() else { return };
2422        let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2423        let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2424            return;
2425        };
2426        let Some(default_fields) = self.field_defaults(def_id) else { return };
2427        if struct_expr.fields.is_empty() {
2428            return;
2429        }
2430        let last_span = struct_expr.fields.iter().last().unwrap().span;
2431        let mut iter = struct_expr.fields.iter().peekable();
2432        let mut prev: Option<Span> = None;
2433        while let Some(field) = iter.next() {
2434            if field.expr.span.overlaps(ident.span) {
2435                err.span_label(field.ident.span, "while setting this field");
2436                if default_fields.contains(&field.ident.name) {
2437                    let sugg = if last_span == field.span {
2438                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(field.span, "..".to_string())]))vec![(field.span, "..".to_string())]
2439                    } else {
2440                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(match (prev, iter.peek()) {
                        (_, Some(next)) => field.span.with_hi(next.span.lo()),
                        (Some(prev), _) => field.span.with_lo(prev.hi()),
                        (None, None) => field.span,
                    }, String::new()),
                (last_span.shrink_to_hi(), ", ..".to_string())]))vec![
2441                            (
2442                                // Account for trailing commas and ensure we remove them.
2443                                match (prev, iter.peek()) {
2444                                    (_, Some(next)) => field.span.with_hi(next.span.lo()),
2445                                    (Some(prev), _) => field.span.with_lo(prev.hi()),
2446                                    (None, None) => field.span,
2447                                },
2448                                String::new(),
2449                            ),
2450                            (last_span.shrink_to_hi(), ", ..".to_string()),
2451                        ]
2452                    };
2453                    err.multipart_suggestion(
2454                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the type `{2}` of field `{0}` is private, but you can construct the default value defined for it in `{1}` using `..` in the struct initializer expression",
                field.ident, self.tcx.item_name(def_id), ident))
    })format!(
2455                            "the type `{ident}` of field `{}` is private, but you can construct \
2456                             the default value defined for it in `{}` using `..` in the struct \
2457                             initializer expression",
2458                            field.ident,
2459                            self.tcx.item_name(def_id),
2460                        ),
2461                        sugg,
2462                        Applicability::MachineApplicable,
2463                    );
2464                    break;
2465                }
2466            }
2467            prev = Some(field.span);
2468        }
2469    }
2470
2471    pub(crate) fn find_similarly_named_module_or_crate(
2472        &self,
2473        ident: Symbol,
2474        current_module: Module<'ra>,
2475    ) -> Option<Symbol> {
2476        let mut candidates = self
2477            .extern_prelude
2478            .keys()
2479            .map(|ident| ident.name)
2480            .chain(
2481                self.local_module_map
2482                    .iter()
2483                    .filter(|(_, module)| {
2484                        let module = module.to_module();
2485                        current_module.is_ancestor_of(module) && current_module != module
2486                    })
2487                    .flat_map(|(_, module)| module.kind.name()),
2488            )
2489            .chain(
2490                self.extern_module_map
2491                    .borrow()
2492                    .iter()
2493                    .filter(|(_, module)| {
2494                        let module = module.to_module();
2495                        current_module.is_ancestor_of(module) && current_module != module
2496                    })
2497                    .flat_map(|(_, module)| module.kind.name()),
2498            )
2499            .filter(|c| !c.to_string().is_empty())
2500            .collect::<Vec<_>>();
2501        candidates.sort();
2502        candidates.dedup();
2503        find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2504    }
2505
2506    pub(crate) fn report_path_resolution_error(
2507        &mut self,
2508        path: &[Segment],
2509        opt_ns: Option<Namespace>, // `None` indicates a module path in import
2510        parent_scope: &ParentScope<'ra>,
2511        ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2512        ignore_decl: Option<Decl<'ra>>,
2513        ignore_import: Option<Import<'ra>>,
2514        module: Option<ModuleOrUniformRoot<'ra>>,
2515        failed_segment_idx: usize,
2516        ident: Ident,
2517        diag_metadata: Option<&DiagMetadata<'_>>,
2518    ) -> (String, String, Option<Suggestion>) {
2519        let is_last = failed_segment_idx == path.len() - 1;
2520        let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2521        let module_res = match module {
2522            Some(ModuleOrUniformRoot::Module(module)) => module.res(),
2523            _ => None,
2524        };
2525        let scope = match &path[..failed_segment_idx] {
2526            [.., prev] => {
2527                if prev.ident.name == kw::PathRoot {
2528                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the crate root"))
    })format!("the crate root")
2529                } else {
2530                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", prev.ident))
    })format!("`{}`", prev.ident)
2531                }
2532            }
2533            _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this scope"))
    })format!("this scope"),
2534        };
2535        let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
                scope))
    })format!("cannot find `{ident}` in {scope}");
2536
2537        if module_res == self.graph_root.res() {
2538            let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(DefKind::Mod, _) => true,
    _ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2539            let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2540            candidates
2541                .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2542            if let Some(candidate) = candidates.get(0) {
2543                let path = {
2544                    // remove the possible common prefix of the path
2545                    let len = candidate.path.segments.len();
2546                    let start_index = (0..=failed_segment_idx.min(len - 1))
2547                        .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2548                        .unwrap_or_default();
2549                    let segments =
2550                        (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2551                    Path { segments, span: Span::default(), tokens: None }
2552                };
2553                (
2554                    message,
2555                    String::from("unresolved import"),
2556                    Some((
2557                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span, pprust::path_to_string(&path))]))vec![(ident.span, pprust::path_to_string(&path))],
2558                        String::from("a similar path exists"),
2559                        Applicability::MaybeIncorrect,
2560                    )),
2561                )
2562            } else if ident.name == sym::core {
2563                (
2564                    message,
2565                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
                ident))
    })format!("you might be missing crate `{ident}`"),
2566                    Some((
2567                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span, "std".to_string())]))vec![(ident.span, "std".to_string())],
2568                        "try using `std` instead of `core`".to_string(),
2569                        Applicability::MaybeIncorrect,
2570                    )),
2571                )
2572            } else if ident.name == kw::Underscore {
2573                (
2574                    "invalid crate or module name `_`".to_string(),
2575                    "`_` is not a valid crate or module name".to_string(),
2576                    None,
2577                )
2578            } else if self.tcx.sess.is_rust_2015() {
2579                (
2580                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
                ident, scope))
    })format!("cannot find module or crate `{ident}` in {scope}"),
2581                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use of unresolved module or unlinked crate `{0}`",
                ident))
    })format!("use of unresolved module or unlinked crate `{ident}`"),
2582                    Some((
2583                        ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(self.current_crate_outer_attr_insert_span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("extern crate {0};\n",
                                    ident))
                        }))]))vec![(
2584                            self.current_crate_outer_attr_insert_span,
2585                            format!("extern crate {ident};\n"),
2586                        )],
2587                        if was_invoked_from_cargo() {
2588                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you wanted to use a crate named `{0}`, use `cargo add {0}` to add it to your `Cargo.toml` and import it in your code",
                ident))
    })format!(
2589                                "if you wanted to use a crate named `{ident}`, use `cargo add \
2590                                 {ident}` to add it to your `Cargo.toml` and import it in your \
2591                                 code",
2592                            )
2593                        } else {
2594                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might be missing a crate named `{0}`, add it to your project and import it in your code",
                ident))
    })format!(
2595                                "you might be missing a crate named `{ident}`, add it to your \
2596                                 project and import it in your code",
2597                            )
2598                        },
2599                        Applicability::MaybeIncorrect,
2600                    )),
2601                )
2602            } else {
2603                (message, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("could not find `{0}` in the crate root",
                ident))
    })format!("could not find `{ident}` in the crate root"), None)
2604            }
2605        } else if failed_segment_idx > 0 {
2606            let parent = path[failed_segment_idx - 1].ident.name;
2607            let parent = match parent {
2608                // ::foo is mounted at the crate root for 2015, and is the extern
2609                // prelude for 2018+
2610                kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
2611                    "the list of imported crates".to_owned()
2612                }
2613                kw::PathRoot | kw::Crate => "the crate root".to_owned(),
2614                _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", parent))
    })format!("`{parent}`"),
2615            };
2616
2617            let mut msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("could not find `{0}` in {1}",
                ident, parent))
    })format!("could not find `{ident}` in {parent}");
2618            if ns == TypeNS || ns == ValueNS {
2619                let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
2620                let binding = if let Some(module) = module {
2621                    self.cm()
2622                        .resolve_ident_in_module(
2623                            module,
2624                            ident,
2625                            ns_to_try,
2626                            parent_scope,
2627                            None,
2628                            ignore_decl,
2629                            ignore_import,
2630                        )
2631                        .ok()
2632                } else if let Some(ribs) = ribs
2633                    && let Some(TypeNS | ValueNS) = opt_ns
2634                {
2635                    if !ignore_import.is_none() {
    ::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2636                    match self.resolve_ident_in_lexical_scope(
2637                        ident,
2638                        ns_to_try,
2639                        parent_scope,
2640                        None,
2641                        &ribs[ns_to_try],
2642                        ignore_decl,
2643                        diag_metadata,
2644                    ) {
2645                        // we found a locally-imported or available item/module
2646                        Some(LateDecl::Decl(binding)) => Some(binding),
2647                        _ => None,
2648                    }
2649                } else {
2650                    self.cm()
2651                        .resolve_ident_in_scope_set(
2652                            ident,
2653                            ScopeSet::All(ns_to_try),
2654                            parent_scope,
2655                            None,
2656                            ignore_decl,
2657                            ignore_import,
2658                        )
2659                        .ok()
2660                };
2661                if let Some(binding) = binding {
2662                    msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("expected {0}, found {1} `{2}` in {3}",
                ns.descr(), binding.res().descr(), ident, parent))
    })format!(
2663                        "expected {}, found {} `{ident}` in {parent}",
2664                        ns.descr(),
2665                        binding.res().descr(),
2666                    );
2667                };
2668            }
2669            (message, msg, None)
2670        } else if ident.name == kw::SelfUpper {
2671            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
2672            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
2673            // impl
2674            if opt_ns.is_none() {
2675                (message, "`Self` cannot be used in imports".to_string(), None)
2676            } else {
2677                (
2678                    message,
2679                    "`Self` is only available in impls, traits, and type definitions".to_string(),
2680                    None,
2681                )
2682            }
2683        } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
2684            // Check whether the name refers to an item in the value namespace.
2685            let binding = if let Some(ribs) = ribs {
2686                if !ignore_import.is_none() {
    ::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2687                self.resolve_ident_in_lexical_scope(
2688                    ident,
2689                    ValueNS,
2690                    parent_scope,
2691                    None,
2692                    &ribs[ValueNS],
2693                    ignore_decl,
2694                    diag_metadata,
2695                )
2696            } else {
2697                None
2698            };
2699            let match_span = match binding {
2700                // Name matches a local variable. For example:
2701                // ```
2702                // fn f() {
2703                //     let Foo: &str = "";
2704                //     println!("{}", Foo::Bar); // Name refers to local
2705                //                               // variable `Foo`.
2706                // }
2707                // ```
2708                Some(LateDecl::RibDef(Res::Local(id))) => {
2709                    Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
2710                }
2711                // Name matches item from a local name binding
2712                // created by `use` declaration. For example:
2713                // ```
2714                // pub const Foo: &str = "";
2715                //
2716                // mod submod {
2717                //     use super::Foo;
2718                //     println!("{}", Foo::Bar); // Name refers to local
2719                //                               // binding `Foo`.
2720                // }
2721                // ```
2722                Some(LateDecl::Decl(name_binding)) => Some((
2723                    name_binding.span,
2724                    name_binding.res().article(),
2725                    name_binding.res().descr(),
2726                )),
2727                _ => None,
2728            };
2729
2730            let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find type `{0}` in {1}",
                ident, scope))
    })format!("cannot find type `{ident}` in {scope}");
2731            let label = if let Some((span, article, descr)) = match_span {
2732                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{1}` is declared as {2} {3} at `{0}`, not a type",
                self.tcx.sess.source_map().span_to_short_string(span,
                    RemapPathScopeComponents::DIAGNOSTICS), ident, article,
                descr))
    })format!(
2733                    "`{ident}` is declared as {article} {descr} at `{}`, not a type",
2734                    self.tcx
2735                        .sess
2736                        .source_map()
2737                        .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
2738                )
2739            } else {
2740                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
                ident))
    })format!("use of undeclared type `{ident}`")
2741            };
2742            (message, label, None)
2743        } else {
2744            let mut suggestion = None;
2745            if ident.name == sym::alloc {
2746                suggestion = Some((
2747                    ::alloc::vec::Vec::new()vec![],
2748                    String::from("add `extern crate alloc` to use the `alloc` crate"),
2749                    Applicability::MaybeIncorrect,
2750                ))
2751            }
2752
2753            suggestion = suggestion.or_else(|| {
2754                self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
2755                    |sugg| {
2756                        (
2757                            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span, sugg.to_string())]))vec![(ident.span, sugg.to_string())],
2758                            String::from("there is a crate or module with a similar name"),
2759                            Applicability::MaybeIncorrect,
2760                        )
2761                    },
2762                )
2763            });
2764            if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2765                ident,
2766                ScopeSet::All(ValueNS),
2767                parent_scope,
2768                None,
2769                ignore_decl,
2770                ignore_import,
2771            ) {
2772                let descr = binding.res().descr();
2773                let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
                ident, scope))
    })format!("cannot find module or crate `{ident}` in {scope}");
2774                (message, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} `{1}` is not a crate or module",
                descr, ident))
    })format!("{descr} `{ident}` is not a crate or module"), suggestion)
2775            } else {
2776                let suggestion = if suggestion.is_some() {
2777                    suggestion
2778                } else if let Some(m) = self.undeclared_module_exists(ident) {
2779                    self.undeclared_module_suggest_declare(ident, m)
2780                } else if was_invoked_from_cargo() {
2781                    Some((
2782                        ::alloc::vec::Vec::new()vec![],
2783                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you wanted to use a crate named `{0}`, use `cargo add {0}` to add it to your `Cargo.toml`",
                ident))
    })format!(
2784                            "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
2785                             to add it to your `Cargo.toml`",
2786                        ),
2787                        Applicability::MaybeIncorrect,
2788                    ))
2789                } else {
2790                    Some((
2791                        ::alloc::vec::Vec::new()vec![],
2792                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might be missing a crate named `{0}`",
                ident))
    })format!("you might be missing a crate named `{ident}`",),
2793                        Applicability::MaybeIncorrect,
2794                    ))
2795                };
2796                let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
                ident, scope))
    })format!("cannot find module or crate `{ident}` in {scope}");
2797                (
2798                    message,
2799                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use of unresolved module or unlinked crate `{0}`",
                ident))
    })format!("use of unresolved module or unlinked crate `{ident}`"),
2800                    suggestion,
2801                )
2802            }
2803        }
2804    }
2805
2806    fn undeclared_module_suggest_declare(
2807        &self,
2808        ident: Ident,
2809        path: std::path::PathBuf,
2810    ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
2811        Some((
2812            ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(self.current_crate_outer_attr_insert_span,
                    ::alloc::__export::must_use({
                            ::alloc::fmt::format(format_args!("mod {0};\n", ident))
                        }))]))vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
2813            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("to make use of source file {0}, use `mod {1}` in this file to declare the module",
                path.display(), ident))
    })format!(
2814                "to make use of source file {}, use `mod {ident}` \
2815                 in this file to declare the module",
2816                path.display()
2817            ),
2818            Applicability::MaybeIncorrect,
2819        ))
2820    }
2821
2822    fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
2823        let map = self.tcx.sess.source_map();
2824
2825        let src = map.span_to_filename(ident.span).into_local_path()?;
2826        let i = ident.as_str();
2827        // FIXME: add case where non parent using undeclared module (hard?)
2828        let dir = src.parent()?;
2829        let src = src.file_stem()?.to_str()?;
2830        for file in [
2831            // …/x.rs
2832            dir.join(i).with_extension("rs"),
2833            // …/x/mod.rs
2834            dir.join(i).join("mod.rs"),
2835        ] {
2836            if file.exists() {
2837                return Some(file);
2838            }
2839        }
2840        if !#[allow(non_exhaustive_omitted_patterns)] match src {
    "main" | "lib" | "mod" => true,
    _ => false,
}matches!(src, "main" | "lib" | "mod") {
2841            for file in [
2842                // …/x/y.rs
2843                dir.join(src).join(i).with_extension("rs"),
2844                // …/x/y/mod.rs
2845                dir.join(src).join(i).join("mod.rs"),
2846            ] {
2847                if file.exists() {
2848                    return Some(file);
2849                }
2850            }
2851        }
2852        None
2853    }
2854
2855    /// Adds suggestions for a path that cannot be resolved.
2856    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_path_suggestion",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2856u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Option<(Vec<Segment>, Option<String>)> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            match path[..] {
                [first, second, ..] if
                    first.ident.name == kw::PathRoot &&
                        !second.ident.is_path_segment_keyword() => {}
                [first, ..] if
                    first.ident.span.at_least_rust_2018() &&
                        !first.ident.is_path_segment_keyword() => {
                    path.insert(0, Segment::from_ident(Ident::dummy()));
                }
                _ => return None,
            }
            self.make_missing_self_suggestion(path.clone(),
                            parent_scope).or_else(||
                            self.make_missing_crate_suggestion(path.clone(),
                                parent_scope)).or_else(||
                        self.make_missing_super_suggestion(path.clone(),
                            parent_scope)).or_else(||
                    self.make_external_crate_suggestion(path, parent_scope))
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
2857    pub(crate) fn make_path_suggestion(
2858        &mut self,
2859        mut path: Vec<Segment>,
2860        parent_scope: &ParentScope<'ra>,
2861    ) -> Option<(Vec<Segment>, Option<String>)> {
2862        match path[..] {
2863            // `{{root}}::ident::...` on both editions.
2864            // On 2015 `{{root}}` is usually added implicitly.
2865            [first, second, ..]
2866                if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
2867            // `ident::...` on 2018.
2868            [first, ..]
2869                if first.ident.span.at_least_rust_2018()
2870                    && !first.ident.is_path_segment_keyword() =>
2871            {
2872                // Insert a placeholder that's later replaced by `self`/`super`/etc.
2873                path.insert(0, Segment::from_ident(Ident::dummy()));
2874            }
2875            _ => return None,
2876        }
2877
2878        self.make_missing_self_suggestion(path.clone(), parent_scope)
2879            .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
2880            .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
2881            .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
2882    }
2883
2884    /// Suggest a missing `self::` if that resolves to an correct module.
2885    ///
2886    /// ```text
2887    ///    |
2888    /// LL | use foo::Bar;
2889    ///    |     ^^^ did you mean `self::foo`?
2890    /// ```
2891    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_missing_self_suggestion",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2891u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Option<(Vec<Segment>, Option<String>)> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            path[0].ident.name = kw::SelfLower;
            let result =
                self.cm().maybe_resolve_path(&path, None, parent_scope, None);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2900",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2900u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path", "result"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&path) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&result) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            if let PathResult::Module(..) = result {
                Some((path, None))
            } else { None }
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
2892    fn make_missing_self_suggestion(
2893        &mut self,
2894        mut path: Vec<Segment>,
2895        parent_scope: &ParentScope<'ra>,
2896    ) -> Option<(Vec<Segment>, Option<String>)> {
2897        // Replace first ident with `self` and check if that is valid.
2898        path[0].ident.name = kw::SelfLower;
2899        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2900        debug!(?path, ?result);
2901        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
2902    }
2903
2904    /// Suggests a missing `crate::` if that resolves to an correct module.
2905    ///
2906    /// ```text
2907    ///    |
2908    /// LL | use foo::Bar;
2909    ///    |     ^^^ did you mean `crate::foo`?
2910    /// ```
2911    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_missing_crate_suggestion",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2911u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Option<(Vec<Segment>, Option<String>)> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            path[0].ident.name = kw::Crate;
            let result =
                self.cm().maybe_resolve_path(&path, None, parent_scope, None);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2920",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2920u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path", "result"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&path) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&result) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            if let PathResult::Module(..) = result {
                Some((path,
                        Some("`use` statements changed in Rust 2018; read more at \
                     <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
                     clarity.html>".to_string())))
            } else { None }
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
2912    fn make_missing_crate_suggestion(
2913        &mut self,
2914        mut path: Vec<Segment>,
2915        parent_scope: &ParentScope<'ra>,
2916    ) -> Option<(Vec<Segment>, Option<String>)> {
2917        // Replace first ident with `crate` and check if that is valid.
2918        path[0].ident.name = kw::Crate;
2919        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2920        debug!(?path, ?result);
2921        if let PathResult::Module(..) = result {
2922            Some((
2923                path,
2924                Some(
2925                    "`use` statements changed in Rust 2018; read more at \
2926                     <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
2927                     clarity.html>"
2928                        .to_string(),
2929                ),
2930            ))
2931        } else {
2932            None
2933        }
2934    }
2935
2936    /// Suggests a missing `super::` if that resolves to an correct module.
2937    ///
2938    /// ```text
2939    ///    |
2940    /// LL | use foo::Bar;
2941    ///    |     ^^^ did you mean `super::foo`?
2942    /// ```
2943    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_missing_super_suggestion",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2943u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Option<(Vec<Segment>, Option<String>)> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            path[0].ident.name = kw::Super;
            let result =
                self.cm().maybe_resolve_path(&path, None, parent_scope, None);
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2952",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2952u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path", "result"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::EVENT)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let enabled =
                    ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::STATIC_MAX_LEVEL &&
                            ::tracing::Level::DEBUG <=
                                ::tracing::level_filters::LevelFilter::current() &&
                        {
                            let interest = __CALLSITE.interest();
                            !interest.is_never() &&
                                ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                    interest)
                        };
                if enabled {
                    (|value_set: ::tracing::field::ValueSet|
                                {
                                    let meta = __CALLSITE.metadata();
                                    ::tracing::Event::dispatch(meta, &value_set);
                                    ;
                                })({
                            #[allow(unused_imports)]
                            use ::tracing::field::{debug, display, Value};
                            let mut iter = __CALLSITE.metadata().fields().iter();
                            __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&path) as
                                                        &dyn Value)),
                                            (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                ::tracing::__macro_support::Option::Some(&debug(&result) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            if let PathResult::Module(..) = result {
                Some((path, None))
            } else { None }
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
2944    fn make_missing_super_suggestion(
2945        &mut self,
2946        mut path: Vec<Segment>,
2947        parent_scope: &ParentScope<'ra>,
2948    ) -> Option<(Vec<Segment>, Option<String>)> {
2949        // Replace first ident with `crate` and check if that is valid.
2950        path[0].ident.name = kw::Super;
2951        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2952        debug!(?path, ?result);
2953        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
2954    }
2955
2956    /// Suggests a missing external crate name if that resolves to an correct module.
2957    ///
2958    /// ```text
2959    ///    |
2960    /// LL | use foobar::Baz;
2961    ///    |     ^^^^^^ did you mean `baz::foobar`?
2962    /// ```
2963    ///
2964    /// Used when importing a submodule of an external crate but missing that crate's
2965    /// name as the first part of path.
2966    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("make_external_crate_suggestion",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(2966u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["path"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return:
                    Option<(Vec<Segment>, Option<String>)> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if path[1].ident.span.is_rust_2015() { return None; }
            let mut extern_crate_names =
                self.extern_prelude.keys().map(|ident|
                            ident.name).collect::<Vec<_>>();
            extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
            for name in extern_crate_names.into_iter() {
                path[0].ident.name = name;
                let result =
                    self.cm().maybe_resolve_path(&path, None, parent_scope,
                        None);
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2987",
                                        "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                        ::tracing_core::__macro_support::Option::Some(2987u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                        ::tracing_core::field::FieldSet::new(&["path", "name",
                                                        "result"],
                                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                        ::tracing::metadata::Kind::EVENT)
                                };
                            ::tracing::callsite::DefaultCallsite::new(&META)
                        };
                    let enabled =
                        ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            {
                                let interest = __CALLSITE.interest();
                                !interest.is_never() &&
                                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                        interest)
                            };
                    if enabled {
                        (|value_set: ::tracing::field::ValueSet|
                                    {
                                        let meta = __CALLSITE.metadata();
                                        ::tracing::Event::dispatch(meta, &value_set);
                                        ;
                                    })({
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = __CALLSITE.metadata().fields().iter();
                                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&path) as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&name) as
                                                            &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&debug(&result) as
                                                            &dyn Value))])
                            });
                    } else { ; }
                };
                if let PathResult::Module(..) = result {
                    return Some((path, None));
                }
            }
            None
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
2967    fn make_external_crate_suggestion(
2968        &mut self,
2969        mut path: Vec<Segment>,
2970        parent_scope: &ParentScope<'ra>,
2971    ) -> Option<(Vec<Segment>, Option<String>)> {
2972        if path[1].ident.span.is_rust_2015() {
2973            return None;
2974        }
2975
2976        // Sort extern crate names in *reverse* order to get
2977        // 1) some consistent ordering for emitted diagnostics, and
2978        // 2) `std` suggestions before `core` suggestions.
2979        let mut extern_crate_names =
2980            self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
2981        extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
2982
2983        for name in extern_crate_names.into_iter() {
2984            // Replace first ident with a crate name and check if that is valid.
2985            path[0].ident.name = name;
2986            let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2987            debug!(?path, ?name, ?result);
2988            if let PathResult::Module(..) = result {
2989                return Some((path, None));
2990            }
2991        }
2992
2993        None
2994    }
2995
2996    /// Suggests importing a macro from the root of the crate rather than a module within
2997    /// the crate.
2998    ///
2999    /// ```text
3000    /// help: a macro with this name exists at the root of the crate
3001    ///    |
3002    /// LL | use issue_59764::makro;
3003    ///    |     ^^^^^^^^^^^^^^^^^^
3004    ///    |
3005    ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
3006    ///            at the root of the crate instead of the module where it is defined
3007    /// ```
3008    pub(crate) fn check_for_module_export_macro(
3009        &mut self,
3010        import: Import<'ra>,
3011        module: ModuleOrUniformRoot<'ra>,
3012        ident: Ident,
3013    ) -> Option<(Option<Suggestion>, Option<String>)> {
3014        let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3015            return None;
3016        };
3017
3018        while let Some(parent) = crate_module.parent {
3019            crate_module = parent;
3020        }
3021
3022        if module == ModuleOrUniformRoot::Module(crate_module) {
3023            // Don't make a suggestion if the import was already from the root of the crate.
3024            return None;
3025        }
3026
3027        let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3028        let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3029        let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3030            return None;
3031        };
3032        if !kinds.contains(MacroKinds::BANG) {
3033            return None;
3034        }
3035        let module_name = crate_module.kind.name().unwrap_or(kw::Crate);
3036        let import_snippet = match import.kind {
3037            ImportKind::Single { source, target, .. } if source != target => {
3038                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} as {1}", source, target))
    })format!("{source} as {target}")
3039            }
3040            _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", ident))
    })format!("{ident}"),
3041        };
3042
3043        let mut corrections: Vec<(Span, String)> = Vec::new();
3044        if !import.is_nested() {
3045            // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
3046            // intermediate segments.
3047            corrections.push((import.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1}", module_name,
                import_snippet))
    })format!("{module_name}::{import_snippet}")));
3048        } else {
3049            // Find the binding span (and any trailing commas and spaces).
3050            //   i.e. `use a::b::{c, d, e};`
3051            //                      ^^^
3052            let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3053                self.tcx.sess,
3054                import.span,
3055                import.use_span,
3056            );
3057            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3057",
                        "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                        ::tracing_core::__macro_support::Option::Some(3057u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                        ::tracing_core::field::FieldSet::new(&["found_closing_brace",
                                        "binding_span"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&found_closing_brace
                                            as &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&binding_span)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(found_closing_brace, ?binding_span);
3058
3059            let mut removal_span = binding_span;
3060
3061            // If the binding span ended with a closing brace, as in the below example:
3062            //   i.e. `use a::b::{c, d};`
3063            //                      ^
3064            // Then expand the span of characters to remove to include the previous
3065            // binding's trailing comma.
3066            //   i.e. `use a::b::{c, d};`
3067            //                    ^^^
3068            if found_closing_brace
3069                && let Some(previous_span) =
3070                    extend_span_to_previous_binding(self.tcx.sess, binding_span)
3071            {
3072                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3072",
                        "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                        ::tracing_core::__macro_support::Option::Some(3072u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                        ::tracing_core::field::FieldSet::new(&["previous_span"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&previous_span)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(?previous_span);
3073                removal_span = removal_span.with_lo(previous_span.lo());
3074            }
3075            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3075",
                        "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                        ::tracing_core::__macro_support::Option::Some(3075u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                        ::tracing_core::field::FieldSet::new(&["removal_span"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&removal_span)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(?removal_span);
3076
3077            // Remove the `removal_span`.
3078            corrections.push((removal_span, "".to_string()));
3079
3080            // Find the span after the crate name and if it has nested imports immediately
3081            // after the crate name already.
3082            //   i.e. `use a::b::{c, d};`
3083            //               ^^^^^^^^^
3084            //   or  `use a::{b, c, d}};`
3085            //               ^^^^^^^^^^^
3086            let (has_nested, after_crate_name) =
3087                find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3088            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3088",
                        "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                        ::tracing_core::__macro_support::Option::Some(3088u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                        ::tracing_core::field::FieldSet::new(&["has_nested",
                                        "after_crate_name"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() &&
            {
                let interest = __CALLSITE.interest();
                !interest.is_never() &&
                    ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                        interest)
            };
    if enabled {
        (|value_set: ::tracing::field::ValueSet|
                    {
                        let meta = __CALLSITE.metadata();
                        ::tracing::Event::dispatch(meta, &value_set);
                        ;
                    })({
                #[allow(unused_imports)]
                use ::tracing::field::{debug, display, Value};
                let mut iter = __CALLSITE.metadata().fields().iter();
                __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&has_nested as
                                            &dyn Value)),
                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                    ::tracing::__macro_support::Option::Some(&debug(&after_crate_name)
                                            as &dyn Value))])
            });
    } else { ; }
};debug!(has_nested, ?after_crate_name);
3089
3090            let source_map = self.tcx.sess.source_map();
3091
3092            // Make sure this is actually crate-relative.
3093            let is_definitely_crate = import
3094                .module_path
3095                .first()
3096                .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3097
3098            // Add the import to the start, with a `{` if required.
3099            let start_point = source_map.start_point(after_crate_name);
3100            if is_definitely_crate
3101                && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3102            {
3103                corrections.push((
3104                    start_point,
3105                    if has_nested {
3106                        // In this case, `start_snippet` must equal '{'.
3107                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
                import_snippet))
    })format!("{start_snippet}{import_snippet}, ")
3108                    } else {
3109                        // In this case, add a `{`, then the moved import, then whatever
3110                        // was there before.
3111                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
                start_snippet))
    })format!("{{{import_snippet}, {start_snippet}")
3112                    },
3113                ));
3114
3115                // Add a `};` to the end if nested, matching the `{` added at the start.
3116                if !has_nested {
3117                    corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3118                }
3119            } else {
3120                // If the root import is module-relative, add the import separately
3121                corrections.push((
3122                    import.use_span.shrink_to_lo(),
3123                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
                import_snippet))
    })format!("use {module_name}::{import_snippet};\n"),
3124                ));
3125            }
3126        }
3127
3128        let suggestion = Some((
3129            corrections,
3130            String::from("a macro with this name exists at the root of the crate"),
3131            Applicability::MaybeIncorrect,
3132        ));
3133        Some((
3134            suggestion,
3135            Some(
3136                "this could be because a macro annotated with `#[macro_export]` will be exported \
3137            at the root of the crate instead of the module where it is defined"
3138                    .to_string(),
3139            ),
3140        ))
3141    }
3142
3143    /// Finds a cfg-ed out item inside `module` with the matching name.
3144    pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3145        let local_items;
3146        let symbols = if module.is_local() {
3147            local_items = self
3148                .stripped_cfg_items
3149                .iter()
3150                .filter_map(|item| {
3151                    let parent_scope = self.opt_local_def_id(item.parent_scope)?.to_def_id();
3152                    Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3153                })
3154                .collect::<Vec<_>>();
3155            local_items.as_slice()
3156        } else {
3157            self.tcx.stripped_cfg_items(module.krate)
3158        };
3159
3160        for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3161            if ident.name != *segment {
3162                continue;
3163            }
3164
3165            let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3166
3167            fn comes_from_same_module_for_glob(
3168                r: &Resolver<'_, '_>,
3169                parent_module: DefId,
3170                module: DefId,
3171                visited: &mut FxHashMap<DefId, bool>,
3172            ) -> bool {
3173                if let Some(&cached) = visited.get(&parent_module) {
3174                    // this branch is prevent from being called recursively infinity,
3175                    // because there has some cycles in globs imports,
3176                    // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32`
3177                    return cached;
3178                }
3179                visited.insert(parent_module, false);
3180                let m = r.expect_module(parent_module);
3181                let mut res = false;
3182                for importer in m.glob_importers.borrow().iter() {
3183                    if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() {
3184                        if next_parent_module == module
3185                            || comes_from_same_module_for_glob(
3186                                r,
3187                                next_parent_module,
3188                                module,
3189                                visited,
3190                            )
3191                        {
3192                            res = true;
3193                            break;
3194                        }
3195                    }
3196                }
3197                visited.insert(parent_module, res);
3198                res
3199            }
3200
3201            let comes_from_same_module = parent_module == module
3202                || comes_from_same_module_for_glob(
3203                    self,
3204                    parent_module,
3205                    module,
3206                    &mut Default::default(),
3207                );
3208            if !comes_from_same_module {
3209                continue;
3210            }
3211
3212            let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3213                errors::ItemWas::BehindFeature { feature, span: cfg.1 }
3214            } else {
3215                errors::ItemWas::CfgOut { span: cfg.1 }
3216            };
3217            let note = errors::FoundItemConfigureOut { span: ident.span, item_was };
3218            err.subdiagnostic(note);
3219        }
3220    }
3221
3222    pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3223        match def_id.as_local() {
3224            Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3225            None => {
3226                self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3227                    let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3228                    let vis = self.tcx.visibility(ctor_def_id);
3229                    let field_visibilities = self
3230                        .tcx
3231                        .associated_item_def_ids(def_id)
3232                        .iter()
3233                        .map(|&field_id| self.tcx.visibility(field_id))
3234                        .collect();
3235                    StructCtor { res, vis, field_visibilities }
3236                })
3237            }
3238        }
3239    }
3240}
3241
3242/// Given a `binding_span` of a binding within a use statement:
3243///
3244/// ```ignore (illustrative)
3245/// use foo::{a, b, c};
3246/// //           ^
3247/// ```
3248///
3249/// then return the span until the next binding or the end of the statement:
3250///
3251/// ```ignore (illustrative)
3252/// use foo::{a, b, c};
3253/// //           ^^^
3254/// ```
3255fn find_span_of_binding_until_next_binding(
3256    sess: &Session,
3257    binding_span: Span,
3258    use_span: Span,
3259) -> (bool, Span) {
3260    let source_map = sess.source_map();
3261
3262    // Find the span of everything after the binding.
3263    //   i.e. `a, e};` or `a};`
3264    let binding_until_end = binding_span.with_hi(use_span.hi());
3265
3266    // Find everything after the binding but not including the binding.
3267    //   i.e. `, e};` or `};`
3268    let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3269
3270    // Keep characters in the span until we encounter something that isn't a comma or
3271    // whitespace.
3272    //   i.e. `, ` or ``.
3273    //
3274    // Also note whether a closing brace character was encountered. If there
3275    // was, then later go backwards to remove any trailing commas that are left.
3276    let mut found_closing_brace = false;
3277    let after_binding_until_next_binding =
3278        source_map.span_take_while(after_binding_until_end, |&ch| {
3279            if ch == '}' {
3280                found_closing_brace = true;
3281            }
3282            ch == ' ' || ch == ','
3283        });
3284
3285    // Combine the two spans.
3286    //   i.e. `a, ` or `a`.
3287    //
3288    // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
3289    let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3290
3291    (found_closing_brace, span)
3292}
3293
3294/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
3295/// binding.
3296///
3297/// ```ignore (illustrative)
3298/// use foo::a::{a, b, c};
3299/// //            ^^--- binding span
3300/// //            |
3301/// //            returned span
3302///
3303/// use foo::{a, b, c};
3304/// //        --- binding span
3305/// ```
3306fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3307    let source_map = sess.source_map();
3308
3309    // `prev_source` will contain all of the source that came before the span.
3310    // Then split based on a command and take the first (i.e. closest to our span)
3311    // snippet. In the example, this is a space.
3312    let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3313
3314    let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3315    let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3316    if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3317        return None;
3318    }
3319
3320    let prev_comma = prev_comma.first().unwrap();
3321    let prev_starting_brace = prev_starting_brace.first().unwrap();
3322
3323    // If the amount of source code before the comma is greater than
3324    // the amount of source code before the starting brace then we've only
3325    // got one item in the nested item (eg. `issue_52891::{self}`).
3326    if prev_comma.len() > prev_starting_brace.len() {
3327        return None;
3328    }
3329
3330    Some(binding_span.with_lo(BytePos(
3331        // Take away the number of bytes for the characters we've found and an
3332        // extra for the comma.
3333        binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3334    )))
3335}
3336
3337/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
3338/// it is a nested use tree.
3339///
3340/// ```ignore (illustrative)
3341/// use foo::a::{b, c};
3342/// //       ^^^^^^^^^^ -- false
3343///
3344/// use foo::{a, b, c};
3345/// //       ^^^^^^^^^^ -- true
3346///
3347/// use foo::{a, b::{c, d}};
3348/// //       ^^^^^^^^^^^^^^^ -- true
3349/// ```
3350#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("find_span_immediately_after_crate_name",
                                    "rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3350u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
                                    ::tracing_core::field::FieldSet::new(&["use_span"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_span)
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: (bool, Span) = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let source_map = sess.source_map();
            let mut num_colons = 0;
            let until_second_colon =
                source_map.span_take_while(use_span,
                    |c|
                        {
                            if *c == ':' { num_colons += 1; }
                            !#[allow(non_exhaustive_omitted_patterns)] match c {
                                    ':' if num_colons == 2 => true,
                                    _ => false,
                                }
                        });
            let from_second_colon =
                use_span.with_lo(until_second_colon.hi() + BytePos(1));
            let mut found_a_non_whitespace_character = false;
            let after_second_colon =
                source_map.span_take_while(from_second_colon,
                    |c|
                        {
                            if found_a_non_whitespace_character { return false; }
                            if !c.is_whitespace() {
                                found_a_non_whitespace_character = true;
                            }
                            true
                        });
            let next_left_bracket =
                source_map.span_through_char(from_second_colon, '{');
            (next_left_bracket == after_second_colon, from_second_colon)
        }
    }
}#[instrument(level = "debug", skip(sess))]
3351fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3352    let source_map = sess.source_map();
3353
3354    // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
3355    let mut num_colons = 0;
3356    // Find second colon.. `use issue_59764:`
3357    let until_second_colon = source_map.span_take_while(use_span, |c| {
3358        if *c == ':' {
3359            num_colons += 1;
3360        }
3361        !matches!(c, ':' if num_colons == 2)
3362    });
3363    // Find everything after the second colon.. `foo::{baz, makro};`
3364    let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3365
3366    let mut found_a_non_whitespace_character = false;
3367    // Find the first non-whitespace character in `from_second_colon`.. `f`
3368    let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3369        if found_a_non_whitespace_character {
3370            return false;
3371        }
3372        if !c.is_whitespace() {
3373            found_a_non_whitespace_character = true;
3374        }
3375        true
3376    });
3377
3378    // Find the first `{` in from_second_colon.. `foo::{`
3379    let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3380
3381    (next_left_bracket == after_second_colon, from_second_colon)
3382}
3383
3384/// A suggestion has already been emitted, change the wording slightly to clarify that both are
3385/// independent options.
3386enum Instead {
3387    Yes,
3388    No,
3389}
3390
3391/// Whether an existing place with an `use` item was found.
3392enum FoundUse {
3393    Yes,
3394    No,
3395}
3396
3397/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
3398pub(crate) enum DiagMode {
3399    Normal,
3400    /// The binding is part of a pattern
3401    Pattern,
3402    /// The binding is part of a use statement
3403    Import {
3404        /// `true` means diagnostics is for unresolved import
3405        unresolved_import: bool,
3406        /// `true` mean add the tips afterward for case `use a::{b,c}`,
3407        /// rather than replacing within.
3408        append: bool,
3409    },
3410}
3411
3412pub(crate) fn import_candidates(
3413    tcx: TyCtxt<'_>,
3414    err: &mut Diag<'_>,
3415    // This is `None` if all placement locations are inside expansions
3416    use_placement_span: Option<Span>,
3417    candidates: &[ImportSuggestion],
3418    mode: DiagMode,
3419    append: &str,
3420) {
3421    show_candidates(
3422        tcx,
3423        err,
3424        use_placement_span,
3425        candidates,
3426        Instead::Yes,
3427        FoundUse::Yes,
3428        mode,
3429        ::alloc::vec::Vec::new()vec![],
3430        append,
3431    );
3432}
3433
3434type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3435
3436/// When an entity with a given name is not available in scope, we search for
3437/// entities with that name in all crates. This method allows outputting the
3438/// results of this search in a programmer-friendly way. If any entities are
3439/// found and suggested, returns `true`, otherwise returns `false`.
3440fn show_candidates(
3441    tcx: TyCtxt<'_>,
3442    err: &mut Diag<'_>,
3443    // This is `None` if all placement locations are inside expansions
3444    use_placement_span: Option<Span>,
3445    candidates: &[ImportSuggestion],
3446    instead: Instead,
3447    found_use: FoundUse,
3448    mode: DiagMode,
3449    path: Vec<Segment>,
3450    append: &str,
3451) -> bool {
3452    if candidates.is_empty() {
3453        return false;
3454    }
3455
3456    let mut showed = false;
3457    let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3458    let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3459
3460    candidates.iter().for_each(|c| {
3461        if c.accessible {
3462            // Don't suggest `#[doc(hidden)]` items from other crates
3463            if c.doc_visible {
3464                accessible_path_strings.push((
3465                    pprust::path_to_string(&c.path),
3466                    c.descr,
3467                    c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3468                    &c.note,
3469                    c.via_import,
3470                ))
3471            }
3472        } else {
3473            inaccessible_path_strings.push((
3474                pprust::path_to_string(&c.path),
3475                c.descr,
3476                c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3477                &c.note,
3478                c.via_import,
3479            ))
3480        }
3481    });
3482
3483    // we want consistent results across executions, but candidates are produced
3484    // by iterating through a hash map, so make sure they are ordered:
3485    for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3486        path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3487        path_strings.dedup_by(|a, b| a.0 == b.0);
3488        let core_path_strings =
3489            path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3490        let std_path_strings =
3491            path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3492        let foreign_crate_path_strings =
3493            path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3494
3495        // We list the `crate` local paths first.
3496        // Then we list the `std`/`core` paths.
3497        if std_path_strings.len() == core_path_strings.len() {
3498            // Do not list `core::` paths if we are already listing the `std::` ones.
3499            path_strings.extend(std_path_strings);
3500        } else {
3501            path_strings.extend(std_path_strings);
3502            path_strings.extend(core_path_strings);
3503        }
3504        // List all paths from foreign crates last.
3505        path_strings.extend(foreign_crate_path_strings);
3506    }
3507
3508    if !accessible_path_strings.is_empty() {
3509        let (determiner, kind, s, name, through) =
3510            if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3511                (
3512                    "this",
3513                    *descr,
3514                    "",
3515                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", name))
    })format!(" `{name}`"),
3516                    if *via_import { " through its public re-export" } else { "" },
3517                )
3518            } else {
3519                // Get the unique item kinds and if there's only one, we use the right kind name
3520                // instead of the more generic "items".
3521                let kinds = accessible_path_strings
3522                    .iter()
3523                    .map(|(_, descr, _, _, _)| *descr)
3524                    .collect::<UnordSet<&str>>();
3525                let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3526                let s = if kind.ends_with('s') { "es" } else { "s" };
3527
3528                ("one of these", kind, s, String::new(), "")
3529            };
3530
3531        let instead = if let Instead::Yes = instead { " instead" } else { "" };
3532        let mut msg = if let DiagMode::Pattern = mode {
3533            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you meant to match on {0}{1}{2}{3}, use the full path in the pattern",
                kind, s, instead, name))
    })format!(
3534                "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3535                 pattern",
3536            )
3537        } else {
3538            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider importing {0} {1}{2}{3}{4}",
                determiner, kind, s, through, instead))
    })format!("consider importing {determiner} {kind}{s}{through}{instead}")
3539        };
3540
3541        for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3542            err.note(note.clone());
3543        }
3544
3545        let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3546            msg.push(':');
3547
3548            for candidate in accessible_path_strings {
3549                msg.push('\n');
3550                msg.push_str(&candidate.0);
3551            }
3552        };
3553
3554        if let Some(span) = use_placement_span {
3555            let (add_use, trailing) = match mode {
3556                DiagMode::Pattern => {
3557                    err.span_suggestions(
3558                        span,
3559                        msg,
3560                        accessible_path_strings.into_iter().map(|a| a.0),
3561                        Applicability::MaybeIncorrect,
3562                    );
3563                    return true;
3564                }
3565                DiagMode::Import { .. } => ("", ""),
3566                DiagMode::Normal => ("use ", ";\n"),
3567            };
3568            for candidate in &mut accessible_path_strings {
3569                // produce an additional newline to separate the new use statement
3570                // from the directly following item.
3571                let additional_newline = if let FoundUse::No = found_use
3572                    && let DiagMode::Normal = mode
3573                {
3574                    "\n"
3575                } else {
3576                    ""
3577                };
3578                candidate.0 =
3579                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}{0}{2}{3}{4}", candidate.0,
                add_use, append, trailing, additional_newline))
    })format!("{add_use}{}{append}{trailing}{additional_newline}", candidate.0);
3580            }
3581
3582            match mode {
3583                DiagMode::Import { append: true, .. } => {
3584                    append_candidates(&mut msg, accessible_path_strings);
3585                    err.span_help(span, msg);
3586                }
3587                _ => {
3588                    err.span_suggestions_with_style(
3589                        span,
3590                        msg,
3591                        accessible_path_strings.into_iter().map(|a| a.0),
3592                        Applicability::MaybeIncorrect,
3593                        SuggestionStyle::ShowAlways,
3594                    );
3595                }
3596            }
3597
3598            if let [first, .., last] = &path[..] {
3599                let sp = first.ident.span.until(last.ident.span);
3600                // Our suggestion is empty, so make sure the span is not empty (or we'd ICE).
3601                // Can happen for derive-generated spans.
3602                if sp.can_be_used_for_suggestions() && !sp.is_empty() {
3603                    err.span_suggestion_verbose(
3604                        sp,
3605                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you import `{0}`, refer to it directly",
                last.ident))
    })format!("if you import `{}`, refer to it directly", last.ident),
3606                        "",
3607                        Applicability::Unspecified,
3608                    );
3609                }
3610            }
3611        } else {
3612            append_candidates(&mut msg, accessible_path_strings);
3613            err.help(msg);
3614        }
3615        showed = true;
3616    }
3617    if !inaccessible_path_strings.is_empty()
3618        && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
    DiagMode::Import { unresolved_import: false, .. } => true,
    _ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
3619    {
3620        let prefix =
3621            if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
3622        if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
3623            let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{1}{2} `{3}`{0} exists but is inaccessible",
                if let DiagMode::Pattern = mode { ", which" } else { "" },
                prefix, descr, name))
    })format!(
3624                "{prefix}{descr} `{name}`{} exists but is inaccessible",
3625                if let DiagMode::Pattern = mode { ", which" } else { "" }
3626            );
3627
3628            if let Some(source_span) = source_span {
3629                let span = tcx.sess.source_map().guess_head_span(*source_span);
3630                let mut multi_span = MultiSpan::from_span(span);
3631                multi_span.push_span_label(span, "not accessible");
3632                err.span_note(multi_span, msg);
3633            } else {
3634                err.note(msg);
3635            }
3636            if let Some(note) = (*note).as_deref() {
3637                err.note(note.to_string());
3638            }
3639        } else {
3640            let descr = inaccessible_path_strings
3641                .iter()
3642                .map(|&(_, descr, _, _, _)| descr)
3643                .all_equal_value()
3644                .unwrap_or("item");
3645            let plural_descr =
3646                if descr.ends_with('s') { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}es", descr))
    })format!("{descr}es") } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}s", descr))
    })format!("{descr}s") };
3647
3648            let mut msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}these {1} exist but are inaccessible",
                prefix, plural_descr))
    })format!("{prefix}these {plural_descr} exist but are inaccessible");
3649            let mut has_colon = false;
3650
3651            let mut spans = Vec::new();
3652            for (name, _, source_span, _, _) in &inaccessible_path_strings {
3653                if let Some(source_span) = source_span {
3654                    let span = tcx.sess.source_map().guess_head_span(*source_span);
3655                    spans.push((name, span));
3656                } else {
3657                    if !has_colon {
3658                        msg.push(':');
3659                        has_colon = true;
3660                    }
3661                    msg.push('\n');
3662                    msg.push_str(name);
3663                }
3664            }
3665
3666            let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
3667            for (name, span) in spans {
3668                multi_span.push_span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
    })format!("`{name}`: not accessible"));
3669            }
3670
3671            for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3672                err.note(note.clone());
3673            }
3674
3675            err.span_note(multi_span, msg);
3676        }
3677        showed = true;
3678    }
3679    showed
3680}
3681
3682#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UsePlacementFinder {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field3_finish(f,
            "UsePlacementFinder", "target_module", &self.target_module,
            "first_legal_span", &self.first_legal_span, "first_use_span",
            &&self.first_use_span)
    }
}Debug)]
3683struct UsePlacementFinder {
3684    target_module: NodeId,
3685    first_legal_span: Option<Span>,
3686    first_use_span: Option<Span>,
3687}
3688
3689impl UsePlacementFinder {
3690    fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
3691        let mut finder =
3692            UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
3693        finder.visit_crate(krate);
3694        if let Some(use_span) = finder.first_use_span {
3695            (Some(use_span), FoundUse::Yes)
3696        } else {
3697            (finder.first_legal_span, FoundUse::No)
3698        }
3699    }
3700}
3701
3702impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
3703    fn visit_crate(&mut self, c: &Crate) {
3704        if self.target_module == CRATE_NODE_ID {
3705            let inject = c.spans.inject_use_span;
3706            if is_span_suitable_for_use_injection(inject) {
3707                self.first_legal_span = Some(inject);
3708            }
3709            self.first_use_span = search_for_any_use_in_items(&c.items);
3710        } else {
3711            visit::walk_crate(self, c);
3712        }
3713    }
3714
3715    fn visit_item(&mut self, item: &'tcx ast::Item) {
3716        if self.target_module == item.id {
3717            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
3718                let inject = mod_spans.inject_use_span;
3719                if is_span_suitable_for_use_injection(inject) {
3720                    self.first_legal_span = Some(inject);
3721                }
3722                self.first_use_span = search_for_any_use_in_items(items);
3723            }
3724        } else {
3725            visit::walk_item(self, item);
3726        }
3727    }
3728}
3729
3730#[derive(#[automatically_derived]
impl ::core::default::Default for BindingVisitor {
    #[inline]
    fn default() -> BindingVisitor {
        BindingVisitor {
            identifiers: ::core::default::Default::default(),
            spans: ::core::default::Default::default(),
        }
    }
}Default)]
3731struct BindingVisitor {
3732    identifiers: Vec<Symbol>,
3733    spans: FxHashMap<Symbol, Vec<Span>>,
3734}
3735
3736impl<'tcx> Visitor<'tcx> for BindingVisitor {
3737    fn visit_pat(&mut self, pat: &ast::Pat) {
3738        if let ast::PatKind::Ident(_, ident, _) = pat.kind {
3739            self.identifiers.push(ident.name);
3740            self.spans.entry(ident.name).or_default().push(ident.span);
3741        }
3742        visit::walk_pat(self, pat);
3743    }
3744}
3745
3746fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
3747    for item in items {
3748        if let ItemKind::Use(..) = item.kind
3749            && is_span_suitable_for_use_injection(item.span)
3750        {
3751            let mut lo = item.span.lo();
3752            for attr in &item.attrs {
3753                if attr.span.eq_ctxt(item.span) {
3754                    lo = std::cmp::min(lo, attr.span.lo());
3755                }
3756            }
3757            return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
3758        }
3759    }
3760    None
3761}
3762
3763fn is_span_suitable_for_use_injection(s: Span) -> bool {
3764    // don't suggest placing a use before the prelude
3765    // import or other generated ones
3766    !s.from_expansion()
3767}