]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_resolve/src/diagnostics.rs
migrating rustc_resolve to SessionDiagnostic. work in progress. start
[rust.git] / compiler / rustc_resolve / src / diagnostics.rs
1 use std::ptr;
2
3 use rustc_ast::ptr::P;
4 use rustc_ast::visit::{self, Visitor};
5 use rustc_ast::{self as ast, Crate, ItemKind, ModKind, NodeId, Path, CRATE_NODE_ID};
6 use rustc_ast_pretty::pprust;
7 use rustc_data_structures::fx::FxHashSet;
8 use rustc_errors::struct_span_err;
9 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan};
10 use rustc_feature::BUILTIN_ATTRIBUTES;
11 use rustc_hir::def::Namespace::{self, *};
12 use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind, PerNS};
13 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
14 use rustc_hir::PrimTy;
15 use rustc_index::vec::IndexVec;
16 use rustc_middle::bug;
17 use rustc_middle::ty::DefIdTree;
18 use rustc_session::lint::builtin::ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE;
19 use rustc_session::lint::builtin::MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS;
20 use rustc_session::lint::BuiltinLintDiagnostics;
21 use rustc_session::Session;
22 use rustc_span::edition::Edition;
23 use rustc_span::hygiene::MacroKind;
24 use rustc_span::lev_distance::find_best_match_for_name;
25 use rustc_span::source_map::SourceMap;
26 use rustc_span::symbol::{kw, sym, Ident, Symbol};
27 use rustc_span::{BytePos, Span, SyntaxContext};
28
29 use crate::errors as errs;
30 use crate::imports::{Import, ImportKind, ImportResolver};
31 use crate::late::{PatternSource, Rib};
32 use crate::path_names_to_string;
33 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingError, Finalize};
34 use crate::{HasGenericParams, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot};
35 use crate::{LexicalScopeBinding, NameBinding, NameBindingKind, PrivacyError, VisResolutionError};
36 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet};
37 use crate::{Segment, UseError};
38
39 #[cfg(test)]
40 mod tests;
41
42 type Res = def::Res<ast::NodeId>;
43
44 /// A vector of spans and replacements, a message and applicability.
45 pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
46
47 /// Potential candidate for an undeclared or out-of-scope label - contains the ident of a
48 /// similarly named label and whether or not it is reachable.
49 pub(crate) type LabelSuggestion = (Ident, bool);
50
51 #[derive(Debug)]
52 pub(crate) enum SuggestionTarget {
53     /// The target has a similar name as the name used by the programmer (probably a typo)
54     SimilarlyNamed,
55     /// The target is the only valid item that can be used in the corresponding context
56     SingleItem,
57 }
58
59 #[derive(Debug)]
60 pub(crate) struct TypoSuggestion {
61     pub candidate: Symbol,
62     /// The source location where the name is defined; None if the name is not defined
63     /// in source e.g. primitives
64     pub span: Option<Span>,
65     pub res: Res,
66     pub target: SuggestionTarget,
67 }
68
69 impl TypoSuggestion {
70     pub(crate) fn typo_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
71         Self {
72             candidate: ident.name,
73             span: Some(ident.span),
74             res,
75             target: SuggestionTarget::SimilarlyNamed,
76         }
77     }
78     pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
79         Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
80     }
81     pub(crate) fn single_item_from_ident(ident: Ident, res: Res) -> TypoSuggestion {
82         Self {
83             candidate: ident.name,
84             span: Some(ident.span),
85             res,
86             target: SuggestionTarget::SingleItem,
87         }
88     }
89 }
90
91 /// A free importable items suggested in case of resolution failure.
92 #[derive(Debug, Clone)]
93 pub(crate) struct ImportSuggestion {
94     pub did: Option<DefId>,
95     pub descr: &'static str,
96     pub path: Path,
97     pub accessible: bool,
98     /// An extra note that should be issued if this item is suggested
99     pub note: Option<String>,
100 }
101
102 /// Adjust the impl span so that just the `impl` keyword is taken by removing
103 /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
104 /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
105 ///
106 /// *Attention*: the method used is very fragile since it essentially duplicates the work of the
107 /// parser. If you need to use this function or something similar, please consider updating the
108 /// `source_map` functions and this function to something more robust.
109 fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
110     let impl_span = sm.span_until_char(impl_span, '<');
111     sm.span_until_whitespace(impl_span)
112 }
113
114 impl<'a> Resolver<'a> {
115     pub(crate) fn report_errors(&mut self, krate: &Crate) {
116         self.report_with_use_injections(krate);
117
118         for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
119             let msg = "macro-expanded `macro_export` macros from the current crate \
120                        cannot be referred to by absolute paths";
121             self.lint_buffer.buffer_lint_with_diagnostic(
122                 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
123                 CRATE_NODE_ID,
124                 span_use,
125                 msg,
126                 BuiltinLintDiagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths(span_def),
127             );
128         }
129
130         for ambiguity_error in &self.ambiguity_errors {
131             self.report_ambiguity_error(ambiguity_error);
132         }
133
134         let mut reported_spans = FxHashSet::default();
135         for error in &self.privacy_errors {
136             if reported_spans.insert(error.dedup_span) {
137                 self.report_privacy_error(error);
138             }
139         }
140     }
141
142     fn report_with_use_injections(&mut self, krate: &Crate) {
143         for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
144             self.use_injections.drain(..)
145         {
146             let (span, found_use) = if let Some(def_id) = def_id.as_local() {
147                 UsePlacementFinder::check(krate, self.def_id_to_node_id[def_id])
148             } else {
149                 (None, FoundUse::No)
150             };
151
152             if !candidates.is_empty() {
153                 show_candidates(
154                     &self.session,
155                     &self.source_span,
156                     &mut err,
157                     span,
158                     &candidates,
159                     if instead { Instead::Yes } else { Instead::No },
160                     found_use,
161                     DiagnosticMode::Normal,
162                     path,
163                 );
164                 err.emit();
165             } else if let Some((span, msg, sugg, appl)) = suggestion {
166                 err.span_suggestion(span, msg, sugg, appl);
167                 err.emit();
168             } else if let [segment] = path.as_slice() && is_call {
169                 err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
170             } else {
171                 err.emit();
172             }
173         }
174     }
175
176     pub(crate) fn report_conflict<'b>(
177         &mut self,
178         parent: Module<'_>,
179         ident: Ident,
180         ns: Namespace,
181         new_binding: &NameBinding<'b>,
182         old_binding: &NameBinding<'b>,
183     ) {
184         // Error on the second of two conflicting names
185         if old_binding.span.lo() > new_binding.span.lo() {
186             return self.report_conflict(parent, ident, ns, old_binding, new_binding);
187         }
188
189         let container = match parent.kind {
190             ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()),
191             ModuleKind::Block => "block",
192         };
193
194         let old_noun = match old_binding.is_import_user_facing() {
195             true => "import",
196             false => "definition",
197         };
198
199         let new_participle = match new_binding.is_import_user_facing() {
200             true => "imported",
201             false => "defined",
202         };
203
204         let (name, span) =
205             (ident.name, self.session.source_map().guess_head_span(new_binding.span));
206
207         if let Some(s) = self.name_already_seen.get(&name) {
208             if s == &span {
209                 return;
210             }
211         }
212
213         let old_kind = match (ns, old_binding.module()) {
214             (ValueNS, _) => "value",
215             (MacroNS, _) => "macro",
216             (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
217             (TypeNS, Some(module)) if module.is_normal() => "module",
218             (TypeNS, Some(module)) if module.is_trait() => "trait",
219             (TypeNS, _) => "type",
220         };
221
222         let msg = format!("the name `{}` is defined multiple times", name);
223
224         let mut err = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
225             (true, true) => struct_span_err!(self.session, span, E0259, "{}", msg),
226             (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
227                 true => struct_span_err!(self.session, span, E0254, "{}", msg),
228                 false => struct_span_err!(self.session, span, E0260, "{}", msg),
229             },
230             _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
231                 (false, false) => struct_span_err!(self.session, span, E0428, "{}", msg),
232                 (true, true) => struct_span_err!(self.session, span, E0252, "{}", msg),
233                 _ => struct_span_err!(self.session, span, E0255, "{}", msg),
234             },
235         };
236
237         err.note(&format!(
238             "`{}` must be defined only once in the {} namespace of this {}",
239             name,
240             ns.descr(),
241             container
242         ));
243
244         err.span_label(span, format!("`{}` re{} here", name, new_participle));
245         if !old_binding.span.is_dummy() && old_binding.span != span {
246             err.span_label(
247                 self.session.source_map().guess_head_span(old_binding.span),
248                 format!("previous {} of the {} `{}` here", old_noun, old_kind, name),
249             );
250         }
251
252         // See https://github.com/rust-lang/rust/issues/32354
253         use NameBindingKind::Import;
254         let can_suggest = |binding: &NameBinding<'_>, import: &self::Import<'_>| {
255             !binding.span.is_dummy()
256                 && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
257         };
258         let import = match (&new_binding.kind, &old_binding.kind) {
259             // If there are two imports where one or both have attributes then prefer removing the
260             // import without attributes.
261             (Import { import: new, .. }, Import { import: old, .. })
262                 if {
263                     (new.has_attributes || old.has_attributes)
264                         && can_suggest(old_binding, old)
265                         && can_suggest(new_binding, new)
266                 } =>
267             {
268                 if old.has_attributes {
269                     Some((new, new_binding.span, true))
270                 } else {
271                     Some((old, old_binding.span, true))
272                 }
273             }
274             // Otherwise prioritize the new binding.
275             (Import { import, .. }, other) if can_suggest(new_binding, import) => {
276                 Some((import, new_binding.span, other.is_import()))
277             }
278             (other, Import { import, .. }) if can_suggest(old_binding, import) => {
279                 Some((import, old_binding.span, other.is_import()))
280             }
281             _ => None,
282         };
283
284         // Check if the target of the use for both bindings is the same.
285         let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
286         let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
287         let from_item =
288             self.extern_prelude.get(&ident).map_or(true, |entry| entry.introduced_by_item);
289         // Only suggest removing an import if both bindings are to the same def, if both spans
290         // aren't dummy spans. Further, if both bindings are imports, then the ident must have
291         // been introduced by an item.
292         let should_remove_import = duplicate
293             && !has_dummy_span
294             && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
295
296         match import {
297             Some((import, span, true)) if should_remove_import && import.is_nested() => {
298                 self.add_suggestion_for_duplicate_nested_use(&mut err, import, span)
299             }
300             Some((import, _, true)) if should_remove_import && !import.is_glob() => {
301                 // Simple case - remove the entire import. Due to the above match arm, this can
302                 // only be a single use so just remove it entirely.
303                 err.tool_only_span_suggestion(
304                     import.use_span_with_attributes,
305                     "remove unnecessary import",
306                     "",
307                     Applicability::MaybeIncorrect,
308                 );
309             }
310             Some((import, span, _)) => {
311                 self.add_suggestion_for_rename_of_use(&mut err, name, import, span)
312             }
313             _ => {}
314         }
315
316         err.emit();
317         self.name_already_seen.insert(name, span);
318     }
319
320     /// This function adds a suggestion to change the binding name of a new import that conflicts
321     /// with an existing import.
322     ///
323     /// ```text,ignore (diagnostic)
324     /// help: you can use `as` to change the binding name of the import
325     ///    |
326     /// LL | use foo::bar as other_bar;
327     ///    |     ^^^^^^^^^^^^^^^^^^^^^
328     /// ```
329     fn add_suggestion_for_rename_of_use(
330         &self,
331         err: &mut Diagnostic,
332         name: Symbol,
333         import: &Import<'_>,
334         binding_span: Span,
335     ) {
336         let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
337             format!("Other{}", name)
338         } else {
339             format!("other_{}", name)
340         };
341
342         let mut suggestion = None;
343         match import.kind {
344             ImportKind::Single { type_ns_only: true, .. } => {
345                 suggestion = Some(format!("self as {}", suggested_name))
346             }
347             ImportKind::Single { source, .. } => {
348                 if let Some(pos) =
349                     source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize)
350                 {
351                     if let Ok(snippet) = self.session.source_map().span_to_snippet(binding_span) {
352                         if pos <= snippet.len() {
353                             suggestion = Some(format!(
354                                 "{} as {}{}",
355                                 &snippet[..pos],
356                                 suggested_name,
357                                 if snippet.ends_with(';') { ";" } else { "" }
358                             ))
359                         }
360                     }
361                 }
362             }
363             ImportKind::ExternCrate { source, target, .. } => {
364                 suggestion = Some(format!(
365                     "extern crate {} as {};",
366                     source.unwrap_or(target.name),
367                     suggested_name,
368                 ))
369             }
370             _ => unreachable!(),
371         }
372
373         let rename_msg = "you can use `as` to change the binding name of the import";
374         if let Some(suggestion) = suggestion {
375             err.span_suggestion(
376                 binding_span,
377                 rename_msg,
378                 suggestion,
379                 Applicability::MaybeIncorrect,
380             );
381         } else {
382             err.span_label(binding_span, rename_msg);
383         }
384     }
385
386     /// This function adds a suggestion to remove an unnecessary binding from an import that is
387     /// nested. In the following example, this function will be invoked to remove the `a` binding
388     /// in the second use statement:
389     ///
390     /// ```ignore (diagnostic)
391     /// use issue_52891::a;
392     /// use issue_52891::{d, a, e};
393     /// ```
394     ///
395     /// The following suggestion will be added:
396     ///
397     /// ```ignore (diagnostic)
398     /// use issue_52891::{d, a, e};
399     ///                      ^-- help: remove unnecessary import
400     /// ```
401     ///
402     /// If the nested use contains only one import then the suggestion will remove the entire
403     /// line.
404     ///
405     /// It is expected that the provided import is nested - this isn't checked by the
406     /// function. If this invariant is not upheld, this function's behaviour will be unexpected
407     /// as characters expected by span manipulations won't be present.
408     fn add_suggestion_for_duplicate_nested_use(
409         &self,
410         err: &mut Diagnostic,
411         import: &Import<'_>,
412         binding_span: Span,
413     ) {
414         assert!(import.is_nested());
415         let message = "remove unnecessary import";
416
417         // Two examples will be used to illustrate the span manipulations we're doing:
418         //
419         // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
420         //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.
421         // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
422         //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.
423
424         let (found_closing_brace, span) =
425             find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span);
426
427         // If there was a closing brace then identify the span to remove any trailing commas from
428         // previous imports.
429         if found_closing_brace {
430             if let Some(span) = extend_span_to_previous_binding(self.session, span) {
431                 err.tool_only_span_suggestion(span, message, "", Applicability::MaybeIncorrect);
432             } else {
433                 // Remove the entire line if we cannot extend the span back, this indicates an
434                 // `issue_52891::{self}` case.
435                 err.span_suggestion(
436                     import.use_span_with_attributes,
437                     message,
438                     "",
439                     Applicability::MaybeIncorrect,
440                 );
441             }
442
443             return;
444         }
445
446         err.span_suggestion(span, message, "", Applicability::MachineApplicable);
447     }
448
449     pub(crate) fn lint_if_path_starts_with_module(
450         &mut self,
451         finalize: Option<Finalize>,
452         path: &[Segment],
453         second_binding: Option<&NameBinding<'_>>,
454     ) {
455         let Some(Finalize { node_id, root_span, .. }) = finalize else {
456             return;
457         };
458
459         let first_name = match path.get(0) {
460             // In the 2018 edition this lint is a hard error, so nothing to do
461             Some(seg) if seg.ident.span.rust_2015() && self.session.rust_2015() => seg.ident.name,
462             _ => return,
463         };
464
465         // We're only interested in `use` paths which should start with
466         // `{{root}}` currently.
467         if first_name != kw::PathRoot {
468             return;
469         }
470
471         match path.get(1) {
472             // If this import looks like `crate::...` it's already good
473             Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
474             // Otherwise go below to see if it's an extern crate
475             Some(_) => {}
476             // If the path has length one (and it's `PathRoot` most likely)
477             // then we don't know whether we're gonna be importing a crate or an
478             // item in our crate. Defer this lint to elsewhere
479             None => return,
480         }
481
482         // If the first element of our path was actually resolved to an
483         // `ExternCrate` (also used for `crate::...`) then no need to issue a
484         // warning, this looks all good!
485         if let Some(binding) = second_binding {
486             if let NameBindingKind::Import { import, .. } = binding.kind {
487                 // Careful: we still want to rewrite paths from renamed extern crates.
488                 if let ImportKind::ExternCrate { source: None, .. } = import.kind {
489                     return;
490                 }
491             }
492         }
493
494         let diag = BuiltinLintDiagnostics::AbsPathWithModule(root_span);
495         self.lint_buffer.buffer_lint_with_diagnostic(
496             ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
497             node_id,
498             root_span,
499             "absolute paths must start with `self`, `super`, \
500              `crate`, or an external crate name in the 2018 edition",
501             diag,
502         );
503     }
504
505     pub(crate) fn add_module_candidates(
506         &mut self,
507         module: Module<'a>,
508         names: &mut Vec<TypoSuggestion>,
509         filter_fn: &impl Fn(Res) -> bool,
510         ctxt: Option<SyntaxContext>,
511     ) {
512         for (key, resolution) in self.resolutions(module).borrow().iter() {
513             if let Some(binding) = resolution.borrow().binding {
514                 let res = binding.res();
515                 if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) {
516                     names.push(TypoSuggestion::typo_from_ident(key.ident, res));
517                 }
518             }
519         }
520     }
521
522     /// Combines an error with provided span and emits it.
523     ///
524     /// This takes the error provided, combines it with the span and any additional spans inside the
525     /// error and emits it.
526     pub(crate) fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'a>) {
527         self.into_struct_error(span, resolution_error).emit();
528     }
529
530     pub(crate) fn into_struct_error(
531         &mut self,
532         span: Span,
533         resolution_error: ResolutionError<'a>,
534     ) -> DiagnosticBuilder<'_, ErrorGuaranteed> {
535         match resolution_error {
536             ResolutionError::GenericParamsFromOuterFunction(outer_res, has_generic_params) => {
537                 let mut err = struct_span_err!(
538                     self.session,
539                     span,
540                     E0401,
541                     "can't use generic parameters from outer function",
542                 );
543                 err.span_label(span, "use of generic parameter from outer function");
544
545                 let sm = self.session.source_map();
546                 let def_id = match outer_res {
547                     Res::SelfTyParam { .. } => {
548                         err.span_label(span, "can't use `Self` here");
549                         return err;
550                     }
551                     Res::SelfTyAlias { alias_to: def_id, .. } => {
552                         if let Some(impl_span) = self.opt_span(def_id) {
553                             err.span_label(
554                                 reduce_impl_span_to_impl_keyword(sm, impl_span),
555                                 "`Self` type implicitly declared here, by this `impl`",
556                             );
557                         }
558                         err.span_label(span, "use a type here instead");
559                         return err;
560                     }
561                     Res::Def(DefKind::TyParam, def_id) => {
562                         if let Some(span) = self.opt_span(def_id) {
563                             err.span_label(span, "type parameter from outer function");
564                         }
565                         def_id
566                     }
567                     Res::Def(DefKind::ConstParam, def_id) => {
568                         if let Some(span) = self.opt_span(def_id) {
569                             err.span_label(span, "const parameter from outer function");
570                         }
571                         def_id
572                     }
573                     _ => {
574                         bug!(
575                             "GenericParamsFromOuterFunction should only be used with \
576                             Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
577                             DefKind::ConstParam"
578                         );
579                     }
580                 };
581
582                 if let HasGenericParams::Yes(span) = has_generic_params {
583                     // Try to retrieve the span of the function signature and generate a new
584                     // message with a local type or const parameter.
585                     let sugg_msg = "try using a local generic parameter instead";
586                     let name = self.opt_name(def_id).unwrap_or(sym::T);
587                     let (span, snippet) = if span.is_empty() {
588                         let snippet = format!("<{}>", name);
589                         (span, snippet)
590                     } else {
591                         let span = sm.span_through_char(span, '<').shrink_to_hi();
592                         let snippet = format!("{}, ", name);
593                         (span, snippet)
594                     };
595                     // Suggest the modification to the user
596                     err.span_suggestion(span, sugg_msg, snippet, Applicability::MaybeIncorrect);
597                 }
598
599                 err
600             }
601             ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
602                 .session
603                 .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
604             ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
605                 self.session.create_err(errs::MethodNotMemberOfTrait {
606                     span,
607                     method,
608                     trait_,
609                     sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
610                         span: method.span,
611                         candidate: c,
612                     }),
613                 })
614             }
615             ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
616                 self.session.create_err(errs::TypeNotMemberOfTrait {
617                     span,
618                     type_,
619                     trait_,
620                     sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
621                         span: type_.span,
622                         candidate: c,
623                     }),
624                 })
625             }
626             ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
627                 self.session.create_err(errs::ConstNotMemberOfTrait {
628                     span,
629                     const_,
630                     trait_,
631                     sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
632                         span: const_.span,
633                         candidate: c,
634                     }),
635                 })
636             }
637             ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
638                 let BindingError { name, target, origin, could_be_path } = binding_error;
639
640                 let target_sp = target.iter().copied().collect::<Vec<_>>();
641                 let origin_sp = origin.iter().copied().collect::<Vec<_>>();
642
643                 let msp = MultiSpan::from_spans(target_sp.clone());
644                 let mut err = struct_span_err!(
645                     self.session,
646                     msp,
647                     E0408,
648                     "variable `{}` is not bound in all patterns",
649                     name,
650                 );
651                 for sp in target_sp {
652                     err.span_label(sp, format!("pattern doesn't bind `{}`", name));
653                 }
654                 for sp in origin_sp {
655                     err.span_label(sp, "variable not in all patterns");
656                 }
657                 if could_be_path {
658                     let import_suggestions = self.lookup_import_candidates(
659                         Ident::with_dummy_span(name),
660                         Namespace::ValueNS,
661                         &parent_scope,
662                         &|res: Res| match res {
663                             Res::Def(
664                                 DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
665                                 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
666                                 | DefKind::Const
667                                 | DefKind::AssocConst,
668                                 _,
669                             ) => true,
670                             _ => false,
671                         },
672                     );
673
674                     if import_suggestions.is_empty() {
675                         let help_msg = format!(
676                             "if you meant to match on a variant or a `const` item, consider \
677                              making the path in the pattern qualified: `path::to::ModOrType::{}`",
678                             name,
679                         );
680                         err.span_help(span, &help_msg);
681                     }
682                     show_candidates(
683                         &self.session,
684                         &self.source_span,
685                         &mut err,
686                         Some(span),
687                         &import_suggestions,
688                         Instead::No,
689                         FoundUse::Yes,
690                         DiagnosticMode::Pattern,
691                         vec![],
692                     );
693                 }
694                 err
695             }
696             ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
697                 self.session.create_err(errs::VariableBoundWithDifferentMode {
698                     span,
699                     first_binding_span,
700                     variable_name,
701                 })
702             }
703             ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
704                 .session
705                 .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
706             ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
707                 .session
708                 .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
709             ResolutionError::UndeclaredLabel { name, suggestion } => {
710                 let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
711                 {
712                     // A reachable label with a similar name exists.
713                     Some((ident, true)) => (
714                         (
715                             Some(errs::LabelWithSimilarNameReachable(ident.span)),
716                             Some(errs::TryUsingSimilarlyNamedLabel {
717                                 span,
718                                 ident_name: ident.name,
719                             }),
720                         ),
721                         None,
722                     ),
723                     // An unreachable label with a similar name exists.
724                     Some((ident, false)) => (
725                         (None, None),
726                         Some(errs::UnreachableLabelWithSimilarNameExists {
727                             ident_span: ident.span,
728                         }),
729                     ),
730                     // No similarly-named labels exist.
731                     None => ((None, None), None),
732                 };
733                 self.session.create_err(errs::UndeclaredLabel {
734                     span,
735                     name,
736                     sub_reachable,
737                     sub_reachable_suggestion,
738                     sub_unreachable,
739                 })
740             }
741             ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
742                 // None of the suggestions below would help with a case like `use self`.
743                 let (suggestion, mpart_suggestion) = if root {
744                     (None, None)
745                 } else {
746                     // use foo::bar::self        -> foo::bar
747                     // use foo::bar::self as abc -> foo::bar as abc
748                     let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
749
750                     // use foo::bar::self        -> foo::bar::{self}
751                     // use foo::bar::self as abc -> foo::bar::{self as abc}
752                     let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
753                         multipart_start: span_with_rename.shrink_to_lo(),
754                         multipart_end: span_with_rename.shrink_to_hi(),
755                     };
756                     (Some(suggestion), Some(mpart_suggestion))
757                 };
758                 self.session.create_err(errs::SelfImportsOnlyAllowedWithin {
759                     span,
760                     suggestion,
761                     mpart_suggestion,
762                 })
763             }
764             ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
765                 self.session.create_err(errs::SelfImportCanOnlyAppearOnceInTheList { span })
766             }
767             ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
768                 self.session.create_err(errs::SelfImportOnlyInImportListWithNonEmptyPrefix { span })
769             }
770             ResolutionError::FailedToResolve { label, suggestion } => {
771                 let mut err =
772                     struct_span_err!(self.session, span, E0433, "failed to resolve: {}", &label);
773                 err.span_label(span, label);
774
775                 if let Some((suggestions, msg, applicability)) = suggestion {
776                     if suggestions.is_empty() {
777                         err.help(&msg);
778                         return err;
779                     }
780                     err.multipart_suggestion(&msg, suggestions, applicability);
781                 }
782
783                 err
784             }
785             ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
786                 self.session.create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
787             }
788             ResolutionError::AttemptToUseNonConstantValueInConstant(ident, suggestion, current) => {
789                 // let foo =...
790                 //     ^^^ given this Span
791                 // ------- get this Span to have an applicable suggestion
792
793                 // edit:
794                 // only do this if the const and usage of the non-constant value are on the same line
795                 // the further the two are apart, the higher the chance of the suggestion being wrong
796
797                 let sp = self
798                     .session
799                     .source_map()
800                     .span_extend_to_prev_str(ident.span, current, true, false);
801
802                 let ((with, with_label), without) = match sp {
803                     Some(sp) if !self.session.source_map().is_multiline(sp) => {
804                         let sp = sp.with_lo(BytePos(sp.lo().0 - (current.len() as u32)));
805                         (
806                         (Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
807                                 span: sp,
808                                 ident,
809                                 suggestion,
810                                 current,
811                             }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})),
812                             None,
813                         )
814                     }
815                     _ => (
816                         (None, None),
817                         Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
818                             ident_span: ident.span,
819                             suggestion,
820                         }),
821                     ),
822                 };
823
824                 self.session.create_err(errs::AttemptToUseNonConstantValueInConstant {
825                     span,
826                     with,
827                     with_label,
828                     without,
829                 })
830             }
831             ResolutionError::BindingShadowsSomethingUnacceptable {
832                 shadowing_binding,
833                 name,
834                 participle,
835                 article,
836                 shadowed_binding,
837                 shadowed_binding_span,
838             } => self.session.create_err(errs::BindingShadowsSomethingUnacceptable {
839                 span,
840                 shadowing_binding,
841                 shadowed_binding,
842                 article,
843                 sub_suggestion: match (shadowing_binding, shadowed_binding) {
844                     (
845                         PatternSource::Match,
846                         Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
847                     ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
848                     _ => None,
849                 },
850                 shadowed_binding_span,
851                 participle,
852                 name,
853             }),
854             ResolutionError::ForwardDeclaredGenericParam => {
855                 self.session.create_err(errs::ForwardDeclaredGenericParam { span })
856             }
857             ResolutionError::ParamInTyOfConstParam(name) => {
858                 self.session.create_err(errs::ParamInTyOfConstParam { span, name })
859             }
860             ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
861                 self.session.create_err(errs::ParamInNonTrivialAnonConst {
862                     span,
863                     name,
864                     sub_is_type: if is_type {
865                         errs::ParamInNonTrivialAnonConstIsType::AType
866                     } else {
867                         errs::ParamInNonTrivialAnonConstIsType::NotAType { name }
868                     },
869                     help: self
870                         .session
871                         .is_nightly_build()
872                         .then_some(errs::ParamInNonTrivialAnonConstHelp),
873                 })
874             }
875             ResolutionError::SelfInGenericParamDefault => {
876                 self.session.create_err(errs::SelfInGenericParamDefault { span })
877             }
878             ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
879                 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
880                     match suggestion {
881                         // A reachable label with a similar name exists.
882                         Some((ident, true)) => (
883                             (
884                                 Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
885                                 Some(errs::UnreachableLabelSubSuggestion {
886                                     span,
887                                     // intentionally taking 'ident.name' instead of 'ident' itself, as this
888                                     // could be used in suggestion context
889                                     ident_name: ident.name,
890                                 }),
891                             ),
892                             None,
893                         ),
894                         // An unreachable label with a similar name exists.
895                         Some((ident, false)) => (
896                             (None, None),
897                             Some(errs::UnreachableLabelSubLabelUnreachable {
898                                 ident_span: ident.span,
899                             }),
900                         ),
901                         // No similarly-named labels exist.
902                         None => ((None, None), None),
903                     };
904                 self.session.create_err(errs::UnreachableLabel {
905                     span,
906                     name,
907                     definition_span,
908                     sub_suggestion,
909                     sub_suggestion_label,
910                     sub_unreachable_label,
911                 })
912             }
913             ResolutionError::TraitImplMismatch {
914                 name,
915                 kind,
916                 code,
917                 trait_item_span,
918                 trait_path,
919             } => {
920                 let mut err = self.session.struct_span_err_with_code(
921                     span,
922                     &format!(
923                         "item `{}` is an associated {}, which doesn't match its trait `{}`",
924                         name, kind, trait_path,
925                     ),
926                     code,
927                 );
928                 err.span_label(span, "does not match trait");
929                 err.span_label(trait_item_span, "item in trait");
930                 err
931             }
932             ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
933                 .session
934                 .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
935             ResolutionError::InvalidAsmSym => self.session.create_err(errs::InvalidAsmSym { span }),
936         }
937     }
938
939     pub(crate) fn report_vis_error(
940         &mut self,
941         vis_resolution_error: VisResolutionError<'_>,
942     ) -> ErrorGuaranteed {
943         match vis_resolution_error {
944             VisResolutionError::Relative2018(span, path) => {
945                 self.session.create_err(errs::Relative2018 {
946                     span,
947                     path_span: path.span,
948                     // intentionally converting to String, as the text would also be used as
949                     // in suggestion context
950                     path_str: pprust::path_to_string(&path),
951                 })
952             }
953             VisResolutionError::AncestorOnly(span) => {
954                 self.session.create_err(errs::AncestorOnly(span))
955             }
956             VisResolutionError::FailedToResolve(span, label, suggestion) => {
957                 self.into_struct_error(span, ResolutionError::FailedToResolve { label, suggestion })
958             }
959             VisResolutionError::ExpectedFound(span, path_str, res) => {
960                 self.session.create_err(errs::ExpectedFound { span, res, path_str })
961             }
962             VisResolutionError::Indeterminate(span) => {
963                 self.session.create_err(errs::Indeterminate(span))
964             }
965             VisResolutionError::ModuleOnly(span) => self.session.create_err(errs::ModuleOnly(span)),
966         }
967         .emit()
968     }
969
970     /// Lookup typo candidate in scope for a macro or import.
971     fn early_lookup_typo_candidate(
972         &mut self,
973         scope_set: ScopeSet<'a>,
974         parent_scope: &ParentScope<'a>,
975         ident: Ident,
976         filter_fn: &impl Fn(Res) -> bool,
977     ) -> Option<TypoSuggestion> {
978         let mut suggestions = Vec::new();
979         let ctxt = ident.span.ctxt();
980         self.visit_scopes(scope_set, parent_scope, ctxt, |this, scope, use_prelude, _| {
981             match scope {
982                 Scope::DeriveHelpers(expn_id) => {
983                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
984                     if filter_fn(res) {
985                         suggestions.extend(
986                             this.helper_attrs
987                                 .get(&expn_id)
988                                 .into_iter()
989                                 .flatten()
990                                 .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
991                         );
992                     }
993                 }
994                 Scope::DeriveHelpersCompat => {
995                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);
996                     if filter_fn(res) {
997                         for derive in parent_scope.derives {
998                             let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
999                             if let Ok((Some(ext), _)) = this.resolve_macro_path(
1000                                 derive,
1001                                 Some(MacroKind::Derive),
1002                                 parent_scope,
1003                                 false,
1004                                 false,
1005                             ) {
1006                                 suggestions.extend(
1007                                     ext.helper_attrs
1008                                         .iter()
1009                                         .map(|name| TypoSuggestion::typo_from_name(*name, res)),
1010                                 );
1011                             }
1012                         }
1013                     }
1014                 }
1015                 Scope::MacroRules(macro_rules_scope) => {
1016                     if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope.get() {
1017                         let res = macro_rules_binding.binding.res();
1018                         if filter_fn(res) {
1019                             suggestions.push(TypoSuggestion::typo_from_ident(
1020                                 macro_rules_binding.ident,
1021                                 res,
1022                             ))
1023                         }
1024                     }
1025                 }
1026                 Scope::CrateRoot => {
1027                     let root_ident = Ident::new(kw::PathRoot, ident.span);
1028                     let root_module = this.resolve_crate_root(root_ident);
1029                     this.add_module_candidates(root_module, &mut suggestions, filter_fn, None);
1030                 }
1031                 Scope::Module(module) => {
1032                     this.add_module_candidates(module, &mut suggestions, filter_fn, None);
1033                 }
1034                 Scope::MacroUsePrelude => {
1035                     suggestions.extend(this.macro_use_prelude.iter().filter_map(
1036                         |(name, binding)| {
1037                             let res = binding.res();
1038                             filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1039                         },
1040                     ));
1041                 }
1042                 Scope::BuiltinAttrs => {
1043                     let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(kw::Empty));
1044                     if filter_fn(res) {
1045                         suggestions.extend(
1046                             BUILTIN_ATTRIBUTES
1047                                 .iter()
1048                                 .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
1049                         );
1050                     }
1051                 }
1052                 Scope::ExternPrelude => {
1053                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
1054                         let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1055                         filter_fn(res).then_some(TypoSuggestion::typo_from_ident(*ident, res))
1056                     }));
1057                 }
1058                 Scope::ToolPrelude => {
1059                     let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1060                     suggestions.extend(
1061                         this.registered_tools
1062                             .iter()
1063                             .map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
1064                     );
1065                 }
1066                 Scope::StdLibPrelude => {
1067                     if let Some(prelude) = this.prelude {
1068                         let mut tmp_suggestions = Vec::new();
1069                         this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1070                         suggestions.extend(
1071                             tmp_suggestions
1072                                 .into_iter()
1073                                 .filter(|s| use_prelude || this.is_builtin_macro(s.res)),
1074                         );
1075                     }
1076                 }
1077                 Scope::BuiltinTypes => {
1078                     suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1079                         let res = Res::PrimTy(*prim_ty);
1080                         filter_fn(res)
1081                             .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1082                     }))
1083                 }
1084             }
1085
1086             None::<()>
1087         });
1088
1089         // Make sure error reporting is deterministic.
1090         suggestions.sort_by(|a, b| a.candidate.as_str().partial_cmp(b.candidate.as_str()).unwrap());
1091
1092         match find_best_match_for_name(
1093             &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1094             ident.name,
1095             None,
1096         ) {
1097             Some(found) if found != ident.name => {
1098                 suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1099             }
1100             _ => None,
1101         }
1102     }
1103
1104     fn lookup_import_candidates_from_module<FilterFn>(
1105         &mut self,
1106         lookup_ident: Ident,
1107         namespace: Namespace,
1108         parent_scope: &ParentScope<'a>,
1109         start_module: Module<'a>,
1110         crate_name: Ident,
1111         filter_fn: FilterFn,
1112     ) -> Vec<ImportSuggestion>
1113     where
1114         FilterFn: Fn(Res) -> bool,
1115     {
1116         let mut candidates = Vec::new();
1117         let mut seen_modules = FxHashSet::default();
1118         let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), true)];
1119         let mut worklist_via_import = vec![];
1120
1121         while let Some((in_module, path_segments, accessible)) = match worklist.pop() {
1122             None => worklist_via_import.pop(),
1123             Some(x) => Some(x),
1124         } {
1125             let in_module_is_extern = !in_module.def_id().is_local();
1126             // We have to visit module children in deterministic order to avoid
1127             // instabilities in reported imports (#43552).
1128             in_module.for_each_child(self, |this, ident, ns, name_binding| {
1129                 // avoid non-importable candidates
1130                 if !name_binding.is_importable() {
1131                     return;
1132                 }
1133
1134                 let child_accessible =
1135                     accessible && this.is_accessible_from(name_binding.vis, parent_scope.module);
1136
1137                 // do not venture inside inaccessible items of other crates
1138                 if in_module_is_extern && !child_accessible {
1139                     return;
1140                 }
1141
1142                 let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1143
1144                 // There is an assumption elsewhere that paths of variants are in the enum's
1145                 // declaration and not imported. With this assumption, the variant component is
1146                 // chopped and the rest of the path is assumed to be the enum's own path. For
1147                 // errors where a variant is used as the type instead of the enum, this causes
1148                 // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
1149                 if via_import && name_binding.is_possibly_imported_variant() {
1150                     return;
1151                 }
1152
1153                 // #90113: Do not count an inaccessible reexported item as a candidate.
1154                 if let NameBindingKind::Import { binding, .. } = name_binding.kind {
1155                     if this.is_accessible_from(binding.vis, parent_scope.module)
1156                         && !this.is_accessible_from(name_binding.vis, parent_scope.module)
1157                     {
1158                         return;
1159                     }
1160                 }
1161
1162                 // collect results based on the filter function
1163                 // avoid suggesting anything from the same module in which we are resolving
1164                 // avoid suggesting anything with a hygienic name
1165                 if ident.name == lookup_ident.name
1166                     && ns == namespace
1167                     && !ptr::eq(in_module, parent_scope.module)
1168                     && !ident.span.normalize_to_macros_2_0().from_expansion()
1169                 {
1170                     let res = name_binding.res();
1171                     if filter_fn(res) {
1172                         // create the path
1173                         let mut segms = path_segments.clone();
1174                         if lookup_ident.span.rust_2018() {
1175                             // crate-local absolute paths start with `crate::` in edition 2018
1176                             // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
1177                             segms.insert(0, ast::PathSegment::from_ident(crate_name));
1178                         }
1179
1180                         segms.push(ast::PathSegment::from_ident(ident));
1181                         let path = Path { span: name_binding.span, segments: segms, tokens: None };
1182                         let did = match res {
1183                             Res::Def(DefKind::Ctor(..), did) => this.opt_parent(did),
1184                             _ => res.opt_def_id(),
1185                         };
1186
1187                         if child_accessible {
1188                             // Remove invisible match if exists
1189                             if let Some(idx) = candidates
1190                                 .iter()
1191                                 .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1192                             {
1193                                 candidates.remove(idx);
1194                             }
1195                         }
1196
1197                         if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1198                             // See if we're recommending TryFrom, TryInto, or FromIterator and add
1199                             // a note about editions
1200                             let note = if let Some(did) = did {
1201                                 let requires_note = !did.is_local()
1202                                     && this.cstore().item_attrs_untracked(did, this.session).any(
1203                                         |attr| {
1204                                             if attr.has_name(sym::rustc_diagnostic_item) {
1205                                                 [sym::TryInto, sym::TryFrom, sym::FromIterator]
1206                                                     .map(|x| Some(x))
1207                                                     .contains(&attr.value_str())
1208                                             } else {
1209                                                 false
1210                                             }
1211                                         },
1212                                     );
1213
1214                                 requires_note.then(|| {
1215                                     format!(
1216                                         "'{}' is included in the prelude starting in Edition 2021",
1217                                         path_names_to_string(&path)
1218                                     )
1219                                 })
1220                             } else {
1221                                 None
1222                             };
1223
1224                             candidates.push(ImportSuggestion {
1225                                 did,
1226                                 descr: res.descr(),
1227                                 path,
1228                                 accessible: child_accessible,
1229                                 note,
1230                             });
1231                         }
1232                     }
1233                 }
1234
1235                 // collect submodules to explore
1236                 if let Some(module) = name_binding.module() {
1237                     // form the path
1238                     let mut path_segments = path_segments.clone();
1239                     path_segments.push(ast::PathSegment::from_ident(ident));
1240
1241                     let is_extern_crate_that_also_appears_in_prelude =
1242                         name_binding.is_extern_crate() && lookup_ident.span.rust_2018();
1243
1244                     if !is_extern_crate_that_also_appears_in_prelude {
1245                         // add the module to the lookup
1246                         if seen_modules.insert(module.def_id()) {
1247                             if via_import { &mut worklist_via_import } else { &mut worklist }
1248                                 .push((module, path_segments, child_accessible));
1249                         }
1250                     }
1251                 }
1252             })
1253         }
1254
1255         // If only some candidates are accessible, take just them
1256         if !candidates.iter().all(|v: &ImportSuggestion| !v.accessible) {
1257             candidates.retain(|x| x.accessible)
1258         }
1259
1260         candidates
1261     }
1262
1263     /// When name resolution fails, this method can be used to look up candidate
1264     /// entities with the expected name. It allows filtering them using the
1265     /// supplied predicate (which should be used to only accept the types of
1266     /// definitions expected, e.g., traits). The lookup spans across all crates.
1267     ///
1268     /// N.B., the method does not look into imports, but this is not a problem,
1269     /// since we report the definitions (thus, the de-aliased imports).
1270     pub(crate) fn lookup_import_candidates<FilterFn>(
1271         &mut self,
1272         lookup_ident: Ident,
1273         namespace: Namespace,
1274         parent_scope: &ParentScope<'a>,
1275         filter_fn: FilterFn,
1276     ) -> Vec<ImportSuggestion>
1277     where
1278         FilterFn: Fn(Res) -> bool,
1279     {
1280         let mut suggestions = self.lookup_import_candidates_from_module(
1281             lookup_ident,
1282             namespace,
1283             parent_scope,
1284             self.graph_root,
1285             Ident::with_dummy_span(kw::Crate),
1286             &filter_fn,
1287         );
1288
1289         if lookup_ident.span.rust_2018() {
1290             let extern_prelude_names = self.extern_prelude.clone();
1291             for (ident, _) in extern_prelude_names.into_iter() {
1292                 if ident.span.from_expansion() {
1293                     // Idents are adjusted to the root context before being
1294                     // resolved in the extern prelude, so reporting this to the
1295                     // user is no help. This skips the injected
1296                     // `extern crate std` in the 2018 edition, which would
1297                     // otherwise cause duplicate suggestions.
1298                     continue;
1299                 }
1300                 if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) {
1301                     let crate_root = self.expect_module(crate_id.as_def_id());
1302                     suggestions.extend(self.lookup_import_candidates_from_module(
1303                         lookup_ident,
1304                         namespace,
1305                         parent_scope,
1306                         crate_root,
1307                         ident,
1308                         &filter_fn,
1309                     ));
1310                 }
1311             }
1312         }
1313
1314         suggestions
1315     }
1316
1317     pub(crate) fn unresolved_macro_suggestions(
1318         &mut self,
1319         err: &mut Diagnostic,
1320         macro_kind: MacroKind,
1321         parent_scope: &ParentScope<'a>,
1322         ident: Ident,
1323     ) {
1324         let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
1325         let suggestion = self.early_lookup_typo_candidate(
1326             ScopeSet::Macro(macro_kind),
1327             parent_scope,
1328             ident,
1329             is_expected,
1330         );
1331         self.add_typo_suggestion(err, suggestion, ident.span);
1332
1333         let import_suggestions =
1334             self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1335         show_candidates(
1336             &self.session,
1337             &self.source_span,
1338             err,
1339             None,
1340             &import_suggestions,
1341             Instead::No,
1342             FoundUse::Yes,
1343             DiagnosticMode::Normal,
1344             vec![],
1345         );
1346
1347         if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1348             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
1349             err.span_note(ident.span, &msg);
1350             return;
1351         }
1352         if self.macro_names.contains(&ident.normalize_to_macros_2_0()) {
1353             err.help("have you added the `#[macro_use]` on the module/import?");
1354             return;
1355         }
1356         if ident.name == kw::Default
1357             && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
1358             && let Some(span) = self.opt_span(def_id)
1359         {
1360             let source_map = self.session.source_map();
1361             let head_span = source_map.guess_head_span(span);
1362             if let Ok(head) = source_map.span_to_snippet(head_span) {
1363                 err.span_suggestion(head_span, "consider adding a derive", format!("#[derive(Default)]\n{head}"), Applicability::MaybeIncorrect);
1364             } else {
1365                 err.span_help(
1366                     head_span,
1367                     "consider adding `#[derive(Default)]` to this enum",
1368                 );
1369             }
1370         }
1371         for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
1372             if let Ok(binding) = self.early_resolve_ident_in_lexical_scope(
1373                 ident,
1374                 ScopeSet::All(ns, false),
1375                 &parent_scope,
1376                 None,
1377                 false,
1378                 None,
1379             ) {
1380                 let desc = match binding.res() {
1381                     Res::Def(DefKind::Macro(MacroKind::Bang), _) => {
1382                         "a function-like macro".to_string()
1383                     }
1384                     Res::Def(DefKind::Macro(MacroKind::Attr), _) | Res::NonMacroAttr(..) => {
1385                         format!("an attribute: `#[{}]`", ident)
1386                     }
1387                     Res::Def(DefKind::Macro(MacroKind::Derive), _) => {
1388                         format!("a derive macro: `#[derive({})]`", ident)
1389                     }
1390                     Res::ToolMod => {
1391                         // Don't confuse the user with tool modules.
1392                         continue;
1393                     }
1394                     Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
1395                         "only a trait, without a derive macro".to_string()
1396                     }
1397                     res => format!(
1398                         "{} {}, not {} {}",
1399                         res.article(),
1400                         res.descr(),
1401                         macro_kind.article(),
1402                         macro_kind.descr_expected(),
1403                     ),
1404                 };
1405                 if let crate::NameBindingKind::Import { import, .. } = binding.kind {
1406                     if !import.span.is_dummy() {
1407                         err.span_note(
1408                             import.span,
1409                             &format!("`{}` is imported here, but it is {}", ident, desc),
1410                         );
1411                         // Silence the 'unused import' warning we might get,
1412                         // since this diagnostic already covers that import.
1413                         self.record_use(ident, binding, false);
1414                         return;
1415                     }
1416                 }
1417                 err.note(&format!("`{}` is in scope, but it is {}", ident, desc));
1418                 return;
1419             }
1420         }
1421     }
1422
1423     pub(crate) fn add_typo_suggestion(
1424         &self,
1425         err: &mut Diagnostic,
1426         suggestion: Option<TypoSuggestion>,
1427         span: Span,
1428     ) -> bool {
1429         let suggestion = match suggestion {
1430             None => return false,
1431             // We shouldn't suggest underscore.
1432             Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
1433             Some(suggestion) => suggestion,
1434         };
1435         let def_span = suggestion.res.opt_def_id().and_then(|def_id| match def_id.krate {
1436             LOCAL_CRATE => self.opt_span(def_id),
1437             _ => Some(self.cstore().get_span_untracked(def_id, self.session)),
1438         });
1439         if let Some(def_span) = def_span {
1440             if span.overlaps(def_span) {
1441                 // Don't suggest typo suggestion for itself like in the following:
1442                 // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
1443                 //   --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
1444                 //    |
1445                 // LL | struct X {}
1446                 //    | ----------- `X` defined here
1447                 // LL |
1448                 // LL | const Y: X = X("ö");
1449                 //    | -------------^^^^^^- similarly named constant `Y` defined here
1450                 //    |
1451                 // help: use struct literal syntax instead
1452                 //    |
1453                 // LL | const Y: X = X {};
1454                 //    |              ^^^^
1455                 // help: a constant with a similar name exists
1456                 //    |
1457                 // LL | const Y: X = Y("ö");
1458                 //    |              ^
1459                 return false;
1460             }
1461             let prefix = match suggestion.target {
1462                 SuggestionTarget::SimilarlyNamed => "similarly named ",
1463                 SuggestionTarget::SingleItem => "",
1464             };
1465
1466             err.span_label(
1467                 self.session.source_map().guess_head_span(def_span),
1468                 &format!(
1469                     "{}{} `{}` defined here",
1470                     prefix,
1471                     suggestion.res.descr(),
1472                     suggestion.candidate,
1473                 ),
1474             );
1475         }
1476         let msg = match suggestion.target {
1477             SuggestionTarget::SimilarlyNamed => format!(
1478                 "{} {} with a similar name exists",
1479                 suggestion.res.article(),
1480                 suggestion.res.descr()
1481             ),
1482             SuggestionTarget::SingleItem => {
1483                 format!("maybe you meant this {}", suggestion.res.descr())
1484             }
1485         };
1486         err.span_suggestion(span, &msg, suggestion.candidate, Applicability::MaybeIncorrect);
1487         true
1488     }
1489
1490     fn binding_description(&self, b: &NameBinding<'_>, ident: Ident, from_prelude: bool) -> String {
1491         let res = b.res();
1492         if b.span.is_dummy() || !self.session.source_map().is_span_accessible(b.span) {
1493             // These already contain the "built-in" prefix or look bad with it.
1494             let add_built_in =
1495                 !matches!(b.res(), Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod);
1496             let (built_in, from) = if from_prelude {
1497                 ("", " from prelude")
1498             } else if b.is_extern_crate()
1499                 && !b.is_import()
1500                 && self.session.opts.externs.get(ident.as_str()).is_some()
1501             {
1502                 ("", " passed with `--extern`")
1503             } else if add_built_in {
1504                 (" built-in", "")
1505             } else {
1506                 ("", "")
1507             };
1508
1509             let a = if built_in.is_empty() { res.article() } else { "a" };
1510             format!("{a}{built_in} {thing}{from}", thing = res.descr())
1511         } else {
1512             let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
1513             format!("the {thing} {introduced} here", thing = res.descr())
1514         }
1515     }
1516
1517     fn report_ambiguity_error(&self, ambiguity_error: &AmbiguityError<'_>) {
1518         let AmbiguityError { kind, ident, b1, b2, misc1, misc2 } = *ambiguity_error;
1519         let (b1, b2, misc1, misc2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
1520             // We have to print the span-less alternative first, otherwise formatting looks bad.
1521             (b2, b1, misc2, misc1, true)
1522         } else {
1523             (b1, b2, misc1, misc2, false)
1524         };
1525
1526         let mut err = struct_span_err!(self.session, ident.span, E0659, "`{ident}` is ambiguous");
1527         err.span_label(ident.span, "ambiguous name");
1528         err.note(&format!("ambiguous because of {}", kind.descr()));
1529
1530         let mut could_refer_to = |b: &NameBinding<'_>, misc: AmbiguityErrorMisc, also: &str| {
1531             let what = self.binding_description(b, ident, misc == AmbiguityErrorMisc::FromPrelude);
1532             let note_msg = format!("`{ident}` could{also} refer to {what}");
1533
1534             let thing = b.res().descr();
1535             let mut help_msgs = Vec::new();
1536             if b.is_glob_import()
1537                 && (kind == AmbiguityKind::GlobVsGlob
1538                     || kind == AmbiguityKind::GlobVsExpanded
1539                     || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
1540             {
1541                 help_msgs.push(format!(
1542                     "consider adding an explicit import of `{ident}` to disambiguate"
1543                 ))
1544             }
1545             if b.is_extern_crate() && ident.span.rust_2018() {
1546                 help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
1547             }
1548             if misc == AmbiguityErrorMisc::SuggestCrate {
1549                 help_msgs
1550                     .push(format!("use `crate::{ident}` to refer to this {thing} unambiguously"))
1551             } else if misc == AmbiguityErrorMisc::SuggestSelf {
1552                 help_msgs
1553                     .push(format!("use `self::{ident}` to refer to this {thing} unambiguously"))
1554             }
1555
1556             err.span_note(b.span, &note_msg);
1557             for (i, help_msg) in help_msgs.iter().enumerate() {
1558                 let or = if i == 0 { "" } else { "or " };
1559                 err.help(&format!("{}{}", or, help_msg));
1560             }
1561         };
1562
1563         could_refer_to(b1, misc1, "");
1564         could_refer_to(b2, misc2, " also");
1565         err.emit();
1566     }
1567
1568     /// If the binding refers to a tuple struct constructor with fields,
1569     /// returns the span of its fields.
1570     fn ctor_fields_span(&self, binding: &NameBinding<'_>) -> Option<Span> {
1571         if let NameBindingKind::Res(Res::Def(
1572             DefKind::Ctor(CtorOf::Struct, CtorKind::Fn),
1573             ctor_def_id,
1574         )) = binding.kind
1575         {
1576             let def_id = self.parent(ctor_def_id);
1577             let fields = self.field_names.get(&def_id)?;
1578             return fields.iter().map(|name| name.span).reduce(Span::to); // None for `struct Foo()`
1579         }
1580         None
1581     }
1582
1583     fn report_privacy_error(&self, privacy_error: &PrivacyError<'_>) {
1584         let PrivacyError { ident, binding, .. } = *privacy_error;
1585
1586         let res = binding.res();
1587         let ctor_fields_span = self.ctor_fields_span(binding);
1588         let plain_descr = res.descr().to_string();
1589         let nonimport_descr =
1590             if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
1591         let import_descr = nonimport_descr.clone() + " import";
1592         let get_descr =
1593             |b: &NameBinding<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
1594
1595         // Print the primary message.
1596         let descr = get_descr(binding);
1597         let mut err =
1598             struct_span_err!(self.session, ident.span, E0603, "{} `{}` is private", descr, ident);
1599         err.span_label(ident.span, &format!("private {}", descr));
1600         if let Some(span) = ctor_fields_span {
1601             err.span_label(span, "a constructor is private if any of the fields is private");
1602         }
1603
1604         // Print the whole import chain to make it easier to see what happens.
1605         let first_binding = binding;
1606         let mut next_binding = Some(binding);
1607         let mut next_ident = ident;
1608         while let Some(binding) = next_binding {
1609             let name = next_ident;
1610             next_binding = match binding.kind {
1611                 _ if res == Res::Err => None,
1612                 NameBindingKind::Import { binding, import, .. } => match import.kind {
1613                     _ if binding.span.is_dummy() => None,
1614                     ImportKind::Single { source, .. } => {
1615                         next_ident = source;
1616                         Some(binding)
1617                     }
1618                     ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => {
1619                         Some(binding)
1620                     }
1621                     ImportKind::ExternCrate { .. } => None,
1622                 },
1623                 _ => None,
1624             };
1625
1626             let first = ptr::eq(binding, first_binding);
1627             let msg = format!(
1628                 "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
1629                 and_refers_to = if first { "" } else { "...and refers to " },
1630                 item = get_descr(binding),
1631                 which = if first { "" } else { " which" },
1632                 dots = if next_binding.is_some() { "..." } else { "" },
1633             );
1634             let def_span = self.session.source_map().guess_head_span(binding.span);
1635             let mut note_span = MultiSpan::from_span(def_span);
1636             if !first && binding.vis.is_public() {
1637                 note_span.push_span_label(def_span, "consider importing it directly");
1638             }
1639             err.span_note(note_span, &msg);
1640         }
1641
1642         err.emit();
1643     }
1644
1645     pub(crate) fn find_similarly_named_module_or_crate(
1646         &mut self,
1647         ident: Symbol,
1648         current_module: &Module<'a>,
1649     ) -> Option<Symbol> {
1650         let mut candidates = self
1651             .extern_prelude
1652             .iter()
1653             .map(|(ident, _)| ident.name)
1654             .chain(
1655                 self.module_map
1656                     .iter()
1657                     .filter(|(_, module)| {
1658                         current_module.is_ancestor_of(module) && !ptr::eq(current_module, *module)
1659                     })
1660                     .flat_map(|(_, module)| module.kind.name()),
1661             )
1662             .filter(|c| !c.to_string().is_empty())
1663             .collect::<Vec<_>>();
1664         candidates.sort();
1665         candidates.dedup();
1666         match find_best_match_for_name(&candidates, ident, None) {
1667             Some(sugg) if sugg == ident => None,
1668             sugg => sugg,
1669         }
1670     }
1671
1672     pub(crate) fn report_path_resolution_error(
1673         &mut self,
1674         path: &[Segment],
1675         opt_ns: Option<Namespace>, // `None` indicates a module path in import
1676         parent_scope: &ParentScope<'a>,
1677         ribs: Option<&PerNS<Vec<Rib<'a>>>>,
1678         ignore_binding: Option<&'a NameBinding<'a>>,
1679         module: Option<ModuleOrUniformRoot<'a>>,
1680         i: usize,
1681         ident: Ident,
1682     ) -> (String, Option<Suggestion>) {
1683         let is_last = i == path.len() - 1;
1684         let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
1685         let module_res = match module {
1686             Some(ModuleOrUniformRoot::Module(module)) => module.res(),
1687             _ => None,
1688         };
1689         if module_res == self.graph_root.res() {
1690             let is_mod = |res| matches!(res, Res::Def(DefKind::Mod, _));
1691             let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
1692             candidates
1693                 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
1694             if let Some(candidate) = candidates.get(0) {
1695                 (
1696                     String::from("unresolved import"),
1697                     Some((
1698                         vec![(ident.span, pprust::path_to_string(&candidate.path))],
1699                         String::from("a similar path exists"),
1700                         Applicability::MaybeIncorrect,
1701                     )),
1702                 )
1703             } else if self.session.edition() == Edition::Edition2015 {
1704                 (
1705                     format!("maybe a missing crate `{ident}`?"),
1706                     Some((
1707                         vec![],
1708                         format!(
1709                             "consider adding `extern crate {ident}` to use the `{ident}` crate"
1710                         ),
1711                         Applicability::MaybeIncorrect,
1712                     )),
1713                 )
1714             } else {
1715                 (format!("could not find `{ident}` in the crate root"), None)
1716             }
1717         } else if i > 0 {
1718             let parent = path[i - 1].ident.name;
1719             let parent = match parent {
1720                 // ::foo is mounted at the crate root for 2015, and is the extern
1721                 // prelude for 2018+
1722                 kw::PathRoot if self.session.edition() > Edition::Edition2015 => {
1723                     "the list of imported crates".to_owned()
1724                 }
1725                 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
1726                 _ => format!("`{parent}`"),
1727             };
1728
1729             let mut msg = format!("could not find `{}` in {}", ident, parent);
1730             if ns == TypeNS || ns == ValueNS {
1731                 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
1732                 let binding = if let Some(module) = module {
1733                     self.resolve_ident_in_module(
1734                         module,
1735                         ident,
1736                         ns_to_try,
1737                         parent_scope,
1738                         None,
1739                         ignore_binding,
1740                     ).ok()
1741                 } else if let Some(ribs) = ribs
1742                     && let Some(TypeNS | ValueNS) = opt_ns
1743                 {
1744                     match self.resolve_ident_in_lexical_scope(
1745                         ident,
1746                         ns_to_try,
1747                         parent_scope,
1748                         None,
1749                         &ribs[ns_to_try],
1750                         ignore_binding,
1751                     ) {
1752                         // we found a locally-imported or available item/module
1753                         Some(LexicalScopeBinding::Item(binding)) => Some(binding),
1754                         _ => None,
1755                     }
1756                 } else {
1757                     let scopes = ScopeSet::All(ns_to_try, opt_ns.is_none());
1758                     self.early_resolve_ident_in_lexical_scope(
1759                         ident,
1760                         scopes,
1761                         parent_scope,
1762                         None,
1763                         false,
1764                         ignore_binding,
1765                     ).ok()
1766                 };
1767                 if let Some(binding) = binding {
1768                     let mut found = |what| {
1769                         msg = format!(
1770                             "expected {}, found {} `{}` in {}",
1771                             ns.descr(),
1772                             what,
1773                             ident,
1774                             parent
1775                         )
1776                     };
1777                     if binding.module().is_some() {
1778                         found("module")
1779                     } else {
1780                         match binding.res() {
1781                             Res::Def(kind, id) => found(kind.descr(id)),
1782                             _ => found(ns_to_try.descr()),
1783                         }
1784                     }
1785                 };
1786             }
1787             (msg, None)
1788         } else if ident.name == kw::SelfUpper {
1789             ("`Self` is only available in impls, traits, and type definitions".to_string(), None)
1790         } else if ident.name.as_str().chars().next().map_or(false, |c| c.is_ascii_uppercase()) {
1791             // Check whether the name refers to an item in the value namespace.
1792             let binding = if let Some(ribs) = ribs {
1793                 self.resolve_ident_in_lexical_scope(
1794                     ident,
1795                     ValueNS,
1796                     parent_scope,
1797                     None,
1798                     &ribs[ValueNS],
1799                     ignore_binding,
1800                 )
1801             } else {
1802                 None
1803             };
1804             let match_span = match binding {
1805                 // Name matches a local variable. For example:
1806                 // ```
1807                 // fn f() {
1808                 //     let Foo: &str = "";
1809                 //     println!("{}", Foo::Bar); // Name refers to local
1810                 //                               // variable `Foo`.
1811                 // }
1812                 // ```
1813                 Some(LexicalScopeBinding::Res(Res::Local(id))) => {
1814                     Some(*self.pat_span_map.get(&id).unwrap())
1815                 }
1816                 // Name matches item from a local name binding
1817                 // created by `use` declaration. For example:
1818                 // ```
1819                 // pub Foo: &str = "";
1820                 //
1821                 // mod submod {
1822                 //     use super::Foo;
1823                 //     println!("{}", Foo::Bar); // Name refers to local
1824                 //                               // binding `Foo`.
1825                 // }
1826                 // ```
1827                 Some(LexicalScopeBinding::Item(name_binding)) => Some(name_binding.span),
1828                 _ => None,
1829             };
1830             let suggestion = if let Some(span) = match_span {
1831                 Some((
1832                     vec![(span, String::from(""))],
1833                     format!("`{}` is defined here, but is not a type", ident),
1834                     Applicability::MaybeIncorrect,
1835                 ))
1836             } else {
1837                 None
1838             };
1839
1840             (format!("use of undeclared type `{}`", ident), suggestion)
1841         } else {
1842             let suggestion = if ident.name == sym::alloc {
1843                 Some((
1844                     vec![],
1845                     String::from("add `extern crate alloc` to use the `alloc` crate"),
1846                     Applicability::MaybeIncorrect,
1847                 ))
1848             } else {
1849                 self.find_similarly_named_module_or_crate(ident.name, &parent_scope.module).map(
1850                     |sugg| {
1851                         (
1852                             vec![(ident.span, sugg.to_string())],
1853                             String::from("there is a crate or module with a similar name"),
1854                             Applicability::MaybeIncorrect,
1855                         )
1856                     },
1857                 )
1858             };
1859             (format!("use of undeclared crate or module `{}`", ident), suggestion)
1860         }
1861     }
1862 }
1863
1864 impl<'a, 'b> ImportResolver<'a, 'b> {
1865     /// Adds suggestions for a path that cannot be resolved.
1866     pub(crate) fn make_path_suggestion(
1867         &mut self,
1868         span: Span,
1869         mut path: Vec<Segment>,
1870         parent_scope: &ParentScope<'b>,
1871     ) -> Option<(Vec<Segment>, Option<String>)> {
1872         debug!("make_path_suggestion: span={:?} path={:?}", span, path);
1873
1874         match (path.get(0), path.get(1)) {
1875             // `{{root}}::ident::...` on both editions.
1876             // On 2015 `{{root}}` is usually added implicitly.
1877             (Some(fst), Some(snd))
1878                 if fst.ident.name == kw::PathRoot && !snd.ident.is_path_segment_keyword() => {}
1879             // `ident::...` on 2018.
1880             (Some(fst), _)
1881                 if fst.ident.span.rust_2018() && !fst.ident.is_path_segment_keyword() =>
1882             {
1883                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
1884                 path.insert(0, Segment::from_ident(Ident::empty()));
1885             }
1886             _ => return None,
1887         }
1888
1889         self.make_missing_self_suggestion(path.clone(), parent_scope)
1890             .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
1891             .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
1892             .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
1893     }
1894
1895     /// Suggest a missing `self::` if that resolves to an correct module.
1896     ///
1897     /// ```text
1898     ///    |
1899     /// LL | use foo::Bar;
1900     ///    |     ^^^ did you mean `self::foo`?
1901     /// ```
1902     fn make_missing_self_suggestion(
1903         &mut self,
1904         mut path: Vec<Segment>,
1905         parent_scope: &ParentScope<'b>,
1906     ) -> Option<(Vec<Segment>, Option<String>)> {
1907         // Replace first ident with `self` and check if that is valid.
1908         path[0].ident.name = kw::SelfLower;
1909         let result = self.r.maybe_resolve_path(&path, None, parent_scope);
1910         debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
1911         if let PathResult::Module(..) = result { Some((path, None)) } else { None }
1912     }
1913
1914     /// Suggests a missing `crate::` if that resolves to an correct module.
1915     ///
1916     /// ```text
1917     ///    |
1918     /// LL | use foo::Bar;
1919     ///    |     ^^^ did you mean `crate::foo`?
1920     /// ```
1921     fn make_missing_crate_suggestion(
1922         &mut self,
1923         mut path: Vec<Segment>,
1924         parent_scope: &ParentScope<'b>,
1925     ) -> Option<(Vec<Segment>, Option<String>)> {
1926         // Replace first ident with `crate` and check if that is valid.
1927         path[0].ident.name = kw::Crate;
1928         let result = self.r.maybe_resolve_path(&path, None, parent_scope);
1929         debug!("make_missing_crate_suggestion:  path={:?} result={:?}", path, result);
1930         if let PathResult::Module(..) = result {
1931             Some((
1932                 path,
1933                 Some(
1934                     "`use` statements changed in Rust 2018; read more at \
1935                      <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
1936                      clarity.html>"
1937                         .to_string(),
1938                 ),
1939             ))
1940         } else {
1941             None
1942         }
1943     }
1944
1945     /// Suggests a missing `super::` if that resolves to an correct module.
1946     ///
1947     /// ```text
1948     ///    |
1949     /// LL | use foo::Bar;
1950     ///    |     ^^^ did you mean `super::foo`?
1951     /// ```
1952     fn make_missing_super_suggestion(
1953         &mut self,
1954         mut path: Vec<Segment>,
1955         parent_scope: &ParentScope<'b>,
1956     ) -> Option<(Vec<Segment>, Option<String>)> {
1957         // Replace first ident with `crate` and check if that is valid.
1958         path[0].ident.name = kw::Super;
1959         let result = self.r.maybe_resolve_path(&path, None, parent_scope);
1960         debug!("make_missing_super_suggestion:  path={:?} result={:?}", path, result);
1961         if let PathResult::Module(..) = result { Some((path, None)) } else { None }
1962     }
1963
1964     /// Suggests a missing external crate name if that resolves to an correct module.
1965     ///
1966     /// ```text
1967     ///    |
1968     /// LL | use foobar::Baz;
1969     ///    |     ^^^^^^ did you mean `baz::foobar`?
1970     /// ```
1971     ///
1972     /// Used when importing a submodule of an external crate but missing that crate's
1973     /// name as the first part of path.
1974     fn make_external_crate_suggestion(
1975         &mut self,
1976         mut path: Vec<Segment>,
1977         parent_scope: &ParentScope<'b>,
1978     ) -> Option<(Vec<Segment>, Option<String>)> {
1979         if path[1].ident.span.rust_2015() {
1980             return None;
1981         }
1982
1983         // Sort extern crate names in *reverse* order to get
1984         // 1) some consistent ordering for emitted diagnostics, and
1985         // 2) `std` suggestions before `core` suggestions.
1986         let mut extern_crate_names =
1987             self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>();
1988         extern_crate_names.sort_by(|a, b| b.as_str().partial_cmp(a.as_str()).unwrap());
1989
1990         for name in extern_crate_names.into_iter() {
1991             // Replace first ident with a crate name and check if that is valid.
1992             path[0].ident.name = name;
1993             let result = self.r.maybe_resolve_path(&path, None, parent_scope);
1994             debug!(
1995                 "make_external_crate_suggestion: name={:?} path={:?} result={:?}",
1996                 name, path, result
1997             );
1998             if let PathResult::Module(..) = result {
1999                 return Some((path, None));
2000             }
2001         }
2002
2003         None
2004     }
2005
2006     /// Suggests importing a macro from the root of the crate rather than a module within
2007     /// the crate.
2008     ///
2009     /// ```text
2010     /// help: a macro with this name exists at the root of the crate
2011     ///    |
2012     /// LL | use issue_59764::makro;
2013     ///    |     ^^^^^^^^^^^^^^^^^^
2014     ///    |
2015     ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
2016     ///            at the root of the crate instead of the module where it is defined
2017     /// ```
2018     pub(crate) fn check_for_module_export_macro(
2019         &mut self,
2020         import: &'b Import<'b>,
2021         module: ModuleOrUniformRoot<'b>,
2022         ident: Ident,
2023     ) -> Option<(Option<Suggestion>, Option<String>)> {
2024         let ModuleOrUniformRoot::Module(mut crate_module) = module else {
2025             return None;
2026         };
2027
2028         while let Some(parent) = crate_module.parent {
2029             crate_module = parent;
2030         }
2031
2032         if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
2033             // Don't make a suggestion if the import was already from the root of the
2034             // crate.
2035             return None;
2036         }
2037
2038         let resolutions = self.r.resolutions(crate_module).borrow();
2039         let resolution = resolutions.get(&self.r.new_key(ident, MacroNS))?;
2040         let binding = resolution.borrow().binding()?;
2041         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
2042             let module_name = crate_module.kind.name().unwrap();
2043             let import_snippet = match import.kind {
2044                 ImportKind::Single { source, target, .. } if source != target => {
2045                     format!("{} as {}", source, target)
2046                 }
2047                 _ => format!("{}", ident),
2048             };
2049
2050             let mut corrections: Vec<(Span, String)> = Vec::new();
2051             if !import.is_nested() {
2052                 // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
2053                 // intermediate segments.
2054                 corrections.push((import.span, format!("{}::{}", module_name, import_snippet)));
2055             } else {
2056                 // Find the binding span (and any trailing commas and spaces).
2057                 //   ie. `use a::b::{c, d, e};`
2058                 //                      ^^^
2059                 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
2060                     self.r.session,
2061                     import.span,
2062                     import.use_span,
2063                 );
2064                 debug!(
2065                     "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
2066                     found_closing_brace, binding_span
2067                 );
2068
2069                 let mut removal_span = binding_span;
2070                 if found_closing_brace {
2071                     // If the binding span ended with a closing brace, as in the below example:
2072                     //   ie. `use a::b::{c, d};`
2073                     //                      ^
2074                     // Then expand the span of characters to remove to include the previous
2075                     // binding's trailing comma.
2076                     //   ie. `use a::b::{c, d};`
2077                     //                    ^^^
2078                     if let Some(previous_span) =
2079                         extend_span_to_previous_binding(self.r.session, binding_span)
2080                     {
2081                         debug!("check_for_module_export_macro: previous_span={:?}", previous_span);
2082                         removal_span = removal_span.with_lo(previous_span.lo());
2083                     }
2084                 }
2085                 debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
2086
2087                 // Remove the `removal_span`.
2088                 corrections.push((removal_span, "".to_string()));
2089
2090                 // Find the span after the crate name and if it has nested imports immediately
2091                 // after the crate name already.
2092                 //   ie. `use a::b::{c, d};`
2093                 //               ^^^^^^^^^
2094                 //   or  `use a::{b, c, d}};`
2095                 //               ^^^^^^^^^^^
2096                 let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
2097                     self.r.session,
2098                     module_name,
2099                     import.use_span,
2100                 );
2101                 debug!(
2102                     "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
2103                     has_nested, after_crate_name
2104                 );
2105
2106                 let source_map = self.r.session.source_map();
2107
2108                 // Add the import to the start, with a `{` if required.
2109                 let start_point = source_map.start_point(after_crate_name);
2110                 if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
2111                     corrections.push((
2112                         start_point,
2113                         if has_nested {
2114                             // In this case, `start_snippet` must equal '{'.
2115                             format!("{}{}, ", start_snippet, import_snippet)
2116                         } else {
2117                             // In this case, add a `{`, then the moved import, then whatever
2118                             // was there before.
2119                             format!("{{{}, {}", import_snippet, start_snippet)
2120                         },
2121                     ));
2122                 }
2123
2124                 // Add a `};` to the end if nested, matching the `{` added at the start.
2125                 if !has_nested {
2126                     corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
2127                 }
2128             }
2129
2130             let suggestion = Some((
2131                 corrections,
2132                 String::from("a macro with this name exists at the root of the crate"),
2133                 Applicability::MaybeIncorrect,
2134             ));
2135             Some((suggestion, Some("this could be because a macro annotated with `#[macro_export]` will be exported \
2136             at the root of the crate instead of the module where it is defined"
2137                .to_string())))
2138         } else {
2139             None
2140         }
2141     }
2142 }
2143
2144 /// Given a `binding_span` of a binding within a use statement:
2145 ///
2146 /// ```ignore (illustrative)
2147 /// use foo::{a, b, c};
2148 /// //           ^
2149 /// ```
2150 ///
2151 /// then return the span until the next binding or the end of the statement:
2152 ///
2153 /// ```ignore (illustrative)
2154 /// use foo::{a, b, c};
2155 /// //           ^^^
2156 /// ```
2157 fn find_span_of_binding_until_next_binding(
2158     sess: &Session,
2159     binding_span: Span,
2160     use_span: Span,
2161 ) -> (bool, Span) {
2162     let source_map = sess.source_map();
2163
2164     // Find the span of everything after the binding.
2165     //   ie. `a, e};` or `a};`
2166     let binding_until_end = binding_span.with_hi(use_span.hi());
2167
2168     // Find everything after the binding but not including the binding.
2169     //   ie. `, e};` or `};`
2170     let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
2171
2172     // Keep characters in the span until we encounter something that isn't a comma or
2173     // whitespace.
2174     //   ie. `, ` or ``.
2175     //
2176     // Also note whether a closing brace character was encountered. If there
2177     // was, then later go backwards to remove any trailing commas that are left.
2178     let mut found_closing_brace = false;
2179     let after_binding_until_next_binding =
2180         source_map.span_take_while(after_binding_until_end, |&ch| {
2181             if ch == '}' {
2182                 found_closing_brace = true;
2183             }
2184             ch == ' ' || ch == ','
2185         });
2186
2187     // Combine the two spans.
2188     //   ie. `a, ` or `a`.
2189     //
2190     // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
2191     let span = binding_span.with_hi(after_binding_until_next_binding.hi());
2192
2193     (found_closing_brace, span)
2194 }
2195
2196 /// Given a `binding_span`, return the span through to the comma or opening brace of the previous
2197 /// binding.
2198 ///
2199 /// ```ignore (illustrative)
2200 /// use foo::a::{a, b, c};
2201 /// //            ^^--- binding span
2202 /// //            |
2203 /// //            returned span
2204 ///
2205 /// use foo::{a, b, c};
2206 /// //        --- binding span
2207 /// ```
2208 fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
2209     let source_map = sess.source_map();
2210
2211     // `prev_source` will contain all of the source that came before the span.
2212     // Then split based on a command and take the first (ie. closest to our span)
2213     // snippet. In the example, this is a space.
2214     let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
2215
2216     let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
2217     let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
2218     if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
2219         return None;
2220     }
2221
2222     let prev_comma = prev_comma.first().unwrap();
2223     let prev_starting_brace = prev_starting_brace.first().unwrap();
2224
2225     // If the amount of source code before the comma is greater than
2226     // the amount of source code before the starting brace then we've only
2227     // got one item in the nested item (eg. `issue_52891::{self}`).
2228     if prev_comma.len() > prev_starting_brace.len() {
2229         return None;
2230     }
2231
2232     Some(binding_span.with_lo(BytePos(
2233         // Take away the number of bytes for the characters we've found and an
2234         // extra for the comma.
2235         binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
2236     )))
2237 }
2238
2239 /// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
2240 /// it is a nested use tree.
2241 ///
2242 /// ```ignore (illustrative)
2243 /// use foo::a::{b, c};
2244 /// //       ^^^^^^^^^^ -- false
2245 ///
2246 /// use foo::{a, b, c};
2247 /// //       ^^^^^^^^^^ -- true
2248 ///
2249 /// use foo::{a, b::{c, d}};
2250 /// //       ^^^^^^^^^^^^^^^ -- true
2251 /// ```
2252 fn find_span_immediately_after_crate_name(
2253     sess: &Session,
2254     module_name: Symbol,
2255     use_span: Span,
2256 ) -> (bool, Span) {
2257     debug!(
2258         "find_span_immediately_after_crate_name: module_name={:?} use_span={:?}",
2259         module_name, use_span
2260     );
2261     let source_map = sess.source_map();
2262
2263     // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
2264     let mut num_colons = 0;
2265     // Find second colon.. `use issue_59764:`
2266     let until_second_colon = source_map.span_take_while(use_span, |c| {
2267         if *c == ':' {
2268             num_colons += 1;
2269         }
2270         !matches!(c, ':' if num_colons == 2)
2271     });
2272     // Find everything after the second colon.. `foo::{baz, makro};`
2273     let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
2274
2275     let mut found_a_non_whitespace_character = false;
2276     // Find the first non-whitespace character in `from_second_colon`.. `f`
2277     let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
2278         if found_a_non_whitespace_character {
2279             return false;
2280         }
2281         if !c.is_whitespace() {
2282             found_a_non_whitespace_character = true;
2283         }
2284         true
2285     });
2286
2287     // Find the first `{` in from_second_colon.. `foo::{`
2288     let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
2289
2290     (next_left_bracket == after_second_colon, from_second_colon)
2291 }
2292
2293 /// A suggestion has already been emitted, change the wording slightly to clarify that both are
2294 /// independent options.
2295 enum Instead {
2296     Yes,
2297     No,
2298 }
2299
2300 /// Whether an existing place with an `use` item was found.
2301 enum FoundUse {
2302     Yes,
2303     No,
2304 }
2305
2306 /// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
2307 enum DiagnosticMode {
2308     Normal,
2309     /// The binding is part of a pattern
2310     Pattern,
2311     /// The binding is part of a use statement
2312     Import,
2313 }
2314
2315 pub(crate) fn import_candidates(
2316     session: &Session,
2317     source_span: &IndexVec<LocalDefId, Span>,
2318     err: &mut Diagnostic,
2319     // This is `None` if all placement locations are inside expansions
2320     use_placement_span: Option<Span>,
2321     candidates: &[ImportSuggestion],
2322 ) {
2323     show_candidates(
2324         session,
2325         source_span,
2326         err,
2327         use_placement_span,
2328         candidates,
2329         Instead::Yes,
2330         FoundUse::Yes,
2331         DiagnosticMode::Import,
2332         vec![],
2333     );
2334 }
2335
2336 /// When an entity with a given name is not available in scope, we search for
2337 /// entities with that name in all crates. This method allows outputting the
2338 /// results of this search in a programmer-friendly way
2339 fn show_candidates(
2340     session: &Session,
2341     source_span: &IndexVec<LocalDefId, Span>,
2342     err: &mut Diagnostic,
2343     // This is `None` if all placement locations are inside expansions
2344     use_placement_span: Option<Span>,
2345     candidates: &[ImportSuggestion],
2346     instead: Instead,
2347     found_use: FoundUse,
2348     mode: DiagnosticMode,
2349     path: Vec<Segment>,
2350 ) {
2351     if candidates.is_empty() {
2352         return;
2353     }
2354
2355     let mut accessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
2356         Vec::new();
2357     let mut inaccessible_path_strings: Vec<(String, &str, Option<DefId>, &Option<String>)> =
2358         Vec::new();
2359
2360     candidates.iter().for_each(|c| {
2361         (if c.accessible { &mut accessible_path_strings } else { &mut inaccessible_path_strings })
2362             .push((path_names_to_string(&c.path), c.descr, c.did, &c.note))
2363     });
2364
2365     // we want consistent results across executions, but candidates are produced
2366     // by iterating through a hash map, so make sure they are ordered:
2367     for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
2368         path_strings.sort_by(|a, b| a.0.cmp(&b.0));
2369         let core_path_strings =
2370             path_strings.drain_filter(|p| p.0.starts_with("core::")).collect::<Vec<_>>();
2371         path_strings.extend(core_path_strings);
2372         path_strings.dedup_by(|a, b| a.0 == b.0);
2373     }
2374
2375     if !accessible_path_strings.is_empty() {
2376         let (determiner, kind, name) = if accessible_path_strings.len() == 1 {
2377             ("this", accessible_path_strings[0].1, format!(" `{}`", accessible_path_strings[0].0))
2378         } else {
2379             ("one of these", "items", String::new())
2380         };
2381
2382         let instead = if let Instead::Yes = instead { " instead" } else { "" };
2383         let mut msg = if let DiagnosticMode::Pattern = mode {
2384             format!(
2385                 "if you meant to match on {}{}{}, use the full path in the pattern",
2386                 kind, instead, name
2387             )
2388         } else {
2389             format!("consider importing {} {}{}", determiner, kind, instead)
2390         };
2391
2392         for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
2393             err.note(note);
2394         }
2395
2396         if let Some(span) = use_placement_span {
2397             let add_use = match mode {
2398                 DiagnosticMode::Pattern => {
2399                     err.span_suggestions(
2400                         span,
2401                         &msg,
2402                         accessible_path_strings.into_iter().map(|a| a.0),
2403                         Applicability::MaybeIncorrect,
2404                     );
2405                     return;
2406                 }
2407                 DiagnosticMode::Import => "",
2408                 DiagnosticMode::Normal => "use ",
2409             };
2410             for candidate in &mut accessible_path_strings {
2411                 // produce an additional newline to separate the new use statement
2412                 // from the directly following item.
2413                 let additional_newline = if let FoundUse::Yes = found_use { "" } else { "\n" };
2414                 candidate.0 = format!("{}{};\n{}", add_use, &candidate.0, additional_newline);
2415             }
2416
2417             err.span_suggestions(
2418                 span,
2419                 &msg,
2420                 accessible_path_strings.into_iter().map(|a| a.0),
2421                 Applicability::MaybeIncorrect,
2422             );
2423             if let [first, .., last] = &path[..] {
2424                 let sp = first.ident.span.until(last.ident.span);
2425                 if sp.can_be_used_for_suggestions() {
2426                     err.span_suggestion_verbose(
2427                         sp,
2428                         &format!("if you import `{}`, refer to it directly", last.ident),
2429                         "",
2430                         Applicability::Unspecified,
2431                     );
2432                 }
2433             }
2434         } else {
2435             msg.push(':');
2436
2437             for candidate in accessible_path_strings {
2438                 msg.push('\n');
2439                 msg.push_str(&candidate.0);
2440             }
2441
2442             err.note(&msg);
2443         }
2444     } else if !matches!(mode, DiagnosticMode::Import) {
2445         assert!(!inaccessible_path_strings.is_empty());
2446
2447         let prefix = if let DiagnosticMode::Pattern = mode {
2448             "you might have meant to match on "
2449         } else {
2450             ""
2451         };
2452         if inaccessible_path_strings.len() == 1 {
2453             let (name, descr, def_id, note) = &inaccessible_path_strings[0];
2454             let msg = format!(
2455                 "{}{} `{}`{} exists but is inaccessible",
2456                 prefix,
2457                 descr,
2458                 name,
2459                 if let DiagnosticMode::Pattern = mode { ", which" } else { "" }
2460             );
2461
2462             if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
2463                 let span = source_span[local_def_id];
2464                 let span = session.source_map().guess_head_span(span);
2465                 let mut multi_span = MultiSpan::from_span(span);
2466                 multi_span.push_span_label(span, "not accessible");
2467                 err.span_note(multi_span, &msg);
2468             } else {
2469                 err.note(&msg);
2470             }
2471             if let Some(note) = (*note).as_deref() {
2472                 err.note(note);
2473             }
2474         } else {
2475             let (_, descr_first, _, _) = &inaccessible_path_strings[0];
2476             let descr = if inaccessible_path_strings
2477                 .iter()
2478                 .skip(1)
2479                 .all(|(_, descr, _, _)| descr == descr_first)
2480             {
2481                 descr_first
2482             } else {
2483                 "item"
2484             };
2485             let plural_descr =
2486                 if descr.ends_with('s') { format!("{}es", descr) } else { format!("{}s", descr) };
2487
2488             let mut msg = format!("{}these {} exist but are inaccessible", prefix, plural_descr);
2489             let mut has_colon = false;
2490
2491             let mut spans = Vec::new();
2492             for (name, _, def_id, _) in &inaccessible_path_strings {
2493                 if let Some(local_def_id) = def_id.and_then(|did| did.as_local()) {
2494                     let span = source_span[local_def_id];
2495                     let span = session.source_map().guess_head_span(span);
2496                     spans.push((name, span));
2497                 } else {
2498                     if !has_colon {
2499                         msg.push(':');
2500                         has_colon = true;
2501                     }
2502                     msg.push('\n');
2503                     msg.push_str(name);
2504                 }
2505             }
2506
2507             let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
2508             for (name, span) in spans {
2509                 multi_span.push_span_label(span, format!("`{}`: not accessible", name));
2510             }
2511
2512             for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
2513                 err.note(note);
2514             }
2515
2516             err.span_note(multi_span, &msg);
2517         }
2518     }
2519 }
2520
2521 #[derive(Debug)]
2522 struct UsePlacementFinder {
2523     target_module: NodeId,
2524     first_legal_span: Option<Span>,
2525     first_use_span: Option<Span>,
2526 }
2527
2528 impl UsePlacementFinder {
2529     fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
2530         let mut finder =
2531             UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
2532         finder.visit_crate(krate);
2533         if let Some(use_span) = finder.first_use_span {
2534             (Some(use_span), FoundUse::Yes)
2535         } else {
2536             (finder.first_legal_span, FoundUse::No)
2537         }
2538     }
2539 }
2540
2541 impl<'tcx> visit::Visitor<'tcx> for UsePlacementFinder {
2542     fn visit_crate(&mut self, c: &Crate) {
2543         if self.target_module == CRATE_NODE_ID {
2544             let inject = c.spans.inject_use_span;
2545             if is_span_suitable_for_use_injection(inject) {
2546                 self.first_legal_span = Some(inject);
2547             }
2548             self.first_use_span = search_for_any_use_in_items(&c.items);
2549             return;
2550         } else {
2551             visit::walk_crate(self, c);
2552         }
2553     }
2554
2555     fn visit_item(&mut self, item: &'tcx ast::Item) {
2556         if self.target_module == item.id {
2557             if let ItemKind::Mod(_, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
2558                 let inject = mod_spans.inject_use_span;
2559                 if is_span_suitable_for_use_injection(inject) {
2560                     self.first_legal_span = Some(inject);
2561                 }
2562                 self.first_use_span = search_for_any_use_in_items(items);
2563                 return;
2564             }
2565         } else {
2566             visit::walk_item(self, item);
2567         }
2568     }
2569 }
2570
2571 fn search_for_any_use_in_items(items: &[P<ast::Item>]) -> Option<Span> {
2572     for item in items {
2573         if let ItemKind::Use(..) = item.kind {
2574             if is_span_suitable_for_use_injection(item.span) {
2575                 return Some(item.span.shrink_to_lo());
2576             }
2577         }
2578     }
2579     return None;
2580 }
2581
2582 fn is_span_suitable_for_use_injection(s: Span) -> bool {
2583     // don't suggest placing a use before the prelude
2584     // import or other generated ones
2585     !s.from_expansion()
2586 }
2587
2588 /// Convert the given number into the corresponding ordinal
2589 pub(crate) fn ordinalize(v: usize) -> String {
2590     let suffix = match ((11..=13).contains(&(v % 100)), v % 10) {
2591         (false, 1) => "st",
2592         (false, 2) => "nd",
2593         (false, 3) => "rd",
2594         _ => "th",
2595     };
2596     format!("{v}{suffix}")
2597 }