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