1use std::ops::ControlFlow;
3
4use itertools::Itertools as _;
5use rustc_ast::visit::{self, Visitor};
6use rustc_ast::{
7 self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents,
8};
9use rustc_ast_pretty::pprust;
10use rustc_data_structures::fx::{FxHashMap, FxHashSet};
11use rustc_data_structures::unord::{UnordMap, UnordSet};
12use rustc_errors::codes::*;
13use rustc_errors::{
14 Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
15 struct_span_code_err,
16};
17use rustc_feature::BUILTIN_ATTRIBUTES;
18use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
19use rustc_hir::def::Namespace::{self, *};
20use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
21use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
22use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr};
23use rustc_middle::bug;
24use rustc_middle::ty::{TyCtxt, Visibility};
25use rustc_session::Session;
26use rustc_session::lint::builtin::{
27 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
28 AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
29};
30use rustc_session::utils::was_invoked_from_cargo;
31use rustc_span::edit_distance::find_best_match_for_name;
32use rustc_span::edition::Edition;
33use rustc_span::hygiene::MacroKind;
34use rustc_span::source_map::SourceMap;
35use rustc_span::{
36 BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,
37};
38use thin_vec::{ThinVec, thin_vec};
39use tracing::{debug, instrument};
40
41use crate::errors::{
42 self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
43 ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
44 MaybeMissingMacroRulesName,
45};
46use crate::hygiene::Macros20NormalizedSyntaxContext;
47use crate::imports::{Import, ImportKind};
48use crate::late::{DiagMetadata, PatternSource, Rib};
49use crate::{
50 AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
51 Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey, LateDecl, MacroRulesScope,
52 Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PrivacyError, Res,
53 ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used, VisResolutionError,
54 errors as errs, path_names_to_string,
55};
56
57pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
59
60pub(crate) type LabelSuggestion = (Ident, bool);
63
64#[derive(#[automatically_derived]
impl ::core::clone::Clone for StructCtor {
#[inline]
fn clone(&self) -> StructCtor {
StructCtor {
res: ::core::clone::Clone::clone(&self.res),
vis: ::core::clone::Clone::clone(&self.vis),
field_visibilities: ::core::clone::Clone::clone(&self.field_visibilities),
}
}
}Clone)]
65pub(crate) struct StructCtor {
66 pub res: Res,
67 pub vis: Visibility<DefId>,
68 pub field_visibilities: Vec<Visibility<DefId>>,
69}
70
71impl StructCtor {
72 pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
73 self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
74 }
75}
76
77#[derive(#[automatically_derived]
impl ::core::fmt::Debug for SuggestionTarget {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
SuggestionTarget::SimilarlyNamed => "SimilarlyNamed",
SuggestionTarget::SingleItem => "SingleItem",
})
}
}Debug)]
78pub(crate) enum SuggestionTarget {
79 SimilarlyNamed,
81 SingleItem,
83}
84
85#[derive(#[automatically_derived]
impl ::core::fmt::Debug for TypoSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f,
"TypoSuggestion", "candidate", &self.candidate, "span",
&self.span, "res", &self.res, "target", &&self.target)
}
}Debug)]
86pub(crate) struct TypoSuggestion {
87 pub candidate: Symbol,
88 pub span: Option<Span>,
91 pub res: Res,
92 pub target: SuggestionTarget,
93}
94
95impl TypoSuggestion {
96 pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
97 Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
98 }
99 pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
100 Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
101 }
102 pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
103 Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
104 }
105}
106
107#[derive(#[automatically_derived]
impl ::core::fmt::Debug for ImportSuggestion {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["did", "descr", "path", "accessible", "doc_visible",
"via_import", "note", "is_stable"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.did, &self.descr, &self.path, &self.accessible,
&self.doc_visible, &self.via_import, &self.note,
&&self.is_stable];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"ImportSuggestion", names, values)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for ImportSuggestion {
#[inline]
fn clone(&self) -> ImportSuggestion {
ImportSuggestion {
did: ::core::clone::Clone::clone(&self.did),
descr: ::core::clone::Clone::clone(&self.descr),
path: ::core::clone::Clone::clone(&self.path),
accessible: ::core::clone::Clone::clone(&self.accessible),
doc_visible: ::core::clone::Clone::clone(&self.doc_visible),
via_import: ::core::clone::Clone::clone(&self.via_import),
note: ::core::clone::Clone::clone(&self.note),
is_stable: ::core::clone::Clone::clone(&self.is_stable),
}
}
}Clone)]
109pub(crate) struct ImportSuggestion {
110 pub did: Option<DefId>,
111 pub descr: &'static str,
112 pub path: Path,
113 pub accessible: bool,
114 pub doc_visible: bool,
116 pub via_import: bool,
117 pub note: Option<String>,
119 pub is_stable: bool,
120}
121
122fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
130 let impl_span = sm.span_until_char(impl_span, '<');
131 sm.span_until_whitespace(impl_span)
132}
133
134impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
135 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
136 self.tcx.dcx()
137 }
138
139 pub(crate) fn report_errors(&mut self, krate: &Crate) {
140 self.report_with_use_injections(krate);
141
142 for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
143 self.lint_buffer.buffer_lint(
144 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
145 CRATE_NODE_ID,
146 span_use,
147 errors::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
148 );
149 }
150
151 for ambiguity_error in &self.ambiguity_errors {
152 let mut diag = self.ambiguity_diagnostic(ambiguity_error);
153
154 if let Some(ambiguity_warning) = ambiguity_error.warning {
155 let node_id = match ambiguity_error.b1.0.kind {
156 DeclKind::Import { import, .. } => import.root_id,
157 DeclKind::Def(_) => CRATE_NODE_ID,
158 };
159
160 let lint = match ambiguity_warning {
161 _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
162 AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
163 AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
164 };
165
166 self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
167 } else {
168 diag.is_error = true;
169 self.dcx().emit_err(diag);
170 }
171 }
172
173 let mut reported_spans = FxHashSet::default();
174 for error in std::mem::take(&mut self.privacy_errors) {
175 if reported_spans.insert(error.dedup_span) {
176 self.report_privacy_error(&error);
177 }
178 }
179 }
180
181 fn report_with_use_injections(&mut self, krate: &Crate) {
182 for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in
183 std::mem::take(&mut self.use_injections)
184 {
185 let (span, found_use) = if let Some(def_id) = def_id.as_local() {
186 UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id))
187 } else {
188 (None, FoundUse::No)
189 };
190
191 if !candidates.is_empty() {
192 show_candidates(
193 self.tcx,
194 &mut err,
195 span,
196 &candidates,
197 if instead { Instead::Yes } else { Instead::No },
198 found_use,
199 DiagMode::Normal,
200 path,
201 "",
202 );
203 err.emit();
204 } else if let Some((span, msg, sugg, appl)) = suggestion {
205 err.span_suggestion_verbose(span, msg, sugg, appl);
206 err.emit();
207 } else if let [segment] = path.as_slice()
208 && is_call
209 {
210 err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
211 } else {
212 err.emit();
213 }
214 }
215 }
216
217 pub(crate) fn report_conflict(
218 &mut self,
219 ident: IdentKey,
220 ns: Namespace,
221 old_binding: Decl<'ra>,
222 new_binding: Decl<'ra>,
223 ) {
224 if old_binding.span.lo() > new_binding.span.lo() {
226 return self.report_conflict(ident, ns, new_binding, old_binding);
227 }
228
229 let container = match old_binding.parent_module.unwrap().kind {
230 ModuleKind::Def(kind, def_id, _) => kind.descr(def_id),
233 ModuleKind::Block => "block",
234 };
235
236 let (name, span) =
237 (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
238
239 if self.name_already_seen.get(&name) == Some(&span) {
240 return;
241 }
242
243 let old_kind = match (ns, old_binding.res()) {
244 (ValueNS, _) => "value",
245 (MacroNS, _) => "macro",
246 (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
247 (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
248 (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
249 (TypeNS, _) => "type",
250 };
251
252 let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
253 (true, true) => E0259,
254 (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
255 true => E0254,
256 false => E0260,
257 },
258 _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
259 (false, false) => E0428,
260 (true, true) => E0252,
261 _ => E0255,
262 },
263 };
264
265 let label = match new_binding.is_import_user_facing() {
266 true => errors::NameDefinedMultipleTimeLabel::Reimported { span, name },
267 false => errors::NameDefinedMultipleTimeLabel::Redefined { span, name },
268 };
269
270 let old_binding_label =
271 (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
272 let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
273 match old_binding.is_import_user_facing() {
274 true => errors::NameDefinedMultipleTimeOldBindingLabel::Import {
275 span,
276 old_kind,
277 name,
278 },
279 false => errors::NameDefinedMultipleTimeOldBindingLabel::Definition {
280 span,
281 old_kind,
282 name,
283 },
284 }
285 });
286
287 let mut err = self
288 .dcx()
289 .create_err(errors::NameDefinedMultipleTime {
290 span,
291 name,
292 descr: ns.descr(),
293 container,
294 label,
295 old_binding_label,
296 })
297 .with_code(code);
298
299 use DeclKind::Import;
301 let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
302 !binding.span.is_dummy()
303 && !#[allow(non_exhaustive_omitted_patterns)] match import.kind {
ImportKind::MacroUse { .. } | ImportKind::MacroExport => true,
_ => false,
}matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
304 };
305 let import = match (&new_binding.kind, &old_binding.kind) {
306 (Import { import: new, .. }, Import { import: old, .. })
309 if {
310 (new.has_attributes || old.has_attributes)
311 && can_suggest(old_binding, *old)
312 && can_suggest(new_binding, *new)
313 } =>
314 {
315 if old.has_attributes {
316 Some((*new, new_binding.span, true))
317 } else {
318 Some((*old, old_binding.span, true))
319 }
320 }
321 (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
323 Some((*import, new_binding.span, other.is_import()))
324 }
325 (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
326 Some((*import, old_binding.span, other.is_import()))
327 }
328 _ => None,
329 };
330
331 let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
333 let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
334 let from_item =
335 self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
336 let should_remove_import = duplicate
340 && !has_dummy_span
341 && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
342
343 match import {
344 Some((import, span, true)) if should_remove_import && import.is_nested() => {
345 self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
346 }
347 Some((import, _, true)) if should_remove_import && !import.is_glob() => {
348 err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport {
351 span: import.use_span_with_attributes,
352 });
353 }
354 Some((import, span, _)) => {
355 self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
356 }
357 _ => {}
358 }
359
360 err.emit();
361 self.name_already_seen.insert(name, span);
362 }
363
364 fn add_suggestion_for_rename_of_use(
374 &self,
375 err: &mut Diag<'_>,
376 name: Symbol,
377 import: Import<'_>,
378 binding_span: Span,
379 ) {
380 let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
381 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Other{0}", name))
})format!("Other{name}")
382 } else {
383 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("other_{0}", name))
})format!("other_{name}")
384 };
385
386 let mut suggestion = None;
387 let mut span = binding_span;
388 match import.kind {
389 ImportKind::Single { type_ns_only: true, .. } => {
390 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("self as {0}", suggested_name))
})format!("self as {suggested_name}"))
391 }
392 ImportKind::Single { source, .. } => {
393 if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
394 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
395 && pos as usize <= snippet.len()
396 {
397 span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
398 binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
399 );
400 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" as {0}", suggested_name))
})format!(" as {suggested_name}"));
401 }
402 }
403 ImportKind::ExternCrate { source, target, .. } => {
404 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern crate {0} as {1};",
source.unwrap_or(target.name), suggested_name))
})format!(
405 "extern crate {} as {};",
406 source.unwrap_or(target.name),
407 suggested_name,
408 ))
409 }
410 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
411 }
412
413 if let Some(suggestion) = suggestion {
414 err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
415 } else {
416 err.subdiagnostic(ChangeImportBinding { span });
417 }
418 }
419
420 fn add_suggestion_for_duplicate_nested_use(
443 &self,
444 err: &mut Diag<'_>,
445 import: Import<'_>,
446 binding_span: Span,
447 ) {
448 if !import.is_nested() {
::core::panicking::panic("assertion failed: import.is_nested()")
};assert!(import.is_nested());
449
450 let (found_closing_brace, span) =
458 find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
459
460 if found_closing_brace {
463 if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
464 err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport { span });
465 } else {
466 err.subdiagnostic(errors::RemoveUnnecessaryImport {
469 span: import.use_span_with_attributes,
470 });
471 }
472
473 return;
474 }
475
476 err.subdiagnostic(errors::RemoveUnnecessaryImport { span });
477 }
478
479 pub(crate) fn lint_if_path_starts_with_module(
480 &mut self,
481 finalize: Finalize,
482 path: &[Segment],
483 second_binding: Option<Decl<'_>>,
484 ) {
485 let Finalize { node_id, root_span, .. } = finalize;
486
487 let first_name = match path.get(0) {
488 Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
490 seg.ident.name
491 }
492 _ => return,
493 };
494
495 if first_name != kw::PathRoot {
498 return;
499 }
500
501 match path.get(1) {
502 Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
504 Some(_) => {}
506 None => return,
510 }
511
512 if let Some(binding) = second_binding
516 && let DeclKind::Import { import, .. } = binding.kind
517 && let ImportKind::ExternCrate { source: None, .. } = import.kind
519 {
520 return;
521 }
522
523 self.lint_buffer.dyn_buffer_lint_any(
524 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
525 node_id,
526 root_span,
527 move |dcx, level, sess| {
528 let (replacement, applicability) = match sess
529 .downcast_ref::<Session>()
530 .expect("expected a `Session`")
531 .source_map()
532 .span_to_snippet(root_span)
533 {
534 Ok(ref s) => {
535 let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
538
539 (::alloc::__export::must_use({
::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
})format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
540 }
541 Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
542 };
543 errors::AbsPathWithModule {
544 sugg: errors::AbsPathWithModuleSugg {
545 span: root_span,
546 applicability,
547 replacement,
548 },
549 }
550 .into_diag(dcx, level)
551 },
552 );
553 }
554
555 pub(crate) fn add_module_candidates(
556 &self,
557 module: Module<'ra>,
558 names: &mut Vec<TypoSuggestion>,
559 filter_fn: &impl Fn(Res) -> bool,
560 ctxt: Option<SyntaxContext>,
561 ) {
562 module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
563 let res = binding.res();
564 if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
565 names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
566 }
567 });
568 }
569
570 pub(crate) fn report_error(
575 &mut self,
576 span: Span,
577 resolution_error: ResolutionError<'ra>,
578 ) -> ErrorGuaranteed {
579 self.into_struct_error(span, resolution_error).emit()
580 }
581
582 pub(crate) fn into_struct_error(
583 &mut self,
584 span: Span,
585 resolution_error: ResolutionError<'ra>,
586 ) -> Diag<'_> {
587 match resolution_error {
588 ResolutionError::GenericParamsFromOuterItem {
589 outer_res,
590 has_generic_params,
591 def_kind,
592 inner_item,
593 current_self_ty,
594 } => {
595 use errs::GenericParamsFromOuterItemLabel as Label;
596 let static_or_const = match def_kind {
597 DefKind::Static { .. } => {
598 Some(errs::GenericParamsFromOuterItemStaticOrConst::Static)
599 }
600 DefKind::Const { .. } => {
601 Some(errs::GenericParamsFromOuterItemStaticOrConst::Const)
602 }
603 _ => None,
604 };
605 let is_self =
606 #[allow(non_exhaustive_omitted_patterns)] match outer_res {
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => true,
_ => false,
}matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
607 let mut err = errs::GenericParamsFromOuterItem {
608 span,
609 label: None,
610 refer_to_type_directly: None,
611 sugg: None,
612 static_or_const,
613 is_self,
614 item: inner_item.as_ref().map(|(span, kind)| {
615 errs::GenericParamsFromOuterItemInnerItem {
616 span: *span,
617 descr: kind.descr().to_string(),
618 is_self,
619 }
620 }),
621 };
622
623 let sm = self.tcx.sess.source_map();
624 let def_id = match outer_res {
625 Res::SelfTyParam { .. } => {
626 err.label = Some(Label::SelfTyParam(span));
627 return self.dcx().create_err(err);
628 }
629 Res::SelfTyAlias { alias_to: def_id, .. } => {
630 err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
631 sm,
632 self.def_span(def_id),
633 )));
634 err.refer_to_type_directly =
635 current_self_ty.map(|snippet| errs::UseTypeDirectly { span, snippet });
636 return self.dcx().create_err(err);
637 }
638 Res::Def(DefKind::TyParam, def_id) => {
639 err.label = Some(Label::TyParam(self.def_span(def_id)));
640 def_id
641 }
642 Res::Def(DefKind::ConstParam, def_id) => {
643 err.label = Some(Label::ConstParam(self.def_span(def_id)));
644 def_id
645 }
646 _ => {
647 ::rustc_middle::util::bug::bug_fmt(format_args!("GenericParamsFromOuterItem should only be used with Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or DefKind::ConstParam"));bug!(
648 "GenericParamsFromOuterItem should only be used with \
649 Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
650 DefKind::ConstParam"
651 );
652 }
653 };
654
655 if let HasGenericParams::Yes(span) = has_generic_params
656 && !#[allow(non_exhaustive_omitted_patterns)] match inner_item {
Some((_, ItemKind::Delegation(..))) => true,
_ => false,
}matches!(inner_item, Some((_, ItemKind::Delegation(..))))
657 {
658 let name = self.tcx.item_name(def_id);
659 let (span, snippet) = if span.is_empty() {
660 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", name))
})format!("<{name}>");
661 (span, snippet)
662 } else {
663 let span = sm.span_through_char(span, '<').shrink_to_hi();
664 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", name))
})format!("{name}, ");
665 (span, snippet)
666 };
667 err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
668 }
669
670 self.dcx().create_err(err)
671 }
672 ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
673 .dcx()
674 .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
675 ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
676 self.dcx().create_err(errs::MethodNotMemberOfTrait {
677 span,
678 method,
679 trait_,
680 sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
681 span: method.span,
682 candidate: c,
683 }),
684 })
685 }
686 ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
687 self.dcx().create_err(errs::TypeNotMemberOfTrait {
688 span,
689 type_,
690 trait_,
691 sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
692 span: type_.span,
693 candidate: c,
694 }),
695 })
696 }
697 ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
698 self.dcx().create_err(errs::ConstNotMemberOfTrait {
699 span,
700 const_,
701 trait_,
702 sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
703 span: const_.span,
704 candidate: c,
705 }),
706 })
707 }
708 ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
709 let BindingError { name, target, origin, could_be_path } = binding_error;
710
711 let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
712 target_sp.sort();
713 target_sp.dedup();
714 let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
715 origin_sp.sort();
716 origin_sp.dedup();
717
718 let msp = MultiSpan::from_spans(target_sp.clone());
719 let mut err = self
720 .dcx()
721 .create_err(errors::VariableIsNotBoundInAllPatterns { multispan: msp, name });
722 for sp in target_sp {
723 err.subdiagnostic(errors::PatternDoesntBindName { span: sp, name });
724 }
725 for sp in &origin_sp {
726 err.subdiagnostic(errors::VariableNotInAllPatterns { span: *sp });
727 }
728 let mut suggested_typo = false;
729 if !target.iter().all(|pat| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
730 && !origin.iter().all(|(_, pat)| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
731 {
732 let mut target_visitor = BindingVisitor::default();
735 for pat in &target {
736 target_visitor.visit_pat(pat);
737 }
738 target_visitor.identifiers.sort();
739 target_visitor.identifiers.dedup();
740 let mut origin_visitor = BindingVisitor::default();
741 for (_, pat) in &origin {
742 origin_visitor.visit_pat(pat);
743 }
744 origin_visitor.identifiers.sort();
745 origin_visitor.identifiers.dedup();
746 if let Some(typo) =
748 find_best_match_for_name(&target_visitor.identifiers, name.name, None)
749 && !origin_visitor.identifiers.contains(&typo)
750 {
751 err.subdiagnostic(errors::PatternBindingTypo { spans: origin_sp, typo });
752 suggested_typo = true;
753 }
754 }
755 if could_be_path {
756 let import_suggestions = self.lookup_import_candidates(
757 name,
758 Namespace::ValueNS,
759 &parent_scope,
760 &|res: Res| {
761 #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const) |
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) | DefKind::Const { .. }
| DefKind::AssocConst { .. }, _) => true,
_ => false,
}matches!(
762 res,
763 Res::Def(
764 DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
765 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
766 | DefKind::Const { .. }
767 | DefKind::AssocConst { .. },
768 _,
769 )
770 )
771 },
772 );
773
774 if import_suggestions.is_empty() && !suggested_typo {
775 let kind_matches: [fn(DefKind) -> bool; 4] = [
776 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
777 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
778 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Const { .. } => true,
_ => false,
}matches!(kind, DefKind::Const { .. }),
779 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::AssocConst { .. } => true,
_ => false,
}matches!(kind, DefKind::AssocConst { .. }),
780 ];
781 let mut local_names = ::alloc::vec::Vec::new()vec![];
782 self.add_module_candidates(
783 parent_scope.module,
784 &mut local_names,
785 &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(_, _) => true,
_ => false,
}matches!(res, Res::Def(_, _)),
786 None,
787 );
788 let local_names: FxHashSet<_> = local_names
789 .into_iter()
790 .filter_map(|s| match s.res {
791 Res::Def(_, def_id) => Some(def_id),
792 _ => None,
793 })
794 .collect();
795
796 let mut local_suggestions = ::alloc::vec::Vec::new()vec![];
797 let mut suggestions = ::alloc::vec::Vec::new()vec![];
798 for matches_kind in kind_matches {
799 if let Some(suggestion) = self.early_lookup_typo_candidate(
800 ScopeSet::All(Namespace::ValueNS),
801 &parent_scope,
802 name,
803 &|res: Res| match res {
804 Res::Def(k, _) => matches_kind(k),
805 _ => false,
806 },
807 ) && let Res::Def(kind, mut def_id) = suggestion.res
808 {
809 if let DefKind::Ctor(_, _) = kind {
810 def_id = self.tcx.parent(def_id);
811 }
812 let kind = kind.descr(def_id);
813 if local_names.contains(&def_id) {
814 local_suggestions.push((
817 suggestion.candidate,
818 suggestion.candidate.to_string(),
819 kind,
820 ));
821 } else {
822 suggestions.push((
823 suggestion.candidate,
824 self.def_path_str(def_id),
825 kind,
826 ));
827 }
828 }
829 }
830 let suggestions = if !local_suggestions.is_empty() {
831 local_suggestions
834 } else {
835 suggestions
836 };
837 for (name, sugg, kind) in suggestions {
838 err.span_suggestion_verbose(
839 span,
840 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might have meant to use the similarly named {0} `{1}`",
kind, name))
})format!(
841 "you might have meant to use the similarly named {kind} `{name}`",
842 ),
843 sugg,
844 Applicability::MaybeIncorrect,
845 );
846 suggested_typo = true;
847 }
848 }
849 if import_suggestions.is_empty() && !suggested_typo {
850 let help_msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if you meant to match on a unit struct, unit variant or a `const` item, consider making the path in the pattern qualified: `path::to::ModOrType::{0}`",
name))
})format!(
851 "if you meant to match on a unit struct, unit variant or a `const` \
852 item, consider making the path in the pattern qualified: \
853 `path::to::ModOrType::{name}`",
854 );
855 err.span_help(span, help_msg);
856 }
857 show_candidates(
858 self.tcx,
859 &mut err,
860 Some(span),
861 &import_suggestions,
862 Instead::No,
863 FoundUse::Yes,
864 DiagMode::Pattern,
865 ::alloc::vec::Vec::new()vec![],
866 "",
867 );
868 }
869 err
870 }
871 ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
872 self.dcx().create_err(errs::VariableBoundWithDifferentMode {
873 span,
874 first_binding_span,
875 variable_name,
876 })
877 }
878 ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
879 .dcx()
880 .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
881 ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
882 .dcx()
883 .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
884 ResolutionError::UndeclaredLabel { name, suggestion } => {
885 let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
886 {
887 Some((ident, true)) => (
889 (
890 Some(errs::LabelWithSimilarNameReachable(ident.span)),
891 Some(errs::TryUsingSimilarlyNamedLabel {
892 span,
893 ident_name: ident.name,
894 }),
895 ),
896 None,
897 ),
898 Some((ident, false)) => (
900 (None, None),
901 Some(errs::UnreachableLabelWithSimilarNameExists {
902 ident_span: ident.span,
903 }),
904 ),
905 None => ((None, None), None),
907 };
908 self.dcx().create_err(errs::UndeclaredLabel {
909 span,
910 name,
911 sub_reachable,
912 sub_reachable_suggestion,
913 sub_unreachable,
914 })
915 }
916 ResolutionError::SelfImportsOnlyAllowedWithin { root, span_with_rename } => {
917 let (suggestion, mpart_suggestion) = if root {
919 (None, None)
920 } else {
921 let suggestion = errs::SelfImportsOnlyAllowedWithinSuggestion { span };
924
925 let mpart_suggestion = errs::SelfImportsOnlyAllowedWithinMultipartSuggestion {
928 multipart_start: span_with_rename.shrink_to_lo(),
929 multipart_end: span_with_rename.shrink_to_hi(),
930 };
931 (Some(suggestion), Some(mpart_suggestion))
932 };
933 self.dcx().create_err(errs::SelfImportsOnlyAllowedWithin {
934 span,
935 suggestion,
936 mpart_suggestion,
937 })
938 }
939 ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
940 let mut err = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", message))
})).with_code(E0433)
}struct_span_code_err!(self.dcx(), span, E0433, "{message}");
941 err.span_label(span, label);
942
943 if let Some((suggestions, msg, applicability)) = suggestion {
944 if suggestions.is_empty() {
945 err.help(msg);
946 return err;
947 }
948 err.multipart_suggestion(msg, suggestions, applicability);
949 }
950
951 let module = match module {
952 Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
953 _ => CRATE_DEF_ID.to_def_id(),
954 };
955 self.find_cfg_stripped(&mut err, &segment, module);
956
957 err
958 }
959 ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
960 self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
961 }
962 ResolutionError::AttemptToUseNonConstantValueInConstant {
963 ident,
964 suggestion,
965 current,
966 type_span,
967 } => {
968 let sp = self
977 .tcx
978 .sess
979 .source_map()
980 .span_extend_to_prev_str(ident.span, current, true, false);
981
982 let ((with, with_label), without) = match sp {
983 Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
984 let sp = sp
985 .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
986 .until(ident.span);
987 (
988 (Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
989 span: sp,
990 suggestion,
991 current,
992 type_span,
993 }), Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion {span})),
994 None,
995 )
996 }
997 _ => (
998 (None, None),
999 Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
1000 ident_span: ident.span,
1001 suggestion,
1002 }),
1003 ),
1004 };
1005
1006 self.dcx().create_err(errs::AttemptToUseNonConstantValueInConstant {
1007 span,
1008 with,
1009 with_label,
1010 without,
1011 })
1012 }
1013 ResolutionError::BindingShadowsSomethingUnacceptable {
1014 shadowing_binding,
1015 name,
1016 participle,
1017 article,
1018 shadowed_binding,
1019 shadowed_binding_span,
1020 } => self.dcx().create_err(errs::BindingShadowsSomethingUnacceptable {
1021 span,
1022 shadowing_binding,
1023 shadowed_binding,
1024 article,
1025 sub_suggestion: match (shadowing_binding, shadowed_binding) {
1026 (
1027 PatternSource::Match,
1028 Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
1029 ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
1030 _ => None,
1031 },
1032 shadowed_binding_span,
1033 participle,
1034 name,
1035 }),
1036 ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
1037 ForwardGenericParamBanReason::Default => {
1038 self.dcx().create_err(errs::ForwardDeclaredGenericParam { param, span })
1039 }
1040 ForwardGenericParamBanReason::ConstParamTy => self
1041 .dcx()
1042 .create_err(errs::ForwardDeclaredGenericInConstParamTy { param, span }),
1043 },
1044 ResolutionError::ParamInTyOfConstParam { name } => {
1045 self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
1046 }
1047 ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {
1048 self.dcx().create_err(errs::ParamInNonTrivialAnonConst {
1049 span,
1050 name,
1051 param_kind: is_type,
1052 help: self.tcx.sess.is_nightly_build(),
1053 is_gca,
1054 help_gca: is_gca,
1055 })
1056 }
1057 ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
1058 .dcx()
1059 .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
1060 ResolutionError::ForwardDeclaredSelf(reason) => match reason {
1061 ForwardGenericParamBanReason::Default => {
1062 self.dcx().create_err(errs::SelfInGenericParamDefault { span })
1063 }
1064 ForwardGenericParamBanReason::ConstParamTy => {
1065 self.dcx().create_err(errs::SelfInConstGenericTy { span })
1066 }
1067 },
1068 ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
1069 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
1070 match suggestion {
1071 Some((ident, true)) => (
1073 (
1074 Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
1075 Some(errs::UnreachableLabelSubSuggestion {
1076 span,
1077 ident_name: ident.name,
1080 }),
1081 ),
1082 None,
1083 ),
1084 Some((ident, false)) => (
1086 (None, None),
1087 Some(errs::UnreachableLabelSubLabelUnreachable {
1088 ident_span: ident.span,
1089 }),
1090 ),
1091 None => ((None, None), None),
1093 };
1094 self.dcx().create_err(errs::UnreachableLabel {
1095 span,
1096 name,
1097 definition_span,
1098 sub_suggestion,
1099 sub_suggestion_label,
1100 sub_unreachable_label,
1101 })
1102 }
1103 ResolutionError::TraitImplMismatch {
1104 name,
1105 kind,
1106 code,
1107 trait_item_span,
1108 trait_path,
1109 } => self
1110 .dcx()
1111 .create_err(errors::TraitImplMismatch {
1112 span,
1113 name,
1114 kind,
1115 trait_path,
1116 trait_item_span,
1117 })
1118 .with_code(code),
1119 ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
1120 .dcx()
1121 .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
1122 ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
1123 ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
1124 ResolutionError::BindingInNeverPattern => {
1125 self.dcx().create_err(errs::BindingInNeverPattern { span })
1126 }
1127 }
1128 }
1129
1130 pub(crate) fn report_vis_error(
1131 &mut self,
1132 vis_resolution_error: VisResolutionError<'_>,
1133 ) -> ErrorGuaranteed {
1134 match vis_resolution_error {
1135 VisResolutionError::Relative2018(span, path) => {
1136 self.dcx().create_err(errs::Relative2018 {
1137 span,
1138 path_span: path.span,
1139 path_str: pprust::path_to_string(path),
1142 })
1143 }
1144 VisResolutionError::AncestorOnly(span) => {
1145 self.dcx().create_err(errs::AncestorOnly(span))
1146 }
1147 VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self
1148 .into_struct_error(
1149 span,
1150 ResolutionError::FailedToResolve {
1151 segment,
1152 label,
1153 suggestion,
1154 module: None,
1155 message,
1156 },
1157 ),
1158 VisResolutionError::ExpectedFound(span, path_str, res) => {
1159 self.dcx().create_err(errs::ExpectedModuleFound { span, res, path_str })
1160 }
1161 VisResolutionError::Indeterminate(span) => {
1162 self.dcx().create_err(errs::Indeterminate(span))
1163 }
1164 VisResolutionError::ModuleOnly(span) => self.dcx().create_err(errs::ModuleOnly(span)),
1165 }
1166 .emit()
1167 }
1168
1169 fn def_path_str(&self, mut def_id: DefId) -> String {
1170 let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[def_id]))vec![def_id];
1172 while let Some(parent) = self.tcx.opt_parent(def_id) {
1173 def_id = parent;
1174 path.push(def_id);
1175 if def_id.is_top_level_module() {
1176 break;
1177 }
1178 }
1179 path.into_iter()
1181 .rev()
1182 .map(|def_id| {
1183 self.tcx
1184 .opt_item_name(def_id)
1185 .map(|name| {
1186 match (
1187 def_id.is_top_level_module(),
1188 def_id.is_local(),
1189 self.tcx.sess.edition(),
1190 ) {
1191 (true, true, Edition::Edition2015) => String::new(),
1192 (true, true, _) => kw::Crate.to_string(),
1193 (true, false, _) | (false, _, _) => name.to_string(),
1194 }
1195 })
1196 .unwrap_or_else(|| "_".to_string())
1197 })
1198 .collect::<Vec<String>>()
1199 .join("::")
1200 }
1201
1202 pub(crate) fn add_scope_set_candidates(
1203 &mut self,
1204 suggestions: &mut Vec<TypoSuggestion>,
1205 scope_set: ScopeSet<'ra>,
1206 ps: &ParentScope<'ra>,
1207 sp: Span,
1208 filter_fn: &impl Fn(Res) -> bool,
1209 ) {
1210 let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
1211 self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
1212 match scope {
1213 Scope::DeriveHelpers(expn_id) => {
1214 let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
1215 if filter_fn(res) {
1216 suggestions.extend(
1217 this.helper_attrs.get(&expn_id).into_iter().flatten().map(
1218 |&(ident, orig_ident_span, _)| {
1219 TypoSuggestion::new(ident.name, orig_ident_span, res)
1220 },
1221 ),
1222 );
1223 }
1224 }
1225 Scope::DeriveHelpersCompat => {
1226 }
1228 Scope::MacroRules(macro_rules_scope) => {
1229 if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
1230 let res = macro_rules_def.decl.res();
1231 if filter_fn(res) {
1232 suggestions.push(TypoSuggestion::new(
1233 macro_rules_def.ident.name,
1234 macro_rules_def.orig_ident_span,
1235 res,
1236 ))
1237 }
1238 }
1239 }
1240 Scope::ModuleNonGlobs(module, _) => {
1241 this.add_module_candidates(module, suggestions, filter_fn, None);
1242 }
1243 Scope::ModuleGlobs(..) => {
1244 }
1246 Scope::MacroUsePrelude => {
1247 suggestions.extend(this.macro_use_prelude.iter().filter_map(
1248 |(name, binding)| {
1249 let res = binding.res();
1250 filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1251 },
1252 ));
1253 }
1254 Scope::BuiltinAttrs => {
1255 let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
1256 if filter_fn(res) {
1257 suggestions.extend(
1258 BUILTIN_ATTRIBUTES
1259 .iter()
1260 .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
1261 );
1262 }
1263 }
1264 Scope::ExternPreludeItems => {
1265 suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
1267 let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1268 filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
1269 }));
1270 }
1271 Scope::ExternPreludeFlags => {}
1272 Scope::ToolPrelude => {
1273 let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1274 suggestions.extend(
1275 this.registered_tools
1276 .iter()
1277 .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
1278 );
1279 }
1280 Scope::StdLibPrelude => {
1281 if let Some(prelude) = this.prelude {
1282 let mut tmp_suggestions = Vec::new();
1283 this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1284 suggestions.extend(
1285 tmp_suggestions
1286 .into_iter()
1287 .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
1288 );
1289 }
1290 }
1291 Scope::BuiltinTypes => {
1292 suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1293 let res = Res::PrimTy(*prim_ty);
1294 filter_fn(res)
1295 .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1296 }))
1297 }
1298 }
1299
1300 ControlFlow::<()>::Continue(())
1301 });
1302 }
1303
1304 fn early_lookup_typo_candidate(
1306 &mut self,
1307 scope_set: ScopeSet<'ra>,
1308 parent_scope: &ParentScope<'ra>,
1309 ident: Ident,
1310 filter_fn: &impl Fn(Res) -> bool,
1311 ) -> Option<TypoSuggestion> {
1312 let mut suggestions = Vec::new();
1313 self.add_scope_set_candidates(
1314 &mut suggestions,
1315 scope_set,
1316 parent_scope,
1317 ident.span,
1318 filter_fn,
1319 );
1320
1321 suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
1323
1324 match find_best_match_for_name(
1325 &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1326 ident.name,
1327 None,
1328 ) {
1329 Some(found) if found != ident.name => {
1330 suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1331 }
1332 _ => None,
1333 }
1334 }
1335
1336 fn lookup_import_candidates_from_module<FilterFn>(
1337 &self,
1338 lookup_ident: Ident,
1339 namespace: Namespace,
1340 parent_scope: &ParentScope<'ra>,
1341 start_module: Module<'ra>,
1342 crate_path: ThinVec<ast::PathSegment>,
1343 filter_fn: FilterFn,
1344 ) -> Vec<ImportSuggestion>
1345 where
1346 FilterFn: Fn(Res) -> bool,
1347 {
1348 let mut candidates = Vec::new();
1349 let mut seen_modules = FxHashSet::default();
1350 let start_did = start_module.def_id();
1351 let mut worklist = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(start_module, ThinVec::<ast::PathSegment>::new(), true,
start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
true)]))vec![(
1352 start_module,
1353 ThinVec::<ast::PathSegment>::new(),
1354 true,
1355 start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1356 true,
1357 )];
1358 let mut worklist_via_import = ::alloc::vec::Vec::new()vec![];
1359
1360 while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1361 match worklist.pop() {
1362 None => worklist_via_import.pop(),
1363 Some(x) => Some(x),
1364 }
1365 {
1366 let in_module_is_extern = !in_module.def_id().is_local();
1367 in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
1368 if name_binding.is_assoc_item()
1370 && !this.tcx.features().import_trait_associated_functions()
1371 {
1372 return;
1373 }
1374
1375 if ident.name == kw::Underscore {
1376 return;
1377 }
1378
1379 let child_accessible =
1380 accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);
1381
1382 if in_module_is_extern && !child_accessible {
1384 return;
1385 }
1386
1387 let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1388
1389 if via_import && name_binding.is_possibly_imported_variant() {
1395 return;
1396 }
1397
1398 if let DeclKind::Import { source_decl, .. } = name_binding.kind
1400 && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1401 && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
1402 {
1403 return;
1404 }
1405
1406 let res = name_binding.res();
1407 let did = match res {
1408 Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
1409 _ => res.opt_def_id(),
1410 };
1411 let child_doc_visible = doc_visible
1412 && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));
1413
1414 if ident.name == lookup_ident.name
1418 && ns == namespace
1419 && in_module != parent_scope.module
1420 && ident.ctxt.is_root()
1421 && filter_fn(res)
1422 {
1423 let mut segms = if lookup_ident.span.at_least_rust_2018() {
1425 crate_path.clone()
1428 } else {
1429 ThinVec::new()
1430 };
1431 segms.append(&mut path_segments.clone());
1432
1433 segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1434 let path = Path { span: name_binding.span, segments: segms, tokens: None };
1435
1436 if child_accessible
1437 && let Some(idx) = candidates
1439 .iter()
1440 .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1441 {
1442 candidates.remove(idx);
1443 }
1444
1445 let is_stable = if is_stable
1446 && let Some(did) = did
1447 && this.is_stable(did, path.span)
1448 {
1449 true
1450 } else {
1451 false
1452 };
1453
1454 if is_stable
1459 && let Some(idx) = candidates
1460 .iter()
1461 .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1462 {
1463 candidates.remove(idx);
1464 }
1465
1466 if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1467 let note = if let Some(did) = did {
1470 let requires_note = !did.is_local()
1471 && {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(did, &this.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDiagnosticItem(sym::TryInto
| sym::TryFrom | sym::FromIterator)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(
1472 this.tcx,
1473 did,
1474 RustcDiagnosticItem(
1475 sym::TryInto | sym::TryFrom | sym::FromIterator
1476 )
1477 );
1478 requires_note.then(|| {
1479 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("\'{0}\' is included in the prelude starting in Edition 2021",
path_names_to_string(&path)))
})format!(
1480 "'{}' is included in the prelude starting in Edition 2021",
1481 path_names_to_string(&path)
1482 )
1483 })
1484 } else {
1485 None
1486 };
1487
1488 candidates.push(ImportSuggestion {
1489 did,
1490 descr: res.descr(),
1491 path,
1492 accessible: child_accessible,
1493 doc_visible: child_doc_visible,
1494 note,
1495 via_import,
1496 is_stable,
1497 });
1498 }
1499 }
1500
1501 if let Some(def_id) = name_binding.res().module_like_def_id() {
1503 let mut path_segments = path_segments.clone();
1505 path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1506
1507 let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
1508 && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
1509 && import.parent_scope.expansion == parent_scope.expansion
1510 {
1511 true
1512 } else {
1513 false
1514 };
1515
1516 let is_extern_crate_that_also_appears_in_prelude =
1517 name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
1518
1519 if !is_extern_crate_that_also_appears_in_prelude || alias_import {
1520 if seen_modules.insert(def_id) {
1522 if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1523 (
1524 this.expect_module(def_id),
1525 path_segments,
1526 child_accessible,
1527 child_doc_visible,
1528 is_stable && this.is_stable(def_id, name_binding.span),
1529 ),
1530 );
1531 }
1532 }
1533 }
1534 })
1535 }
1536
1537 candidates
1538 }
1539
1540 fn is_stable(&self, did: DefId, span: Span) -> bool {
1541 if did.is_local() {
1542 return true;
1543 }
1544
1545 match self.tcx.lookup_stability(did) {
1546 Some(Stability {
1547 level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
1548 }) => {
1549 if span.allows_unstable(feature) {
1550 true
1551 } else if self.tcx.features().enabled(feature) {
1552 true
1553 } else if let Some(implied_by) = implied_by
1554 && self.tcx.features().enabled(implied_by)
1555 {
1556 true
1557 } else {
1558 false
1559 }
1560 }
1561 Some(_) => true,
1562 None => false,
1563 }
1564 }
1565
1566 pub(crate) fn lookup_import_candidates<FilterFn>(
1574 &mut self,
1575 lookup_ident: Ident,
1576 namespace: Namespace,
1577 parent_scope: &ParentScope<'ra>,
1578 filter_fn: FilterFn,
1579 ) -> Vec<ImportSuggestion>
1580 where
1581 FilterFn: Fn(Res) -> bool,
1582 {
1583 let crate_path = {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate)));
vec
}thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];
1584 let mut suggestions = self.lookup_import_candidates_from_module(
1585 lookup_ident,
1586 namespace,
1587 parent_scope,
1588 self.graph_root.to_module(),
1589 crate_path,
1590 &filter_fn,
1591 );
1592
1593 if lookup_ident.span.at_least_rust_2018() {
1594 for (ident, entry) in &self.extern_prelude {
1595 if entry.span().from_expansion() {
1596 continue;
1602 }
1603 let Some(crate_id) =
1604 self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
1605 else {
1606 continue;
1607 };
1608
1609 let crate_def_id = crate_id.as_def_id();
1610 let crate_root = self.expect_module(crate_def_id);
1611
1612 let needs_disambiguation =
1616 self.resolutions(parent_scope.module).borrow().iter().any(
1617 |(key, name_resolution)| {
1618 if key.ns == TypeNS
1619 && key.ident == *ident
1620 && let Some(decl) = name_resolution.borrow().best_decl()
1621 {
1622 match decl.res() {
1623 Res::Def(_, def_id) => def_id != crate_def_id,
1626 Res::PrimTy(_) => true,
1627 _ => false,
1628 }
1629 } else {
1630 false
1631 }
1632 },
1633 );
1634 let mut crate_path = ThinVec::new();
1635 if needs_disambiguation {
1636 crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
1637 }
1638 crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
1639
1640 suggestions.extend(self.lookup_import_candidates_from_module(
1641 lookup_ident,
1642 namespace,
1643 parent_scope,
1644 crate_root,
1645 crate_path,
1646 &filter_fn,
1647 ));
1648 }
1649 }
1650
1651 suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
1652 suggestions
1653 }
1654
1655 pub(crate) fn unresolved_macro_suggestions(
1656 &mut self,
1657 err: &mut Diag<'_>,
1658 macro_kind: MacroKind,
1659 parent_scope: &ParentScope<'ra>,
1660 ident: Ident,
1661 krate: &Crate,
1662 sugg_span: Option<Span>,
1663 ) {
1664 self.register_macros_for_all_crates();
1667
1668 let is_expected =
1669 &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
1670 let suggestion = self.early_lookup_typo_candidate(
1671 ScopeSet::Macro(macro_kind),
1672 parent_scope,
1673 ident,
1674 is_expected,
1675 );
1676 if !self.add_typo_suggestion(err, suggestion, ident.span) {
1677 self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
1678 }
1679
1680 let import_suggestions =
1681 self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1682 let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() {
1683 Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)),
1684 None => (None, FoundUse::No),
1685 };
1686 show_candidates(
1687 self.tcx,
1688 err,
1689 span,
1690 &import_suggestions,
1691 Instead::No,
1692 found_use,
1693 DiagMode::Normal,
1694 ::alloc::vec::Vec::new()vec![],
1695 "",
1696 );
1697
1698 if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
1699 let label_span = ident.span.shrink_to_hi();
1700 let mut spans = MultiSpan::from_span(label_span);
1701 spans.push_span_label(label_span, "put a macro name here");
1702 err.subdiagnostic(MaybeMissingMacroRulesName { spans });
1703 return;
1704 }
1705
1706 if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1707 err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
1708 return;
1709 }
1710
1711 let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
1712 if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
1713 });
1714
1715 if let Some((def_id, unused_ident)) = unused_macro {
1716 let scope = self.local_macro_def_scopes[&def_id];
1717 let parent_nearest = parent_scope.module.nearest_parent_mod();
1718 let unused_macro_kinds = self.local_macro_map[def_id].ext.macro_kinds();
1719 if !unused_macro_kinds.contains(macro_kind.into()) {
1720 match macro_kind {
1721 MacroKind::Bang => {
1722 err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
1723 }
1724 MacroKind::Attr => {
1725 err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
1726 }
1727 MacroKind::Derive => {
1728 err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
1729 }
1730 }
1731 return;
1732 }
1733 if Some(parent_nearest) == scope.opt_def_id() {
1734 err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1735 err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1736 return;
1737 }
1738 }
1739
1740 if ident.name == kw::Default
1741 && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind
1742 {
1743 let span = self.def_span(def_id);
1744 let source_map = self.tcx.sess.source_map();
1745 let head_span = source_map.guess_head_span(span);
1746 err.subdiagnostic(ConsiderAddingADerive {
1747 span: head_span.shrink_to_lo(),
1748 suggestion: "#[derive(Default)]\n".to_string(),
1749 });
1750 }
1751 for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
1752 let Ok(binding) = self.cm().resolve_ident_in_scope_set(
1753 ident,
1754 ScopeSet::All(ns),
1755 parent_scope,
1756 None,
1757 None,
1758 None,
1759 ) else {
1760 continue;
1761 };
1762
1763 let desc = match binding.res() {
1764 Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
1765 "a function-like macro".to_string()
1766 }
1767 Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
1768 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
})format!("an attribute: `#[{ident}]`")
1769 }
1770 Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
1771 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
ident))
})format!("a derive macro: `#[derive({ident})]`")
1772 }
1773 Res::Def(DefKind::Macro(kinds), _) => {
1774 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
kinds.descr()))
})format!("{} {}", kinds.article(), kinds.descr())
1775 }
1776 Res::ToolMod | Res::OpenMod(..) => {
1777 continue;
1779 }
1780 Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
1781 "only a trait, without a derive macro".to_string()
1782 }
1783 res => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}, not {2} {3}",
res.article(), res.descr(), macro_kind.article(),
macro_kind.descr_expected()))
})format!(
1784 "{} {}, not {} {}",
1785 res.article(),
1786 res.descr(),
1787 macro_kind.article(),
1788 macro_kind.descr_expected(),
1789 ),
1790 };
1791 if let crate::DeclKind::Import { import, .. } = binding.kind
1792 && !import.span.is_dummy()
1793 {
1794 let note = errors::IdentImporterHereButItIsDesc {
1795 span: import.span,
1796 imported_ident: ident,
1797 imported_ident_desc: &desc,
1798 };
1799 err.subdiagnostic(note);
1800 self.record_use(ident, binding, Used::Other);
1803 return;
1804 }
1805 let note = errors::IdentInScopeButItIsDesc {
1806 imported_ident: ident,
1807 imported_ident_desc: &desc,
1808 };
1809 err.subdiagnostic(note);
1810 return;
1811 }
1812
1813 if self.macro_names.contains(&IdentKey::new(ident)) {
1814 err.subdiagnostic(AddedMacroUse);
1815 return;
1816 }
1817 }
1818
1819 fn detect_derive_attribute(
1822 &self,
1823 err: &mut Diag<'_>,
1824 ident: Ident,
1825 parent_scope: &ParentScope<'ra>,
1826 sugg_span: Option<Span>,
1827 ) {
1828 let mut derives = ::alloc::vec::Vec::new()vec![];
1833 let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
1834 #[allow(rustc::potential_query_instability)]
1836 for (def_id, data) in self
1837 .local_macro_map
1838 .iter()
1839 .map(|(local_id, data)| (local_id.to_def_id(), data))
1840 .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
1841 {
1842 for helper_attr in &data.ext.helper_attrs {
1843 let item_name = self.tcx.item_name(def_id);
1844 all_attrs.entry(*helper_attr).or_default().push(item_name);
1845 if helper_attr == &ident.name {
1846 derives.push(item_name);
1847 }
1848 }
1849 }
1850 let kind = MacroKind::Derive.descr();
1851 if !derives.is_empty() {
1852 let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
1854 derives.sort();
1855 derives.dedup();
1856 let msg = match &derives[..] {
1857 [derive] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", derive))
})format!(" `{derive}`"),
1858 [start @ .., last] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("s {0} and `{1}`",
start.iter().map(|d|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", d))
})).collect::<Vec<_>>().join(", "), last))
})format!(
1859 "s {} and `{last}`",
1860 start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
1861 ),
1862 [] => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("we checked for this to be non-empty 10 lines above!?")));
}unreachable!("we checked for this to be non-empty 10 lines above!?"),
1863 };
1864 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` is an attribute that can be used by the {1}{2}, you might be missing a `derive` attribute",
ident.name, kind, msg))
})format!(
1865 "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
1866 missing a `derive` attribute",
1867 ident.name,
1868 );
1869 let sugg_span = if let ModuleKind::Def(DefKind::Enum, id, _) = parent_scope.module.kind
1870 {
1871 let span = self.def_span(id);
1872 if span.from_expansion() {
1873 None
1874 } else {
1875 Some(span.shrink_to_lo())
1877 }
1878 } else {
1879 sugg_span
1881 };
1882 match sugg_span {
1883 Some(span) => {
1884 err.span_suggestion_verbose(
1885 span,
1886 msg,
1887 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#[derive({0})]\n",
derives.join(", ")))
})format!("#[derive({})]\n", derives.join(", ")),
1888 Applicability::MaybeIncorrect,
1889 );
1890 }
1891 None => {
1892 err.note(msg);
1893 }
1894 }
1895 } else {
1896 let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
1898 if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
1899 && let Some(macros) = all_attrs.get(&best_match)
1900 {
1901 let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
1902 macros.sort();
1903 macros.dedup();
1904 let msg = match ¯os[..] {
1905 [] => return,
1906 [name] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}` accepts", name))
})format!(" `{name}` accepts"),
1907 [start @ .., end] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("s {0} and `{1}` accept",
start.iter().map(|m|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", m))
})).collect::<Vec<_>>().join(", "), end))
})format!(
1908 "s {} and `{end}` accept",
1909 start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
1910 ),
1911 };
1912 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the {0}{1} the similarly named `{2}` attribute",
kind, msg, best_match))
})format!("the {kind}{msg} the similarly named `{best_match}` attribute");
1913 err.span_suggestion_verbose(
1914 ident.span,
1915 msg,
1916 best_match,
1917 Applicability::MaybeIncorrect,
1918 );
1919 }
1920 }
1921 }
1922
1923 pub(crate) fn add_typo_suggestion(
1924 &self,
1925 err: &mut Diag<'_>,
1926 suggestion: Option<TypoSuggestion>,
1927 span: Span,
1928 ) -> bool {
1929 let suggestion = match suggestion {
1930 None => return false,
1931 Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
1933 Some(suggestion) => suggestion,
1934 };
1935
1936 let mut did_label_def_span = false;
1937
1938 if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
1939 if span.overlaps(def_span) {
1940 return false;
1959 }
1960 let span = self.tcx.sess.source_map().guess_head_span(def_span);
1961 let candidate_descr = suggestion.res.descr();
1962 let candidate = suggestion.candidate;
1963 let label = match suggestion.target {
1964 SuggestionTarget::SimilarlyNamed => {
1965 errors::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
1966 }
1967 SuggestionTarget::SingleItem => {
1968 errors::DefinedHere::SingleItem { span, candidate_descr, candidate }
1969 }
1970 };
1971 did_label_def_span = true;
1972 err.subdiagnostic(label);
1973 }
1974
1975 let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
1976 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
1977 && let Some(span) = suggestion.span
1978 && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
1979 && snippet == candidate
1980 {
1981 let candidate = suggestion.candidate;
1982 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the leading underscore in `{0}` marks it as unused, consider renaming it to `{1}`",
candidate, snippet))
})format!(
1985 "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
1986 );
1987 if !did_label_def_span {
1988 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
})format!("`{candidate}` defined here"));
1989 }
1990 (span, msg, snippet)
1991 } else {
1992 let msg = match suggestion.target {
1993 SuggestionTarget::SimilarlyNamed => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1} with a similar name exists",
suggestion.res.article(), suggestion.res.descr()))
})format!(
1994 "{} {} with a similar name exists",
1995 suggestion.res.article(),
1996 suggestion.res.descr()
1997 ),
1998 SuggestionTarget::SingleItem => {
1999 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("maybe you meant this {0}",
suggestion.res.descr()))
})format!("maybe you meant this {}", suggestion.res.descr())
2000 }
2001 };
2002 (span, msg, suggestion.candidate.to_ident_string())
2003 };
2004 err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2005 true
2006 }
2007
2008 fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2009 let res = b.res();
2010 if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2011 let (built_in, from) = match scope {
2012 Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2013 Scope::ExternPreludeFlags
2014 if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2015 || #[allow(non_exhaustive_omitted_patterns)] match res {
Res::OpenMod(..) => true,
_ => false,
}matches!(res, Res::OpenMod(..)) =>
2016 {
2017 ("", " passed with `--extern`")
2018 }
2019 _ => {
2020 if #[allow(non_exhaustive_omitted_patterns)] match res {
Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
_ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2021 ("", "")
2023 } else {
2024 (" built-in", "")
2025 }
2026 }
2027 };
2028
2029 let a = if built_in.is_empty() { res.article() } else { "a" };
2030 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}{2} {0}{3}", res.descr(), a,
built_in, from))
})format!("{a}{built_in} {thing}{from}", thing = res.descr())
2031 } else {
2032 let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2033 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
introduced))
})format!("the {thing} {introduced} here", thing = res.descr())
2034 }
2035 }
2036
2037 fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity {
2038 let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2039 *ambiguity_error;
2040 let extern_prelude_ambiguity = || {
2041 #[allow(non_exhaustive_omitted_patterns)] match scope2 {
Scope::ExternPreludeFlags => true,
_ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2043 && self
2044 .extern_prelude
2045 .get(&IdentKey::new(ident))
2046 .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2047 };
2048 let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2049 (b2, b1, scope2, scope1, true)
2051 } else {
2052 (b1, b2, scope1, scope2, false)
2053 };
2054
2055 let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2056 let what = self.decl_description(b, ident, scope);
2057 let note_msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` could{1} refer to {2}",
ident, also, what))
})format!("`{ident}` could{also} refer to {what}");
2058
2059 let thing = b.res().descr();
2060 let mut help_msgs = Vec::new();
2061 if b.is_glob_import()
2062 && (kind == AmbiguityKind::GlobVsGlob
2063 || kind == AmbiguityKind::GlobVsExpanded
2064 || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2065 {
2066 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
ident))
})format!(
2067 "consider adding an explicit import of `{ident}` to disambiguate"
2068 ))
2069 }
2070 if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2071 {
2072 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!("use `::{ident}` to refer to this {thing} unambiguously"))
2073 }
2074
2075 if kind != AmbiguityKind::GlobVsGlob {
2076 if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2077 if module == self.graph_root.to_module() {
2078 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2079 "use `crate::{ident}` to refer to this {thing} unambiguously"
2080 ));
2081 } else if module.is_normal() {
2082 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2083 "use `self::{ident}` to refer to this {thing} unambiguously"
2084 ));
2085 }
2086 }
2087 }
2088
2089 (
2090 Spanned { node: note_msg, span: b.span },
2091 help_msgs
2092 .iter()
2093 .enumerate()
2094 .map(|(i, help_msg)| {
2095 let or = if i == 0 { "" } else { "or " };
2096 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
})format!("{or}{help_msg}")
2097 })
2098 .collect::<Vec<_>>(),
2099 )
2100 };
2101 let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2102 let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2103 let help = if kind == AmbiguityKind::GlobVsGlob
2104 && b1
2105 .parent_module
2106 .and_then(|m| m.opt_def_id())
2107 .map(|d| !d.is_local())
2108 .unwrap_or_default()
2109 {
2110 Some(&[
2111 "consider updating this dependency to resolve this error",
2112 "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2113 ] as &[_])
2114 } else {
2115 None
2116 };
2117
2118 let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2119 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} or {1}",
vis1.to_string(CRATE_DEF_ID, self.tcx),
vis2.to_string(CRATE_DEF_ID, self.tcx)))
})format!(
2120 "{} or {}",
2121 vis1.to_string(CRATE_DEF_ID, self.tcx),
2122 vis2.to_string(CRATE_DEF_ID, self.tcx)
2123 )
2124 });
2125
2126 errors::Ambiguity {
2127 ident,
2128 help,
2129 ambig_vis,
2130 kind: kind.descr(),
2131 b1_note,
2132 b1_help_msgs,
2133 b2_note,
2134 b2_help_msgs,
2135 is_error: false,
2136 }
2137 }
2138
2139 fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2142 let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
2143 decl.kind
2144 else {
2145 return None;
2146 };
2147
2148 let def_id = self.tcx.parent(ctor_def_id);
2149 self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) }
2151
2152 fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2153 let PrivacyError {
2154 ident,
2155 decl,
2156 outermost_res,
2157 parent_scope,
2158 single_nested,
2159 dedup_span,
2160 ref source,
2161 } = *privacy_error;
2162
2163 let res = decl.res();
2164 let ctor_fields_span = self.ctor_fields_span(decl);
2165 let plain_descr = res.descr().to_string();
2166 let nonimport_descr =
2167 if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2168 let import_descr = nonimport_descr.clone() + " import";
2169 let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2170
2171 let ident_descr = get_descr(decl);
2173 let mut err =
2174 self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident });
2175
2176 self.mention_default_field_values(source, ident, &mut err);
2177
2178 let mut not_publicly_reexported = false;
2179 if let Some((this_res, outer_ident)) = outermost_res {
2180 let import_suggestions = self.lookup_import_candidates(
2181 outer_ident,
2182 this_res.ns().unwrap_or(Namespace::TypeNS),
2183 &parent_scope,
2184 &|res: Res| res == this_res,
2185 );
2186 let point_to_def = !show_candidates(
2187 self.tcx,
2188 &mut err,
2189 Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2190 &import_suggestions,
2191 Instead::Yes,
2192 FoundUse::Yes,
2193 DiagMode::Import { append: single_nested, unresolved_import: false },
2194 ::alloc::vec::Vec::new()vec![],
2195 "",
2196 );
2197 if point_to_def && ident.span != outer_ident.span {
2199 not_publicly_reexported = true;
2200 let label = errors::OuterIdentIsNotPubliclyReexported {
2201 span: outer_ident.span,
2202 outer_ident_descr: this_res.descr(),
2203 outer_ident,
2204 };
2205 err.subdiagnostic(label);
2206 }
2207 }
2208
2209 let mut non_exhaustive = None;
2210 if let Some(def_id) = res.opt_def_id()
2214 && !def_id.is_local()
2215 && let Some(attr_span) = {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NonExhaustive(span)) => {
break 'done Some(*span);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
2216 {
2217 non_exhaustive = Some(attr_span);
2218 } else if let Some(span) = ctor_fields_span {
2219 let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
2220 err.subdiagnostic(label);
2221 if let Res::Def(_, d) = res
2222 && let Some(fields) = self.field_visibility_spans.get(&d)
2223 {
2224 let spans = fields.iter().map(|span| *span).collect();
2225 let sugg =
2226 errors::ConsiderMakingTheFieldPublic { spans, number_of_fields: fields.len() };
2227 err.subdiagnostic(sugg);
2228 }
2229 }
2230
2231 let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2232 if let Some(mut def_id) = res.opt_def_id() {
2233 let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[def_id]))vec![def_id];
2235 while let Some(parent) = self.tcx.opt_parent(def_id) {
2236 def_id = parent;
2237 if !def_id.is_top_level_module() {
2238 path.push(def_id);
2239 } else {
2240 break;
2241 }
2242 }
2243 let path_names: Option<Vec<Ident>> = path
2245 .iter()
2246 .rev()
2247 .map(|def_id| {
2248 self.tcx.opt_item_name(*def_id).map(|name| {
2249 Ident::with_dummy_span(if def_id.is_top_level_module() {
2250 kw::Crate
2251 } else {
2252 name
2253 })
2254 })
2255 })
2256 .collect();
2257 if let Some(&def_id) = path.get(0)
2258 && let Some(path) = path_names
2259 {
2260 if let Some(def_id) = def_id.as_local() {
2261 if self.effective_visibilities.is_directly_public(def_id) {
2262 sugg_paths.push((path, false));
2263 }
2264 } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2265 {
2266 sugg_paths.push((path, false));
2267 }
2268 }
2269 }
2270
2271 let first_binding = decl;
2273 let mut next_binding = Some(decl);
2274 let mut next_ident = ident;
2275 let mut path = ::alloc::vec::Vec::new()vec![];
2276 while let Some(binding) = next_binding {
2277 let name = next_ident;
2278 next_binding = match binding.kind {
2279 _ if res == Res::Err => None,
2280 DeclKind::Import { source_decl, import, .. } => match import.kind {
2281 _ if source_decl.span.is_dummy() => None,
2282 ImportKind::Single { source, .. } => {
2283 next_ident = source;
2284 Some(source_decl)
2285 }
2286 ImportKind::Glob { .. }
2287 | ImportKind::MacroUse { .. }
2288 | ImportKind::MacroExport => Some(source_decl),
2289 ImportKind::ExternCrate { .. } => None,
2290 },
2291 _ => None,
2292 };
2293
2294 match binding.kind {
2295 DeclKind::Import { import, .. } => {
2296 for segment in import.module_path.iter().skip(1) {
2297 if segment.ident.name != kw::PathRoot {
2300 path.push(segment.ident);
2301 }
2302 }
2303 sugg_paths.push((
2304 path.iter().cloned().chain(std::iter::once(ident)).collect::<Vec<_>>(),
2305 true, ));
2307 }
2308 DeclKind::Def(_) => {}
2309 }
2310 let first = binding == first_binding;
2311 let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2312 let mut note_span = MultiSpan::from_span(def_span);
2313 if !first && binding.vis().is_public() {
2314 let desc = match binding.kind {
2315 DeclKind::Import { .. } => "re-export",
2316 _ => "directly",
2317 };
2318 note_span.push_span_label(def_span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you could import this {0}", desc))
})format!("you could import this {desc}"));
2319 }
2320 if next_binding.is_none()
2323 && let Some(span) = non_exhaustive
2324 {
2325 note_span.push_span_label(
2326 span,
2327 "cannot be constructed because it is `#[non_exhaustive]`",
2328 );
2329 }
2330 let note = errors::NoteAndRefersToTheItemDefinedHere {
2331 span: note_span,
2332 binding_descr: get_descr(binding),
2333 binding_name: name,
2334 first,
2335 dots: next_binding.is_some(),
2336 };
2337 err.subdiagnostic(note);
2338 }
2339 sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2341 for (sugg, reexport) in sugg_paths {
2342 if not_publicly_reexported {
2343 break;
2344 }
2345 if sugg.len() <= 1 {
2346 continue;
2349 }
2350 let path = join_path_idents(sugg);
2351 let sugg = if reexport {
2352 errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2353 } else {
2354 errors::ImportIdent::Directly { span: dedup_span, ident, path }
2355 };
2356 err.subdiagnostic(sugg);
2357 break;
2358 }
2359
2360 err.emit();
2361 }
2362
2363 fn mention_default_field_values(
2383 &self,
2384 source: &Option<ast::Expr>,
2385 ident: Ident,
2386 err: &mut Diag<'_>,
2387 ) {
2388 let Some(expr) = source else { return };
2389 let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2390 let Some(segment) = struct_expr.path.segments.last() else { return };
2393 let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2394 let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2395 return;
2396 };
2397 let Some(default_fields) = self.field_defaults(def_id) else { return };
2398 if struct_expr.fields.is_empty() {
2399 return;
2400 }
2401 let last_span = struct_expr.fields.iter().last().unwrap().span;
2402 let mut iter = struct_expr.fields.iter().peekable();
2403 let mut prev: Option<Span> = None;
2404 while let Some(field) = iter.next() {
2405 if field.expr.span.overlaps(ident.span) {
2406 err.span_label(field.ident.span, "while setting this field");
2407 if default_fields.contains(&field.ident.name) {
2408 let sugg = if last_span == field.span {
2409 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(field.span, "..".to_string())]))vec![(field.span, "..".to_string())]
2410 } else {
2411 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(match (prev, iter.peek()) {
(_, Some(next)) => field.span.with_hi(next.span.lo()),
(Some(prev), _) => field.span.with_lo(prev.hi()),
(None, None) => field.span,
}, String::new()),
(last_span.shrink_to_hi(), ", ..".to_string())]))vec![
2412 (
2413 match (prev, iter.peek()) {
2415 (_, Some(next)) => field.span.with_hi(next.span.lo()),
2416 (Some(prev), _) => field.span.with_lo(prev.hi()),
2417 (None, None) => field.span,
2418 },
2419 String::new(),
2420 ),
2421 (last_span.shrink_to_hi(), ", ..".to_string()),
2422 ]
2423 };
2424 err.multipart_suggestion(
2425 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the type `{2}` of field `{0}` is private, but you can construct the default value defined for it in `{1}` using `..` in the struct initializer expression",
field.ident, self.tcx.item_name(def_id), ident))
})format!(
2426 "the type `{ident}` of field `{}` is private, but you can construct \
2427 the default value defined for it in `{}` using `..` in the struct \
2428 initializer expression",
2429 field.ident,
2430 self.tcx.item_name(def_id),
2431 ),
2432 sugg,
2433 Applicability::MachineApplicable,
2434 );
2435 break;
2436 }
2437 }
2438 prev = Some(field.span);
2439 }
2440 }
2441
2442 pub(crate) fn find_similarly_named_module_or_crate(
2443 &self,
2444 ident: Symbol,
2445 current_module: Module<'ra>,
2446 ) -> Option<Symbol> {
2447 let mut candidates = self
2448 .extern_prelude
2449 .keys()
2450 .map(|ident| ident.name)
2451 .chain(
2452 self.local_module_map
2453 .iter()
2454 .filter(|(_, module)| {
2455 let module = module.to_module();
2456 current_module.is_ancestor_of(module) && current_module != module
2457 })
2458 .flat_map(|(_, module)| module.kind.name()),
2459 )
2460 .chain(
2461 self.extern_module_map
2462 .borrow()
2463 .iter()
2464 .filter(|(_, module)| {
2465 let module = module.to_module();
2466 current_module.is_ancestor_of(module) && current_module != module
2467 })
2468 .flat_map(|(_, module)| module.kind.name()),
2469 )
2470 .filter(|c| !c.to_string().is_empty())
2471 .collect::<Vec<_>>();
2472 candidates.sort();
2473 candidates.dedup();
2474 find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2475 }
2476
2477 pub(crate) fn report_path_resolution_error(
2478 &mut self,
2479 path: &[Segment],
2480 opt_ns: Option<Namespace>, parent_scope: &ParentScope<'ra>,
2482 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2483 ignore_decl: Option<Decl<'ra>>,
2484 ignore_import: Option<Import<'ra>>,
2485 module: Option<ModuleOrUniformRoot<'ra>>,
2486 failed_segment_idx: usize,
2487 ident: Ident,
2488 diag_metadata: Option<&DiagMetadata<'_>>,
2489 ) -> (String, String, Option<Suggestion>) {
2490 let is_last = failed_segment_idx == path.len() - 1;
2491 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2492 let module_res = match module {
2493 Some(ModuleOrUniformRoot::Module(module)) => module.res(),
2494 _ => None,
2495 };
2496 let scope = match &path[..failed_segment_idx] {
2497 [.., prev] => {
2498 if prev.ident.name == kw::PathRoot {
2499 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the crate root"))
})format!("the crate root")
2500 } else {
2501 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", prev.ident))
})format!("`{}`", prev.ident)
2502 }
2503 }
2504 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this scope"))
})format!("this scope"),
2505 };
2506 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
scope))
})format!("cannot find `{ident}` in {scope}");
2507
2508 if module_res == self.graph_root.res() {
2509 let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Mod, _) => true,
_ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2510 let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2511 candidates
2512 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2513 if let Some(candidate) = candidates.get(0) {
2514 let path = {
2515 let len = candidate.path.segments.len();
2517 let start_index = (0..=failed_segment_idx.min(len - 1))
2518 .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2519 .unwrap_or_default();
2520 let segments =
2521 (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2522 Path { segments, span: Span::default(), tokens: None }
2523 };
2524 (
2525 message,
2526 String::from("unresolved import"),
2527 Some((
2528 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, pprust::path_to_string(&path))]))vec![(ident.span, pprust::path_to_string(&path))],
2529 String::from("a similar path exists"),
2530 Applicability::MaybeIncorrect,
2531 )),
2532 )
2533 } else if ident.name == sym::core {
2534 (
2535 message,
2536 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
ident))
})format!("you might be missing crate `{ident}`"),
2537 Some((
2538 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, "std".to_string())]))vec![(ident.span, "std".to_string())],
2539 "try using `std` instead of `core`".to_string(),
2540 Applicability::MaybeIncorrect,
2541 )),
2542 )
2543 } else if ident.name == kw::Underscore {
2544 (
2545 "invalid crate or module name `_`".to_string(),
2546 "`_` is not a valid crate or module name".to_string(),
2547 None,
2548 )
2549 } else if self.tcx.sess.is_rust_2015() {
2550 (
2551 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}"),
2552 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of unresolved module or unlinked crate `{0}`",
ident))
})format!("use of unresolved module or unlinked crate `{ident}`"),
2553 Some((
2554 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(self.current_crate_outer_attr_insert_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern crate {0};\n",
ident))
}))]))vec![(
2555 self.current_crate_outer_attr_insert_span,
2556 format!("extern crate {ident};\n"),
2557 )],
2558 if was_invoked_from_cargo() {
2559 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if you wanted to use a crate named `{0}`, use `cargo add {0}` to add it to your `Cargo.toml` and import it in your code",
ident))
})format!(
2560 "if you wanted to use a crate named `{ident}`, use `cargo add \
2561 {ident}` to add it to your `Cargo.toml` and import it in your \
2562 code",
2563 )
2564 } else {
2565 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing a crate named `{0}`, add it to your project and import it in your code",
ident))
})format!(
2566 "you might be missing a crate named `{ident}`, add it to your \
2567 project and import it in your code",
2568 )
2569 },
2570 Applicability::MaybeIncorrect,
2571 )),
2572 )
2573 } else {
2574 (message, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("could not find `{0}` in the crate root",
ident))
})format!("could not find `{ident}` in the crate root"), None)
2575 }
2576 } else if failed_segment_idx > 0 {
2577 let parent = path[failed_segment_idx - 1].ident.name;
2578 let parent = match parent {
2579 kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
2582 "the list of imported crates".to_owned()
2583 }
2584 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
2585 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", parent))
})format!("`{parent}`"),
2586 };
2587
2588 let mut msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("could not find `{0}` in {1}",
ident, parent))
})format!("could not find `{ident}` in {parent}");
2589 if ns == TypeNS || ns == ValueNS {
2590 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
2591 let binding = if let Some(module) = module {
2592 self.cm()
2593 .resolve_ident_in_module(
2594 module,
2595 ident,
2596 ns_to_try,
2597 parent_scope,
2598 None,
2599 ignore_decl,
2600 ignore_import,
2601 )
2602 .ok()
2603 } else if let Some(ribs) = ribs
2604 && let Some(TypeNS | ValueNS) = opt_ns
2605 {
2606 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2607 match self.resolve_ident_in_lexical_scope(
2608 ident,
2609 ns_to_try,
2610 parent_scope,
2611 None,
2612 &ribs[ns_to_try],
2613 ignore_decl,
2614 diag_metadata,
2615 ) {
2616 Some(LateDecl::Decl(binding)) => Some(binding),
2618 _ => None,
2619 }
2620 } else {
2621 self.cm()
2622 .resolve_ident_in_scope_set(
2623 ident,
2624 ScopeSet::All(ns_to_try),
2625 parent_scope,
2626 None,
2627 ignore_decl,
2628 ignore_import,
2629 )
2630 .ok()
2631 };
2632 if let Some(binding) = binding {
2633 msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("expected {0}, found {1} `{2}` in {3}",
ns.descr(), binding.res().descr(), ident, parent))
})format!(
2634 "expected {}, found {} `{ident}` in {parent}",
2635 ns.descr(),
2636 binding.res().descr(),
2637 );
2638 };
2639 }
2640 (message, msg, None)
2641 } else if ident.name == kw::SelfUpper {
2642 if opt_ns.is_none() {
2646 (message, "`Self` cannot be used in imports".to_string(), None)
2647 } else {
2648 (
2649 message,
2650 "`Self` is only available in impls, traits, and type definitions".to_string(),
2651 None,
2652 )
2653 }
2654 } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
2655 let binding = if let Some(ribs) = ribs {
2657 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2658 self.resolve_ident_in_lexical_scope(
2659 ident,
2660 ValueNS,
2661 parent_scope,
2662 None,
2663 &ribs[ValueNS],
2664 ignore_decl,
2665 diag_metadata,
2666 )
2667 } else {
2668 None
2669 };
2670 let match_span = match binding {
2671 Some(LateDecl::RibDef(Res::Local(id))) => {
2680 Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
2681 }
2682 Some(LateDecl::Decl(name_binding)) => Some((
2694 name_binding.span,
2695 name_binding.res().article(),
2696 name_binding.res().descr(),
2697 )),
2698 _ => None,
2699 };
2700
2701 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find type `{0}` in {1}",
ident, scope))
})format!("cannot find type `{ident}` in {scope}");
2702 let label = if let Some((span, article, descr)) = match_span {
2703 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{1}` is declared as {2} {3} at `{0}`, not a type",
self.tcx.sess.source_map().span_to_short_string(span,
RemapPathScopeComponents::DIAGNOSTICS), ident, article,
descr))
})format!(
2704 "`{ident}` is declared as {article} {descr} at `{}`, not a type",
2705 self.tcx
2706 .sess
2707 .source_map()
2708 .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
2709 )
2710 } else {
2711 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
ident))
})format!("use of undeclared type `{ident}`")
2712 };
2713 (message, label, None)
2714 } else {
2715 let mut suggestion = None;
2716 if ident.name == sym::alloc {
2717 suggestion = Some((
2718 ::alloc::vec::Vec::new()vec![],
2719 String::from("add `extern crate alloc` to use the `alloc` crate"),
2720 Applicability::MaybeIncorrect,
2721 ))
2722 }
2723
2724 suggestion = suggestion.or_else(|| {
2725 self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
2726 |sugg| {
2727 (
2728 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, sugg.to_string())]))vec![(ident.span, sugg.to_string())],
2729 String::from("there is a crate or module with a similar name"),
2730 Applicability::MaybeIncorrect,
2731 )
2732 },
2733 )
2734 });
2735 if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2736 ident,
2737 ScopeSet::All(ValueNS),
2738 parent_scope,
2739 None,
2740 ignore_decl,
2741 ignore_import,
2742 ) {
2743 let descr = binding.res().descr();
2744 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}");
2745 (message, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` is not a crate or module",
descr, ident))
})format!("{descr} `{ident}` is not a crate or module"), suggestion)
2746 } else {
2747 let suggestion = if suggestion.is_some() {
2748 suggestion
2749 } else if let Some(m) = self.undeclared_module_exists(ident) {
2750 self.undeclared_module_suggest_declare(ident, m)
2751 } else if was_invoked_from_cargo() {
2752 Some((
2753 ::alloc::vec::Vec::new()vec![],
2754 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if you wanted to use a crate named `{0}`, use `cargo add {0}` to add it to your `Cargo.toml`",
ident))
})format!(
2755 "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
2756 to add it to your `Cargo.toml`",
2757 ),
2758 Applicability::MaybeIncorrect,
2759 ))
2760 } else {
2761 Some((
2762 ::alloc::vec::Vec::new()vec![],
2763 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing a crate named `{0}`",
ident))
})format!("you might be missing a crate named `{ident}`",),
2764 Applicability::MaybeIncorrect,
2765 ))
2766 };
2767 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}");
2768 (
2769 message,
2770 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of unresolved module or unlinked crate `{0}`",
ident))
})format!("use of unresolved module or unlinked crate `{ident}`"),
2771 suggestion,
2772 )
2773 }
2774 }
2775 }
2776
2777 fn undeclared_module_suggest_declare(
2778 &self,
2779 ident: Ident,
2780 path: std::path::PathBuf,
2781 ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
2782 Some((
2783 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(self.current_crate_outer_attr_insert_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mod {0};\n", ident))
}))]))vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
2784 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("to make use of source file {0}, use `mod {1}` in this file to declare the module",
path.display(), ident))
})format!(
2785 "to make use of source file {}, use `mod {ident}` \
2786 in this file to declare the module",
2787 path.display()
2788 ),
2789 Applicability::MaybeIncorrect,
2790 ))
2791 }
2792
2793 fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
2794 let map = self.tcx.sess.source_map();
2795
2796 let src = map.span_to_filename(ident.span).into_local_path()?;
2797 let i = ident.as_str();
2798 let dir = src.parent()?;
2800 let src = src.file_stem()?.to_str()?;
2801 for file in [
2802 dir.join(i).with_extension("rs"),
2804 dir.join(i).join("mod.rs"),
2806 ] {
2807 if file.exists() {
2808 return Some(file);
2809 }
2810 }
2811 if !#[allow(non_exhaustive_omitted_patterns)] match src {
"main" | "lib" | "mod" => true,
_ => false,
}matches!(src, "main" | "lib" | "mod") {
2812 for file in [
2813 dir.join(src).join(i).with_extension("rs"),
2815 dir.join(src).join(i).join("mod.rs"),
2817 ] {
2818 if file.exists() {
2819 return Some(file);
2820 }
2821 }
2822 }
2823 None
2824 }
2825
2826 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_path_suggestion",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2827u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
match path[..] {
[first, second, ..] if
first.ident.name == kw::PathRoot &&
!second.ident.is_path_segment_keyword() => {}
[first, ..] if
first.ident.span.at_least_rust_2018() &&
!first.ident.is_path_segment_keyword() => {
path.insert(0, Segment::from_ident(Ident::dummy()));
}
_ => return None,
}
self.make_missing_self_suggestion(path.clone(),
parent_scope).or_else(||
self.make_missing_crate_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_missing_super_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_external_crate_suggestion(path, parent_scope))
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
2828 pub(crate) fn make_path_suggestion(
2829 &mut self,
2830 mut path: Vec<Segment>,
2831 parent_scope: &ParentScope<'ra>,
2832 ) -> Option<(Vec<Segment>, Option<String>)> {
2833 match path[..] {
2834 [first, second, ..]
2837 if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
2838 [first, ..]
2840 if first.ident.span.at_least_rust_2018()
2841 && !first.ident.is_path_segment_keyword() =>
2842 {
2843 path.insert(0, Segment::from_ident(Ident::dummy()));
2845 }
2846 _ => return None,
2847 }
2848
2849 self.make_missing_self_suggestion(path.clone(), parent_scope)
2850 .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
2851 .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
2852 .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
2853 }
2854
2855 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_self_suggestion",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2862u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::SelfLower;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2871",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2871u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
2863 fn make_missing_self_suggestion(
2864 &mut self,
2865 mut path: Vec<Segment>,
2866 parent_scope: &ParentScope<'ra>,
2867 ) -> Option<(Vec<Segment>, Option<String>)> {
2868 path[0].ident.name = kw::SelfLower;
2870 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2871 debug!(?path, ?result);
2872 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
2873 }
2874
2875 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_crate_suggestion",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2882u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Crate;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2891",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2891u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path,
Some("`use` statements changed in Rust 2018; read more at \
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
clarity.html>".to_string())))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
2883 fn make_missing_crate_suggestion(
2884 &mut self,
2885 mut path: Vec<Segment>,
2886 parent_scope: &ParentScope<'ra>,
2887 ) -> Option<(Vec<Segment>, Option<String>)> {
2888 path[0].ident.name = kw::Crate;
2890 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2891 debug!(?path, ?result);
2892 if let PathResult::Module(..) = result {
2893 Some((
2894 path,
2895 Some(
2896 "`use` statements changed in Rust 2018; read more at \
2897 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
2898 clarity.html>"
2899 .to_string(),
2900 ),
2901 ))
2902 } else {
2903 None
2904 }
2905 }
2906
2907 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_super_suggestion",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2914u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Super;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2923",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2923u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
2915 fn make_missing_super_suggestion(
2916 &mut self,
2917 mut path: Vec<Segment>,
2918 parent_scope: &ParentScope<'ra>,
2919 ) -> Option<(Vec<Segment>, Option<String>)> {
2920 path[0].ident.name = kw::Super;
2922 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2923 debug!(?path, ?result);
2924 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
2925 }
2926
2927 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_external_crate_suggestion",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2937u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
if path[1].ident.span.is_rust_2015() { return None; }
let mut extern_crate_names =
self.extern_prelude.keys().map(|ident|
ident.name).collect::<Vec<_>>();
extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
for name in extern_crate_names.into_iter() {
path[0].ident.name = name;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope,
None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:2958",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(2958u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["path", "name",
"result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&name) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
return Some((path, None));
}
}
None
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
2938 fn make_external_crate_suggestion(
2939 &mut self,
2940 mut path: Vec<Segment>,
2941 parent_scope: &ParentScope<'ra>,
2942 ) -> Option<(Vec<Segment>, Option<String>)> {
2943 if path[1].ident.span.is_rust_2015() {
2944 return None;
2945 }
2946
2947 let mut extern_crate_names =
2951 self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
2952 extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
2953
2954 for name in extern_crate_names.into_iter() {
2955 path[0].ident.name = name;
2957 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
2958 debug!(?path, ?name, ?result);
2959 if let PathResult::Module(..) = result {
2960 return Some((path, None));
2961 }
2962 }
2963
2964 None
2965 }
2966
2967 pub(crate) fn check_for_module_export_macro(
2980 &mut self,
2981 import: Import<'ra>,
2982 module: ModuleOrUniformRoot<'ra>,
2983 ident: Ident,
2984 ) -> Option<(Option<Suggestion>, Option<String>)> {
2985 let ModuleOrUniformRoot::Module(mut crate_module) = module else {
2986 return None;
2987 };
2988
2989 while let Some(parent) = crate_module.parent {
2990 crate_module = parent;
2991 }
2992
2993 if module == ModuleOrUniformRoot::Module(crate_module) {
2994 return None;
2996 }
2997
2998 let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
2999 let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3000 let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3001 return None;
3002 };
3003 if !kinds.contains(MacroKinds::BANG) {
3004 return None;
3005 }
3006 let module_name = crate_module.kind.name().unwrap_or(kw::Crate);
3007 let import_snippet = match import.kind {
3008 ImportKind::Single { source, target, .. } if source != target => {
3009 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}", source, target))
})format!("{source} as {target}")
3010 }
3011 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}"),
3012 };
3013
3014 let mut corrections: Vec<(Span, String)> = Vec::new();
3015 if !import.is_nested() {
3016 corrections.push((import.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}", module_name,
import_snippet))
})format!("{module_name}::{import_snippet}")));
3019 } else {
3020 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3024 self.tcx.sess,
3025 import.span,
3026 import.use_span,
3027 );
3028 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3028",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(3028u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["found_closing_brace",
"binding_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&found_closing_brace
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&binding_span)
as &dyn Value))])
});
} else { ; }
};debug!(found_closing_brace, ?binding_span);
3029
3030 let mut removal_span = binding_span;
3031
3032 if found_closing_brace
3040 && let Some(previous_span) =
3041 extend_span_to_previous_binding(self.tcx.sess, binding_span)
3042 {
3043 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3043",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(3043u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["previous_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&previous_span)
as &dyn Value))])
});
} else { ; }
};debug!(?previous_span);
3044 removal_span = removal_span.with_lo(previous_span.lo());
3045 }
3046 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3046",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(3046u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["removal_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&removal_span)
as &dyn Value))])
});
} else { ; }
};debug!(?removal_span);
3047
3048 corrections.push((removal_span, "".to_string()));
3050
3051 let (has_nested, after_crate_name) =
3058 find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3059 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics.rs:3059",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(3059u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["has_nested",
"after_crate_name"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&has_nested as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&after_crate_name)
as &dyn Value))])
});
} else { ; }
};debug!(has_nested, ?after_crate_name);
3060
3061 let source_map = self.tcx.sess.source_map();
3062
3063 let is_definitely_crate = import
3065 .module_path
3066 .first()
3067 .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3068
3069 let start_point = source_map.start_point(after_crate_name);
3071 if is_definitely_crate
3072 && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3073 {
3074 corrections.push((
3075 start_point,
3076 if has_nested {
3077 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
import_snippet))
})format!("{start_snippet}{import_snippet}, ")
3079 } else {
3080 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
start_snippet))
})format!("{{{import_snippet}, {start_snippet}")
3083 },
3084 ));
3085
3086 if !has_nested {
3088 corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3089 }
3090 } else {
3091 corrections.push((
3093 import.use_span.shrink_to_lo(),
3094 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
import_snippet))
})format!("use {module_name}::{import_snippet};\n"),
3095 ));
3096 }
3097 }
3098
3099 let suggestion = Some((
3100 corrections,
3101 String::from("a macro with this name exists at the root of the crate"),
3102 Applicability::MaybeIncorrect,
3103 ));
3104 Some((
3105 suggestion,
3106 Some(
3107 "this could be because a macro annotated with `#[macro_export]` will be exported \
3108 at the root of the crate instead of the module where it is defined"
3109 .to_string(),
3110 ),
3111 ))
3112 }
3113
3114 pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3116 let local_items;
3117 let symbols = if module.is_local() {
3118 local_items = self
3119 .stripped_cfg_items
3120 .iter()
3121 .filter_map(|item| {
3122 let parent_scope = self.opt_local_def_id(item.parent_scope)?.to_def_id();
3123 Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3124 })
3125 .collect::<Vec<_>>();
3126 local_items.as_slice()
3127 } else {
3128 self.tcx.stripped_cfg_items(module.krate)
3129 };
3130
3131 for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3132 if ident.name != *segment {
3133 continue;
3134 }
3135
3136 let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3137
3138 fn comes_from_same_module_for_glob(
3139 r: &Resolver<'_, '_>,
3140 parent_module: DefId,
3141 module: DefId,
3142 visited: &mut FxHashMap<DefId, bool>,
3143 ) -> bool {
3144 if let Some(&cached) = visited.get(&parent_module) {
3145 return cached;
3149 }
3150 visited.insert(parent_module, false);
3151 let m = r.expect_module(parent_module);
3152 let mut res = false;
3153 for importer in m.glob_importers.borrow().iter() {
3154 if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id() {
3155 if next_parent_module == module
3156 || comes_from_same_module_for_glob(
3157 r,
3158 next_parent_module,
3159 module,
3160 visited,
3161 )
3162 {
3163 res = true;
3164 break;
3165 }
3166 }
3167 }
3168 visited.insert(parent_module, res);
3169 res
3170 }
3171
3172 let comes_from_same_module = parent_module == module
3173 || comes_from_same_module_for_glob(
3174 self,
3175 parent_module,
3176 module,
3177 &mut Default::default(),
3178 );
3179 if !comes_from_same_module {
3180 continue;
3181 }
3182
3183 let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3184 errors::ItemWas::BehindFeature { feature, span: cfg.1 }
3185 } else {
3186 errors::ItemWas::CfgOut { span: cfg.1 }
3187 };
3188 let note = errors::FoundItemConfigureOut { span: ident.span, item_was };
3189 err.subdiagnostic(note);
3190 }
3191 }
3192
3193 pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3194 match def_id.as_local() {
3195 Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3196 None => {
3197 self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3198 let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3199 let vis = self.tcx.visibility(ctor_def_id);
3200 let field_visibilities = self
3201 .tcx
3202 .associated_item_def_ids(def_id)
3203 .iter()
3204 .map(|&field_id| self.tcx.visibility(field_id))
3205 .collect();
3206 StructCtor { res, vis, field_visibilities }
3207 })
3208 }
3209 }
3210 }
3211}
3212
3213fn find_span_of_binding_until_next_binding(
3227 sess: &Session,
3228 binding_span: Span,
3229 use_span: Span,
3230) -> (bool, Span) {
3231 let source_map = sess.source_map();
3232
3233 let binding_until_end = binding_span.with_hi(use_span.hi());
3236
3237 let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3240
3241 let mut found_closing_brace = false;
3248 let after_binding_until_next_binding =
3249 source_map.span_take_while(after_binding_until_end, |&ch| {
3250 if ch == '}' {
3251 found_closing_brace = true;
3252 }
3253 ch == ' ' || ch == ','
3254 });
3255
3256 let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3261
3262 (found_closing_brace, span)
3263}
3264
3265fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3278 let source_map = sess.source_map();
3279
3280 let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3284
3285 let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3286 let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3287 if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3288 return None;
3289 }
3290
3291 let prev_comma = prev_comma.first().unwrap();
3292 let prev_starting_brace = prev_starting_brace.first().unwrap();
3293
3294 if prev_comma.len() > prev_starting_brace.len() {
3298 return None;
3299 }
3300
3301 Some(binding_span.with_lo(BytePos(
3302 binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3305 )))
3306}
3307
3308#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("find_span_immediately_after_crate_name",
"rustc_resolve::diagnostics", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics.rs"),
::tracing_core::__macro_support::Option::Some(3321u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics"),
::tracing_core::field::FieldSet::new(&["use_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_span)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: (bool, Span) = loop {};
return __tracing_attr_fake_return;
}
{
let source_map = sess.source_map();
let mut num_colons = 0;
let until_second_colon =
source_map.span_take_while(use_span,
|c|
{
if *c == ':' { num_colons += 1; }
!#[allow(non_exhaustive_omitted_patterns)] match c {
':' if num_colons == 2 => true,
_ => false,
}
});
let from_second_colon =
use_span.with_lo(until_second_colon.hi() + BytePos(1));
let mut found_a_non_whitespace_character = false;
let after_second_colon =
source_map.span_take_while(from_second_colon,
|c|
{
if found_a_non_whitespace_character { return false; }
if !c.is_whitespace() {
found_a_non_whitespace_character = true;
}
true
});
let next_left_bracket =
source_map.span_through_char(from_second_colon, '{');
(next_left_bracket == after_second_colon, from_second_colon)
}
}
}#[instrument(level = "debug", skip(sess))]
3322fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3323 let source_map = sess.source_map();
3324
3325 let mut num_colons = 0;
3327 let until_second_colon = source_map.span_take_while(use_span, |c| {
3329 if *c == ':' {
3330 num_colons += 1;
3331 }
3332 !matches!(c, ':' if num_colons == 2)
3333 });
3334 let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3336
3337 let mut found_a_non_whitespace_character = false;
3338 let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3340 if found_a_non_whitespace_character {
3341 return false;
3342 }
3343 if !c.is_whitespace() {
3344 found_a_non_whitespace_character = true;
3345 }
3346 true
3347 });
3348
3349 let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3351
3352 (next_left_bracket == after_second_colon, from_second_colon)
3353}
3354
3355enum Instead {
3358 Yes,
3359 No,
3360}
3361
3362enum FoundUse {
3364 Yes,
3365 No,
3366}
3367
3368pub(crate) enum DiagMode {
3370 Normal,
3371 Pattern,
3373 Import {
3375 unresolved_import: bool,
3377 append: bool,
3380 },
3381}
3382
3383pub(crate) fn import_candidates(
3384 tcx: TyCtxt<'_>,
3385 err: &mut Diag<'_>,
3386 use_placement_span: Option<Span>,
3388 candidates: &[ImportSuggestion],
3389 mode: DiagMode,
3390 append: &str,
3391) {
3392 show_candidates(
3393 tcx,
3394 err,
3395 use_placement_span,
3396 candidates,
3397 Instead::Yes,
3398 FoundUse::Yes,
3399 mode,
3400 ::alloc::vec::Vec::new()vec![],
3401 append,
3402 );
3403}
3404
3405type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3406
3407fn show_candidates(
3412 tcx: TyCtxt<'_>,
3413 err: &mut Diag<'_>,
3414 use_placement_span: Option<Span>,
3416 candidates: &[ImportSuggestion],
3417 instead: Instead,
3418 found_use: FoundUse,
3419 mode: DiagMode,
3420 path: Vec<Segment>,
3421 append: &str,
3422) -> bool {
3423 if candidates.is_empty() {
3424 return false;
3425 }
3426
3427 let mut showed = false;
3428 let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3429 let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3430
3431 candidates.iter().for_each(|c| {
3432 if c.accessible {
3433 if c.doc_visible {
3435 accessible_path_strings.push((
3436 pprust::path_to_string(&c.path),
3437 c.descr,
3438 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3439 &c.note,
3440 c.via_import,
3441 ))
3442 }
3443 } else {
3444 inaccessible_path_strings.push((
3445 pprust::path_to_string(&c.path),
3446 c.descr,
3447 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3448 &c.note,
3449 c.via_import,
3450 ))
3451 }
3452 });
3453
3454 for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3457 path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3458 path_strings.dedup_by(|a, b| a.0 == b.0);
3459 let core_path_strings =
3460 path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3461 let std_path_strings =
3462 path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3463 let foreign_crate_path_strings =
3464 path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3465
3466 if std_path_strings.len() == core_path_strings.len() {
3469 path_strings.extend(std_path_strings);
3471 } else {
3472 path_strings.extend(std_path_strings);
3473 path_strings.extend(core_path_strings);
3474 }
3475 path_strings.extend(foreign_crate_path_strings);
3477 }
3478
3479 if !accessible_path_strings.is_empty() {
3480 let (determiner, kind, s, name, through) =
3481 if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3482 (
3483 "this",
3484 *descr,
3485 "",
3486 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", name))
})format!(" `{name}`"),
3487 if *via_import { " through its public re-export" } else { "" },
3488 )
3489 } else {
3490 let kinds = accessible_path_strings
3493 .iter()
3494 .map(|(_, descr, _, _, _)| *descr)
3495 .collect::<UnordSet<&str>>();
3496 let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3497 let s = if kind.ends_with('s') { "es" } else { "s" };
3498
3499 ("one of these", kind, s, String::new(), "")
3500 };
3501
3502 let instead = if let Instead::Yes = instead { " instead" } else { "" };
3503 let mut msg = if let DiagMode::Pattern = mode {
3504 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if you meant to match on {0}{1}{2}{3}, use the full path in the pattern",
kind, s, instead, name))
})format!(
3505 "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3506 pattern",
3507 )
3508 } else {
3509 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider importing {0} {1}{2}{3}{4}",
determiner, kind, s, through, instead))
})format!("consider importing {determiner} {kind}{s}{through}{instead}")
3510 };
3511
3512 for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3513 err.note(note.clone());
3514 }
3515
3516 let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3517 msg.push(':');
3518
3519 for candidate in accessible_path_strings {
3520 msg.push('\n');
3521 msg.push_str(&candidate.0);
3522 }
3523 };
3524
3525 if let Some(span) = use_placement_span {
3526 let (add_use, trailing) = match mode {
3527 DiagMode::Pattern => {
3528 err.span_suggestions(
3529 span,
3530 msg,
3531 accessible_path_strings.into_iter().map(|a| a.0),
3532 Applicability::MaybeIncorrect,
3533 );
3534 return true;
3535 }
3536 DiagMode::Import { .. } => ("", ""),
3537 DiagMode::Normal => ("use ", ";\n"),
3538 };
3539 for candidate in &mut accessible_path_strings {
3540 let additional_newline = if let FoundUse::No = found_use
3543 && let DiagMode::Normal = mode
3544 {
3545 "\n"
3546 } else {
3547 ""
3548 };
3549 candidate.0 =
3550 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}{0}{2}{3}{4}", candidate.0,
add_use, append, trailing, additional_newline))
})format!("{add_use}{}{append}{trailing}{additional_newline}", candidate.0);
3551 }
3552
3553 match mode {
3554 DiagMode::Import { append: true, .. } => {
3555 append_candidates(&mut msg, accessible_path_strings);
3556 err.span_help(span, msg);
3557 }
3558 _ => {
3559 err.span_suggestions_with_style(
3560 span,
3561 msg,
3562 accessible_path_strings.into_iter().map(|a| a.0),
3563 Applicability::MaybeIncorrect,
3564 SuggestionStyle::ShowAlways,
3565 );
3566 }
3567 }
3568
3569 if let [first, .., last] = &path[..] {
3570 let sp = first.ident.span.until(last.ident.span);
3571 if sp.can_be_used_for_suggestions() && !sp.is_empty() {
3574 err.span_suggestion_verbose(
3575 sp,
3576 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("if you import `{0}`, refer to it directly",
last.ident))
})format!("if you import `{}`, refer to it directly", last.ident),
3577 "",
3578 Applicability::Unspecified,
3579 );
3580 }
3581 }
3582 } else {
3583 append_candidates(&mut msg, accessible_path_strings);
3584 err.help(msg);
3585 }
3586 showed = true;
3587 }
3588 if !inaccessible_path_strings.is_empty()
3589 && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
DiagMode::Import { unresolved_import: false, .. } => true,
_ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
3590 {
3591 let prefix =
3592 if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
3593 if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
3594 let msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}{2} `{3}`{0} exists but is inaccessible",
if let DiagMode::Pattern = mode { ", which" } else { "" },
prefix, descr, name))
})format!(
3595 "{prefix}{descr} `{name}`{} exists but is inaccessible",
3596 if let DiagMode::Pattern = mode { ", which" } else { "" }
3597 );
3598
3599 if let Some(source_span) = source_span {
3600 let span = tcx.sess.source_map().guess_head_span(*source_span);
3601 let mut multi_span = MultiSpan::from_span(span);
3602 multi_span.push_span_label(span, "not accessible");
3603 err.span_note(multi_span, msg);
3604 } else {
3605 err.note(msg);
3606 }
3607 if let Some(note) = (*note).as_deref() {
3608 err.note(note.to_string());
3609 }
3610 } else {
3611 let descr = inaccessible_path_strings
3612 .iter()
3613 .map(|&(_, descr, _, _, _)| descr)
3614 .all_equal_value()
3615 .unwrap_or("item");
3616 let plural_descr =
3617 if descr.ends_with('s') { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}es", descr))
})format!("{descr}es") } else { ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}s", descr))
})format!("{descr}s") };
3618
3619 let mut msg = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}these {1} exist but are inaccessible",
prefix, plural_descr))
})format!("{prefix}these {plural_descr} exist but are inaccessible");
3620 let mut has_colon = false;
3621
3622 let mut spans = Vec::new();
3623 for (name, _, source_span, _, _) in &inaccessible_path_strings {
3624 if let Some(source_span) = source_span {
3625 let span = tcx.sess.source_map().guess_head_span(*source_span);
3626 spans.push((name, span));
3627 } else {
3628 if !has_colon {
3629 msg.push(':');
3630 has_colon = true;
3631 }
3632 msg.push('\n');
3633 msg.push_str(name);
3634 }
3635 }
3636
3637 let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
3638 for (name, span) in spans {
3639 multi_span.push_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
})format!("`{name}`: not accessible"));
3640 }
3641
3642 for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3643 err.note(note.clone());
3644 }
3645
3646 err.span_note(multi_span, msg);
3647 }
3648 showed = true;
3649 }
3650 showed
3651}
3652
3653#[derive(#[automatically_derived]
impl ::core::fmt::Debug for UsePlacementFinder {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"UsePlacementFinder", "target_module", &self.target_module,
"first_legal_span", &self.first_legal_span, "first_use_span",
&&self.first_use_span)
}
}Debug)]
3654struct UsePlacementFinder {
3655 target_module: NodeId,
3656 first_legal_span: Option<Span>,
3657 first_use_span: Option<Span>,
3658}
3659
3660impl UsePlacementFinder {
3661 fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
3662 let mut finder =
3663 UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
3664 finder.visit_crate(krate);
3665 if let Some(use_span) = finder.first_use_span {
3666 (Some(use_span), FoundUse::Yes)
3667 } else {
3668 (finder.first_legal_span, FoundUse::No)
3669 }
3670 }
3671}
3672
3673impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
3674 fn visit_crate(&mut self, c: &Crate) {
3675 if self.target_module == CRATE_NODE_ID {
3676 let inject = c.spans.inject_use_span;
3677 if is_span_suitable_for_use_injection(inject) {
3678 self.first_legal_span = Some(inject);
3679 }
3680 self.first_use_span = search_for_any_use_in_items(&c.items);
3681 } else {
3682 visit::walk_crate(self, c);
3683 }
3684 }
3685
3686 fn visit_item(&mut self, item: &'tcx ast::Item) {
3687 if self.target_module == item.id {
3688 if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
3689 let inject = mod_spans.inject_use_span;
3690 if is_span_suitable_for_use_injection(inject) {
3691 self.first_legal_span = Some(inject);
3692 }
3693 self.first_use_span = search_for_any_use_in_items(items);
3694 }
3695 } else {
3696 visit::walk_item(self, item);
3697 }
3698 }
3699}
3700
3701#[derive(#[automatically_derived]
impl ::core::default::Default for BindingVisitor {
#[inline]
fn default() -> BindingVisitor {
BindingVisitor {
identifiers: ::core::default::Default::default(),
spans: ::core::default::Default::default(),
}
}
}Default)]
3702struct BindingVisitor {
3703 identifiers: Vec<Symbol>,
3704 spans: FxHashMap<Symbol, Vec<Span>>,
3705}
3706
3707impl<'tcx> Visitor<'tcx> for BindingVisitor {
3708 fn visit_pat(&mut self, pat: &ast::Pat) {
3709 if let ast::PatKind::Ident(_, ident, _) = pat.kind {
3710 self.identifiers.push(ident.name);
3711 self.spans.entry(ident.name).or_default().push(ident.span);
3712 }
3713 visit::walk_pat(self, pat);
3714 }
3715}
3716
3717fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
3718 for item in items {
3719 if let ItemKind::Use(..) = item.kind
3720 && is_span_suitable_for_use_injection(item.span)
3721 {
3722 let mut lo = item.span.lo();
3723 for attr in &item.attrs {
3724 if attr.span.eq_ctxt(item.span) {
3725 lo = std::cmp::min(lo, attr.span.lo());
3726 }
3727 }
3728 return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
3729 }
3730 }
3731 None
3732}
3733
3734fn is_span_suitable_for_use_injection(s: Span) -> bool {
3735 !s.from_expansion()
3738}