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