Skip to main content

rustc_resolve/diagnostics/
impls.rs

1// ignore-tidy-file-filelength
2use std::mem;
3use std::ops::ControlFlow;
4
5use itertools::Itertools as _;
6use rustc_ast::visit::{self, Visitor};
7use rustc_ast::{
8    self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path,
9    join_path_idents,
10};
11use rustc_ast_pretty::pprust;
12use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs};
13use rustc_attr_ir::{
14    Attribute, AttributeKind, CfgEntry, Stability, StabilityLevel, StrippedCfgItem, find_attr,
15};
16use rustc_attr_parsing::AttributeParser;
17use rustc_data_structures::fx::{FxHashMap, FxHashSet};
18use rustc_data_structures::unord::{UnordMap, UnordSet};
19use rustc_errors::codes::*;
20use rustc_errors::{
21    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
22    pluralize, struct_span_code_err,
23};
24use rustc_feature::BUILTIN_ATTRIBUTES;
25use rustc_hir::PrimTy;
26use rustc_hir::def::Namespace::{self, *};
27use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
28use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
29use rustc_lint_defs::builtin::{
30    ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
31    AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
32};
33use rustc_middle::ty::{TyCtxt, Visibility};
34use rustc_session::Session;
35use rustc_session::utils::was_invoked_from_cargo;
36use rustc_span::def_id::ModId;
37use rustc_span::edit_distance::find_best_match_for_name;
38use rustc_span::edition::Edition;
39use rustc_span::hygiene::MacroKind;
40use rustc_span::source_map::SourceMap;
41use rustc_span::{
42    BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, bug, kw, sym,
43};
44use thin_vec::{ThinVec, thin_vec};
45use tracing::{debug, instrument};
46
47use crate::diagnostics::{
48    self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
49    ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
50    MaybeMissingMacroRulesName,
51};
52use crate::hygiene::Macros20NormalizedSyntaxContext;
53use crate::imports::{Import, ImportKind, UnresolvedImportError, import_path_to_string};
54use crate::late::{ConstantRequiresType, DiagMetadata, PatternSource, Rib};
55use crate::{
56    AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
57    DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey,
58    LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
59    PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
60    VisResolutionError, path_names_to_string,
61};
62
63/// A vector of spans and replacements, a message and applicability.
64pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
65
66/// Potential candidate for an undeclared or out-of-scope label - contains the ident of a
67/// similarly named label and whether or not it is reachable.
68pub(crate) type LabelSuggestion = (Ident, bool);
69
70#[derive(#[automatically_derived]impl ::core::clone::Clone for StructCtor {
    #[inline]
    fn clone(&self) -> Self {
        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)]
71pub(crate) struct StructCtor {
72    pub res: Res,
73    pub vis: Visibility<ModId>,
74    pub field_visibilities: Vec<Visibility<ModId>>,
75}
76
77impl StructCtor {
78    pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
79        self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
80    }
81}
82
83#[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)]
84pub(crate) enum SuggestionTarget {
85    /// The target has a similar name as the name used by the programmer (probably a typo)
86    SimilarlyNamed,
87    /// The target is the only valid item that can be used in the corresponding context
88    SingleItem,
89}
90
91#[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 span res target", &self.candidate,
            &self.span, &self.res, &&self.target)
    }
}Debug)]
92pub(crate) struct TypoSuggestion {
93    pub candidate: Symbol,
94    /// The source location where the name is defined; None if the name is not defined
95    /// in source e.g. primitives
96    pub span: Option<Span>,
97    pub res: Res,
98    pub target: SuggestionTarget,
99}
100
101impl TypoSuggestion {
102    pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
103        Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
104    }
105    pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
106        Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
107    }
108    pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
109        Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
110    }
111}
112
113/// A free importable items suggested in case of resolution failure.
114#[derive(#[automatically_derived]impl ::core::fmt::Debug for ImportSuggestion {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        let names: &'static _ =
            "ImportSuggestion 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, names, values)
    }
}Debug)]
115pub(crate) struct ImportSuggestion {
116    pub did: Option<DefId>,
117    pub descr: &'static str,
118    pub path: Path,
119    pub accessible: bool,
120    // false if the path traverses a foreign `#[doc(hidden)]` item.
121    pub doc_visible: bool,
122    pub via_import: bool,
123    /// An extra note that should be issued if this item is suggested
124    pub note: Option<String>,
125    pub is_stable: bool,
126}
127
128/// Adjust the impl span so that just the `impl` keyword is taken by removing
129/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
130/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
131///
132/// *Attention*: the method used is very fragile since it essentially duplicates the work of the
133/// parser. If you need to use this function or something similar, please consider updating the
134/// `source_map` functions and this function to something more robust.
135fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
136    let impl_span = sm.span_until_char(impl_span, '<');
137    sm.span_until_whitespace(impl_span)
138}
139
140impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
141    /// Reports unresolved imports.
142    ///
143    /// Multiple unresolved import errors within the same use tree are combined into a single
144    /// diagnostic.
145    pub(crate) fn throw_unresolved_import_error(
146        &mut self,
147        mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
148        glob_error: bool,
149    ) {
150        errors.retain(|(_import, err)| match err.module {
151            // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.
152            Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
153            // If we've encountered something like `use _;`, we've already emitted an error stating
154            // that `_` is not a valid identifier, so we ignore that resolve error.
155            _ => err.segment.map(|s| s.name) != Some(kw::Underscore),
156        });
157        if errors.is_empty() {
158            self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");
159            return;
160        }
161
162        let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
163
164        let paths = errors
165            .iter()
166            .map(|(import, err)| {
167                let path = import_path_to_string(
168                    &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
169                    &import.kind,
170                    err.span,
171                );
172                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", path))
    })format!("`{path}`")
173            })
174            .collect::<Vec<_>>();
175        let default_message =
176            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("unresolved import{0} {1}",
                if paths.len() == 1 { "" } else { "s" }, paths.join(", ")))
    })format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
177
178        // Process `import` use of  the `#[diagnostic::on_unknown]` attribute.
179        //
180        // We don't need to check feature gates here; that happens on initialization of the
181        // `on_unknown_attr` fields.
182        let (mut message, label, mut notes) =
183            if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) {
184                let this = errors
185                    .iter()
186                    .map(|(_import, err)| {
187                        // Is this unwrap_or reachable?
188                        err.segment.map(|s| s.name).unwrap_or(kw::Underscore)
189                    })
190                    .join(", ");
191
192                let args = FormatArgs { unresolved: this.clone(), this, .. };
193
194                let CustomDiagnostic { message, label, notes, parent_label: _dead } =
195                    directive.eval(None, &args);
196
197                (message, label, notes)
198            } else {
199                (None, None, Vec::new())
200            };
201
202        // `module` use of the `#[diagnostic::on_unknown]` attribute.
203        // We assume that someone who put the attribute on the import has more information than
204        // the person who put it on the module, so we choose to prioritize the import attribute.
205        let mut mod_diagnostics: Vec<CustomDiagnostic> = errors
206            .iter()
207            .map(|(import, import_error)| {
208                if let Some(ModuleOrUniformRoot::Module(module_data)) = import.imported_module.get()
209                    && let ModuleKind::Def(DefKind::Mod, def_id, ..) = module_data.kind
210                {
211                    let Some((this, directive)) = self.on_unknown_data(def_id) else {
212                        return CustomDiagnostic::default();
213                    };
214
215                    let unresolved = import_error.segment.map(|s| s.name).unwrap_or(kw::Underscore);
216                    let args = FormatArgs {
217                        this: this.to_string(),
218                        unresolved: unresolved.to_string(),
219                        ..
220                    };
221
222                    directive.eval(None, &args)
223                } else {
224                    CustomDiagnostic::default()
225                }
226            })
227            .collect();
228
229        // If there is no import attribute with a message,
230        // but all mod messages are the same, use that.
231        let mod_message =
232            mod_diagnostics.iter_mut().flat_map(|d| d.message.take()).all_equal_value();
233        if message.is_none()
234            && let Ok(mod_msg) = mod_message
235        {
236            message = Some(mod_msg);
237        }
238
239        let mut diag = if let Some(message) = message {
240            {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", message))
                })).with_code(E0432)
}struct_span_code_err!(self.dcx(), span, E0432, "{message}").with_note(default_message)
241        } else {
242            {
    self.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", default_message))
                })).with_code(E0432)
}struct_span_code_err!(self.dcx(), span, E0432, "{default_message}")
243        };
244
245        for mod_diag in mod_diagnostics.iter_mut() {
246            for mod_note in mod_diag.notes.drain(..) {
247                if !notes.contains(&mod_note) {
248                    notes.push(mod_note);
249                }
250            }
251        }
252
253        if !notes.is_empty() {
254            for note in notes {
255                diag.note(note);
256            }
257        } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.last() {
258            diag.note(note.clone());
259        }
260
261        /// Upper limit on the number of `span_label` messages.
262        const MAX_LABEL_COUNT: usize = 10;
263        let mod_labels = mod_diagnostics.into_iter().map(|cd| cd.label);
264
265        for ((import, err), mod_label) in errors.into_iter().zip(mod_labels).take(MAX_LABEL_COUNT) {
266            let label_span = match err.segment {
267                Some(segment) => segment.span,
268                None => err.span,
269            };
270            if let Some(label) = &label {
271                diag.span_label(label_span, label.clone());
272            } else if let Some(label) = mod_label {
273                diag.span_label(label_span, label);
274            } else if let Some(label) = &err.label {
275                diag.span_label(label_span, label.clone());
276            }
277
278            if let Some((suggestions, msg, applicability)) = err.suggestion {
279                if suggestions.is_empty() {
280                    diag.help(msg);
281                    continue;
282                }
283                diag.multipart_suggestion(msg, suggestions, applicability);
284            }
285
286            if let Some(help) = err.help {
287                diag.help(help);
288            }
289
290            if let Some(candidates) = &err.candidates {
291                match &import.kind {
292                    ImportKind::Single { nested: false, source, target, .. } => import_candidates(
293                        self.tcx,
294                        &mut diag,
295                        Some(err.span),
296                        candidates,
297                        DiagMode::Import { append: false, unresolved_import: true },
298                        (source != target)
299                            .then(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" as {0}", target))
    })format!(" as {target}"))
300                            .as_deref()
301                            .unwrap_or(""),
302                    ),
303                    ImportKind::Single { nested: true, source, target, .. } => {
304                        import_candidates(
305                            self.tcx,
306                            &mut diag,
307                            None,
308                            candidates,
309                            DiagMode::Normal,
310                            (source != target)
311                                .then(|| ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" as {0}", target))
    })format!(" as {target}"))
312                                .as_deref()
313                                .unwrap_or(""),
314                        );
315                    }
316                    _ => {}
317                }
318            }
319
320            if #[allow(non_exhaustive_omitted_patterns)] match import.kind {
    ImportKind::Single { .. } => true,
    _ => false,
}matches!(import.kind, ImportKind::Single { .. })
321                && let Some(segment) = err.segment
322                && let Some(module) = err.module
323            {
324                self.find_cfg_stripped(&mut diag, &segment.name, module)
325            }
326        }
327
328        let guar = diag.emit_err();
329        if glob_error {
330            self.glob_error = Some(guar);
331        }
332    }
333
334    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
335        self.tcx.dcx()
336    }
337
338    pub(crate) fn report_errors(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {
339        self.report_delayed_vis_resolution_errors();
340        self.report_with_use_injections(krate, use_injections);
341
342        for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
343            self.lint_buffer.buffer_lint(
344                MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
345                CRATE_NODE_ID,
346                span_use.0,
347                diagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths {
348                    definition: span_def.0,
349                },
350            );
351        }
352
353        for ambiguity_error in &self.ambiguity_errors {
354            let mut diag = self.ambiguity_diagnostic(ambiguity_error);
355
356            if let Some(ambiguity_warning) = ambiguity_error.warning {
357                let node_id = match ambiguity_error.b1.0.kind {
358                    DeclKind::Import { import, .. } => import.root_id,
359                    DeclKind::Def(..) => CRATE_NODE_ID,
360                };
361
362                let lint = match ambiguity_warning {
363                    _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
364                    AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
365                    AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
366                };
367
368                self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
369            } else {
370                diag.is_error = true;
371                self.dcx().emit_err(diag);
372            }
373        }
374
375        let mut reported_spans = FxHashSet::default();
376        for error in mem::take(&mut self.privacy_errors) {
377            if reported_spans.insert(error.dedup_span) {
378                self.report_privacy_error(&error);
379            }
380        }
381    }
382
383    fn report_delayed_vis_resolution_errors(&mut self) {
384        for DelayedVisResolutionError { vis, parent_scope, error } in
385            mem::take(&mut self.delayed_vis_resolution_errors)
386        {
387            match self.try_resolve_visibility(&parent_scope, &vis, true) {
388                Ok(_) => self.report_vis_error(error),
389                Err(error) => self.report_vis_error(error),
390            };
391        }
392    }
393
394    fn report_with_use_injections(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {
395        for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in
396            use_injections
397        {
398            let (span, found_use) = if node_id != DUMMY_NODE_ID {
399                UsePlacementFinder::check(krate, node_id)
400            } else {
401                (None, FoundUse::No)
402            };
403
404            if !candidates.is_empty() {
405                show_candidates(
406                    self.tcx,
407                    &mut err,
408                    span,
409                    &candidates,
410                    if instead { Instead::Yes } else { Instead::No },
411                    found_use,
412                    DiagMode::Normal,
413                    path,
414                    "",
415                );
416                err.emit();
417            } else if let Some((span, msg, sugg, appl)) = suggestion {
418                err.span_suggestion_verbose(span, msg, sugg, appl);
419                err.emit();
420            } else if let [segment] = path.as_slice()
421                && is_call
422            {
423                err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
424            } else {
425                err.emit();
426            }
427        }
428    }
429
430    pub(crate) fn report_conflict(
431        &mut self,
432        ident: IdentKey,
433        ns: Namespace,
434        old_binding: Decl<'ra>,
435        new_binding: Decl<'ra>,
436    ) {
437        // Error on the second of two conflicting names
438        if old_binding.span.lo() > new_binding.span.lo() {
439            return self.report_conflict(ident, ns, new_binding, old_binding);
440        }
441
442        let container = match old_binding.parent_module.unwrap().expect_local().kind {
443            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
444            // indirectly *calls* the resolver, and would cause a query cycle.
445            ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id),
446            ModuleKind::Block => "block",
447        };
448
449        let (name, span) =
450            (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
451
452        if self.name_already_seen.get(&name) == Some(&span) {
453            return;
454        }
455
456        let old_kind = match (ns, old_binding.res()) {
457            (ValueNS, _) => "value",
458            (MacroNS, _) => "macro",
459            (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
460            (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
461            (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
462            (TypeNS, _) => "type",
463        };
464
465        let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
466            (true, true) => E0259,
467            (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
468                true => E0254,
469                false => E0260,
470            },
471            _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
472                (false, false) => E0428,
473                (true, true) => E0252,
474                _ => E0255,
475            },
476        };
477
478        let label = match new_binding.is_import_user_facing() {
479            true => diagnostics::NameDefinedMultipleTimeLabel::Reimported { span, name },
480            false => diagnostics::NameDefinedMultipleTimeLabel::Redefined { span, name },
481        };
482
483        let old_binding_label =
484            (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
485                let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
486                match old_binding.is_import_user_facing() {
487                    true => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Import {
488                        span,
489                        old_kind,
490                        name,
491                    },
492                    false => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Definition {
493                        span,
494                        old_kind,
495                        name,
496                    },
497                }
498            });
499
500        let mut err = self
501            .dcx()
502            .create_err(diagnostics::NameDefinedMultipleTime {
503                span,
504                name,
505                descr: ns.descr(),
506                container,
507                label,
508                old_binding_label,
509            })
510            .with_code(code);
511
512        // See https://github.com/rust-lang/rust/issues/32354
513        use DeclKind::Import;
514        let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
515            !binding.span.is_dummy()
516                && !#[allow(non_exhaustive_omitted_patterns)] match import.kind {
    ImportKind::MacroUse { .. } | ImportKind::MacroExport => true,
    _ => false,
}matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
517        };
518        let import = match (&new_binding.kind, &old_binding.kind) {
519            // If there are two imports where one or both have attributes then prefer removing the
520            // import without attributes.
521            (Import { import: new, .. }, Import { import: old, .. })
522                if {
523                    (new.has_attributes || old.has_attributes)
524                        && can_suggest(old_binding, *old)
525                        && can_suggest(new_binding, *new)
526                } =>
527            {
528                if old.has_attributes {
529                    Some((*new, new_binding.span, true))
530                } else {
531                    Some((*old, old_binding.span, true))
532                }
533            }
534            // Otherwise prioritize the new binding.
535            (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
536                Some((*import, new_binding.span, other.is_import()))
537            }
538            (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
539                Some((*import, old_binding.span, other.is_import()))
540            }
541            _ => None,
542        };
543
544        // Check if the target of the use for both bindings is the same.
545        let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
546        let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
547        let from_item =
548            self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
549        // Only suggest removing an import if both bindings are to the same def, if both spans
550        // aren't dummy spans. Further, if both bindings are imports, then the ident must have
551        // been introduced by an item.
552        let should_remove_import = duplicate
553            && !has_dummy_span
554            && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
555
556        match import {
557            Some((import, span, true)) if should_remove_import && import.is_nested() => {
558                self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
559            }
560            Some((import, _, true)) if should_remove_import && !import.is_glob() => {
561                // Simple case - remove the entire import. Due to the above match arm, this can
562                // only be a single use so just remove it entirely.
563                err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport {
564                    span: import.use_span_with_attributes,
565                });
566            }
567            Some((import, span, _)) => {
568                self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
569            }
570            _ => {}
571        }
572
573        err.emit();
574
575        if ns == TypeNS {
576            // Duplicated types wreak havoc on other errors, like impls selecting the wrong
577            // type causing wrong number of generic params and other assorted number of
578            // irrelevant nonsense, so avoid advancing to the next compiler stage.
579            self.raise_fatal_after_resolve = true;
580        }
581        self.name_already_seen.insert(name, span);
582    }
583
584    /// This function adds a suggestion to change the binding name of a new import that conflicts
585    /// with an existing import.
586    ///
587    /// ```text,ignore (diagnostic)
588    /// help: you can use `as` to change the binding name of the import
589    ///    |
590    /// LL | use foo::bar as other_bar;
591    ///    |     ^^^^^^^^^^^^^^^^^^^^^
592    /// ```
593    fn add_suggestion_for_rename_of_use(
594        &self,
595        err: &mut Diag<'_>,
596        name: Symbol,
597        import: Import<'_>,
598        binding_span: Span,
599    ) {
600        let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
601            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("Other{0}", name))
    })format!("Other{name}")
602        } else {
603            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("other_{0}", name))
    })format!("other_{name}")
604        };
605
606        let mut suggestion = None;
607        let mut span = binding_span;
608        match import.kind {
609            ImportKind::Single { source, .. } => {
610                if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
611                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
612                    && pos as usize <= snippet.len()
613                {
614                    span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
615                        binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
616                    );
617                    suggestion = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" as {0}", suggested_name))
    })format!(" as {suggested_name}"));
618                }
619            }
620            ImportKind::ExternCrate { source, target, .. } => {
621                suggestion = Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("extern crate {0} as {1};",
                source.unwrap_or(target.name), suggested_name))
    })format!(
622                    "extern crate {} as {};",
623                    source.unwrap_or(target.name),
624                    suggested_name,
625                ))
626            }
627            _ => ::core::panicking::unreachable_default_msg()unreachable!(),
628        }
629
630        if let Some(suggestion) = suggestion {
631            err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
632        } else {
633            err.subdiagnostic(ChangeImportBinding { span });
634        }
635    }
636
637    /// This function adds a suggestion to remove an unnecessary binding from an import that is
638    /// nested. In the following example, this function will be invoked to remove the `a` binding
639    /// in the second use statement:
640    ///
641    /// ```ignore (diagnostic)
642    /// use issue_52891::a;
643    /// use issue_52891::{d, a, e};
644    /// ```
645    ///
646    /// The following suggestion will be added:
647    ///
648    /// ```ignore (diagnostic)
649    /// use issue_52891::{d, a, e};
650    ///                      ^-- help: remove unnecessary import
651    /// ```
652    ///
653    /// If the nested use contains only one import then the suggestion will remove the entire
654    /// line.
655    ///
656    /// It is expected that the provided import is nested - this isn't checked by the
657    /// function. If this invariant is not upheld, this function's behaviour will be unexpected
658    /// as characters expected by span manipulations won't be present.
659    fn add_suggestion_for_duplicate_nested_use(
660        &self,
661        err: &mut Diag<'_>,
662        import: Import<'_>,
663        binding_span: Span,
664    ) {
665        if !import.is_nested() {
    ::core::panicking::panic("assertion failed: import.is_nested()")
};assert!(import.is_nested());
666
667        // Two examples will be used to illustrate the span manipulations we're doing:
668        //
669        // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
670        //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.
671        // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
672        //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.
673
674        let (found_closing_brace, span) =
675            find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
676
677        // If there was a closing brace then identify the span to remove any trailing commas from
678        // previous imports.
679        if found_closing_brace {
680            if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
681                err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport { span });
682            } else {
683                // Remove the entire line if we cannot extend the span back, this indicates an
684                // `issue_52891::{self}` case.
685                err.subdiagnostic(diagnostics::RemoveUnnecessaryImport {
686                    span: import.use_span_with_attributes,
687                });
688            }
689
690            return;
691        }
692
693        err.subdiagnostic(diagnostics::RemoveUnnecessaryImport { span });
694    }
695
696    pub(crate) fn lint_if_path_starts_with_module(
697        &mut self,
698        finalize: Finalize,
699        path: &[Segment],
700        second_binding: Option<Decl<'_>>,
701    ) {
702        let Finalize { node_id, root_span, .. } = finalize;
703
704        let first_name = match path.get(0) {
705            // In the 2018 edition this lint is a hard error, so nothing to do
706            Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
707                seg.ident.name
708            }
709            _ => return,
710        };
711
712        // We're only interested in `use` paths which should start with
713        // `{{root}}` currently.
714        if first_name != kw::PathRoot {
715            return;
716        }
717
718        match path.get(1) {
719            // If this import looks like `crate::...` it's already good
720            Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
721            // Otherwise go below to see if it's an extern crate
722            Some(_) => {}
723            // If the path has length one (and it's `PathRoot` most likely)
724            // then we don't know whether we're gonna be importing a crate or an
725            // item in our crate. Defer this lint to elsewhere
726            None => return,
727        }
728
729        // If the first element of our path was actually resolved to an
730        // `ExternCrate` (also used for `crate::...`) then no need to issue a
731        // warning, this looks all good!
732        if let Some(binding) = second_binding
733            && let DeclKind::Import { import, .. } = binding.kind
734            // Careful: we still want to rewrite paths from renamed extern crates.
735            && let ImportKind::ExternCrate { source: None, .. } = import.kind
736        {
737            return;
738        }
739
740        self.lint_buffer.dyn_buffer_lint_any(
741            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
742            node_id,
743            root_span,
744            move |dcx, level, sess| {
745                let (replacement, applicability) = match sess
746                    .downcast_ref::<Session>()
747                    .expect("expected a `Session`")
748                    .source_map()
749                    .span_to_snippet(root_span)
750                {
751                    Ok(ref s) => {
752                        // FIXME(Manishearth) ideally the emitting code
753                        // can tell us whether or not this is global
754                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
755
756                        (::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
    })format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
757                    }
758                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
759                };
760                diagnostics::AbsPathWithModule {
761                    sugg: diagnostics::AbsPathWithModuleSugg {
762                        span: root_span,
763                        applicability,
764                        replacement,
765                    },
766                }
767                .into_diag(dcx, level)
768            },
769        );
770    }
771
772    pub(crate) fn add_module_candidates(
773        &self,
774        module: Module<'ra>,
775        names: &mut Vec<TypoSuggestion>,
776        filter_fn: &impl Fn(Res) -> bool,
777        ctxt: Option<SyntaxContext>,
778    ) {
779        module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
780            let res = binding.res();
781            if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
782                names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
783            }
784        });
785    }
786
787    /// Combines an error with provided span and emits it.
788    ///
789    /// This takes the error provided, combines it with the span and any additional spans inside the
790    /// error and emits it.
791    pub(crate) fn report_error(
792        &self,
793        span: Span,
794        resolution_error: ResolutionError<'ra>,
795    ) -> ErrorGuaranteed {
796        self.into_struct_error(span, resolution_error).emit_err()
797    }
798
799    pub(crate) fn into_struct_error(
800        &self,
801        span: Span,
802        resolution_error: ResolutionError<'ra>,
803    ) -> Diag<'_> {
804        match resolution_error {
805            ResolutionError::GenericParamsFromOuterItem {
806                outer_res,
807                has_generic_params,
808                def_kind,
809                inner_item,
810                current_self_ty,
811            } => {
812                use diagnostics::GenericParamsFromOuterItemLabel as Label;
813                let static_or_const = match def_kind {
814                    DefKind::Static { .. } => {
815                        Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Static)
816                    }
817                    DefKind::Const => {
818                        Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Const)
819                    }
820                    _ => None,
821                };
822                let is_self =
823                    #[allow(non_exhaustive_omitted_patterns)] match outer_res {
    Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => true,
    _ => false,
}matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
824                let mut err = diagnostics::GenericParamsFromOuterItem {
825                    span,
826                    label: None,
827                    refer_to_type_directly: None,
828                    use_let: None,
829                    sugg: None,
830                    static_or_const,
831                    is_self,
832                    item: inner_item.as_ref().map(|(label_span, _, kind)| {
833                        diagnostics::GenericParamsFromOuterItemInnerItem {
834                            span: *label_span,
835                            descr: kind.descr().to_string(),
836                            is_self,
837                        }
838                    }),
839                };
840
841                let sm = self.tcx.sess.source_map();
842                // Note: do not early return for missing def_id here,
843                // we still want to provide suggestions for `Res::SelfTyParam` and `Res::SelfTyAlias`.
844                let def_id = match outer_res {
845                    Res::SelfTyParam { .. } => {
846                        err.label = Some(Label::SelfTyParam(span));
847                        None
848                    }
849                    Res::SelfTyAlias { alias_to: def_id, .. } => {
850                        err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
851                            sm,
852                            self.def_span(def_id),
853                        )));
854                        err.refer_to_type_directly = current_self_ty
855                            .map(|snippet| diagnostics::UseTypeDirectly { span, snippet });
856                        None
857                    }
858                    Res::Def(DefKind::TyParam, def_id) => {
859                        err.label = Some(Label::TyParam(self.def_span(def_id)));
860                        Some(def_id)
861                    }
862                    Res::Def(DefKind::ConstParam, def_id) => {
863                        err.label = Some(Label::ConstParam(self.def_span(def_id)));
864                        Some(def_id)
865                    }
866                    _ => {
867                        ::rustc_span::macros::bug_impl(None,
    format_args!("GenericParamsFromOuterItem should only be used with Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or DefKind::ConstParam"),
    Location::caller());bug!(
868                            "GenericParamsFromOuterItem should only be used with \
869                            Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
870                            DefKind::ConstParam"
871                        );
872                    }
873                };
874
875                if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() {
876                    err.use_let = Some(diagnostics::GenericParamsFromOuterItemUseLet {
877                        span: sm.span_until_whitespace(*item_span),
878                    });
879                }
880
881                if let Some(def_id) = def_id
882                    && let HasGenericParams::Yes(span) = has_generic_params
883                    && !#[allow(non_exhaustive_omitted_patterns)] match inner_item {
    Some((_, _, ItemKind::Delegation(..))) => true,
    _ => false,
}matches!(inner_item, Some((_, _, ItemKind::Delegation(..))))
884                {
885                    let name = self.tcx.item_name(def_id);
886                    let (span, snippet) = if span.is_empty() {
887                        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("<{0}>", name))
    })format!("<{name}>");
888                        (span, snippet)
889                    } else {
890                        let span = sm.span_through_char(span, '<').shrink_to_hi();
891                        let snippet = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}, ", name))
    })format!("{name}, ");
892                        (span, snippet)
893                    };
894                    err.sugg = Some(diagnostics::GenericParamsFromOuterItemSugg { span, snippet });
895                }
896
897                self.dcx().create_err(err)
898            }
899            ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
900                self.dcx().create_err(diagnostics::NameAlreadyUsedInParameterList {
901                    span,
902                    first_use_span,
903                    name,
904                })
905            }
906            ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
907                self.dcx().create_err(diagnostics::MethodNotMemberOfTrait {
908                    span,
909                    method,
910                    trait_,
911                    sub: candidate.map(|c| diagnostics::AssociatedFnWithSimilarNameExists {
912                        span: method.span,
913                        candidate: c,
914                    }),
915                })
916            }
917            ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
918                self.dcx().create_err(diagnostics::TypeNotMemberOfTrait {
919                    span,
920                    type_,
921                    trait_,
922                    sub: candidate.map(|c| diagnostics::AssociatedTypeWithSimilarNameExists {
923                        span: type_.span,
924                        candidate: c,
925                    }),
926                })
927            }
928            ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
929                self.dcx().create_err(diagnostics::ConstNotMemberOfTrait {
930                    span,
931                    const_,
932                    trait_,
933                    sub: candidate.map(|c| diagnostics::AssociatedConstWithSimilarNameExists {
934                        span: const_.span,
935                        candidate: c,
936                    }),
937                })
938            }
939            ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
940                let BindingError { name, target, origin, could_be_path } = binding_error;
941
942                let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
943                target_sp.sort_by_key(|sp| sp.lo_hi());
944                target_sp.dedup_by_key(|sp| sp.lo_hi());
945                let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
946                origin_sp.sort_by_key(|sp| sp.lo_hi());
947                origin_sp.dedup_by_key(|sp| sp.lo_hi());
948
949                let msp = MultiSpan::from_spans(target_sp.clone());
950                let mut err = self.dcx().create_err(diagnostics::VariableIsNotBoundInAllPatterns {
951                    multispan: msp,
952                    name,
953                });
954                for sp in target_sp {
955                    err.subdiagnostic(diagnostics::PatternDoesntBindName { span: sp, name });
956                }
957                for sp in &origin_sp {
958                    err.subdiagnostic(diagnostics::VariableNotInAllPatterns { span: *sp });
959                }
960                let mut suggested_typo = false;
961                if !target.iter().all(|pat| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
    ast::PatKind::Ident(..) => true,
    _ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
962                    && !origin.iter().all(|(_, pat)| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
    ast::PatKind::Ident(..) => true,
    _ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
963                {
964                    // The check above is so that when we encounter `match foo { (a | b) => {} }`,
965                    // we don't suggest `(a | a) => {}`, which would never be what the user wants.
966                    let mut target_visitor = BindingVisitor::default();
967                    for pat in &target {
968                        target_visitor.visit_pat(pat);
969                    }
970                    target_visitor.identifiers.sort();
971                    target_visitor.identifiers.dedup();
972                    let mut origin_visitor = BindingVisitor::default();
973                    for (_, pat) in &origin {
974                        origin_visitor.visit_pat(pat);
975                    }
976                    origin_visitor.identifiers.sort();
977                    origin_visitor.identifiers.dedup();
978                    // Find if the binding could have been a typo
979                    if let Some(typo) =
980                        find_best_match_for_name(&target_visitor.identifiers, name.name, None)
981                        && !origin_visitor.identifiers.contains(&typo)
982                    {
983                        err.subdiagnostic(diagnostics::PatternBindingTypo {
984                            spans: origin_sp,
985                            typo,
986                        });
987                        suggested_typo = true;
988                    }
989                }
990                if could_be_path {
991                    let import_suggestions = self.lookup_import_candidates(
992                        name,
993                        Namespace::ValueNS,
994                        &parent_scope,
995                        &|res: Res| {
996                            #[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!(
997                                res,
998                                Res::Def(
999                                    DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
1000                                        | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
1001                                        | DefKind::Const
1002                                        | DefKind::AssocConst,
1003                                    _,
1004                                )
1005                            )
1006                        },
1007                    );
1008
1009                    if import_suggestions.is_empty() && !suggested_typo {
1010                        let kind_matches: [fn(DefKind) -> bool; 4] = [
1011                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => true,
    _ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
1012                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => true,
    _ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
1013                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::Const => true,
    _ => false,
}matches!(kind, DefKind::Const),
1014                            |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
    DefKind::AssocConst => true,
    _ => false,
}matches!(kind, DefKind::AssocConst),
1015                        ];
1016                        let mut local_names = ::alloc::vec::Vec::new()vec![];
1017                        self.add_module_candidates(
1018                            parent_scope.module,
1019                            &mut local_names,
1020                            &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(_, _) => true,
    _ => false,
}matches!(res, Res::Def(_, _)),
1021                            None,
1022                        );
1023                        let local_names: FxHashSet<_> = local_names
1024                            .into_iter()
1025                            .filter_map(|s| match s.res {
1026                                Res::Def(_, def_id) => Some(def_id),
1027                                _ => None,
1028                            })
1029                            .collect();
1030
1031                        let mut local_suggestions = ::alloc::vec::Vec::new()vec![];
1032                        let mut suggestions = ::alloc::vec::Vec::new()vec![];
1033                        for matches_kind in kind_matches {
1034                            if let Some(suggestion) = self.early_lookup_typo_candidate(
1035                                ScopeSet::All(Namespace::ValueNS),
1036                                &parent_scope,
1037                                name,
1038                                &|res: Res| match res {
1039                                    Res::Def(k, _) => matches_kind(k),
1040                                    _ => false,
1041                                },
1042                                &|_| true,
1043                            ) && let Res::Def(kind, mut def_id) = suggestion.res
1044                            {
1045                                if let DefKind::Ctor(_, _) = kind {
1046                                    def_id = self.tcx.parent(def_id);
1047                                }
1048                                let kind = kind.descr(def_id);
1049                                if local_names.contains(&def_id) {
1050                                    // The item is available in the current scope. Very likely to
1051                                    // be a typo. Don't use the full path.
1052                                    local_suggestions.push((
1053                                        suggestion.candidate,
1054                                        suggestion.candidate.to_string(),
1055                                        kind,
1056                                    ));
1057                                } else {
1058                                    suggestions.push((
1059                                        suggestion.candidate,
1060                                        self.def_path_str(def_id),
1061                                        kind,
1062                                    ));
1063                                }
1064                            }
1065                        }
1066                        let suggestions = if !local_suggestions.is_empty() {
1067                            // There is at least one item available in the current scope that is a
1068                            // likely typo. We only show those.
1069                            local_suggestions
1070                        } else {
1071                            suggestions
1072                        };
1073                        for (name, sugg, kind) in suggestions {
1074                            err.span_suggestion_verbose(
1075                                span,
1076                                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might have meant to use the similarly named {0} `{1}`",
                kind, name))
    })format!(
1077                                    "you might have meant to use the similarly named {kind} `{name}`",
1078                                ),
1079                                sugg,
1080                                Applicability::MaybeIncorrect,
1081                            );
1082                            suggested_typo = true;
1083                        }
1084                    }
1085                    if import_suggestions.is_empty() && !suggested_typo {
1086                        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!(
1087                            "if you meant to match on a unit struct, unit variant or a `const` \
1088                             item, consider making the path in the pattern qualified: \
1089                             `path::to::ModOrType::{name}`",
1090                        );
1091                        err.span_help(span, help_msg);
1092                    }
1093                    show_candidates(
1094                        self.tcx,
1095                        &mut err,
1096                        Some(span),
1097                        &import_suggestions,
1098                        Instead::No,
1099                        FoundUse::Yes,
1100                        DiagMode::Pattern,
1101                        ::alloc::vec::Vec::new()vec![],
1102                        "",
1103                    );
1104                }
1105                err
1106            }
1107            ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
1108                self.dcx().create_err(diagnostics::VariableBoundWithDifferentMode {
1109                    span,
1110                    first_binding_span,
1111                    variable_name,
1112                })
1113            }
1114            ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
1115                self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInParameterList {
1116                    span,
1117                    identifier,
1118                })
1119            }
1120            ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
1121                self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInSamePattern {
1122                    span,
1123                    identifier,
1124                })
1125            }
1126            ResolutionError::UndeclaredLabel { name, suggestion } => {
1127                let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
1128                {
1129                    // A reachable label with a similar name exists.
1130                    Some((ident, true)) => (
1131                        (
1132                            Some(diagnostics::LabelWithSimilarNameReachable(ident.span)),
1133                            Some(diagnostics::TryUsingSimilarlyNamedLabel {
1134                                span,
1135                                ident_name: ident.name,
1136                            }),
1137                        ),
1138                        None,
1139                    ),
1140                    // An unreachable label with a similar name exists.
1141                    Some((ident, false)) => (
1142                        (None, None),
1143                        Some(diagnostics::UnreachableLabelWithSimilarNameExists {
1144                            ident_span: ident.span,
1145                        }),
1146                    ),
1147                    // No similarly-named labels exist.
1148                    None => ((None, None), None),
1149                };
1150                self.dcx().create_err(diagnostics::UndeclaredLabel {
1151                    span,
1152                    name,
1153                    sub_reachable,
1154                    sub_reachable_suggestion,
1155                    sub_unreachable,
1156                })
1157            }
1158            ResolutionError::FailedToResolve {
1159                segment,
1160                label,
1161                suggestion,
1162                help,
1163                module,
1164                message,
1165            } => {
1166                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}");
1167                err.span_label(span, label);
1168
1169                if let Some((suggestions, msg, applicability)) = suggestion {
1170                    if suggestions.is_empty() {
1171                        err.help(msg);
1172                        return err;
1173                    }
1174                    err.multipart_suggestion(msg, suggestions, applicability);
1175                }
1176
1177                if let Some(help) = help {
1178                    err.help(help);
1179                }
1180
1181                let module = match module {
1182                    Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
1183                    _ => CRATE_DEF_ID.to_def_id(),
1184                };
1185                self.find_cfg_stripped(&mut err, &segment, module);
1186
1187                err
1188            }
1189            ResolutionError::CannotCaptureDynamicEnvironmentInFnItem { suggest_closure } => {
1190                self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem {
1191                    span,
1192                    suggest_closure,
1193                })
1194            }
1195            ResolutionError::AttemptToUseNonConstantValueInConstant {
1196                ident,
1197                suggestion,
1198                current,
1199                type_span,
1200                requires_type,
1201            } => {
1202                // let foo =...
1203                //     ^^^ given this Span
1204                // ------- get this Span to have an applicable suggestion
1205
1206                // edit:
1207                // only do this if the const and usage of the non-constant value are on the same line
1208                // the further the two are apart, the higher the chance of the suggestion being wrong
1209
1210                let sp = self
1211                    .tcx
1212                    .sess
1213                    .source_map()
1214                    .span_extend_to_prev_str(ident.span, current, true, false);
1215
1216                let (with, with_label, without) = match sp {
1217                    Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
1218                        let sp = sp
1219                            .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
1220                            .until(ident.span);
1221
1222                        // Only suggest replacing the binding keyword if this is a simple
1223                        // binding.
1224                        //
1225                        // Note: this approach still incorrectly suggests for irrefutable
1226                        // patterns like `if let x = 1 { const { x } }`, since the text
1227                        // between `let` and the identifier is just whitespace.
1228                        // See tests/ui/consts/non-const-value-in-const-irrefutable-pat-binding.rs
1229                        let is_simple_binding =
1230                            self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {
1231                                let after_keyword = snippet[current.len()..].trim();
1232                                after_keyword.is_empty() || after_keyword == "mut"
1233                            });
1234
1235                        if is_simple_binding {
1236                            (
1237                                Some(match requires_type {
1238                                    ConstantRequiresType::Usize => {
1239                                        diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Usize {
1240                                            span: sp,
1241                                            suggestion,
1242                                            current,
1243                                            type_span,
1244                                        }
1245                                    }
1246                                    ConstantRequiresType::No => {
1247                                        diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion::Placeholder {
1248                                            span: sp,
1249                                            suggestion,
1250                                            current,
1251                                            type_span,
1252                                        }
1253                                    }
1254                                }),
1255                                Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1256                                None,
1257                            )
1258                        } else {
1259                            (
1260                                None,
1261                                Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1262                                None,
1263                            )
1264                        }
1265                    }
1266                    _ => (
1267                        None,
1268                        None,
1269                        Some(
1270                            diagnostics::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
1271                                ident_span: ident.span,
1272                                suggestion,
1273                            },
1274                        ),
1275                    ),
1276                };
1277
1278                self.dcx().create_err(diagnostics::AttemptToUseNonConstantValueInConstant {
1279                    span,
1280                    with,
1281                    with_label,
1282                    without,
1283                })
1284            }
1285            ResolutionError::BindingShadowsSomethingUnacceptable {
1286                shadowing_binding,
1287                name,
1288                participle,
1289                article,
1290                shadowed_binding,
1291                shadowed_binding_span,
1292            } => self.dcx().create_err(diagnostics::BindingShadowsSomethingUnacceptable {
1293                span,
1294                shadowing_binding,
1295                shadowed_binding,
1296                article,
1297                sub_suggestion: match (shadowing_binding, shadowed_binding) {
1298                    (
1299                        PatternSource::Match,
1300                        Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
1301                    ) => Some(diagnostics::BindingShadowsSomethingUnacceptableSuggestion {
1302                        span,
1303                        name,
1304                    }),
1305                    _ => None,
1306                },
1307                shadowed_binding_span,
1308                participle,
1309                name,
1310            }),
1311            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
1312                ForwardGenericParamBanReason::Default => {
1313                    self.dcx().create_err(diagnostics::ForwardDeclaredGenericParam { param, span })
1314                }
1315                ForwardGenericParamBanReason::ConstParamTy => self
1316                    .dcx()
1317                    .create_err(diagnostics::ForwardDeclaredGenericInConstParamTy { param, span }),
1318            },
1319            ResolutionError::ParamInTyOfConstParam { name } => {
1320                self.dcx().create_err(diagnostics::ParamInTyOfConstParam { span, name })
1321            }
1322            ResolutionError::SelfInConstParam => {
1323                self.dcx().create_err(diagnostics::SelfInConstGenericTy {
1324                    span,
1325                    enable_feature: self.tcx().sess.is_nightly_build(),
1326                })
1327            }
1328            ResolutionError::ParamInNonTrivialAnonConst {
1329                is_gca_const_items,
1330                name,
1331                param_kind,
1332            } => self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst {
1333                span,
1334                name,
1335                param_kind,
1336                help: self.tcx.sess.is_nightly_build() && !self.tcx.features().gca(),
1337                is_gca_const_items,
1338                help_gca: is_gca_const_items,
1339                help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca_const_items,
1340            }),
1341            ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => {
1342                self.dcx().create_err(diagnostics::ParamInEnumDiscriminant {
1343                    span,
1344                    name,
1345                    param_kind: is_type,
1346                })
1347            }
1348            ResolutionError::ForwardDeclaredSelf(reason) => match reason {
1349                ForwardGenericParamBanReason::Default => {
1350                    self.dcx().create_err(diagnostics::SelfInGenericParamDefault { span })
1351                }
1352                ForwardGenericParamBanReason::ConstParamTy => self
1353                    .dcx()
1354                    .create_err(diagnostics::SelfInConstGenericTy { span, enable_feature: false }),
1355            },
1356            ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
1357                let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
1358                    match suggestion {
1359                        // A reachable label with a similar name exists.
1360                        Some((ident, true)) => (
1361                            (
1362                                Some(diagnostics::UnreachableLabelSubLabel {
1363                                    ident_span: ident.span,
1364                                }),
1365                                Some(diagnostics::UnreachableLabelSubSuggestion {
1366                                    span,
1367                                    // intentionally taking 'ident.name' instead of 'ident' itself, as this
1368                                    // could be used in suggestion context
1369                                    ident_name: ident.name,
1370                                }),
1371                            ),
1372                            None,
1373                        ),
1374                        // An unreachable label with a similar name exists.
1375                        Some((ident, false)) => (
1376                            (None, None),
1377                            Some(diagnostics::UnreachableLabelSubLabelUnreachable {
1378                                ident_span: ident.span,
1379                            }),
1380                        ),
1381                        // No similarly-named labels exist.
1382                        None => ((None, None), None),
1383                    };
1384                self.dcx().create_err(diagnostics::UnreachableLabel {
1385                    span,
1386                    name,
1387                    definition_span,
1388                    sub_suggestion,
1389                    sub_suggestion_label,
1390                    sub_unreachable_label,
1391                })
1392            }
1393            ResolutionError::TraitImplMismatch {
1394                name,
1395                kind,
1396                code,
1397                trait_item_span,
1398                trait_path,
1399                trait_span,
1400                impl_span,
1401            } => self
1402                .dcx()
1403                .create_err(diagnostics::TraitImplMismatch {
1404                    span,
1405                    name,
1406                    kind,
1407                    trait_path,
1408                    trait_item_span,
1409                    trait_span,
1410                    impl_span,
1411                })
1412                .with_code(code),
1413            ResolutionError::TraitImplDuplicate {
1414                name,
1415                trait_item_span,
1416                old_span,
1417                trait_span,
1418                impl_span,
1419            } => self.dcx().create_err(diagnostics::TraitImplDuplicate {
1420                span,
1421                name,
1422                trait_item_span,
1423                trait_span,
1424                impl_span,
1425                old_span,
1426            }),
1427            ResolutionError::InvalidAsmSym => {
1428                self.dcx().create_err(diagnostics::InvalidAsmSym { span })
1429            }
1430            ResolutionError::LowercaseSelf => {
1431                self.dcx().create_err(diagnostics::LowercaseSelf { span })
1432            }
1433            ResolutionError::BindingInNeverPattern => {
1434                self.dcx().create_err(diagnostics::BindingInNeverPattern { span })
1435            }
1436            ResolutionError::CannotUseInnerLocalInMoveExpr {
1437                move_expr_span,
1438                ident,
1439                scope_span,
1440            } => self.dcx().create_err(diagnostics::CannotUseInnerLocalInMoveExpr {
1441                span,
1442                ident,
1443                binding_span: ident.span,
1444                move_expr_span,
1445                scope_span,
1446            }),
1447        }
1448    }
1449
1450    pub(crate) fn report_vis_error(
1451        &mut self,
1452        vis_resolution_error: VisResolutionError,
1453    ) -> ErrorGuaranteed {
1454        match vis_resolution_error {
1455            VisResolutionError::Relative2018(span, path) => {
1456                self.dcx().create_err(diagnostics::Relative2018 {
1457                    span,
1458                    path_span: path.span,
1459                    // intentionally converting to String, as the text would also be used as
1460                    // in suggestion context
1461                    path_str: pprust::path_to_string(&path),
1462                })
1463            }
1464            VisResolutionError::AncestorOnly(span) => {
1465                self.dcx().create_err(diagnostics::AncestorOnly(span))
1466            }
1467            VisResolutionError::FailedToResolve {
1468                span,
1469                segment,
1470                label,
1471                suggestion,
1472                help,
1473                message,
1474            } => self.into_struct_error(
1475                span,
1476                ResolutionError::FailedToResolve {
1477                    segment,
1478                    label,
1479                    suggestion,
1480                    help,
1481                    module: None,
1482                    message,
1483                },
1484            ),
1485            VisResolutionError::ExpectedFound(span, path_str, res) => {
1486                self.dcx().create_err(diagnostics::ExpectedModuleFound { span, res, path_str })
1487            }
1488            VisResolutionError::Indeterminate(span) => {
1489                self.dcx().create_err(diagnostics::Indeterminate(span))
1490            }
1491            VisResolutionError::ModuleOnly(span) => {
1492                self.dcx().create_err(diagnostics::ModuleOnly(span))
1493            }
1494        }
1495        .emit_err()
1496    }
1497
1498    pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
1499        // We can't use `def_path_str` in resolve.
1500        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];
1501        while let Some(parent) = self.tcx.opt_parent(def_id) {
1502            def_id = parent;
1503            path.push(def_id);
1504            if def_id.is_top_level_module() {
1505                break;
1506            }
1507        }
1508        // We will only suggest importing directly if it is accessible through that path.
1509        path.into_iter()
1510            .rev()
1511            .map(|def_id| {
1512                self.tcx
1513                    .opt_item_name(def_id)
1514                    .map(|name| {
1515                        match (
1516                            def_id.is_top_level_module(),
1517                            def_id.is_local(),
1518                            self.tcx.sess.edition(),
1519                        ) {
1520                            (true, true, Edition::Edition2015) => String::new(),
1521                            (true, true, _) => kw::Crate.to_string(),
1522                            (true, false, _) | (false, _, _) => name.to_string(),
1523                        }
1524                    })
1525                    .unwrap_or_else(|| "_".to_string())
1526            })
1527            .collect::<Vec<String>>()
1528            .join("::")
1529    }
1530
1531    pub(crate) fn add_scope_set_candidates(
1532        &self,
1533        suggestions: &mut Vec<TypoSuggestion>,
1534        scope_set: ScopeSet<'ra>,
1535        ps: &ParentScope<'ra>,
1536        sp: Span,
1537        filter_fn: &impl Fn(Res) -> bool,
1538    ) {
1539        let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
1540        self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
1541            match scope {
1542                Scope::DeriveHelpers(expn_id) => {
1543                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
1544                    if filter_fn(res) {
1545                        suggestions.extend(this.helper_attrs.get(&expn_id).into_flat_iter().map(
1546                            |&(ident, orig_ident_span, _)| {
1547                                TypoSuggestion::new(ident.name, orig_ident_span, res)
1548                            },
1549                        ));
1550                    }
1551                }
1552                Scope::DeriveHelpersCompat => {
1553                    // Never recommend deprecated helper attributes.
1554                }
1555                Scope::MacroRules(macro_rules_scope) => {
1556                    if let MacroRulesScope::Def(macro_rules_def) = *macro_rules_scope.read() {
1557                        let res = macro_rules_def.decl.res();
1558                        if filter_fn(res) {
1559                            suggestions.push(TypoSuggestion::new(
1560                                macro_rules_def.ident.name,
1561                                macro_rules_def.orig_ident_span,
1562                                res,
1563                            ))
1564                        }
1565                    }
1566                }
1567                Scope::ModuleNonGlobs(module, _) => {
1568                    this.add_module_candidates(module, suggestions, filter_fn, None);
1569                }
1570                Scope::ModuleGlobs(..) => {
1571                    // Already handled in `ModuleNonGlobs`.
1572                }
1573                Scope::MacroUsePrelude => {
1574                    suggestions.extend(this.macro_use_prelude.iter().filter_map(
1575                        |(name, binding)| {
1576                            let res = binding.res();
1577                            filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1578                        },
1579                    ));
1580                }
1581                Scope::BuiltinAttrs => {
1582                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
1583                    if filter_fn(res) {
1584                        suggestions.extend(
1585                            BUILTIN_ATTRIBUTES
1586                                .iter()
1587                                .map(|attr| TypoSuggestion::typo_from_name(*attr, res)),
1588                        );
1589                    }
1590                }
1591                Scope::ExternPreludeItems => {
1592                    // Add idents from both item and flag scopes.
1593                    suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
1594                        let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1595                        filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
1596                    }));
1597                }
1598                Scope::ExternPreludeFlags => {}
1599                Scope::ToolAttributePrelude => {
1600                    let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1601                    suggestions.extend(
1602                        this.registered_attr_tools
1603                            .iter()
1604                            .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
1605                    );
1606                }
1607                Scope::StdLibPrelude => {
1608                    if let Some(prelude) = this.prelude {
1609                        let mut tmp_suggestions = Vec::new();
1610                        this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1611                        suggestions.extend(
1612                            tmp_suggestions
1613                                .into_iter()
1614                                .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
1615                        );
1616                    }
1617                }
1618                Scope::BuiltinTypes => {
1619                    suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1620                        let res = Res::PrimTy(*prim_ty);
1621                        filter_fn(res)
1622                            .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1623                    }))
1624                }
1625            }
1626
1627            ControlFlow::<()>::Continue(())
1628        });
1629    }
1630
1631    /// Lookup typo candidate in scope for a macro or import.
1632    fn early_lookup_typo_candidate(
1633        &self,
1634        scope_set: ScopeSet<'ra>,
1635        parent_scope: &ParentScope<'ra>,
1636        ident: Ident,
1637        filter_fn: &impl Fn(Res) -> bool,
1638        suggestion_filter: &impl Fn(&TypoSuggestion) -> bool,
1639    ) -> Option<TypoSuggestion> {
1640        let mut suggestions = Vec::new();
1641        self.add_scope_set_candidates(
1642            &mut suggestions,
1643            scope_set,
1644            parent_scope,
1645            ident.span,
1646            filter_fn,
1647        );
1648
1649        // Some candidates cannot be decided from the `Res` alone (e.g. they need
1650        // re-resolution or visibility checks), filter them out before picking the
1651        // best name match.
1652        suggestions.retain(suggestion_filter);
1653
1654        // Make sure error reporting is deterministic.
1655        suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
1656
1657        match find_best_match_for_name(
1658            &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1659            ident.name,
1660            None,
1661        ) {
1662            Some(found) if found != ident.name => {
1663                suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1664            }
1665            _ => None,
1666        }
1667    }
1668
1669    fn lookup_import_candidates_from_module<FilterFn>(
1670        &self,
1671        lookup_ident: Ident,
1672        namespace: Namespace,
1673        parent_scope: &ParentScope<'ra>,
1674        start_module: Module<'ra>,
1675        crate_path: ThinVec<ast::PathSegment>,
1676        filter_fn: FilterFn,
1677    ) -> Vec<ImportSuggestion>
1678    where
1679        FilterFn: Fn(Res) -> bool,
1680    {
1681        let mut candidates = Vec::new();
1682        let mut seen_modules = FxHashSet::default();
1683        let start_did = start_module.def_id();
1684        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![(
1685            start_module,
1686            ThinVec::<ast::PathSegment>::new(),
1687            true,
1688            start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1689            true,
1690        )];
1691        let mut worklist_via_import = ::alloc::vec::Vec::new()vec![];
1692
1693        while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1694            match worklist.pop() {
1695                None => worklist_via_import.pop(),
1696                Some(x) => Some(x),
1697            }
1698        {
1699            let in_module_is_extern = !in_module.def_id().is_local();
1700            in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
1701                // Avoid non-importable candidates.
1702                if name_binding.is_assoc_item()
1703                    && !this.features.import_trait_associated_functions()
1704                {
1705                    return;
1706                }
1707
1708                if ident.name == kw::Underscore {
1709                    return;
1710                }
1711
1712                let child_accessible =
1713                    accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);
1714
1715                // do not venture inside inaccessible items of other crates
1716                if in_module_is_extern && !child_accessible {
1717                    return;
1718                }
1719
1720                let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1721
1722                // There is an assumption elsewhere that paths of variants are in the enum's
1723                // declaration and not imported. With this assumption, the variant component is
1724                // chopped and the rest of the path is assumed to be the enum's own path. For
1725                // errors where a variant is used as the type instead of the enum, this causes
1726                // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
1727                if via_import && name_binding.is_possibly_imported_variant() {
1728                    return;
1729                }
1730
1731                // #90113: Do not count an inaccessible reexported item as a candidate.
1732                if let DeclKind::Import { source_decl, .. } = name_binding.kind
1733                    && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1734                    && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
1735                {
1736                    return;
1737                }
1738
1739                let res = name_binding.res();
1740                let did = match res {
1741                    Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
1742                    _ => res.opt_def_id(),
1743                };
1744                let child_doc_visible = doc_visible
1745                    && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));
1746
1747                let mk_path = |target_name| {
1748                    // create the path
1749                    let mut segms = if lookup_ident.span.at_least_rust_2018() {
1750                        // crate-local absolute paths start with `crate::` in edition 2018
1751                        // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
1752                        crate_path.clone()
1753                    } else {
1754                        ThinVec::new()
1755                    };
1756                    segms.append(&mut path_segments.clone());
1757
1758                    segms.push(ast::PathSegment::from_ident(Ident::new(
1759                        target_name,
1760                        orig_ident_span,
1761                    )));
1762                    Path { span: name_binding.span, segments: segms }
1763                };
1764                if let DeclKind::Import { import, source_decl, .. } = name_binding.kind
1765                    && let ImportKind::Single { source, target, .. } = import.kind
1766                    && source != target
1767                    && source.name == lookup_ident.name
1768                    && ns == namespace
1769                    && ident.ctxt.is_root()
1770                    && filter_fn(res)
1771                    && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1772                    && this.is_accessible_from(name_binding.vis(), parent_scope.module)
1773                    && !#[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Err | Res::SelfTyAlias { .. } | Res::SelfTyParam { .. } => true,
    _ => false,
}matches!(res, Res::Err | Res::SelfTyAlias { .. } | Res::SelfTyParam { .. })
1774                    && lookup_ident.name != kw::SelfLower
1775                    && lookup_ident.name != kw::SelfUpper
1776                {
1777                    // Detect we've already imported the item with a different name.
1778                    candidates.push(ImportSuggestion {
1779                        did,
1780                        descr: res.descr(),
1781                        path: mk_path(target.name),
1782                        accessible: child_accessible,
1783                        doc_visible: child_doc_visible,
1784                        note: None,
1785                        via_import,
1786                        is_stable,
1787                    });
1788                }
1789
1790                // collect results based on the filter function
1791                // avoid suggesting anything from the same module in which we are resolving
1792                // avoid suggesting anything with a hygienic name
1793                if ident.name == lookup_ident.name
1794                    && ns == namespace
1795                    && in_module != parent_scope.module
1796                    && ident.ctxt.is_root()
1797                    && filter_fn(res)
1798                    && !#[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Err | Res::SelfTyAlias { .. } | Res::SelfTyParam { .. } => true,
    _ => false,
}matches!(res, Res::Err | Res::SelfTyAlias { .. } | Res::SelfTyParam { .. })
1799                {
1800                    let path = mk_path(ident.name);
1801
1802                    if child_accessible
1803                        // Remove invisible match if exists
1804                        && let Some(idx) = candidates
1805                            .iter()
1806                            .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1807                    {
1808                        candidates.remove(idx);
1809                    }
1810
1811                    let is_stable = if is_stable
1812                        && let Some(did) = did
1813                        && this.is_stable(did, path.span)
1814                    {
1815                        true
1816                    } else {
1817                        false
1818                    };
1819
1820                    // Rreplace unstable suggestions if we meet a new stable one,
1821                    // and do nothing if any other situation. For example, if we
1822                    // meet `std::ops::Range` after `std::range::legacy::Range`,
1823                    // we will remove the latter and then insert the former.
1824                    if is_stable
1825                        && let Some(idx) = candidates
1826                            .iter()
1827                            .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1828                    {
1829                        candidates.remove(idx);
1830                    }
1831
1832                    if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1833                        // See if we're recommending TryFrom, TryInto, or FromIterator and add
1834                        // a note about editions
1835                        let note = if let Some(did) = did {
1836                            let requires_note = !did.is_local()
1837                                && {
        {
            'done:
                {
                for i in ::rustc_attr_ir::HasAttrs::get_attrs(did, &this.tcx)
                    {
                    #[allow(unused_imports)]
                    use ::rustc_attr_ir::AttributeKind::*;
                    let i: &::rustc_attr_ir::Attribute = i;
                    match i {
                        ::rustc_attr_ir::Attribute::Parsed(RustcDiagnosticItem(sym::TryInto
                            | sym::TryFrom | sym::FromIterator)) => {
                            break 'done Some(());
                        }
                        ::rustc_attr_ir::Attribute::Tool(..) |
                            ::rustc_attr_ir::Attribute::DeriveHelper(..) =>
                            {}
                            #[deny(unreachable_patterns)]
                            _ => {}
                    }
                }
                None
            }
        }
    }.is_some()find_attr!(
1838                                    this.tcx,
1839                                    did,
1840                                    RustcDiagnosticItem(
1841                                        sym::TryInto | sym::TryFrom | sym::FromIterator
1842                                    )
1843                                );
1844                            requires_note.then(|| {
1845                                ::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!(
1846                                    "'{}' is included in the prelude starting in Edition 2021",
1847                                    path_names_to_string(&path)
1848                                )
1849                            })
1850                        } else {
1851                            None
1852                        };
1853
1854                        candidates.push(ImportSuggestion {
1855                            did,
1856                            descr: res.descr(),
1857                            path,
1858                            accessible: child_accessible,
1859                            doc_visible: child_doc_visible,
1860                            note,
1861                            via_import,
1862                            is_stable,
1863                        });
1864                    }
1865                }
1866
1867                // collect submodules to explore
1868                if let Some(def_id) = name_binding.res().module_like_def_id() {
1869                    // form the path
1870                    let mut path_segments = path_segments.clone();
1871                    path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1872
1873                    let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
1874                        && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
1875                        && import.parent_scope.expansion == parent_scope.expansion
1876                    {
1877                        true
1878                    } else {
1879                        false
1880                    };
1881
1882                    let is_extern_crate_that_also_appears_in_prelude =
1883                        name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
1884
1885                    if !is_extern_crate_that_also_appears_in_prelude || alias_import {
1886                        // add the module to the lookup
1887                        if seen_modules.insert(def_id) {
1888                            if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1889                                (
1890                                    this.expect_module(def_id),
1891                                    path_segments,
1892                                    child_accessible,
1893                                    child_doc_visible,
1894                                    is_stable && this.is_stable(def_id, name_binding.span),
1895                                ),
1896                            );
1897                        }
1898                    }
1899                }
1900            })
1901        }
1902
1903        candidates
1904    }
1905
1906    fn is_stable(&self, did: DefId, span: Span) -> bool {
1907        if did.is_local() {
1908            return true;
1909        }
1910
1911        match self.tcx.lookup_stability(did) {
1912            Some(Stability {
1913                level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
1914            }) => {
1915                if span.allows_unstable(feature) {
1916                    true
1917                } else if self.features.enabled(feature) {
1918                    true
1919                } else if let Some(implied_by) = implied_by
1920                    && self.features.enabled(implied_by)
1921                {
1922                    true
1923                } else {
1924                    false
1925                }
1926            }
1927            Some(_) => true,
1928            None => false,
1929        }
1930    }
1931
1932    /// When name resolution fails, this method can be used to look up candidate
1933    /// entities with the expected name. It allows filtering them using the
1934    /// supplied predicate (which should be used to only accept the types of
1935    /// definitions expected, e.g., traits). The lookup spans across all crates.
1936    ///
1937    /// N.B., the method does not look into imports, but this is not a problem,
1938    /// since we report the definitions (thus, the de-aliased imports).
1939    pub(crate) fn lookup_import_candidates<FilterFn>(
1940        &self,
1941        lookup_ident: Ident,
1942        namespace: Namespace,
1943        parent_scope: &ParentScope<'ra>,
1944        filter_fn: FilterFn,
1945    ) -> Vec<ImportSuggestion>
1946    where
1947        FilterFn: Fn(Res) -> bool,
1948    {
1949        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))];
1950        let mut suggestions = self.lookup_import_candidates_from_module(
1951            lookup_ident,
1952            namespace,
1953            parent_scope,
1954            self.graph_root.to_module(),
1955            crate_path,
1956            &filter_fn,
1957        );
1958
1959        if lookup_ident.span.at_least_rust_2018() {
1960            for (ident, entry) in &self.extern_prelude {
1961                if entry.span().from_expansion() {
1962                    // Idents are adjusted to the root context before being
1963                    // resolved in the extern prelude, so reporting this to the
1964                    // user is no help. This skips the injected
1965                    // `extern crate std` in the 2018 edition, which would
1966                    // otherwise cause duplicate suggestions.
1967                    continue;
1968                }
1969                let Some(crate_id) =
1970                    self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
1971                else {
1972                    continue;
1973                };
1974
1975                let crate_def_id = crate_id.as_def_id();
1976                let crate_root = self.expect_module(crate_def_id);
1977
1978                // Check if there's already an item in scope with the same name as the crate.
1979                // If so, we have to disambiguate the potential import suggestions by making
1980                // the paths *global* (i.e., by prefixing them with `::`).
1981                let needs_disambiguation =
1982                    self.resolutions(parent_scope.module).iter().any(|(key, name_resolution)| {
1983                        if key.ns == TypeNS
1984                            && key.ident == *ident
1985                            && let Some(decl) = name_resolution.borrow_checked(self).best_decl()
1986                        {
1987                            match decl.res() {
1988                                // No disambiguation needed if the identically named item we
1989                                // found in scope actually refers to the crate in question.
1990                                Res::Def(_, def_id) => def_id != crate_def_id,
1991                                Res::PrimTy(_) => true,
1992                                _ => false,
1993                            }
1994                        } else {
1995                            false
1996                        }
1997                    });
1998                let mut crate_path = ThinVec::new();
1999                if needs_disambiguation {
2000                    crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
2001                }
2002                crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
2003
2004                suggestions.extend(self.lookup_import_candidates_from_module(
2005                    lookup_ident,
2006                    namespace,
2007                    parent_scope,
2008                    crate_root,
2009                    crate_path,
2010                    &filter_fn,
2011                ));
2012            }
2013        }
2014
2015        suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
2016        suggestions
2017    }
2018
2019    pub(crate) fn unresolved_macro_suggestions(
2020        &mut self,
2021        err: &mut Diag<'_>,
2022        macro_kind: MacroKind,
2023        parent_scope: &ParentScope<'ra>,
2024        ident: Ident,
2025        krate: &Crate,
2026        sugg_span: Option<Span>,
2027    ) {
2028        // Bring all unused `derive` macros into `macro_map` so we ensure they can be used for
2029        // suggestions.
2030        self.register_macros_for_all_crates();
2031
2032        let is_expected =
2033            &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
2034        let suggestion = self.early_lookup_typo_candidate(
2035            ScopeSet::Macro(macro_kind),
2036            parent_scope,
2037            ident,
2038            is_expected,
2039            &|_| true,
2040        );
2041        self.add_typo_suggestion(err, suggestion, ident.span, None);
2042        self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
2043
2044        let import_suggestions =
2045            self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
2046        let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {
2047            DUMMY_NODE_ID => (None, FoundUse::No),
2048            node_id => UsePlacementFinder::check(krate, node_id),
2049        };
2050        show_candidates(
2051            self.tcx,
2052            err,
2053            span,
2054            &import_suggestions,
2055            Instead::No,
2056            found_use,
2057            DiagMode::Normal,
2058            ::alloc::vec::Vec::new()vec![],
2059            "",
2060        );
2061
2062        if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
2063            let label_span = ident.span.shrink_to_hi();
2064            let mut spans = MultiSpan::from_span(label_span);
2065            spans.push_span_label(label_span, "put a macro name here");
2066            err.subdiagnostic(MaybeMissingMacroRulesName { spans });
2067            return;
2068        }
2069
2070        if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
2071            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
2072            return;
2073        }
2074
2075        let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident, _))| {
2076            if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
2077        });
2078
2079        if let Some((def_id, unused_ident)) = unused_macro {
2080            let scope = self.local_macro_def_scopes[&def_id];
2081            let parent_nearest = parent_scope.module.nearest_parent_mod();
2082            let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();
2083            if !unused_macro_kinds.contains(macro_kind.into()) {
2084                match macro_kind {
2085                    MacroKind::Bang => {
2086                        err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
2087                    }
2088                    MacroKind::Attr => {
2089                        err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
2090                    }
2091                    MacroKind::Derive => {
2092                        err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
2093                    }
2094                }
2095                return;
2096            }
2097            if Some(parent_nearest.to_def_id()) == scope.opt_def_id() {
2098                err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
2099                err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
2100                return;
2101            }
2102        }
2103
2104        if ident.name == kw::Default
2105            && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind
2106        {
2107            let span = self.def_span(def_id);
2108            let source_map = self.tcx.sess.source_map();
2109            let head_span = source_map.guess_head_span(span);
2110            err.subdiagnostic(ConsiderAddingADerive {
2111                span: head_span.shrink_to_lo(),
2112                suggestion: "#[derive(Default)]\n".to_string(),
2113            });
2114        }
2115        for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
2116            let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2117                ident,
2118                ScopeSet::All(ns),
2119                parent_scope,
2120                None,
2121                None,
2122                None,
2123            ) else {
2124                continue;
2125            };
2126
2127            let desc = match binding.res() {
2128                Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
2129                    "a function-like macro".to_string()
2130                }
2131                Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
2132                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
    })format!("an attribute: `#[{ident}]`")
2133                }
2134                Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
2135                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
                ident))
    })format!("a derive macro: `#[derive({ident})]`")
2136                }
2137                Res::Def(DefKind::Macro(kinds), _) => {
2138                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
                kinds.descr()))
    })format!("{} {}", kinds.article(), kinds.descr())
2139                }
2140                Res::ToolMod | Res::OpenMod(..) => {
2141                    // Don't confuse the user with tool modules or open modules.
2142                    continue;
2143                }
2144                Res::Def(DefKind::Trait, trait_def_id) if macro_kind == MacroKind::Derive => {
2145                    if let crate::DeclKind::Import { import, .. } = binding.kind
2146                        && !import.span.is_dummy()
2147                    {
2148                        self.record_use(ident, binding, Used::Other);
2149                    }
2150                    let trait_span = self.def_span(trait_def_id);
2151                    err.span_note(trait_span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a trait, not a derive macro",
                ident))
    })format!("`{ident}` is a trait, not a derive macro"));
2152                    err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider implementing `{0}` for your type manually",
                ident))
    })format!("consider implementing `{ident}` for your type manually"));
2153                    return;
2154                }
2155                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!(
2156                    "{} {}, not {} {}",
2157                    res.article(),
2158                    res.descr(),
2159                    macro_kind.article(),
2160                    macro_kind.descr_expected(),
2161                ),
2162            };
2163            if let crate::DeclKind::Import { import, .. } = binding.kind
2164                && !import.span.is_dummy()
2165            {
2166                let note = diagnostics::IdentImporterHereButItIsDesc {
2167                    span: import.span,
2168                    imported_ident: ident,
2169                    imported_ident_desc: &desc,
2170                };
2171                err.subdiagnostic(note);
2172                // Silence the 'unused import' warning we might get,
2173                // since this diagnostic already covers that import.
2174                self.record_use(ident, binding, Used::Other);
2175                return;
2176            }
2177            let note = diagnostics::IdentInScopeButItIsDesc {
2178                imported_ident: ident,
2179                imported_ident_desc: &desc,
2180            };
2181            err.subdiagnostic(note);
2182            return;
2183        }
2184
2185        // Not in scope: check if the name refers to a trait importable from elsewhere.
2186        // An exact derive macro candidate is much more likely to be intended than any
2187        // same-named traits, so we only consider them if there are no import suggestions for the derive macro.
2188        if macro_kind == MacroKind::Derive && import_suggestions.is_empty() {
2189            let trait_candidates =
2190                self.lookup_import_candidates(ident, TypeNS, parent_scope, |res| {
2191                    #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(DefKind::Trait, _) => true,
    _ => false,
}matches!(res, Res::Def(DefKind::Trait, _))
2192                });
2193            let mut seen = FxHashSet::default();
2194            for candidate in &trait_candidates {
2195                if let Some(def_id) = candidate.did
2196                    && seen.insert(def_id)
2197                {
2198                    err.span_note(
2199                        self.def_span(def_id),
2200                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a trait, not a derive macro",
                ident))
    })format!("`{ident}` is a trait, not a derive macro"),
2201                    );
2202                }
2203            }
2204            if !seen.is_empty() {
2205                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider implementing `{0}` for your type manually",
                ident))
    })format!("consider implementing `{ident}` for your type manually"));
2206                return;
2207            }
2208        }
2209
2210        if let Some(def_id) = self.macro_names.get(&IdentKey::new(ident)) {
2211            let macro_span = self.def_span(def_id.to_def_id());
2212            let mut span: MultiSpan = macro_span.into();
2213            span.push_span_label(
2214                macro_span,
2215                "a macro with the same name is defined here".to_string(),
2216            );
2217            if let Some(def_id) = self.local_macro_def_scopes[def_id].opt_def_id() {
2218                span.push_span_label(
2219                    self.def_span(def_id),
2220                    "consider annotating this `mod` with `#[macro_use]`".to_string(),
2221                );
2222            }
2223
2224            err.subdiagnostic(AddedMacroUse { span });
2225            return;
2226        }
2227    }
2228
2229    /// Given an attribute macro that failed to be resolved, look for `derive` macros that could
2230    /// provide it, either as-is or with small typos.
2231    fn detect_derive_attribute(
2232        &self,
2233        err: &mut Diag<'_>,
2234        ident: Ident,
2235        parent_scope: &ParentScope<'ra>,
2236        sugg_span: Option<Span>,
2237    ) {
2238        // Find all of the `derive`s in scope and collect their corresponding declared
2239        // attributes.
2240        // FIXME: this only works if the crate that owns the macro that has the helper_attr
2241        // has already been imported.
2242        let mut derives = ::alloc::vec::Vec::new()vec![];
2243        let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
2244        // We're collecting these in a hashmap, and handle ordering the output further down.
2245        #[allow(rustc::potential_query_instability)]
2246        for (def_id, ext) in self
2247            .local_macro_map
2248            .iter()
2249            .map(|(local_id, ext)| (local_id.to_def_id(), ext))
2250            .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
2251        {
2252            for helper_attr in &ext.helper_attrs {
2253                let item_name = self.tcx.item_name(def_id);
2254                all_attrs.entry(*helper_attr).or_default().push(item_name);
2255                if helper_attr == &ident.name {
2256                    derives.push(item_name);
2257                }
2258            }
2259        }
2260        let kind = MacroKind::Derive.descr();
2261        if !derives.is_empty() {
2262            // We found an exact match for the missing attribute in a `derive` macro. Suggest it.
2263            let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
2264            derives.sort();
2265            derives.dedup();
2266            let msg = match &derives[..] {
2267                [derive] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", derive))
    })format!(" `{derive}`"),
2268                [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!(
2269                    "s {} and `{last}`",
2270                    start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
2271                ),
2272                [] => {
    ::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!?"),
2273            };
2274            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!(
2275                "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
2276                     missing a `derive` attribute",
2277                ident.name,
2278            );
2279            let sugg_span =
2280                if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind {
2281                    let span = self.def_span(id);
2282                    if span.from_expansion() {
2283                        None
2284                    } else {
2285                        // For enum variants sugg_span is empty but we can get the enum's Span.
2286                        Some(span.shrink_to_lo())
2287                    }
2288                } else {
2289                    // For items this `Span` will be populated, everything else it'll be None.
2290                    sugg_span
2291                };
2292            match sugg_span {
2293                Some(span) => {
2294                    err.span_suggestion_verbose(
2295                        span,
2296                        msg,
2297                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("#[derive({0})]\n",
                derives.join(", ")))
    })format!("#[derive({})]\n", derives.join(", ")),
2298                        Applicability::MaybeIncorrect,
2299                    );
2300                }
2301                None => {
2302                    err.note(msg);
2303                }
2304            }
2305        } else {
2306            // We didn't find an exact match. Look for close matches. If any, suggest fixing typo.
2307            let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
2308            if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
2309                && let Some(macros) = all_attrs.get(&best_match)
2310            {
2311                let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
2312                macros.sort();
2313                macros.dedup();
2314                let msg = match &macros[..] {
2315                    [] => return,
2316                    [name] => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}` accepts", name))
    })format!(" `{name}` accepts"),
2317                    [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!(
2318                        "s {} and `{end}` accept",
2319                        start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
2320                    ),
2321                };
2322                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");
2323                err.span_suggestion_verbose(
2324                    ident.span,
2325                    msg,
2326                    best_match,
2327                    Applicability::MaybeIncorrect,
2328                );
2329            }
2330        }
2331    }
2332
2333    pub(crate) fn add_typo_suggestion(
2334        &self,
2335        err: &mut Diag<'_>,
2336        suggestion: Option<TypoSuggestion>,
2337        span: Span,
2338        prefix: Option<Ident>,
2339    ) {
2340        let suggestion = match suggestion {
2341            None => return,
2342            // We shouldn't suggest underscore.
2343            Some(suggestion) if suggestion.candidate == kw::Underscore => return,
2344            Some(suggestion) => suggestion,
2345        };
2346
2347        let mut did_label_def_span = false;
2348
2349        if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
2350            if span.overlaps(def_span) {
2351                // Don't suggest typo suggestion for itself like in the following:
2352                // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
2353                //   --> $DIR/unicode-string-literal-syntax-error-64792.rs:4:14
2354                //    |
2355                // LL | struct X {}
2356                //    | ----------- `X` defined here
2357                // LL |
2358                // LL | const Y: X = X("ö");
2359                //    | -------------^^^^^^- similarly named constant `Y` defined here
2360                //    |
2361                // help: use struct literal syntax instead
2362                //    |
2363                // LL | const Y: X = X {};
2364                //    |              ^^^^
2365                // help: a constant with a similar name exists
2366                //    |
2367                // LL | const Y: X = Y("ö");
2368                //    |              ^
2369                return;
2370            }
2371            if span.in_derive_expansion() {
2372                return;
2373            }
2374            let span = self.tcx.sess.source_map().guess_head_span(def_span);
2375            let candidate_descr = suggestion.res.descr();
2376            let candidate = suggestion.candidate;
2377            let label = match suggestion.target {
2378                SuggestionTarget::SimilarlyNamed => {
2379                    diagnostics::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
2380                }
2381                SuggestionTarget::SingleItem => {
2382                    diagnostics::DefinedHere::SingleItem { span, candidate_descr, candidate }
2383                }
2384            };
2385            did_label_def_span = true;
2386            err.subdiagnostic(label);
2387        }
2388
2389        let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
2390            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2391            && let Some(span) = suggestion.span
2392            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
2393            && snippet == candidate
2394        {
2395            let candidate = suggestion.candidate;
2396            // When the suggested binding change would be from `x` to `_x`, suggest changing the
2397            // original binding definition instead. (#60164)
2398            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!(
2399                "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
2400            );
2401            if !did_label_def_span {
2402                err.span_note(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
    })format!("`{candidate}` defined here"));
2403            }
2404            (span, msg, snippet)
2405        } else {
2406            let msg = match suggestion.target {
2407                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!(
2408                    "{} {} with a similar name exists",
2409                    suggestion.res.article(),
2410                    suggestion.res.descr()
2411                ),
2412                SuggestionTarget::SingleItem => {
2413                    ::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())
2414                }
2415            };
2416            let candidate_str = suggestion.candidate.to_ident_string();
2417            let sugg =
2418                if let Some(p) = prefix { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}: {1}", p, candidate_str))
    })format!("{p}: {candidate_str}") } else { candidate_str };
2419            (span, msg, sugg)
2420        };
2421        err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2422    }
2423
2424    fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2425        let res = b.res();
2426        if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2427            let (built_in, from) = match scope {
2428                Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2429                Scope::ExternPreludeFlags
2430                    if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2431                        || #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::OpenMod(..) => true,
    _ => false,
}matches!(res, Res::OpenMod(..)) =>
2432                {
2433                    ("", " passed with `--extern`")
2434                }
2435                _ => {
2436                    if #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
    _ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2437                        // These already contain the "built-in" prefix or look bad with it.
2438                        ("", "")
2439                    } else {
2440                        (" built-in", "")
2441                    }
2442                }
2443            };
2444
2445            let a = if built_in.is_empty() { res.article() } else { "a" };
2446            ::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())
2447        } else {
2448            let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2449            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
                introduced))
    })format!("the {thing} {introduced} here", thing = res.descr())
2450        }
2451    }
2452
2453    fn ambiguity_diagnostic(
2454        &self,
2455        ambiguity_error: &AmbiguityError<'ra>,
2456    ) -> diagnostics::Ambiguity {
2457        let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2458            *ambiguity_error;
2459        let extern_prelude_ambiguity = || {
2460            // Note: b1 may come from a module scope, as an extern crate item in module.
2461            #[allow(non_exhaustive_omitted_patterns)] match scope2 {
    Scope::ExternPreludeFlags => true,
    _ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2462                && self
2463                    .extern_prelude
2464                    .get(&IdentKey::new(ident))
2465                    .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2466        };
2467        let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2468            // We have to print the span-less alternative first, otherwise formatting looks bad.
2469            (b2, b1, scope2, scope1, true)
2470        } else {
2471            (b1, b2, scope1, scope2, false)
2472        };
2473
2474        let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2475            let what = self.decl_description(b, ident, scope);
2476            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}");
2477
2478            let thing = b.res().descr();
2479            let mut help_msgs = Vec::new();
2480            if b.is_glob_import()
2481                && (kind == AmbiguityKind::GlobVsGlob
2482                    || kind == AmbiguityKind::GlobVsExpanded
2483                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2484            {
2485                help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
                ident))
    })format!(
2486                    "consider adding an explicit import of `{ident}` to disambiguate"
2487                ))
2488            }
2489            if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2490            {
2491                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"))
2492            }
2493
2494            if kind != AmbiguityKind::GlobVsGlob {
2495                if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2496                    if b.res() == Res::Err {
2497                        help_msgs.push("consider removing this".to_string());
2498                    } else if module == self.graph_root.to_module() {
2499                        help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
                ident, thing))
    })format!(
2500                            "use `crate::{ident}` to refer to this {thing} unambiguously"
2501                        ));
2502                    } else if module.is_normal() {
2503                        help_msgs.push(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
                ident, thing))
    })format!(
2504                            "use `self::{ident}` to refer to this {thing} unambiguously"
2505                        ));
2506                    }
2507                }
2508            }
2509
2510            (
2511                Spanned { node: note_msg, span: b.span },
2512                help_msgs
2513                    .iter()
2514                    .enumerate()
2515                    .map(|(i, help_msg)| {
2516                        let or = if i == 0 { "" } else { "or " };
2517                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
    })format!("{or}{help_msg}")
2518                    })
2519                    .collect::<Vec<_>>(),
2520            )
2521        };
2522        let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2523        let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2524        let help = if kind == AmbiguityKind::GlobVsGlob
2525            && b1
2526                .parent_module
2527                .and_then(|m| m.opt_def_id())
2528                .map(|d| !d.is_local())
2529                .unwrap_or_default()
2530        {
2531            Some(&[
2532                "consider updating this dependency to resolve this error",
2533                "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2534            ] as &[_])
2535        } else {
2536            None
2537        };
2538
2539        let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2540            ::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!(
2541                "{} or {}",
2542                vis1.to_string(CRATE_DEF_ID, self.tcx),
2543                vis2.to_string(CRATE_DEF_ID, self.tcx)
2544            )
2545        });
2546
2547        diagnostics::Ambiguity {
2548            ident,
2549            help,
2550            ambig_vis,
2551            kind: kind.descr(),
2552            b1_note,
2553            b1_help_msgs,
2554            b2_note,
2555            b2_help_msgs,
2556            is_error: false,
2557        }
2558    }
2559
2560    /// If the binding refers to a tuple struct constructor with fields,
2561    /// returns the span of its fields.
2562    fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2563        let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id), _) =
2564            decl.kind
2565        else {
2566            return None;
2567        };
2568
2569        let def_id = self.tcx.parent(ctor_def_id);
2570        self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()`
2571    }
2572
2573    /// Returns the path segments (as symbols) of a module, including `kw::Crate` at the start.
2574    /// For example, for `crate::foo::bar`, returns `[Crate, foo, bar]`.
2575    /// Returns `None` for block modules that don't have a `DefId`.
2576    fn module_path_names(&self, module: Module<'ra>) -> Option<Vec<Symbol>> {
2577        let mut path = Vec::new();
2578        let mut def_id = module.opt_def_id()?;
2579        while let Some(parent) = self.tcx.opt_parent(def_id) {
2580            if let Some(name) = self.tcx.opt_item_name(def_id) {
2581                path.push(name);
2582            }
2583            if parent.is_top_level_module() {
2584                break;
2585            }
2586            def_id = parent;
2587        }
2588        path.reverse();
2589        path.insert(0, kw::Crate);
2590        Some(path)
2591    }
2592
2593    /// Returns the original import's source path if it resolves to `source_decl` from the use
2594    /// site.
2595    ///
2596    /// The same `Res` may be reachable through several bindings, so resolve the last segment in
2597    /// the module named by the rest of the path and compare the binding itself.
2598    fn import_source_suggestion_path(
2599        &self,
2600        import: Import<'ra>,
2601        source: Ident,
2602        source_decl: Decl<'ra>,
2603        parent_scope: &ParentScope<'ra>,
2604    ) -> Option<Vec<Ident>> {
2605        let ns = source_decl.res().ns()?;
2606        let module_path = import
2607            .module_path
2608            .iter()
2609            .filter(|seg| seg.ident.name != kw::PathRoot || seg.ident.span.at_least_rust_2018())
2610            .cloned()
2611            .collect::<Vec<_>>();
2612
2613        let module = if module_path.is_empty() {
2614            ModuleOrUniformRoot::CurrentScope
2615        } else if let PathResult::Module(module) =
2616            self.cm().maybe_resolve_path(&module_path, None, parent_scope, None)
2617        {
2618            module
2619        } else {
2620            return None;
2621        };
2622
2623        let decl =
2624            self.cm().maybe_resolve_ident_in_module(module, source, ns, parent_scope, None).ok()?;
2625        (decl == source_decl).then(|| {
2626            module_path
2627                .into_iter()
2628                .map(|segment| segment.ident)
2629                .chain(std::iter::once(source))
2630                .collect()
2631        })
2632    }
2633
2634    fn shorten_candidate_path(
2635        &self,
2636        suggestion: &mut ImportSuggestion,
2637        current_module: Module<'ra>,
2638    ) {
2639        self.shorten_import_path(suggestion.did, &mut suggestion.path, current_module);
2640    }
2641
2642    /// Shortens an import path to use `super::` (up to 1 level) or `self::` (same module)
2643    /// relative to the current scope, if possible. Only applies to crate-local items and
2644    /// only when the resulting path is actually shorter than the original.
2645    fn shorten_import_path(
2646        &self,
2647        did: Option<DefId>,
2648        path: &mut Path,
2649        current_module: Module<'ra>,
2650    ) {
2651        const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;
2652
2653        // Only shorten local items.
2654        if did.is_none_or(|did| !did.is_local()) {
2655            return;
2656        }
2657
2658        // Build current module path: [Crate, foo, bar, ...].
2659        let Some(current_mod_path) = self.module_path_names(current_module) else {
2660            return;
2661        };
2662
2663        // Normalise candidate path: filter out `PathRoot` (`::`), and if the path
2664        // doesn't start with `Crate`, prepend it (edition 2015 paths are relative
2665        // to the crate root without an explicit `crate::` prefix).
2666        let candidate_names = {
2667            let filtered_segments: Vec<_> =
2668                path.segments.iter().filter(|segment| segment.ident.name != kw::PathRoot).collect();
2669
2670            let mut candidate_names: Vec<Symbol> =
2671                filtered_segments.iter().map(|segment| segment.ident.name).collect();
2672            if candidate_names.first() != Some(&kw::Crate) {
2673                candidate_names.insert(0, kw::Crate);
2674            }
2675            if candidate_names.len() < 2 {
2676                return;
2677            }
2678            candidate_names
2679        };
2680
2681        // The candidate's module path is everything except the last segment (the item name).
2682        let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];
2683
2684        // Find the longest common prefix between the current module and candidate module paths.
2685        let common_prefix_length = current_mod_path
2686            .iter()
2687            .zip(candidate_mod_names.iter())
2688            .take_while(|(current, candidate)| current == candidate)
2689            .count();
2690
2691        // Non-crate-local item; keep the full absolute path.
2692        if common_prefix_length == 0 {
2693            return;
2694        }
2695
2696        let super_count = current_mod_path.len() - common_prefix_length;
2697
2698        // At the crate root, `use` paths resolve from the crate root anyway, so we can
2699        // drop the `crate::` prefix entirely instead of replacing it with `self::`.
2700        let at_crate_root = current_mod_path.len() == 1;
2701
2702        let mut new_segments = if super_count == 0 && at_crate_root {
2703            ThinVec::new()
2704        } else {
2705            let prefix_keyword = match super_count {
2706                0 => kw::SelfLower,
2707                1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
2708                _ => return, // Too many `super` levels; keep the full absolute path.
2709            };
2710            {
    let len = [()].len();
    let mut vec = ::thin_vec::ThinVec::with_capacity(len);
    vec.push(ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword)));
    vec
}thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword),)]
2711        };
2712        for &name in &candidate_names[common_prefix_length..] {
2713            new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
2714        }
2715
2716        // Only apply if the result is strictly shorter than the original path.
2717        if new_segments.len() >= path.segments.len() {
2718            return;
2719        }
2720
2721        *path = Path { span: path.span, segments: new_segments };
2722    }
2723
2724    fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2725        let PrivacyError {
2726            ident,
2727            decl,
2728            outermost_res,
2729            parent_scope,
2730            single_nested,
2731            dedup_span,
2732            ref source,
2733        } = *privacy_error;
2734
2735        let res = decl.res();
2736        let ctor_fields_span = self.ctor_fields_span(decl);
2737        let plain_descr = res.descr().to_string();
2738        let nonimport_descr =
2739            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2740        let import_descr = nonimport_descr.clone() + " import";
2741        let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2742
2743        // Print the primary message.
2744        let ident_descr = get_descr(decl);
2745        let mut err =
2746            self.dcx().create_err(diagnostics::IsPrivate { span: ident.span, ident_descr, ident });
2747
2748        self.mention_default_field_values(source, ident, &mut err);
2749
2750        let shown_candidates = if let Some((this_res, outer_ident)) = outermost_res {
2751            let mut import_suggestions = self.lookup_import_candidates(
2752                outer_ident,
2753                this_res.ns().unwrap_or(Namespace::TypeNS),
2754                &parent_scope,
2755                &|res: Res| res == this_res,
2756            );
2757            // Shorten candidate paths using `super::` or `self::` when possible.
2758            for suggestion in &mut import_suggestions {
2759                self.shorten_candidate_path(suggestion, parent_scope.module);
2760            }
2761            let point_to_def = !show_candidates(
2762                self.tcx,
2763                &mut err,
2764                Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2765                &import_suggestions,
2766                Instead::Yes,
2767                FoundUse::Yes,
2768                DiagMode::Import { append: single_nested, unresolved_import: false },
2769                ::alloc::vec::Vec::new()vec![],
2770                "",
2771            );
2772            // If we suggest importing a public re-export, don't point at the definition.
2773            if point_to_def && ident.span != outer_ident.span {
2774                let label = diagnostics::OuterIdentIsNotPubliclyReexported {
2775                    span: outer_ident.span,
2776                    outer_ident_descr: this_res.descr(),
2777                    outer_ident,
2778                };
2779                err.subdiagnostic(label);
2780            }
2781            !point_to_def
2782        } else {
2783            false
2784        };
2785
2786        let mut non_exhaustive = None;
2787        // If an ADT is foreign and marked as `non_exhaustive`, then that's
2788        // probably why we have the privacy error.
2789        // Otherwise, point out if the struct has any private fields.
2790        if let Some(def_id) = res.opt_def_id()
2791            && !def_id.is_local()
2792            && let Some(attr_span) = {
    {
        'done:
            {
            for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &self.tcx) {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(NonExhaustive(span)) => {
                        break 'done Some(*span);
                    }
                    ::rustc_attr_ir::Attribute::Tool(..) |
                        ::rustc_attr_ir::Attribute::DeriveHelper(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }
}find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
2793        {
2794            non_exhaustive = Some(attr_span);
2795        } else if let Some(span) = ctor_fields_span {
2796            let label = diagnostics::ConstructorPrivateIfAnyFieldPrivate { span };
2797            err.subdiagnostic(label);
2798            if let Res::Def(_, d) = res
2799                && let Some(fields) = self.field_visibility_spans.get(&d)
2800            {
2801                let spans = fields.iter().map(|span| *span).collect();
2802                let sugg = diagnostics::ConsiderMakingTheFieldPublic {
2803                    spans,
2804                    number_of_fields: fields.len(),
2805                };
2806                err.subdiagnostic(sugg);
2807            }
2808        }
2809
2810        let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2811        if let Some(mut def_id) = res.opt_def_id() {
2812            // We can't use `def_path_str` in resolve.
2813            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];
2814            while let Some(parent) = self.tcx.opt_parent(def_id) {
2815                def_id = parent;
2816                if !def_id.is_top_level_module() {
2817                    path.push(def_id);
2818                } else {
2819                    break;
2820                }
2821            }
2822            // We will only suggest importing directly if it is accessible through that path.
2823            let path_names: Option<Vec<Ident>> = path
2824                .iter()
2825                .rev()
2826                .map(|def_id| {
2827                    self.tcx.opt_item_name(*def_id).map(|name| {
2828                        Ident::with_dummy_span(if def_id.is_top_level_module() {
2829                            kw::Crate
2830                        } else {
2831                            name
2832                        })
2833                    })
2834                })
2835                .collect();
2836            if let Some(&def_id) = path.get(0)
2837                && let Some(path) = path_names
2838            {
2839                if let Some(def_id) = def_id.as_local() {
2840                    if self.effective_visibilities.is_directly_public(def_id) {
2841                        sugg_paths.push((path, false));
2842                    }
2843                } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2844                {
2845                    sugg_paths.push((path, false));
2846                }
2847            }
2848        }
2849
2850        let has_direct_suggestion = !sugg_paths.is_empty();
2851        // Print the whole import chain to make it easier to see what happens.
2852        let first_binding = decl;
2853        let mut next_binding = Some((decl, false));
2854        let mut next_ident = ident;
2855        while let Some((binding, path_to_binding_accessible)) = next_binding {
2856            let name = next_ident;
2857            next_binding = None;
2858            if res != Res::Err
2859                && let DeclKind::Import { source_decl, import, .. } = binding.kind
2860                && !source_decl.span.is_dummy()
2861                && let Some(source) = match import.kind {
2862                    ImportKind::Single { source, .. } => Some(source),
2863                    ImportKind::Glob { .. }
2864                    | ImportKind::MacroUse { .. }
2865                    | ImportKind::MacroExport => Some(next_ident),
2866                    ImportKind::ExternCrate { .. } => None,
2867                }
2868            {
2869                next_ident = source;
2870                let source_res = source_decl.res();
2871                let through_reexport = source_decl.is_import();
2872                let mut path_is_accessible = has_direct_suggestion && !through_reexport;
2873                if let Some(path) =
2874                    self.import_source_suggestion_path(import, source, source_decl, &parent_scope)
2875                {
2876                    path_is_accessible = true;
2877                    sugg_paths.push((path, through_reexport));
2878                } else if !has_direct_suggestion
2879                    && let Some(ns) = source_res.ns()
2880                    && let Some(candidate) = self
2881                        .lookup_import_candidates(source, ns, &parent_scope, |res| {
2882                            res == source_res
2883                        })
2884                        .into_iter()
2885                        .filter(|candidate| candidate.accessible)
2886                        .map(|mut candidate| {
2887                            self.shorten_candidate_path(&mut candidate, parent_scope.module);
2888                            candidate
2889                        })
2890                        .min_by_key(|candidate| {
2891                            (
2892                                candidate.path.segments.len(),
2893                                candidate.path.segments[0].ident.name == sym::core,
2894                            )
2895                        })
2896                {
2897                    // The same item may have several re-exports. Only label this one
2898                    // if the suggested path resolves to its binding.
2899                    let segments = Segment::from_path(&candidate.path);
2900                    path_is_accessible = if let Some((last, prefix)) = segments.split_last()
2901                        && let PathResult::Module(module) =
2902                            self.cm().maybe_resolve_path(prefix, None, &parent_scope, None)
2903                    {
2904                        self.cm()
2905                            .maybe_resolve_ident_in_module(
2906                                module,
2907                                last.ident,
2908                                ns,
2909                                &parent_scope,
2910                                None,
2911                            )
2912                            .is_ok_and(|decl| decl == source_decl)
2913                    } else {
2914                        false
2915                    };
2916                    let path = candidate.path.segments.iter().map(|seg| seg.ident).collect();
2917                    sugg_paths.push((path, candidate.via_import));
2918                }
2919                next_binding = Some((source_decl, path_is_accessible));
2920            }
2921            let first = binding == first_binding;
2922            let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2923            let mut note_span = MultiSpan::from_span(def_span);
2924            if !first
2925                // The same `Res` may be reachable through a different import binding.
2926                && self.is_accessible_from(binding.vis(), parent_scope.module)
2927                && path_to_binding_accessible
2928                // A circular import chain can lead back to the failing import itself.
2929                && !binding.span.contains(ident.span)
2930            {
2931                let desc = match binding.kind {
2932                    DeclKind::Import { .. } => "re-export",
2933                    _ => "directly",
2934                };
2935                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}"));
2936            }
2937            // Final step in the import chain, point out if the ADT is `non_exhaustive`
2938            // which is probably why this privacy violation occurred.
2939            if next_binding.is_none()
2940                && let Some(span) = non_exhaustive
2941            {
2942                note_span.push_span_label(
2943                    span,
2944                    "cannot be constructed because it is `#[non_exhaustive]`",
2945                );
2946            }
2947            let note = diagnostics::NoteAndRefersToTheItemDefinedHere {
2948                span: note_span,
2949                binding_descr: get_descr(binding),
2950                binding_name: name,
2951                first,
2952                dots: next_binding.is_some(),
2953            };
2954            err.subdiagnostic(note);
2955        }
2956        // The suggestion replaces `dedup_span` with a path reaching the failing ident.
2957        // That's valid only when
2958        // 1) the failing ident is the imported leaf, otherwise `as` renames and trailing segments
2959        //    get dropped, and
2960        // 2) the use isn't nested, otherwise `dedup_span` is one ident in `{...}`.
2961        //
2962        // See issue #156060.
2963        let can_replace_use = !shown_candidates
2964            && !single_nested
2965            && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
2966        if can_replace_use {
2967            // We prioritize shorter paths, non-core imports and direct imports over the
2968            // alternatives.
2969            sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2970            for (sugg, reexport) in sugg_paths {
2971                if sugg.len() <= 1 {
2972                    // A single path segment suggestion is wrong. This happens on circular
2973                    // imports. `tests/ui/imports/issue-55884-2.rs`
2974                    continue;
2975                }
2976                // The suggested path may use a different name than the private alias.
2977                let ident = *sugg.last().expect("at least one segment");
2978                let path = join_path_idents(sugg);
2979                let sugg = if reexport {
2980                    diagnostics::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2981                } else {
2982                    diagnostics::ImportIdent::Directly { span: dedup_span, ident, path }
2983                };
2984                err.subdiagnostic(sugg);
2985                break;
2986            }
2987        }
2988        err.emit();
2989    }
2990
2991    /// When a private field is being set that has a default field value, we suggest using `..` and
2992    /// setting the value of that field implicitly with its default.
2993    ///
2994    /// If we encounter code like
2995    /// ```text
2996    /// struct Priv;
2997    /// pub struct S {
2998    ///     pub field: Priv = Priv,
2999    /// }
3000    /// ```
3001    /// which is used from a place where `Priv` isn't accessible
3002    /// ```text
3003    /// let _ = S { field: m::Priv1 {} };
3004    /// //                    ^^^^^ private struct
3005    /// ```
3006    /// we will suggest instead using the `default_field_values` syntax instead:
3007    /// ```text
3008    /// let _ = S { .. };
3009    /// ```
3010    fn mention_default_field_values(
3011        &self,
3012        source: &Option<ast::Expr>,
3013        ident: Ident,
3014        err: &mut Diag<'_>,
3015    ) {
3016        let Some(expr) = source else { return };
3017        let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
3018        // We don't have to handle type-relative paths because they're forbidden in ADT
3019        // expressions, but that would change with `#[feature(more_qualified_paths)]`.
3020        let Some(segment) = struct_expr.path.segments.last() else { return };
3021        let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
3022        let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
3023            return;
3024        };
3025        let Some(default_fields) = self.field_defaults(def_id) else { return };
3026        if struct_expr.fields.is_empty() {
3027            return;
3028        }
3029        let last_span = struct_expr.fields.last().unwrap().span;
3030        let mut iter = struct_expr.fields.iter().peekable();
3031        let mut prev: Option<Span> = None;
3032        while let Some(field) = iter.next() {
3033            if field.expr.span.overlaps(ident.span) {
3034                err.span_label(field.ident.span, "while setting this field");
3035                if default_fields.contains(&field.ident.name) {
3036                    let sugg = if last_span == field.span {
3037                        ::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())]
3038                    } else {
3039                        ::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![
3040                            (
3041                                // Account for trailing commas and ensure we remove them.
3042                                match (prev, iter.peek()) {
3043                                    (_, Some(next)) => field.span.with_hi(next.span.lo()),
3044                                    (Some(prev), _) => field.span.with_lo(prev.hi()),
3045                                    (None, None) => field.span,
3046                                },
3047                                String::new(),
3048                            ),
3049                            (last_span.shrink_to_hi(), ", ..".to_string()),
3050                        ]
3051                    };
3052                    err.multipart_suggestion(
3053                        ::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!(
3054                            "the type `{ident}` of field `{}` is private, but you can construct \
3055                             the default value defined for it in `{}` using `..` in the struct \
3056                             initializer expression",
3057                            field.ident,
3058                            self.tcx.item_name(def_id),
3059                        ),
3060                        sugg,
3061                        Applicability::MachineApplicable,
3062                    );
3063                    break;
3064                }
3065            }
3066            prev = Some(field.span);
3067        }
3068    }
3069
3070    pub(crate) fn find_similarly_named_module_or_crate(
3071        &self,
3072        ident: Symbol,
3073        current_module: Module<'ra>,
3074    ) -> Option<Symbol> {
3075        let mut candidates = self
3076            .extern_prelude
3077            .keys()
3078            .map(|ident| ident.name)
3079            .chain(
3080                self.local_module_map
3081                    .iter()
3082                    .filter(|(_, module)| {
3083                        let module = module.to_module();
3084                        current_module.is_ancestor_of(module) && current_module != module
3085                    })
3086                    .flat_map(|(_, module)| module.name()),
3087            )
3088            .chain(
3089                self.extern_module_map
3090                    .borrow()
3091                    .iter()
3092                    .filter(|(_, module)| {
3093                        let module = module.to_module();
3094                        current_module.is_ancestor_of(module) && current_module != module
3095                    })
3096                    .flat_map(|(_, module)| module.name()),
3097            )
3098            .filter(|c| !c.to_string().is_empty())
3099            .collect::<Vec<_>>();
3100        candidates.sort();
3101        candidates.dedup();
3102        find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
3103    }
3104
3105    pub(crate) fn report_path_resolution_error(
3106        &mut self,
3107        path: &[Segment],
3108        opt_ns: Option<Namespace>, // `None` indicates a module path in import
3109        parent_scope: &ParentScope<'ra>,
3110        ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
3111        ignore_decl: Option<Decl<'ra>>,
3112        ignore_import: Option<Import<'ra>>,
3113        module: Option<ModuleOrUniformRoot<'ra>>,
3114        failed_segment_idx: usize,
3115        ident: Ident,
3116        diag_metadata: Option<&DiagMetadata<'_>>,
3117    ) -> (String, String, Option<Suggestion>, Option<String>) {
3118        let is_last = failed_segment_idx == path.len() - 1;
3119        let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
3120        let module_def_id = match module {
3121            Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
3122            _ => None,
3123        };
3124        let scope = match &path[..failed_segment_idx] {
3125            [.., prev] => {
3126                if prev.ident.name == kw::PathRoot && self.tcx.sess.edition() > Edition::Edition2015
3127                {
3128                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the list of imported crates"))
    })format!("the list of imported crates")
3129                } else if prev.ident.name == kw::PathRoot || prev.ident.name == kw::Crate {
3130                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("the crate root"))
    })format!("the crate root")
3131                } else {
3132                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", prev.ident))
    })format!("`{}`", prev.ident)
3133                }
3134            }
3135            _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("this scope"))
    })format!("this scope"),
3136        };
3137        let message = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
                scope))
    })format!("cannot find `{ident}` in {scope}");
3138
3139        // we may have typo in the middle part of path, try find a candidate with a similar name
3140        // and then check whether it contains a candidate that is accessible from the current scope
3141        let typo_suggestion = if opt_ns.is_none()
3142            && ignore_import.is_some()
3143            && let Some(ModuleOrUniformRoot::Module(module)) = module
3144            && let Some(candidate) = self.early_lookup_typo_candidate(
3145                ScopeSet::Module(TypeNS, module),
3146                parent_scope,
3147                ident,
3148                &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(DefKind::Mod | DefKind::Enum, _) => true,
    _ => false,
}matches!(res, Res::Def(DefKind::Mod | DefKind::Enum, _)),
3149                &|candidate| {
3150                    self.cm()
3151                        .resolve_ident_in_module(
3152                            ModuleOrUniformRoot::Module(module),
3153                            Ident::new(candidate.candidate, ident.span),
3154                            TypeNS,
3155                            parent_scope,
3156                            None,
3157                            ignore_decl,
3158                            ignore_import,
3159                        )
3160                        .is_ok_and(|binding| {
3161                            self.is_accessible_from(binding.vis(), parent_scope.module)
3162                        })
3163                },
3164            ) {
3165            Some((
3166                ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
        [(ident.span,
                    Ident::new(candidate.candidate, ident.span).to_string())]))vec![(ident.span, Ident::new(candidate.candidate, ident.span).to_string())],
3167                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} {1} with a similar name exists",
                candidate.res.article(), candidate.res.descr()))
    })format!(
3168                    "{} {} with a similar name exists",
3169                    candidate.res.article(),
3170                    candidate.res.descr(),
3171                ),
3172                Applicability::MaybeIncorrect,
3173            ))
3174        } else {
3175            None
3176        };
3177
3178        if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
3179            let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
    Res::Def(DefKind::Mod, _) => true,
    _ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
3180            let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
3181            candidates
3182                .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
3183            if let Some(candidate) = candidates.get(0) {
3184                let path = {
3185                    // remove the possible common prefix of the path
3186                    let len = candidate.path.segments.len();
3187                    let start_index = (0..=failed_segment_idx.min(len - 1))
3188                        .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
3189                        .unwrap_or_default();
3190                    let segments =
3191                        (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
3192                    Path { segments, span: Span::default() }
3193                };
3194                (
3195                    message,
3196                    String::from("unresolved import"),
3197                    Some((
3198                        ::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))],
3199                        String::from("a similar path exists"),
3200                        Applicability::MaybeIncorrect,
3201                    )),
3202                    None,
3203                )
3204            } else if let Some(suggestion) = typo_suggestion {
3205                (
3206                    message,
3207                    ::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"),
3208                    Some(suggestion),
3209                    None,
3210                )
3211            } else if ident.name == sym::core {
3212                (
3213                    message,
3214                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
                ident))
    })format!("you might be missing crate `{ident}`"),
3215                    Some((
3216                        ::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())],
3217                        "try using `std` instead of `core`".to_string(),
3218                        Applicability::MaybeIncorrect,
3219                    )),
3220                    None,
3221                )
3222            } else if ident.name == kw::Underscore {
3223                (
3224                    "invalid crate or module name `_`".to_string(),
3225                    "`_` is not a valid crate or module name".to_string(),
3226                    None,
3227                    None,
3228                )
3229            } else if self.tcx.sess.is_rust_2015() {
3230                let crate_is_available = self.tcx.sess.opts.externs.get(ident.as_str()).is_some();
3231                let (suggestion_message, help) = if crate_is_available {
3232                    let edition_help = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("if you\'re trying to use a dependency named `{0}`, upgrade your edition to be able to reference it with a `use` declaration",
                ident))
    })format!(
3233                        "if you're trying to use a dependency named `{ident}`, upgrade your \
3234                         edition to be able to reference it with a `use` declaration"
3235                    );
3236                    (
3237                        "on Rust 2015, `extern crate` is required to specify a dependency on an \
3238                         external crate"
3239                            .to_string(),
3240                        Some(edition_help),
3241                    )
3242                } else if was_invoked_from_cargo() {
3243                    (
3244                        ::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!(
3245                            "if you wanted to use a crate named `{ident}`, use `cargo add \
3246                             {ident}` to add it to your `Cargo.toml` and import it in your code",
3247                        ),
3248                        None,
3249                    )
3250                } else {
3251                    (
3252                        ::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!(
3253                            "you might be missing a crate named `{ident}`, add it to your \
3254                             project and import it in your code",
3255                        ),
3256                        None,
3257                    )
3258                };
3259                (
3260                    ::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}"),
3261                    ::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}`"),
3262                    Some((
3263                        ::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![(
3264                            self.current_crate_outer_attr_insert_span,
3265                            format!("extern crate {ident};\n"),
3266                        )],
3267                        suggestion_message,
3268                        if crate_is_available {
3269                            Applicability::MachineApplicable
3270                        } else {
3271                            Applicability::MaybeIncorrect
3272                        },
3273                    )),
3274                    help,
3275                )
3276            } else {
3277                (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, None)
3278            }
3279        } else if failed_segment_idx > 0 {
3280            let parent = path[failed_segment_idx - 1].ident.name;
3281            let parent = match parent {
3282                // ::foo is mounted at the crate root for 2015, and is the extern
3283                // prelude for 2018+
3284                kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
3285                    "the list of imported crates".to_owned()
3286                }
3287                kw::PathRoot | kw::Crate => "the crate root".to_owned(),
3288                _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`", parent))
    })format!("`{parent}`"),
3289            };
3290
3291            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}");
3292            if ns == TypeNS || ns == ValueNS {
3293                let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
3294                let binding = if let Some(module) = module {
3295                    self.cm()
3296                        .resolve_ident_in_module(
3297                            module,
3298                            ident,
3299                            ns_to_try,
3300                            parent_scope,
3301                            None,
3302                            ignore_decl,
3303                            ignore_import,
3304                        )
3305                        .ok()
3306                } else if let Some(ribs) = ribs
3307                    && let Some(TypeNS | ValueNS) = opt_ns
3308                {
3309                    if !ignore_import.is_none() {
    ::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3310                    match self.resolve_ident_in_lexical_scope(
3311                        ident,
3312                        ns_to_try,
3313                        parent_scope,
3314                        None,
3315                        &ribs[ns_to_try],
3316                        ignore_decl,
3317                        diag_metadata,
3318                    ) {
3319                        // we found a locally-imported or available item/module
3320                        Some(LateDecl::Decl(binding)) => Some(binding),
3321                        _ => None,
3322                    }
3323                } else {
3324                    self.cm()
3325                        .resolve_ident_in_scope_set(
3326                            ident,
3327                            ScopeSet::All(ns_to_try),
3328                            parent_scope,
3329                            None,
3330                            ignore_decl,
3331                            ignore_import,
3332                        )
3333                        .ok()
3334                };
3335                if let Some(binding) = binding {
3336                    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!(
3337                        "expected {}, found {} `{ident}` in {parent}",
3338                        ns.descr(),
3339                        binding.res().descr(),
3340                    );
3341                };
3342            }
3343            (message, msg, typo_suggestion, None)
3344        } else if ident.name == kw::SelfUpper {
3345            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
3346            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
3347            // impl
3348            if opt_ns.is_none() {
3349                (message, "`Self` cannot be used in imports".to_string(), None, None)
3350            } else {
3351                (
3352                    message,
3353                    "`Self` is only available in impls, traits, and type definitions".to_string(),
3354                    None,
3355                    None,
3356                )
3357            }
3358        } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
3359            // Check whether the name refers to an item in the value namespace.
3360            let binding = if let Some(ribs) = ribs {
3361                if !ignore_import.is_none() {
    ::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3362                self.resolve_ident_in_lexical_scope(
3363                    ident,
3364                    ValueNS,
3365                    parent_scope,
3366                    None,
3367                    &ribs[ValueNS],
3368                    ignore_decl,
3369                    diag_metadata,
3370                )
3371            } else {
3372                None
3373            };
3374            let match_span = match binding {
3375                // Name matches a local variable. For example:
3376                // ```
3377                // fn f() {
3378                //     let Foo: &str = "";
3379                //     println!("{}", Foo::Bar); // Name refers to local
3380                //                               // variable `Foo`.
3381                // }
3382                // ```
3383                Some(LateDecl::RibDef(Res::Local(id))) => {
3384                    Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
3385                }
3386                // Name matches item from a local name binding
3387                // created by `use` declaration. For example:
3388                // ```
3389                // pub const Foo: &str = "";
3390                //
3391                // mod submod {
3392                //     use super::Foo;
3393                //     println!("{}", Foo::Bar); // Name refers to local
3394                //                               // binding `Foo`.
3395                // }
3396                // ```
3397                Some(LateDecl::Decl(name_binding)) => Some((
3398                    name_binding.span,
3399                    name_binding.res().article(),
3400                    name_binding.res().descr(),
3401                )),
3402                _ => None,
3403            };
3404
3405            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}");
3406            let label = if let Some((span, article, descr)) = match_span {
3407                ::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!(
3408                    "`{ident}` is declared as {article} {descr} at `{}`, not a type",
3409                    self.tcx
3410                        .sess
3411                        .source_map()
3412                        .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
3413                )
3414            } else {
3415                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
                ident))
    })format!("use of undeclared type `{ident}`")
3416            };
3417            (message, label, None, None)
3418        } else {
3419            let mut suggestion = None;
3420            if ident.name == sym::alloc {
3421                suggestion = Some((
3422                    ::alloc::vec::Vec::new()vec![],
3423                    String::from("add `extern crate alloc` to use the `alloc` crate"),
3424                    Applicability::MaybeIncorrect,
3425                ))
3426            }
3427
3428            suggestion = suggestion.or_else(|| {
3429                self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
3430                    |sugg| {
3431                        (
3432                            ::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())],
3433                            String::from("there is a crate or module with a similar name"),
3434                            Applicability::MaybeIncorrect,
3435                        )
3436                    },
3437                )
3438            });
3439            if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
3440                ident,
3441                ScopeSet::All(ValueNS),
3442                parent_scope,
3443                None,
3444                ignore_decl,
3445                ignore_import,
3446            ) {
3447                let descr = binding.res().descr();
3448                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}");
3449                (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, None)
3450            } else {
3451                let suggestion = if suggestion.is_some() {
3452                    suggestion
3453                } else if let Some(m) = self.undeclared_module_exists(ident) {
3454                    self.undeclared_module_suggest_declare(ident, m)
3455                } else if was_invoked_from_cargo() {
3456                    Some((
3457                        ::alloc::vec::Vec::new()vec![],
3458                        ::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!(
3459                            "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
3460                             to add it to your `Cargo.toml`",
3461                        ),
3462                        Applicability::MaybeIncorrect,
3463                    ))
3464                } else {
3465                    Some((
3466                        ::alloc::vec::Vec::new()vec![],
3467                        ::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}`"),
3468                        Applicability::MaybeIncorrect,
3469                    ))
3470                };
3471                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}");
3472                (
3473                    message,
3474                    ::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}`"),
3475                    suggestion,
3476                    None,
3477                )
3478            }
3479        }
3480    }
3481
3482    fn undeclared_module_suggest_declare(
3483        &self,
3484        ident: Ident,
3485        path: std::path::PathBuf,
3486    ) -> Option<Suggestion> {
3487        Some((
3488            ::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"))],
3489            ::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!(
3490                "to make use of source file {}, use `mod {ident}` \
3491                 in this file to declare the module",
3492                path.display()
3493            ),
3494            Applicability::MaybeIncorrect,
3495        ))
3496    }
3497
3498    fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
3499        let map = self.tcx.sess.source_map();
3500
3501        let src = map.span_to_filename(ident.span).into_local_path()?;
3502        let i = ident.as_str();
3503        // FIXME: add case where non parent using undeclared module (hard?)
3504        let dir = src.parent()?;
3505        let src = src.file_stem()?.to_str()?;
3506        for file in [
3507            // …/x.rs
3508            dir.join(i).with_extension("rs"),
3509            // …/x/mod.rs
3510            dir.join(i).join("mod.rs"),
3511        ] {
3512            if file.exists() {
3513                return Some(file);
3514            }
3515        }
3516        if !#[allow(non_exhaustive_omitted_patterns)] match src {
    "main" | "lib" | "mod" => true,
    _ => false,
}matches!(src, "main" | "lib" | "mod") {
3517            for file in [
3518                // …/x/y.rs
3519                dir.join(src).join(i).with_extension("rs"),
3520                // …/x/y/mod.rs
3521                dir.join(src).join(i).join("mod.rs"),
3522            ] {
3523                if file.exists() {
3524                    return Some(file);
3525                }
3526            }
3527        }
3528        None
3529    }
3530
3531    /// Adds suggestions for a path that cannot be resolved.
3532    {}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3532u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::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))]
3533    pub(crate) fn make_path_suggestion(
3534        &mut self,
3535        mut path: Vec<Segment>,
3536        parent_scope: &ParentScope<'ra>,
3537    ) -> Option<(Vec<Segment>, Option<String>)> {
3538        match path[..] {
3539            // `{{root}}::ident::...` on both editions.
3540            // On 2015 `{{root}}` is usually added implicitly.
3541            [first, second, ..]
3542                if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
3543            // `ident::...` on 2018.
3544            [first, ..]
3545                if first.ident.span.at_least_rust_2018()
3546                    && !first.ident.is_path_segment_keyword() =>
3547            {
3548                // Insert a placeholder that's later replaced by `self`/`super`/etc.
3549                path.insert(0, Segment::from_ident(Ident::dummy()));
3550            }
3551            _ => return None,
3552        }
3553
3554        self.make_missing_self_suggestion(path.clone(), parent_scope)
3555            .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
3556            .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
3557            .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
3558    }
3559
3560    /// Suggest a missing `self::` if that resolves to an correct module.
3561    ///
3562    /// ```text
3563    ///    |
3564    /// LL | use foo::Bar;
3565    ///    |     ^^^ did you mean `self::foo`?
3566    /// ```
3567    {}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3567u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::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 /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3576",
                                    "rustc_resolve::diagnostics::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3576u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("result")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("result");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            if let PathResult::Module(..) = result {
                Some((path, None))
            } else { None }
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
3568    fn make_missing_self_suggestion(
3569        &self,
3570        mut path: Vec<Segment>,
3571        parent_scope: &ParentScope<'ra>,
3572    ) -> Option<(Vec<Segment>, Option<String>)> {
3573        // Replace first ident with `self` and check if that is valid.
3574        path[0].ident.name = kw::SelfLower;
3575        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3576        debug!(?path, ?result);
3577        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3578    }
3579
3580    /// Suggests a missing `crate::` if that resolves to an correct module.
3581    ///
3582    /// ```text
3583    ///    |
3584    /// LL | use foo::Bar;
3585    ///    |     ^^^ did you mean `crate::foo`?
3586    /// ```
3587    {}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3587u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::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 /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3596",
                                    "rustc_resolve::diagnostics::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3596u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("result")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("result");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
                                                        as &dyn ::tracing::field::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))]
3588    fn make_missing_crate_suggestion(
3589        &self,
3590        mut path: Vec<Segment>,
3591        parent_scope: &ParentScope<'ra>,
3592    ) -> Option<(Vec<Segment>, Option<String>)> {
3593        // Replace first ident with `crate` and check if that is valid.
3594        path[0].ident.name = kw::Crate;
3595        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3596        debug!(?path, ?result);
3597        if let PathResult::Module(..) = result {
3598            Some((
3599                path,
3600                Some(
3601                    "`use` statements changed in Rust 2018; read more at \
3602                     <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
3603                     clarity.html>"
3604                        .to_string(),
3605                ),
3606            ))
3607        } else {
3608            None
3609        }
3610    }
3611
3612    /// Suggests a missing `super::` if that resolves to an correct module.
3613    ///
3614    /// ```text
3615    ///    |
3616    /// LL | use foo::Bar;
3617    ///    |     ^^^ did you mean `super::foo`?
3618    /// ```
3619    {}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3619u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::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 /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3628",
                                    "rustc_resolve::diagnostics::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3628u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    },
                                                    {
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("result")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("result");
                                                        NAME.as_str()
                                                    }], ::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};
                            __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                        as &dyn ::tracing::field::Value)),
                                            (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
                                                        as &dyn ::tracing::field::Value))])
                        });
                } else { ; }
            };
            if let PathResult::Module(..) = result {
                Some((path, None))
            } else { None }
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
3620    fn make_missing_super_suggestion(
3621        &self,
3622        mut path: Vec<Segment>,
3623        parent_scope: &ParentScope<'ra>,
3624    ) -> Option<(Vec<Segment>, Option<String>)> {
3625        // Replace first ident with `crate` and check if that is valid.
3626        path[0].ident.name = kw::Super;
3627        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3628        debug!(?path, ?result);
3629        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3630    }
3631
3632    /// Suggests a missing external crate name if that resolves to an correct module.
3633    ///
3634    /// ```text
3635    ///    |
3636    /// LL | use foobar::Baz;
3637    ///    |     ^^^^^^ did you mean `baz::foobar`?
3638    /// ```
3639    ///
3640    /// Used when importing a submodule of an external crate but missing that crate's
3641    /// name as the first part of path.
3642    {}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(3642u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("path")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("path");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::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 /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3663",
                                        "rustc_resolve::diagnostics::impls",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                        ::tracing_core::__macro_support::Option::Some(3663u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                        ::tracing_core::field::FieldSet::new(&[{
                                                            const NAME:
                                                                ::tracing::__macro_support::FieldName<{
                                                                    ::tracing::__macro_support::FieldName::len("path")
                                                                }> =
                                                                ::tracing::__macro_support::FieldName::new("path");
                                                            NAME.as_str()
                                                        },
                                                        {
                                                            const NAME:
                                                                ::tracing::__macro_support::FieldName<{
                                                                    ::tracing::__macro_support::FieldName::len("name")
                                                                }> =
                                                                ::tracing::__macro_support::FieldName::new("name");
                                                            NAME.as_str()
                                                        },
                                                        {
                                                            const NAME:
                                                                ::tracing::__macro_support::FieldName<{
                                                                    ::tracing::__macro_support::FieldName::len("result")
                                                                }> =
                                                                ::tracing::__macro_support::FieldName::new("result");
                                                            NAME.as_str()
                                                        }], ::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};
                                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&name)
                                                            as &dyn ::tracing::field::Value)),
                                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
                                                            as &dyn ::tracing::field::Value))])
                            });
                    } else { ; }
                };
                if let PathResult::Module(..) = result {
                    return Some((path, None));
                }
            }
            None
        }
    }
}#[instrument(level = "debug", skip(self, parent_scope))]
3643    fn make_external_crate_suggestion(
3644        &self,
3645        mut path: Vec<Segment>,
3646        parent_scope: &ParentScope<'ra>,
3647    ) -> Option<(Vec<Segment>, Option<String>)> {
3648        if path[1].ident.span.is_rust_2015() {
3649            return None;
3650        }
3651
3652        // Sort extern crate names in *reverse* order to get
3653        // 1) some consistent ordering for emitted diagnostics, and
3654        // 2) `std` suggestions before `core` suggestions.
3655        let mut extern_crate_names =
3656            self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
3657        extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
3658
3659        for name in extern_crate_names.into_iter() {
3660            // Replace first ident with a crate name and check if that is valid.
3661            path[0].ident.name = name;
3662            let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3663            debug!(?path, ?name, ?result);
3664            if let PathResult::Module(..) = result {
3665                return Some((path, None));
3666            }
3667        }
3668
3669        None
3670    }
3671
3672    /// Suggests importing a macro from the root of the crate rather than a module within
3673    /// the crate.
3674    ///
3675    /// ```text
3676    /// help: a macro with this name exists at the root of the crate
3677    ///    |
3678    /// LL | use issue_59764::makro;
3679    ///    |     ^^^^^^^^^^^^^^^^^^
3680    ///    |
3681    ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
3682    ///            at the root of the crate instead of the module where it is defined
3683    /// ```
3684    pub(crate) fn check_for_module_export_macro(
3685        &mut self,
3686        import: Import<'ra>,
3687        module: ModuleOrUniformRoot<'ra>,
3688        ident: Ident,
3689    ) -> Option<(Option<Suggestion>, Option<String>)> {
3690        let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3691            return None;
3692        };
3693
3694        while let Some(parent) = crate_module.parent {
3695            crate_module = parent;
3696        }
3697
3698        if module == ModuleOrUniformRoot::Module(crate_module) {
3699            // Don't make a suggestion if the import was already from the root of the crate.
3700            return None;
3701        }
3702
3703        let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3704        let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3705        let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3706            return None;
3707        };
3708        if !kinds.contains(MacroKinds::BANG) {
3709            return None;
3710        }
3711        let module_name = crate_module.name().unwrap_or(kw::Crate);
3712        let import_snippet = match import.kind {
3713            ImportKind::Single { source, target, .. } if source != target => {
3714                ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} as {1}", source, target))
    })format!("{source} as {target}")
3715            }
3716            _ => ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}", ident))
    })format!("{ident}"),
3717        };
3718
3719        let mut corrections: Vec<(Span, String)> = Vec::new();
3720        if !import.is_nested() {
3721            // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
3722            // intermediate segments.
3723            corrections.push((import.span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}::{1}", module_name,
                import_snippet))
    })format!("{module_name}::{import_snippet}")));
3724        } else {
3725            // Find the binding span (and any trailing commas and spaces).
3726            //   i.e. `use a::b::{c, d, e};`
3727            //                      ^^^
3728            let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3729                self.tcx.sess,
3730                import.span,
3731                import.use_span,
3732            );
3733            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3733",
                        "rustc_resolve::diagnostics::impls",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                        ::tracing_core::__macro_support::Option::Some(3733u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("found_closing_brace")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("found_closing_brace");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("binding_span")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("binding_span");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&found_closing_brace
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&binding_span)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(found_closing_brace, ?binding_span);
3734
3735            let mut removal_span = binding_span;
3736
3737            // If the binding span ended with a closing brace, as in the below example:
3738            //   i.e. `use a::b::{c, d};`
3739            //                      ^
3740            // Then expand the span of characters to remove to include the previous
3741            // binding's trailing comma.
3742            //   i.e. `use a::b::{c, d};`
3743            //                    ^^^
3744            if found_closing_brace
3745                && let Some(previous_span) =
3746                    extend_span_to_previous_binding(self.tcx.sess, binding_span)
3747            {
3748                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3748",
                        "rustc_resolve::diagnostics::impls",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                        ::tracing_core::__macro_support::Option::Some(3748u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("previous_span")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("previous_span");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&previous_span)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?previous_span);
3749                removal_span = removal_span.with_lo(previous_span.lo());
3750            }
3751            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3751",
                        "rustc_resolve::diagnostics::impls",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                        ::tracing_core::__macro_support::Option::Some(3751u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("removal_span")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("removal_span");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&removal_span)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(?removal_span);
3752
3753            // Remove the `removal_span`.
3754            corrections.push((removal_span, "".to_string()));
3755
3756            // Find the span after the crate name and if it has nested imports immediately
3757            // after the crate name already.
3758            //   i.e. `use a::b::{c, d};`
3759            //               ^^^^^^^^^
3760            //   or  `use a::{b, c, d}};`
3761            //               ^^^^^^^^^^^
3762            let (has_nested, after_crate_name) =
3763                find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3764            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event /rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs:3764",
                        "rustc_resolve::diagnostics::impls",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                        ::tracing_core::__macro_support::Option::Some(3764u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                        ::tracing_core::field::FieldSet::new(&[{
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("has_nested")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("has_nested");
                                            NAME.as_str()
                                        },
                                        {
                                            const NAME:
                                                ::tracing::__macro_support::FieldName<{
                                                    ::tracing::__macro_support::FieldName::len("after_crate_name")
                                                }> =
                                                ::tracing::__macro_support::FieldName::new("after_crate_name");
                                            NAME.as_str()
                                        }], ::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};
                __CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&has_nested
                                            as &dyn ::tracing::field::Value)),
                                (::tracing::__macro_support::Option::Some(&::tracing::field::debug(&after_crate_name)
                                            as &dyn ::tracing::field::Value))])
            });
    } else { ; }
};debug!(has_nested, ?after_crate_name);
3765
3766            let source_map = self.tcx.sess.source_map();
3767
3768            // Make sure this is actually crate-relative.
3769            let is_definitely_crate = import
3770                .module_path
3771                .first()
3772                .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3773
3774            // Add the import to the start, with a `{` if required.
3775            let start_point = source_map.start_point(after_crate_name);
3776            if is_definitely_crate
3777                && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3778            {
3779                corrections.push((
3780                    start_point,
3781                    if has_nested {
3782                        // In this case, `start_snippet` must equal '{'.
3783                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
                import_snippet))
    })format!("{start_snippet}{import_snippet}, ")
3784                    } else {
3785                        // In this case, add a `{`, then the moved import, then whatever
3786                        // was there before.
3787                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
                start_snippet))
    })format!("{{{import_snippet}, {start_snippet}")
3788                    },
3789                ));
3790
3791                // Add a `};` to the end if nested, matching the `{` added at the start.
3792                if !has_nested {
3793                    corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3794                }
3795            } else {
3796                // If the root import is module-relative, add the import separately
3797                if let Ok(vis) = source_map.span_to_snippet(import.vis_span)
3798                    && let Some(indentation) = source_map.indentation_before(import.use_span)
3799                {
3800                    let vis = if vis.trim().is_empty() { String::new() } else { ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} ", vis))
    })format!("{vis} ") };
3801                    corrections.push((
3802                        import.use_span.shrink_to_lo(),
3803                        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0}use {1}::{2};\n{3}", vis,
                module_name, import_snippet, indentation))
    })format!("{vis}use {module_name}::{import_snippet};\n{indentation}"),
3804                    ));
3805                }
3806            }
3807        }
3808
3809        let suggestion = Some((
3810            corrections,
3811            String::from("a macro with this name exists at the root of the crate"),
3812            Applicability::MaybeIncorrect,
3813        ));
3814        Some((
3815            suggestion,
3816            Some(
3817                "this could be because a macro annotated with `#[macro_export]` will be exported \
3818            at the root of the crate instead of the module where it is defined"
3819                    .to_string(),
3820            ),
3821        ))
3822    }
3823
3824    /// Finds a cfg-ed out item inside `module` with the matching name.
3825    pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3826        let local_items;
3827        let symbols = if module.is_local() {
3828            local_items = self
3829                .stripped_cfg_items
3830                .iter()
3831                .filter_map(|item| {
3832                    let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
3833                        ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
3834                            Some(def_id)
3835                        }
3836                        _ => None,
3837                    })?;
3838                    Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3839                })
3840                .collect::<Vec<_>>();
3841            local_items.as_slice()
3842        } else {
3843            self.tcx.stripped_cfg_items(module.krate)
3844        };
3845
3846        for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3847            if ident.name != *segment {
3848                continue;
3849            }
3850
3851            let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3852
3853            fn comes_from_same_module_for_glob(
3854                r: &Resolver<'_, '_>,
3855                parent_module: DefId,
3856                module: DefId,
3857                visited: &mut FxHashMap<DefId, bool>,
3858            ) -> bool {
3859                if let Some(&cached) = visited.get(&parent_module) {
3860                    // this branch is prevent from being called recursively infinity,
3861                    // because there has some cycles in globs imports,
3862                    // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32`
3863                    return cached;
3864                }
3865                visited.insert(parent_module, false);
3866                let mut res = false;
3867                let m = r.expect_module(parent_module);
3868                if m.is_local() {
3869                    for importer in m.glob_importers.borrow_checked(r).iter() {
3870                        if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
3871                        {
3872                            if next_parent_module == module
3873                                || comes_from_same_module_for_glob(
3874                                    r,
3875                                    next_parent_module,
3876                                    module,
3877                                    visited,
3878                                )
3879                            {
3880                                res = true;
3881                                break;
3882                            }
3883                        }
3884                    }
3885                }
3886                visited.insert(parent_module, res);
3887                res
3888            }
3889
3890            let comes_from_same_module = parent_module == module
3891                || comes_from_same_module_for_glob(
3892                    self,
3893                    parent_module,
3894                    module,
3895                    &mut Default::default(),
3896                );
3897            if !comes_from_same_module {
3898                continue;
3899            }
3900
3901            let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3902                diagnostics::ItemWas::BehindFeature { feature, span: cfg.1 }
3903            } else {
3904                diagnostics::ItemWas::CfgOut { span: cfg.1 }
3905            };
3906            let note = diagnostics::FoundItemConfigureOut { span: ident.span, item_was };
3907            err.subdiagnostic(note);
3908        }
3909    }
3910
3911    pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3912        match def_id.as_local() {
3913            Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3914            None => {
3915                self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3916                    let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3917                    let vis = self.tcx.visibility(ctor_def_id);
3918                    let field_visibilities = self
3919                        .tcx
3920                        .associated_item_def_ids(def_id)
3921                        .iter()
3922                        .map(|&field_id| self.tcx.visibility(field_id))
3923                        .collect();
3924                    StructCtor { res, vis, field_visibilities }
3925                })
3926            }
3927        }
3928    }
3929
3930    /// Gets the name and `#[diagnostic::on_unknown]` attribute data associated with this `DefId`.
3931    pub(crate) fn on_unknown_data(&self, def_id: DefId) -> Option<(Symbol, &Directive)> {
3932        let directive = match def_id.as_local() {
3933            Some(local) => Some(self.on_unknown_data.get(&local)?.directive.as_ref()),
3934            None => {
    {
        'done:
            {
            for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &self.tcx) {
                #[allow(unused_imports)]
                use ::rustc_attr_ir::AttributeKind::*;
                let i: &::rustc_attr_ir::Attribute = i;
                match i {
                    ::rustc_attr_ir::Attribute::Parsed(OnUnknown { directive })
                        => {
                        break 'done Some(directive);
                    }
                    ::rustc_attr_ir::Attribute::Tool(..) |
                        ::rustc_attr_ir::Attribute::DeriveHelper(..) =>
                        {}
                        #[deny(unreachable_patterns)]
                        _ => {}
                }
            }
            None
        }
    }
}find_attr!(self.tcx, def_id, OnUnknown { directive } => directive)?.as_deref(),
3935        }?;
3936
3937        let name =
3938            self.expect_module(def_id).name().unwrap_or_else(|| self.tcx.crate_name(def_id.krate));
3939
3940        Some((name, directive))
3941    }
3942}
3943
3944/// Given a `binding_span` of a binding within a use statement:
3945///
3946/// ```ignore (illustrative)
3947/// use foo::{a, b, c};
3948/// //           ^
3949/// ```
3950///
3951/// then return the span until the next binding or the end of the statement:
3952///
3953/// ```ignore (illustrative)
3954/// use foo::{a, b, c};
3955/// //           ^^^
3956/// ```
3957fn find_span_of_binding_until_next_binding(
3958    sess: &Session,
3959    binding_span: Span,
3960    use_span: Span,
3961) -> (bool, Span) {
3962    let source_map = sess.source_map();
3963
3964    // Find the span of everything after the binding.
3965    //   i.e. `a, e};` or `a};`
3966    let binding_until_end = binding_span.with_hi(use_span.hi());
3967
3968    // Find everything after the binding but not including the binding.
3969    //   i.e. `, e};` or `};`
3970    let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3971
3972    // Keep characters in the span until we encounter something that isn't a comma or
3973    // whitespace.
3974    //   i.e. `, ` or ``.
3975    //
3976    // Also note whether a closing brace character was encountered. If there
3977    // was, then later go backwards to remove any trailing commas that are left.
3978    let mut found_closing_brace = false;
3979    let after_binding_until_next_binding =
3980        source_map.span_take_while(after_binding_until_end, |&ch| {
3981            if ch == '}' {
3982                found_closing_brace = true;
3983            }
3984            ch == ' ' || ch == ','
3985        });
3986
3987    // Combine the two spans.
3988    //   i.e. `a, ` or `a`.
3989    //
3990    // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
3991    let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3992
3993    (found_closing_brace, span)
3994}
3995
3996/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
3997/// binding.
3998///
3999/// ```ignore (illustrative)
4000/// use foo::a::{a, b, c};
4001/// //            ^^--- binding span
4002/// //            |
4003/// //            returned span
4004///
4005/// use foo::{a, b, c};
4006/// //        --- binding span
4007/// ```
4008fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
4009    let source_map = sess.source_map();
4010
4011    // `prev_source` will contain all of the source that came before the span.
4012    // Then split based on a command and take the first (i.e. closest to our span)
4013    // snippet. In the example, this is a space.
4014    let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
4015
4016    let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
4017    let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
4018    if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
4019        return None;
4020    }
4021
4022    let prev_comma = prev_comma.first().unwrap();
4023    let prev_starting_brace = prev_starting_brace.first().unwrap();
4024
4025    // If the amount of source code before the comma is greater than
4026    // the amount of source code before the starting brace then we've only
4027    // got one item in the nested item (eg. `issue_52891::{self}`).
4028    if prev_comma.len() > prev_starting_brace.len() {
4029        return None;
4030    }
4031
4032    Some(binding_span.with_lo(BytePos(
4033        // Take away the number of bytes for the characters we've found and an
4034        // extra for the comma.
4035        binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
4036    )))
4037}
4038
4039/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
4040/// it is a nested use tree.
4041///
4042/// ```ignore (illustrative)
4043/// use foo::a::{b, c};
4044/// //       ^^^^^^^^^^ -- false
4045///
4046/// use foo::{a, b, c};
4047/// //       ^^^^^^^^^^ -- true
4048///
4049/// use foo::{a, b::{c, d}};
4050/// //       ^^^^^^^^^^^^^^^ -- true
4051/// ```
4052{}
#[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::impls",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("/rustc-dev/c980177d81d16f843a500905ac98c0cf3af1fd8d/compiler/rustc_resolve/src/diagnostics/impls.rs"),
                                    ::tracing_core::__macro_support::Option::Some(4052u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
                                    ::tracing_core::field::FieldSet::new(&[{
                                                        const NAME:
                                                            ::tracing::__macro_support::FieldName<{
                                                                ::tracing::__macro_support::FieldName::len("use_span")
                                                            }> =
                                                            ::tracing::__macro_support::FieldName::new("use_span");
                                                        NAME.as_str()
                                                    }], ::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};
                                meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_span)
                                                            as &dyn ::tracing::field::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))]
4053fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
4054    let source_map = sess.source_map();
4055
4056    // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
4057    let mut num_colons = 0;
4058    // Find second colon.. `use issue_59764:`
4059    let until_second_colon = source_map.span_take_while(use_span, |c| {
4060        if *c == ':' {
4061            num_colons += 1;
4062        }
4063        !matches!(c, ':' if num_colons == 2)
4064    });
4065    // Find everything after the second colon.. `foo::{baz, makro};`
4066    let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
4067
4068    let mut found_a_non_whitespace_character = false;
4069    // Find the first non-whitespace character in `from_second_colon`.. `f`
4070    let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
4071        if found_a_non_whitespace_character {
4072            return false;
4073        }
4074        if !c.is_whitespace() {
4075            found_a_non_whitespace_character = true;
4076        }
4077        true
4078    });
4079
4080    // Find the first `{` in from_second_colon.. `foo::{`
4081    let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
4082
4083    (next_left_bracket == after_second_colon, from_second_colon)
4084}
4085
4086/// A suggestion has already been emitted, change the wording slightly to clarify that both are
4087/// independent options.
4088enum Instead {
4089    Yes,
4090    No,
4091}
4092
4093/// Whether an existing place with an `use` item was found.
4094enum FoundUse {
4095    Yes,
4096    No,
4097}
4098
4099/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
4100pub(crate) enum DiagMode {
4101    Normal,
4102    /// The binding is part of a pattern
4103    Pattern,
4104    /// The binding is part of a use statement
4105    Import {
4106        /// `true` means diagnostics is for unresolved import
4107        unresolved_import: bool,
4108        /// `true` mean add the tips afterward for case `use a::{b,c}`,
4109        /// rather than replacing within.
4110        append: bool,
4111    },
4112}
4113
4114pub(crate) fn import_candidates(
4115    tcx: TyCtxt<'_>,
4116    err: &mut Diag<'_>,
4117    // This is `None` if all placement locations are inside expansions
4118    use_placement_span: Option<Span>,
4119    candidates: &[ImportSuggestion],
4120    mode: DiagMode,
4121    append: &str,
4122) {
4123    show_candidates(
4124        tcx,
4125        err,
4126        use_placement_span,
4127        candidates,
4128        Instead::Yes,
4129        FoundUse::Yes,
4130        mode,
4131        ::alloc::vec::Vec::new()vec![],
4132        append,
4133    );
4134}
4135
4136type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
4137
4138/// When an entity with a given name is not available in scope, we search for
4139/// entities with that name in all crates. This method allows outputting the
4140/// results of this search in a programmer-friendly way. If any entities are
4141/// found and suggested, returns `true`, otherwise returns `false`.
4142fn show_candidates(
4143    tcx: TyCtxt<'_>,
4144    err: &mut Diag<'_>,
4145    // This is `None` if all placement locations are inside expansions
4146    use_placement_span: Option<Span>,
4147    candidates: &[ImportSuggestion],
4148    instead: Instead,
4149    found_use: FoundUse,
4150    mode: DiagMode,
4151    path: Vec<Segment>,
4152    append: &str,
4153) -> bool {
4154    if candidates.is_empty() {
4155        return false;
4156    }
4157
4158    let mut showed = false;
4159    let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
4160    let mut accessible_renames: Vec<PathString<'_>> = Vec::new();
4161    let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
4162
4163    candidates.iter().for_each(|c| {
4164        if c.accessible {
4165            // Don't suggest `#[doc(hidden)]` items from other crates
4166            if c.doc_visible {
4167                if let [first, .., last] | [first @ last] = &path
4168                    && !first.ident.span.in_external_macro(tcx.sess.source_map())
4169                    && first.ident.span.ctxt() == last.ident.span.ctxt()
4170                    && c.path.segments.len() == 1
4171                {
4172                    accessible_renames.push((
4173                        pprust::path_to_string(&c.path),
4174                        c.descr,
4175                        c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
4176                        &c.note,
4177                        c.via_import,
4178                    ));
4179                } else {
4180                    accessible_path_strings.push((
4181                        pprust::path_to_string(&c.path),
4182                        c.descr,
4183                        c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
4184                        &c.note,
4185                        c.via_import,
4186                    ));
4187                }
4188            }
4189        } else {
4190            inaccessible_path_strings.push((
4191                pprust::path_to_string(&c.path),
4192                c.descr,
4193                c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
4194                &c.note,
4195                c.via_import,
4196            ));
4197        }
4198    });
4199
4200    // we want consistent results across executions, but candidates are produced
4201    // by iterating through a hash map, so make sure they are ordered:
4202    for path_strings in
4203        [&mut accessible_path_strings, &mut accessible_renames, &mut inaccessible_path_strings]
4204    {
4205        path_strings.sort_by(|a, b| a.0.cmp(&b.0));
4206        path_strings.dedup_by(|a, b| a.0 == b.0);
4207        let core_path_strings =
4208            path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
4209        let std_path_strings =
4210            path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
4211        let foreign_crate_path_strings =
4212            path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
4213
4214        // We list the `crate` local paths first.
4215        // Then we list the `std`/`core` paths.
4216        if std_path_strings.len() == core_path_strings.len() {
4217            // Do not list `core::` paths if we are already listing the `std::` ones.
4218            path_strings.extend(std_path_strings);
4219        } else {
4220            path_strings.extend(std_path_strings);
4221            path_strings.extend(core_path_strings);
4222        }
4223        // List all paths from foreign crates last.
4224        path_strings.extend(foreign_crate_path_strings);
4225    }
4226
4227    if !accessible_renames.is_empty() {
4228        let (determiner, kind, s, through) =
4229            if let [(_, descr, _, _, via_import)] = &accessible_renames[..] {
4230                ("this", *descr, "", if *via_import { " through its public re-export" } else { "" })
4231            } else {
4232                // Get the unique item kinds and if there's only one, we use the right kind name
4233                // instead of the more generic "items".
4234                let kinds = accessible_path_strings
4235                    .iter()
4236                    .map(|(_, descr, _, _, _)| *descr)
4237                    .collect::<UnordSet<&str>>();
4238                let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
4239                let s = if kind.ends_with('s') { "es" } else { "s" };
4240
4241                ("one of these", kind, s, "")
4242            };
4243
4244        let instead = if let Instead::Yes = instead { " instead" } else { "" };
4245        let msg = ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("consider using {0} {1}{2}{3}{4}",
                determiner, kind, s, through, instead))
    })format!("consider using {determiner} {kind}{s}{through}{instead}");
4246
4247        for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4248            err.note(note.clone());
4249        }
4250
4251        err.span_suggestions_with_style(
4252            path[0].ident.span.to(path[path.len() - 1].ident.span),
4253            msg,
4254            accessible_renames.into_iter().map(|a| a.0),
4255            Applicability::MaybeIncorrect,
4256            SuggestionStyle::ShowAlways,
4257        );
4258        showed = true;
4259    }
4260    if !accessible_path_strings.is_empty() {
4261        let (determiner, kind, s, name, through) =
4262            if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
4263                (
4264                    "this",
4265                    *descr,
4266                    "",
4267                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" `{0}`", name))
    })format!(" `{name}`"),
4268                    if *via_import { " through its public re-export" } else { "" },
4269                )
4270            } else {
4271                // Get the unique item kinds and if there's only one, we use the right kind name
4272                // instead of the more generic "items".
4273                let kinds = accessible_path_strings
4274                    .iter()
4275                    .map(|(_, descr, _, _, _)| *descr)
4276                    .collect::<UnordSet<&str>>();
4277                let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
4278                let s = if kind.ends_with('s') { "es" } else { "s" };
4279
4280                ("one of these", kind, s, String::new(), "")
4281            };
4282
4283        let instead = if let Instead::Yes = instead { " instead" } else { "" };
4284        let mut msg = if let DiagMode::Pattern = mode {
4285            ::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!(
4286                "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
4287                 pattern",
4288            )
4289        } else {
4290            ::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}")
4291        };
4292
4293        for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4294            err.note(note.clone());
4295        }
4296
4297        let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
4298            msg.push(':');
4299
4300            for candidate in accessible_path_strings {
4301                msg.push('\n');
4302                msg.push_str(&candidate.0);
4303            }
4304        };
4305
4306        if let Some(span) = use_placement_span {
4307            let (add_use, trailing) = match mode {
4308                DiagMode::Pattern => {
4309                    err.span_suggestions(
4310                        span,
4311                        msg,
4312                        accessible_path_strings.into_iter().map(|a| a.0),
4313                        Applicability::MaybeIncorrect,
4314                    );
4315                    return true;
4316                }
4317                DiagMode::Import { .. } => ("", ""),
4318                DiagMode::Normal => ("use ", ";\n"),
4319            };
4320            for candidate in &mut accessible_path_strings {
4321                // produce an additional newline to separate the new use statement
4322                // from the directly following item.
4323                let additional_newline = if let FoundUse::No = found_use
4324                    && let DiagMode::Normal = mode
4325                {
4326                    "\n"
4327                } else {
4328                    ""
4329                };
4330                candidate.0 =
4331                    ::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);
4332            }
4333
4334            match mode {
4335                DiagMode::Import { append: true, .. } => {
4336                    append_candidates(&mut msg, accessible_path_strings);
4337                    err.span_help(span, msg);
4338                }
4339                _ => {
4340                    err.span_suggestions_with_style(
4341                        span,
4342                        msg,
4343                        accessible_path_strings.into_iter().map(|a| a.0),
4344                        Applicability::MaybeIncorrect,
4345                        SuggestionStyle::ShowAlways,
4346                    );
4347                }
4348            }
4349
4350            if let [first, .., last] = &path[..] {
4351                let sp = first.ident.span.until(last.ident.span);
4352                // Our suggestion is empty, so make sure the span is not empty (or we'd ICE).
4353                // Can happen for derive-generated spans.
4354                if sp.can_be_used_for_suggestions() && !sp.is_empty() {
4355                    err.span_suggestion_verbose(
4356                        sp,
4357                        ::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),
4358                        "",
4359                        Applicability::Unspecified,
4360                    );
4361                }
4362            }
4363        } else {
4364            append_candidates(&mut msg, accessible_path_strings);
4365            err.help(msg);
4366        }
4367        showed = true;
4368    }
4369    if !inaccessible_path_strings.is_empty()
4370        && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
    DiagMode::Import { unresolved_import: false, .. } => true,
    _ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
4371    {
4372        let prefix =
4373            if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
4374        if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
4375            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!(
4376                "{prefix}{descr} `{name}`{} exists but is inaccessible",
4377                if let DiagMode::Pattern = mode { ", which" } else { "" }
4378            );
4379
4380            if let Some(source_span) = source_span {
4381                let span = tcx.sess.source_map().guess_head_span(*source_span);
4382                let mut multi_span = MultiSpan::from_span(span);
4383                multi_span.push_span_label(span, "not accessible");
4384                err.span_note(multi_span, msg);
4385            } else {
4386                err.note(msg);
4387            }
4388            if let Some(note) = (*note).as_deref() {
4389                err.note(note.to_string());
4390            }
4391        } else {
4392            let descr = inaccessible_path_strings
4393                .iter()
4394                .map(|&(_, descr, _, _, _)| descr)
4395                .all_equal_value()
4396                .unwrap_or("item");
4397            let plural_descr =
4398                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") };
4399
4400            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");
4401            let mut has_colon = false;
4402
4403            let mut spans = Vec::new();
4404            for (name, _, source_span, _, _) in &inaccessible_path_strings {
4405                if let Some(source_span) = source_span {
4406                    let span = tcx.sess.source_map().guess_head_span(*source_span);
4407                    spans.push((name, span));
4408                } else {
4409                    if !has_colon {
4410                        msg.push(':');
4411                        has_colon = true;
4412                    }
4413                    msg.push('\n');
4414                    msg.push_str(name);
4415                }
4416            }
4417
4418            let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
4419            for (name, span) in spans {
4420                multi_span.push_span_label(span, ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
    })format!("`{name}`: not accessible"));
4421            }
4422
4423            for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4424                err.note(note.clone());
4425            }
4426
4427            err.span_note(multi_span, msg);
4428        }
4429        showed = true;
4430    }
4431    showed
4432}
4433
4434#[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 first_legal_span first_use_span",
            &self.target_module, &self.first_legal_span,
            &&self.first_use_span)
    }
}Debug)]
4435struct UsePlacementFinder {
4436    target_module: NodeId,
4437    first_legal_span: Option<Span>,
4438    first_use_span: Option<Span>,
4439}
4440
4441impl UsePlacementFinder {
4442    fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
4443        let mut finder =
4444            UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
4445        finder.visit_crate(krate);
4446        if let Some(use_span) = finder.first_use_span {
4447            (Some(use_span), FoundUse::Yes)
4448        } else {
4449            (finder.first_legal_span, FoundUse::No)
4450        }
4451    }
4452}
4453
4454impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
4455    fn visit_crate(&mut self, c: &Crate) {
4456        if self.target_module == CRATE_NODE_ID {
4457            let inject = c.spans.inject_use_span;
4458            if is_span_suitable_for_use_injection(inject) {
4459                self.first_legal_span = Some(inject);
4460            }
4461            self.first_use_span = search_for_any_use_in_items(&c.items);
4462        } else {
4463            visit::walk_crate(self, c);
4464        }
4465    }
4466
4467    fn visit_item(&mut self, item: &'tcx ast::Item) {
4468        if self.target_module == item.id {
4469            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
4470                let inject = mod_spans.inject_use_span;
4471                if is_span_suitable_for_use_injection(inject) {
4472                    self.first_legal_span = Some(inject);
4473                }
4474                self.first_use_span = search_for_any_use_in_items(items);
4475            }
4476        } else {
4477            visit::walk_item(self, item);
4478        }
4479    }
4480}
4481
4482#[derive(#[automatically_derived]impl ::core::default::Default for BindingVisitor {
    #[inline]
    fn default() -> Self {
        BindingVisitor {
            identifiers: ::core::default::Default::default(),
            spans: ::core::default::Default::default(),
        }
    }
}Default)]
4483struct BindingVisitor {
4484    identifiers: Vec<Symbol>,
4485    spans: FxHashMap<Symbol, Vec<Span>>,
4486}
4487
4488impl<'tcx> Visitor<'tcx> for BindingVisitor {
4489    fn visit_pat(&mut self, pat: &ast::Pat) {
4490        if let ast::PatKind::Ident(_, ident, _) = pat.kind {
4491            self.identifiers.push(ident.name);
4492            self.spans.entry(ident.name).or_default().push(ident.span);
4493        }
4494        visit::walk_pat(self, pat);
4495    }
4496}
4497
4498fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
4499    for item in items {
4500        if let ItemKind::Use(..) = item.kind
4501            && is_span_suitable_for_use_injection(item.span)
4502        {
4503            let mut lo = item.span.lo();
4504            for attr in &item.attrs {
4505                if attr.span.ctxt() == item.span.ctxt() {
4506                    lo = std::cmp::min(lo, attr.span.lo());
4507                }
4508            }
4509            return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
4510        }
4511    }
4512    None
4513}
4514
4515fn is_span_suitable_for_use_injection(s: Span) -> bool {
4516    // don't suggest placing a use before the prelude
4517    // import or other generated ones
4518    !s.from_expansion()
4519}
4520
4521#[derive(#[automatically_derived]impl ::core::fmt::Debug for OnUnknownData {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field1_finish(f,
            "OnUnknownData directive", &&self.directive)
    }
}Debug, #[automatically_derived]impl ::core::clone::Clone for OnUnknownData {
    #[inline]
    fn clone(&self) -> Self {
        OnUnknownData {
            directive: ::core::clone::Clone::clone(&self.directive),
        }
    }
}Clone, #[automatically_derived]impl ::core::default::Default for OnUnknownData {
    #[inline]
    fn default() -> Self {
        OnUnknownData { directive: ::core::default::Default::default() }
    }
}Default)]
4522pub(crate) struct OnUnknownData {
4523    pub(crate) directive: Box<Directive>,
4524}
4525
4526impl OnUnknownData {
4527    pub(crate) fn from_attrs(
4528        r: &Resolver<'_, '_>,
4529        attrs: &[ast::Attribute],
4530    ) -> Option<OnUnknownData> {
4531        if r.features.diagnostic_on_unknown()
4532            && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) =
4533                AttributeParser::parse_limited_sym(
4534                    r.tcx.sess,
4535                    attrs,
4536                    &[sym::diagnostic, sym::on_unknown],
4537                )
4538        {
4539            Some(Self { directive: directive? })
4540        } else {
4541            None
4542        }
4543    }
4544}