1use std::mem;
3use std::ops::ControlFlow;
4
5use itertools::Itertools as _;
6use rustc_ast::visit::{self, Visitor};
7use rustc_ast::{
8 self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path,
9 join_path_idents,
10};
11use rustc_ast_pretty::pprust;
12use rustc_attr_parsing::AttributeParser;
13use rustc_data_structures::fx::{FxHashMap, FxHashSet};
14use rustc_data_structures::unord::{UnordMap, UnordSet};
15use rustc_errors::codes::*;
16use rustc_errors::{
17 Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
18 pluralize, struct_span_code_err,
19};
20use rustc_feature::BUILTIN_ATTRIBUTES;
21use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};
22use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem};
23use rustc_hir::def::Namespace::{self, *};
24use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
25use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
26use rustc_hir::{Attribute, PrimTy, Stability, StabilityLevel, find_attr};
27use rustc_middle::bug;
28use rustc_middle::ty::{TyCtxt, Visibility};
29use rustc_session::Session;
30use rustc_session::lint::builtin::{
31 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
32 AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
33};
34use rustc_session::utils::was_invoked_from_cargo;
35use rustc_span::def_id::ModId;
36use rustc_span::edit_distance::find_best_match_for_name;
37use rustc_span::edition::Edition;
38use rustc_span::hygiene::MacroKind;
39use rustc_span::source_map::SourceMap;
40use rustc_span::{
41 BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,
42};
43use thin_vec::{ThinVec, thin_vec};
44use tracing::{debug, instrument};
45
46use crate::diagnostics::{
47 self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
48 ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
49 MaybeMissingMacroRulesName,
50};
51use crate::hygiene::Macros20NormalizedSyntaxContext;
52use crate::imports::{Import, ImportKind, UnresolvedImportError, import_path_to_string};
53use crate::late::{DiagMetadata, PatternSource, Rib};
54use crate::{
55 AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
56 DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey,
57 LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
58 PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
59 VisResolutionError, path_names_to_string,
60};
61
62pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
64
65pub(crate) type LabelSuggestion = (Ident, bool);
68
69#[derive(#[automatically_derived]
impl ::core::clone::Clone for StructCtor {
#[inline]
fn clone(&self) -> StructCtor {
StructCtor {
res: ::core::clone::Clone::clone(&self.res),
vis: ::core::clone::Clone::clone(&self.vis),
field_visibilities: ::core::clone::Clone::clone(&self.field_visibilities),
}
}
}Clone)]
70pub(crate) struct StructCtor {
71 pub res: Res,
72 pub vis: Visibility<ModId>,
73 pub field_visibilities: Vec<Visibility<ModId>>,
74}
75
76impl StructCtor {
77 pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
78 self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
79 }
80}
81
82#[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)]
83pub(crate) enum SuggestionTarget {
84 SimilarlyNamed,
86 SingleItem,
88}
89
90#[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)]
91pub(crate) struct TypoSuggestion {
92 pub candidate: Symbol,
93 pub span: Option<Span>,
96 pub res: Res,
97 pub target: SuggestionTarget,
98}
99
100impl TypoSuggestion {
101 pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
102 Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
103 }
104 pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
105 Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
106 }
107 pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
108 Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
109 }
110}
111
112#[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)]
114pub(crate) struct ImportSuggestion {
115 pub did: Option<DefId>,
116 pub descr: &'static str,
117 pub path: Path,
118 pub accessible: bool,
119 pub doc_visible: bool,
121 pub via_import: bool,
122 pub note: Option<String>,
124 pub is_stable: bool,
125}
126
127fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
135 let impl_span = sm.span_until_char(impl_span, '<');
136 sm.span_until_whitespace(impl_span)
137}
138
139impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
140 pub(crate) fn throw_unresolved_import_error(
145 &mut self,
146 mut errors: Vec<(Import<'_>, UnresolvedImportError)>,
147 glob_error: bool,
148 ) {
149 errors.retain(|(_import, err)| match err.module {
150 Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,
152 _ => err.segment.map(|s| s.name) != Some(kw::Underscore),
155 });
156 if errors.is_empty() {
157 self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");
158 return;
159 }
160
161 let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());
162
163 let paths = errors
164 .iter()
165 .map(|(import, err)| {
166 let path = import_path_to_string(
167 &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),
168 &import.kind,
169 err.span,
170 );
171 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", path))
})format!("`{path}`")
172 })
173 .collect::<Vec<_>>();
174 let default_message =
175 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unresolved import{0} {1}",
if paths.len() == 1 { "" } else { "s" }, paths.join(", ")))
})format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);
176
177 let (mut message, label, mut notes) =
182 if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) {
183 let this = errors
184 .iter()
185 .map(|(_import, err)| {
186 err.segment.map(|s| s.name).unwrap_or(kw::Underscore)
188 })
189 .join(", ");
190
191 let args = FormatArgs { unresolved: this.clone(), this, .. };
192
193 let CustomDiagnostic { message, label, notes, parent_label: _dead } =
194 directive.eval(None, &args);
195
196 (message, label, notes)
197 } else {
198 (None, None, Vec::new())
199 };
200
201 let mut mod_diagnostics: Vec<CustomDiagnostic> = errors
205 .iter()
206 .map(|(import, import_error)| {
207 if let Some(ModuleOrUniformRoot::Module(module_data)) = import.imported_module.get()
208 && let ModuleKind::Def(DefKind::Mod, def_id, _, name) = module_data.kind
209 {
210 let Some(directive) = self.on_unknown_data(def_id) else {
211 return CustomDiagnostic::default();
212 };
213
214 let this = if let Some(name) = name {
215 name.to_string()
216 } else if let Some(crate_name) = &self.tcx.sess.opts.crate_name {
217 crate_name.to_string()
218 } else {
219 "<unnamed crate>".to_string()
220 };
221 let unresolved = import_error.segment.map(|s| s.name).unwrap_or(kw::Underscore);
222 let args = FormatArgs { this, unresolved: unresolved.to_string(), .. };
223
224 directive.eval(None, &args)
225 } else {
226 CustomDiagnostic::default()
227 }
228 })
229 .collect();
230
231 let mod_message =
234 mod_diagnostics.iter_mut().flat_map(|d| d.message.take()).all_equal_value();
235 if message.is_none()
236 && let Ok(mod_msg) = mod_message
237 {
238 message = Some(mod_msg);
239 }
240
241 let mut diag = if let Some(message) = message {
242 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", message))
})).with_code(E0432)
}struct_span_code_err!(self.dcx(), span, E0432, "{message}").with_note(default_message)
243 } else {
244 {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", default_message))
})).with_code(E0432)
}struct_span_code_err!(self.dcx(), span, E0432, "{default_message}")
245 };
246
247 for mod_diag in mod_diagnostics.iter_mut() {
248 for mod_note in mod_diag.notes.drain(..) {
249 if !notes.contains(&mod_note) {
250 notes.push(mod_note);
251 }
252 }
253 }
254
255 if !notes.is_empty() {
256 for note in notes {
257 diag.note(note);
258 }
259 } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) =
260 errors.iter().last()
261 {
262 diag.note(note.clone());
263 }
264
265 const MAX_LABEL_COUNT: usize = 10;
267 let mod_labels = mod_diagnostics.into_iter().map(|cd| cd.label);
268
269 for ((import, err), mod_label) in errors.into_iter().zip(mod_labels).take(MAX_LABEL_COUNT) {
270 let label_span = match err.segment {
271 Some(segment) => segment.span,
272 None => err.span,
273 };
274 if let Some(label) = &label {
275 diag.span_label(label_span, label.clone());
276 } else if let Some(label) = mod_label {
277 diag.span_label(label_span, label);
278 } else if let Some(label) = &err.label {
279 diag.span_label(label_span, label.clone());
280 }
281
282 if let Some((suggestions, msg, applicability)) = err.suggestion {
283 if suggestions.is_empty() {
284 diag.help(msg);
285 continue;
286 }
287 diag.multipart_suggestion(msg, suggestions, applicability);
288 }
289
290 if let Some(candidates) = &err.candidates {
291 match &import.kind {
292 ImportKind::Single { nested: false, source, target, .. } => import_candidates(
293 self.tcx,
294 &mut diag,
295 Some(err.span),
296 candidates,
297 DiagMode::Import { append: false, unresolved_import: true },
298 (source != target)
299 .then(|| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" as {0}", target))
})format!(" as {target}"))
300 .as_deref()
301 .unwrap_or(""),
302 ),
303 ImportKind::Single { nested: true, source, target, .. } => {
304 import_candidates(
305 self.tcx,
306 &mut diag,
307 None,
308 candidates,
309 DiagMode::Normal,
310 (source != target)
311 .then(|| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" as {0}", target))
})format!(" as {target}"))
312 .as_deref()
313 .unwrap_or(""),
314 );
315 }
316 _ => {}
317 }
318 }
319
320 if #[allow(non_exhaustive_omitted_patterns)] match import.kind {
ImportKind::Single { .. } => true,
_ => false,
}matches!(import.kind, ImportKind::Single { .. })
321 && let Some(segment) = err.segment
322 && let Some(module) = err.module
323 {
324 self.find_cfg_stripped(&mut diag, &segment.name, module)
325 }
326 }
327
328 let guar = diag.emit();
329 if glob_error {
330 self.glob_error = Some(guar);
331 }
332 }
333
334 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
335 self.tcx.dcx()
336 }
337
338 pub(crate) fn report_errors(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {
339 self.report_delayed_vis_resolution_errors();
340 self.report_with_use_injections(krate, use_injections);
341
342 for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
343 self.lint_buffer.buffer_lint(
344 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
345 CRATE_NODE_ID,
346 span_use,
347 diagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths {
348 definition: span_def,
349 },
350 );
351 }
352
353 for ambiguity_error in &self.ambiguity_errors {
354 let mut diag = self.ambiguity_diagnostic(ambiguity_error);
355
356 if let Some(ambiguity_warning) = ambiguity_error.warning {
357 let node_id = match ambiguity_error.b1.0.kind {
358 DeclKind::Import { import, .. } => import.root_id,
359 DeclKind::Def(_) => CRATE_NODE_ID,
360 };
361
362 let lint = match ambiguity_warning {
363 _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
364 AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
365 AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
366 };
367
368 self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
369 } else {
370 diag.is_error = true;
371 self.dcx().emit_err(diag);
372 }
373 }
374
375 let mut reported_spans = FxHashSet::default();
376 for error in mem::take(&mut self.privacy_errors) {
377 if reported_spans.insert(error.dedup_span) {
378 self.report_privacy_error(&error);
379 }
380 }
381 }
382
383 fn report_delayed_vis_resolution_errors(&mut self) {
384 for DelayedVisResolutionError { vis, parent_scope, error } in
385 mem::take(&mut self.delayed_vis_resolution_errors)
386 {
387 match self.try_resolve_visibility(&parent_scope, &vis, true) {
388 Ok(_) => self.report_vis_error(error),
389 Err(error) => self.report_vis_error(error),
390 };
391 }
392 }
393
394 fn report_with_use_injections(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {
395 for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in
396 use_injections
397 {
398 let (span, found_use) = if node_id != DUMMY_NODE_ID {
399 UsePlacementFinder::check(krate, node_id)
400 } else {
401 (None, FoundUse::No)
402 };
403
404 if !candidates.is_empty() {
405 show_candidates(
406 self.tcx,
407 &mut err,
408 span,
409 &candidates,
410 if instead { Instead::Yes } else { Instead::No },
411 found_use,
412 DiagMode::Normal,
413 path,
414 "",
415 );
416 err.emit();
417 } else if let Some((span, msg, sugg, appl)) = suggestion {
418 err.span_suggestion_verbose(span, msg, sugg, appl);
419 err.emit();
420 } else if let [segment] = path.as_slice()
421 && is_call
422 {
423 err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
424 } else {
425 err.emit();
426 }
427 }
428 }
429
430 pub(crate) fn report_conflict(
431 &mut self,
432 ident: IdentKey,
433 ns: Namespace,
434 old_binding: Decl<'ra>,
435 new_binding: Decl<'ra>,
436 ) {
437 if old_binding.span.lo() > new_binding.span.lo() {
439 return self.report_conflict(ident, ns, new_binding, old_binding);
440 }
441
442 let container = match old_binding.parent_module.unwrap().expect_local().kind {
443 ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id),
446 ModuleKind::Block => "block",
447 };
448
449 let (name, span) =
450 (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
451
452 if self.name_already_seen.get(&name) == Some(&span) {
453 return;
454 }
455
456 let old_kind = match (ns, old_binding.res()) {
457 (ValueNS, _) => "value",
458 (MacroNS, _) => "macro",
459 (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
460 (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
461 (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
462 (TypeNS, _) => "type",
463 };
464
465 let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
466 (true, true) => E0259,
467 (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
468 true => E0254,
469 false => E0260,
470 },
471 _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
472 (false, false) => E0428,
473 (true, true) => E0252,
474 _ => E0255,
475 },
476 };
477
478 let label = match new_binding.is_import_user_facing() {
479 true => diagnostics::NameDefinedMultipleTimeLabel::Reimported { span, name },
480 false => diagnostics::NameDefinedMultipleTimeLabel::Redefined { span, name },
481 };
482
483 let old_binding_label =
484 (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
485 let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
486 match old_binding.is_import_user_facing() {
487 true => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Import {
488 span,
489 old_kind,
490 name,
491 },
492 false => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Definition {
493 span,
494 old_kind,
495 name,
496 },
497 }
498 });
499
500 let mut err = self
501 .dcx()
502 .create_err(diagnostics::NameDefinedMultipleTime {
503 span,
504 name,
505 descr: ns.descr(),
506 container,
507 label,
508 old_binding_label,
509 })
510 .with_code(code);
511
512 use DeclKind::Import;
514 let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
515 !binding.span.is_dummy()
516 && !#[allow(non_exhaustive_omitted_patterns)] match import.kind {
ImportKind::MacroUse { .. } | ImportKind::MacroExport => true,
_ => false,
}matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
517 };
518 let import = match (&new_binding.kind, &old_binding.kind) {
519 (Import { import: new, .. }, Import { import: old, .. })
522 if {
523 (new.has_attributes || old.has_attributes)
524 && can_suggest(old_binding, *old)
525 && can_suggest(new_binding, *new)
526 } =>
527 {
528 if old.has_attributes {
529 Some((*new, new_binding.span, true))
530 } else {
531 Some((*old, old_binding.span, true))
532 }
533 }
534 (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
536 Some((*import, new_binding.span, other.is_import()))
537 }
538 (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
539 Some((*import, old_binding.span, other.is_import()))
540 }
541 _ => None,
542 };
543
544 let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
546 let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
547 let from_item =
548 self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
549 let should_remove_import = duplicate
553 && !has_dummy_span
554 && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
555
556 match import {
557 Some((import, span, true)) if should_remove_import && import.is_nested() => {
558 self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
559 }
560 Some((import, _, true)) if should_remove_import && !import.is_glob() => {
561 err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport {
564 span: import.use_span_with_attributes,
565 });
566 }
567 Some((import, span, _)) => {
568 self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
569 }
570 _ => {}
571 }
572
573 err.emit();
574 self.name_already_seen.insert(name, span);
575 }
576
577 fn add_suggestion_for_rename_of_use(
587 &self,
588 err: &mut Diag<'_>,
589 name: Symbol,
590 import: Import<'_>,
591 binding_span: Span,
592 ) {
593 let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
594 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Other{0}", name))
})format!("Other{name}")
595 } else {
596 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("other_{0}", name))
})format!("other_{name}")
597 };
598
599 let mut suggestion = None;
600 let mut span = binding_span;
601 match import.kind {
602 ImportKind::Single { source, .. } => {
603 if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
604 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
605 && pos as usize <= snippet.len()
606 {
607 span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
608 binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
609 );
610 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" as {0}", suggested_name))
})format!(" as {suggested_name}"));
611 }
612 }
613 ImportKind::ExternCrate { source, target, .. } => {
614 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern crate {0} as {1};",
source.unwrap_or(target.name), suggested_name))
})format!(
615 "extern crate {} as {};",
616 source.unwrap_or(target.name),
617 suggested_name,
618 ))
619 }
620 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
621 }
622
623 if let Some(suggestion) = suggestion {
624 err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
625 } else {
626 err.subdiagnostic(ChangeImportBinding { span });
627 }
628 }
629
630 fn add_suggestion_for_duplicate_nested_use(
653 &self,
654 err: &mut Diag<'_>,
655 import: Import<'_>,
656 binding_span: Span,
657 ) {
658 if !import.is_nested() {
::core::panicking::panic("assertion failed: import.is_nested()")
};assert!(import.is_nested());
659
660 let (found_closing_brace, span) =
668 find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
669
670 if found_closing_brace {
673 if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
674 err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport { span });
675 } else {
676 err.subdiagnostic(diagnostics::RemoveUnnecessaryImport {
679 span: import.use_span_with_attributes,
680 });
681 }
682
683 return;
684 }
685
686 err.subdiagnostic(diagnostics::RemoveUnnecessaryImport { span });
687 }
688
689 pub(crate) fn lint_if_path_starts_with_module(
690 &mut self,
691 finalize: Finalize,
692 path: &[Segment],
693 second_binding: Option<Decl<'_>>,
694 ) {
695 let Finalize { node_id, root_span, .. } = finalize;
696
697 let first_name = match path.get(0) {
698 Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
700 seg.ident.name
701 }
702 _ => return,
703 };
704
705 if first_name != kw::PathRoot {
708 return;
709 }
710
711 match path.get(1) {
712 Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
714 Some(_) => {}
716 None => return,
720 }
721
722 if let Some(binding) = second_binding
726 && let DeclKind::Import { import, .. } = binding.kind
727 && let ImportKind::ExternCrate { source: None, .. } = import.kind
729 {
730 return;
731 }
732
733 self.lint_buffer.dyn_buffer_lint_any(
734 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
735 node_id,
736 root_span,
737 move |dcx, level, sess| {
738 let (replacement, applicability) = match sess
739 .downcast_ref::<Session>()
740 .expect("expected a `Session`")
741 .source_map()
742 .span_to_snippet(root_span)
743 {
744 Ok(ref s) => {
745 let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
748
749 (::alloc::__export::must_use({
::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
})format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
750 }
751 Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
752 };
753 diagnostics::AbsPathWithModule {
754 sugg: diagnostics::AbsPathWithModuleSugg {
755 span: root_span,
756 applicability,
757 replacement,
758 },
759 }
760 .into_diag(dcx, level)
761 },
762 );
763 }
764
765 pub(crate) fn add_module_candidates(
766 &self,
767 module: Module<'ra>,
768 names: &mut Vec<TypoSuggestion>,
769 filter_fn: &impl Fn(Res) -> bool,
770 ctxt: Option<SyntaxContext>,
771 ) {
772 module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
773 let res = binding.res();
774 if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
775 names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
776 }
777 });
778 }
779
780 pub(crate) fn report_error(
785 &mut self,
786 span: Span,
787 resolution_error: ResolutionError<'ra>,
788 ) -> ErrorGuaranteed {
789 self.into_struct_error(span, resolution_error).emit()
790 }
791
792 pub(crate) fn into_struct_error(
793 &mut self,
794 span: Span,
795 resolution_error: ResolutionError<'ra>,
796 ) -> Diag<'_> {
797 match resolution_error {
798 ResolutionError::GenericParamsFromOuterItem {
799 outer_res,
800 has_generic_params,
801 def_kind,
802 inner_item,
803 current_self_ty,
804 } => {
805 use diagnostics::GenericParamsFromOuterItemLabel as Label;
806 let static_or_const = match def_kind {
807 DefKind::Static { .. } => {
808 Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Static)
809 }
810 DefKind::Const { .. } => {
811 Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Const)
812 }
813 _ => None,
814 };
815 let is_self =
816 #[allow(non_exhaustive_omitted_patterns)] match outer_res {
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => true,
_ => false,
}matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
817 let mut err = diagnostics::GenericParamsFromOuterItem {
818 span,
819 label: None,
820 refer_to_type_directly: None,
821 use_let: None,
822 sugg: None,
823 static_or_const,
824 is_self,
825 item: inner_item.as_ref().map(|(label_span, _, kind)| {
826 diagnostics::GenericParamsFromOuterItemInnerItem {
827 span: *label_span,
828 descr: kind.descr().to_string(),
829 is_self,
830 }
831 }),
832 };
833
834 let sm = self.tcx.sess.source_map();
835 let def_id = match outer_res {
838 Res::SelfTyParam { .. } => {
839 err.label = Some(Label::SelfTyParam(span));
840 None
841 }
842 Res::SelfTyAlias { alias_to: def_id, .. } => {
843 err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
844 sm,
845 self.def_span(def_id),
846 )));
847 err.refer_to_type_directly = current_self_ty
848 .map(|snippet| diagnostics::UseTypeDirectly { span, snippet });
849 None
850 }
851 Res::Def(DefKind::TyParam, def_id) => {
852 err.label = Some(Label::TyParam(self.def_span(def_id)));
853 Some(def_id)
854 }
855 Res::Def(DefKind::ConstParam, def_id) => {
856 err.label = Some(Label::ConstParam(self.def_span(def_id)));
857 Some(def_id)
858 }
859 _ => {
860 ::rustc_middle::util::bug::bug_fmt(format_args!("GenericParamsFromOuterItem should only be used with Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or DefKind::ConstParam"));bug!(
861 "GenericParamsFromOuterItem should only be used with \
862 Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
863 DefKind::ConstParam"
864 );
865 }
866 };
867
868 if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() {
869 err.use_let = Some(diagnostics::GenericParamsFromOuterItemUseLet {
870 span: sm.span_until_whitespace(*item_span),
871 });
872 }
873
874 if let Some(def_id) = def_id
875 && let HasGenericParams::Yes(span) = has_generic_params
876 && !#[allow(non_exhaustive_omitted_patterns)] match inner_item {
Some((_, _, ItemKind::Delegation(..))) => true,
_ => false,
}matches!(inner_item, Some((_, _, ItemKind::Delegation(..))))
877 {
878 let name = self.tcx.item_name(def_id);
879 let (span, snippet) = if span.is_empty() {
880 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", name))
})format!("<{name}>");
881 (span, snippet)
882 } else {
883 let span = sm.span_through_char(span, '<').shrink_to_hi();
884 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", name))
})format!("{name}, ");
885 (span, snippet)
886 };
887 err.sugg = Some(diagnostics::GenericParamsFromOuterItemSugg { span, snippet });
888 }
889
890 self.dcx().create_err(err)
891 }
892 ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
893 self.dcx().create_err(diagnostics::NameAlreadyUsedInParameterList {
894 span,
895 first_use_span,
896 name,
897 })
898 }
899 ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
900 self.dcx().create_err(diagnostics::MethodNotMemberOfTrait {
901 span,
902 method,
903 trait_,
904 sub: candidate.map(|c| diagnostics::AssociatedFnWithSimilarNameExists {
905 span: method.span,
906 candidate: c,
907 }),
908 })
909 }
910 ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
911 self.dcx().create_err(diagnostics::TypeNotMemberOfTrait {
912 span,
913 type_,
914 trait_,
915 sub: candidate.map(|c| diagnostics::AssociatedTypeWithSimilarNameExists {
916 span: type_.span,
917 candidate: c,
918 }),
919 })
920 }
921 ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
922 self.dcx().create_err(diagnostics::ConstNotMemberOfTrait {
923 span,
924 const_,
925 trait_,
926 sub: candidate.map(|c| diagnostics::AssociatedConstWithSimilarNameExists {
927 span: const_.span,
928 candidate: c,
929 }),
930 })
931 }
932 ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
933 let BindingError { name, target, origin, could_be_path } = binding_error;
934
935 let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
936 target_sp.sort();
937 target_sp.dedup();
938 let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
939 origin_sp.sort();
940 origin_sp.dedup();
941
942 let msp = MultiSpan::from_spans(target_sp.clone());
943 let mut err = self.dcx().create_err(diagnostics::VariableIsNotBoundInAllPatterns {
944 multispan: msp,
945 name,
946 });
947 for sp in target_sp {
948 err.subdiagnostic(diagnostics::PatternDoesntBindName { span: sp, name });
949 }
950 for sp in &origin_sp {
951 err.subdiagnostic(diagnostics::VariableNotInAllPatterns { span: *sp });
952 }
953 let mut suggested_typo = false;
954 if !target.iter().all(|pat| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
955 && !origin.iter().all(|(_, pat)| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
956 {
957 let mut target_visitor = BindingVisitor::default();
960 for pat in &target {
961 target_visitor.visit_pat(pat);
962 }
963 target_visitor.identifiers.sort();
964 target_visitor.identifiers.dedup();
965 let mut origin_visitor = BindingVisitor::default();
966 for (_, pat) in &origin {
967 origin_visitor.visit_pat(pat);
968 }
969 origin_visitor.identifiers.sort();
970 origin_visitor.identifiers.dedup();
971 if let Some(typo) =
973 find_best_match_for_name(&target_visitor.identifiers, name.name, None)
974 && !origin_visitor.identifiers.contains(&typo)
975 {
976 err.subdiagnostic(diagnostics::PatternBindingTypo {
977 spans: origin_sp,
978 typo,
979 });
980 suggested_typo = true;
981 }
982 }
983 if could_be_path {
984 let import_suggestions = self.lookup_import_candidates(
985 name,
986 Namespace::ValueNS,
987 &parent_scope,
988 &|res: Res| {
989 #[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!(
990 res,
991 Res::Def(
992 DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
993 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
994 | DefKind::Const { .. }
995 | DefKind::AssocConst { .. },
996 _,
997 )
998 )
999 },
1000 );
1001
1002 if import_suggestions.is_empty() && !suggested_typo {
1003 let kind_matches: [fn(DefKind) -> bool; 4] = [
1004 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
1005 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
1006 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Const { .. } => true,
_ => false,
}matches!(kind, DefKind::Const { .. }),
1007 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::AssocConst { .. } => true,
_ => false,
}matches!(kind, DefKind::AssocConst { .. }),
1008 ];
1009 let mut local_names = ::alloc::vec::Vec::new()vec![];
1010 self.add_module_candidates(
1011 parent_scope.module,
1012 &mut local_names,
1013 &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(_, _) => true,
_ => false,
}matches!(res, Res::Def(_, _)),
1014 None,
1015 );
1016 let local_names: FxHashSet<_> = local_names
1017 .into_iter()
1018 .filter_map(|s| match s.res {
1019 Res::Def(_, def_id) => Some(def_id),
1020 _ => None,
1021 })
1022 .collect();
1023
1024 let mut local_suggestions = ::alloc::vec::Vec::new()vec![];
1025 let mut suggestions = ::alloc::vec::Vec::new()vec![];
1026 for matches_kind in kind_matches {
1027 if let Some(suggestion) = self.early_lookup_typo_candidate(
1028 ScopeSet::All(Namespace::ValueNS),
1029 &parent_scope,
1030 name,
1031 &|res: Res| match res {
1032 Res::Def(k, _) => matches_kind(k),
1033 _ => false,
1034 },
1035 ) && let Res::Def(kind, mut def_id) = suggestion.res
1036 {
1037 if let DefKind::Ctor(_, _) = kind {
1038 def_id = self.tcx.parent(def_id);
1039 }
1040 let kind = kind.descr(def_id);
1041 if local_names.contains(&def_id) {
1042 local_suggestions.push((
1045 suggestion.candidate,
1046 suggestion.candidate.to_string(),
1047 kind,
1048 ));
1049 } else {
1050 suggestions.push((
1051 suggestion.candidate,
1052 self.def_path_str(def_id),
1053 kind,
1054 ));
1055 }
1056 }
1057 }
1058 let suggestions = if !local_suggestions.is_empty() {
1059 local_suggestions
1062 } else {
1063 suggestions
1064 };
1065 for (name, sugg, kind) in suggestions {
1066 err.span_suggestion_verbose(
1067 span,
1068 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might have meant to use the similarly named {0} `{1}`",
kind, name))
})format!(
1069 "you might have meant to use the similarly named {kind} `{name}`",
1070 ),
1071 sugg,
1072 Applicability::MaybeIncorrect,
1073 );
1074 suggested_typo = true;
1075 }
1076 }
1077 if import_suggestions.is_empty() && !suggested_typo {
1078 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!(
1079 "if you meant to match on a unit struct, unit variant or a `const` \
1080 item, consider making the path in the pattern qualified: \
1081 `path::to::ModOrType::{name}`",
1082 );
1083 err.span_help(span, help_msg);
1084 }
1085 show_candidates(
1086 self.tcx,
1087 &mut err,
1088 Some(span),
1089 &import_suggestions,
1090 Instead::No,
1091 FoundUse::Yes,
1092 DiagMode::Pattern,
1093 ::alloc::vec::Vec::new()vec![],
1094 "",
1095 );
1096 }
1097 err
1098 }
1099 ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
1100 self.dcx().create_err(diagnostics::VariableBoundWithDifferentMode {
1101 span,
1102 first_binding_span,
1103 variable_name,
1104 })
1105 }
1106 ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
1107 self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInParameterList {
1108 span,
1109 identifier,
1110 })
1111 }
1112 ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
1113 self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInSamePattern {
1114 span,
1115 identifier,
1116 })
1117 }
1118 ResolutionError::UndeclaredLabel { name, suggestion } => {
1119 let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
1120 {
1121 Some((ident, true)) => (
1123 (
1124 Some(diagnostics::LabelWithSimilarNameReachable(ident.span)),
1125 Some(diagnostics::TryUsingSimilarlyNamedLabel {
1126 span,
1127 ident_name: ident.name,
1128 }),
1129 ),
1130 None,
1131 ),
1132 Some((ident, false)) => (
1134 (None, None),
1135 Some(diagnostics::UnreachableLabelWithSimilarNameExists {
1136 ident_span: ident.span,
1137 }),
1138 ),
1139 None => ((None, None), None),
1141 };
1142 self.dcx().create_err(diagnostics::UndeclaredLabel {
1143 span,
1144 name,
1145 sub_reachable,
1146 sub_reachable_suggestion,
1147 sub_unreachable,
1148 })
1149 }
1150 ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
1151 let mut err = {
self.dcx().struct_span_err(span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", message))
})).with_code(E0433)
}struct_span_code_err!(self.dcx(), span, E0433, "{message}");
1152 err.span_label(span, label);
1153
1154 if let Some((suggestions, msg, applicability)) = suggestion {
1155 if suggestions.is_empty() {
1156 err.help(msg);
1157 return err;
1158 }
1159 err.multipart_suggestion(msg, suggestions, applicability);
1160 }
1161
1162 let module = match module {
1163 Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
1164 _ => CRATE_DEF_ID.to_def_id(),
1165 };
1166 self.find_cfg_stripped(&mut err, &segment, module);
1167
1168 err
1169 }
1170 ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
1171 self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem { span })
1172 }
1173 ResolutionError::AttemptToUseNonConstantValueInConstant {
1174 ident,
1175 suggestion,
1176 current,
1177 type_span,
1178 } => {
1179 let sp = self
1188 .tcx
1189 .sess
1190 .source_map()
1191 .span_extend_to_prev_str(ident.span, current, true, false);
1192
1193 let (with, with_label, without) = match sp {
1194 Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
1195 let sp = sp
1196 .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
1197 .until(ident.span);
1198
1199 let is_simple_binding =
1207 self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {
1208 let after_keyword = snippet[current.len()..].trim();
1209 after_keyword.is_empty() || after_keyword == "mut"
1210 });
1211
1212 if is_simple_binding {
1213 (
1214 Some(diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion {
1215 span: sp,
1216 suggestion,
1217 current,
1218 type_span,
1219 }),
1220 Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1221 None,
1222 )
1223 } else {
1224 (
1225 None,
1226 Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1227 None,
1228 )
1229 }
1230 }
1231 _ => (
1232 None,
1233 None,
1234 Some(
1235 diagnostics::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
1236 ident_span: ident.span,
1237 suggestion,
1238 },
1239 ),
1240 ),
1241 };
1242
1243 self.dcx().create_err(diagnostics::AttemptToUseNonConstantValueInConstant {
1244 span,
1245 with,
1246 with_label,
1247 without,
1248 })
1249 }
1250 ResolutionError::BindingShadowsSomethingUnacceptable {
1251 shadowing_binding,
1252 name,
1253 participle,
1254 article,
1255 shadowed_binding,
1256 shadowed_binding_span,
1257 } => self.dcx().create_err(diagnostics::BindingShadowsSomethingUnacceptable {
1258 span,
1259 shadowing_binding,
1260 shadowed_binding,
1261 article,
1262 sub_suggestion: match (shadowing_binding, shadowed_binding) {
1263 (
1264 PatternSource::Match,
1265 Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
1266 ) => Some(diagnostics::BindingShadowsSomethingUnacceptableSuggestion {
1267 span,
1268 name,
1269 }),
1270 _ => None,
1271 },
1272 shadowed_binding_span,
1273 participle,
1274 name,
1275 }),
1276 ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
1277 ForwardGenericParamBanReason::Default => {
1278 self.dcx().create_err(diagnostics::ForwardDeclaredGenericParam { param, span })
1279 }
1280 ForwardGenericParamBanReason::ConstParamTy => self
1281 .dcx()
1282 .create_err(diagnostics::ForwardDeclaredGenericInConstParamTy { param, span }),
1283 },
1284 ResolutionError::ParamInTyOfConstParam { name } => {
1285 self.dcx().create_err(diagnostics::ParamInTyOfConstParam { span, name })
1286 }
1287 ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {
1288 self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst {
1289 span,
1290 name,
1291 param_kind: is_type,
1292 help: self.tcx.sess.is_nightly_build()
1293 && !self.tcx.features().min_generic_const_args(),
1294 is_gca,
1295 help_gca: is_gca,
1296 help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca,
1297 })
1298 }
1299 ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => {
1300 self.dcx().create_err(diagnostics::ParamInEnumDiscriminant {
1301 span,
1302 name,
1303 param_kind: is_type,
1304 })
1305 }
1306 ResolutionError::ForwardDeclaredSelf(reason) => match reason {
1307 ForwardGenericParamBanReason::Default => {
1308 self.dcx().create_err(diagnostics::SelfInGenericParamDefault { span })
1309 }
1310 ForwardGenericParamBanReason::ConstParamTy => {
1311 self.dcx().create_err(diagnostics::SelfInConstGenericTy { span })
1312 }
1313 },
1314 ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
1315 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
1316 match suggestion {
1317 Some((ident, true)) => (
1319 (
1320 Some(diagnostics::UnreachableLabelSubLabel {
1321 ident_span: ident.span,
1322 }),
1323 Some(diagnostics::UnreachableLabelSubSuggestion {
1324 span,
1325 ident_name: ident.name,
1328 }),
1329 ),
1330 None,
1331 ),
1332 Some((ident, false)) => (
1334 (None, None),
1335 Some(diagnostics::UnreachableLabelSubLabelUnreachable {
1336 ident_span: ident.span,
1337 }),
1338 ),
1339 None => ((None, None), None),
1341 };
1342 self.dcx().create_err(diagnostics::UnreachableLabel {
1343 span,
1344 name,
1345 definition_span,
1346 sub_suggestion,
1347 sub_suggestion_label,
1348 sub_unreachable_label,
1349 })
1350 }
1351 ResolutionError::TraitImplMismatch {
1352 name,
1353 kind,
1354 code,
1355 trait_item_span,
1356 trait_path,
1357 } => self
1358 .dcx()
1359 .create_err(diagnostics::TraitImplMismatch {
1360 span,
1361 name,
1362 kind,
1363 trait_path,
1364 trait_item_span,
1365 })
1366 .with_code(code),
1367 ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
1368 self.dcx().create_err(diagnostics::TraitImplDuplicate {
1369 span,
1370 name,
1371 trait_item_span,
1372 old_span,
1373 })
1374 }
1375 ResolutionError::InvalidAsmSym => {
1376 self.dcx().create_err(diagnostics::InvalidAsmSym { span })
1377 }
1378 ResolutionError::LowercaseSelf => {
1379 self.dcx().create_err(diagnostics::LowercaseSelf { span })
1380 }
1381 ResolutionError::BindingInNeverPattern => {
1382 self.dcx().create_err(diagnostics::BindingInNeverPattern { span })
1383 }
1384 }
1385 }
1386
1387 pub(crate) fn report_vis_error(
1388 &mut self,
1389 vis_resolution_error: VisResolutionError,
1390 ) -> ErrorGuaranteed {
1391 match vis_resolution_error {
1392 VisResolutionError::Relative2018(span, path) => {
1393 self.dcx().create_err(diagnostics::Relative2018 {
1394 span,
1395 path_span: path.span,
1396 path_str: pprust::path_to_string(&path),
1399 })
1400 }
1401 VisResolutionError::AncestorOnly(span) => {
1402 self.dcx().create_err(diagnostics::AncestorOnly(span))
1403 }
1404 VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self
1405 .into_struct_error(
1406 span,
1407 ResolutionError::FailedToResolve {
1408 segment,
1409 label,
1410 suggestion,
1411 module: None,
1412 message,
1413 },
1414 ),
1415 VisResolutionError::ExpectedFound(span, path_str, res) => {
1416 self.dcx().create_err(diagnostics::ExpectedModuleFound { span, res, path_str })
1417 }
1418 VisResolutionError::Indeterminate(span) => {
1419 self.dcx().create_err(diagnostics::Indeterminate(span))
1420 }
1421 VisResolutionError::ModuleOnly(span) => {
1422 self.dcx().create_err(diagnostics::ModuleOnly(span))
1423 }
1424 }
1425 .emit()
1426 }
1427
1428 pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
1429 let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[def_id]))vec![def_id];
1431 while let Some(parent) = self.tcx.opt_parent(def_id) {
1432 def_id = parent;
1433 path.push(def_id);
1434 if def_id.is_top_level_module() {
1435 break;
1436 }
1437 }
1438 path.into_iter()
1440 .rev()
1441 .map(|def_id| {
1442 self.tcx
1443 .opt_item_name(def_id)
1444 .map(|name| {
1445 match (
1446 def_id.is_top_level_module(),
1447 def_id.is_local(),
1448 self.tcx.sess.edition(),
1449 ) {
1450 (true, true, Edition::Edition2015) => String::new(),
1451 (true, true, _) => kw::Crate.to_string(),
1452 (true, false, _) | (false, _, _) => name.to_string(),
1453 }
1454 })
1455 .unwrap_or_else(|| "_".to_string())
1456 })
1457 .collect::<Vec<String>>()
1458 .join("::")
1459 }
1460
1461 pub(crate) fn add_scope_set_candidates(
1462 &mut self,
1463 suggestions: &mut Vec<TypoSuggestion>,
1464 scope_set: ScopeSet<'ra>,
1465 ps: &ParentScope<'ra>,
1466 sp: Span,
1467 filter_fn: &impl Fn(Res) -> bool,
1468 ) {
1469 let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
1470 self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
1471 match scope {
1472 Scope::DeriveHelpers(expn_id) => {
1473 let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
1474 if filter_fn(res) {
1475 suggestions.extend(this.helper_attrs.get(&expn_id).into_flat_iter().map(
1476 |&(ident, orig_ident_span, _)| {
1477 TypoSuggestion::new(ident.name, orig_ident_span, res)
1478 },
1479 ));
1480 }
1481 }
1482 Scope::DeriveHelpersCompat => {
1483 }
1485 Scope::MacroRules(macro_rules_scope) => {
1486 if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
1487 let res = macro_rules_def.decl.res();
1488 if filter_fn(res) {
1489 suggestions.push(TypoSuggestion::new(
1490 macro_rules_def.ident.name,
1491 macro_rules_def.orig_ident_span,
1492 res,
1493 ))
1494 }
1495 }
1496 }
1497 Scope::ModuleNonGlobs(module, _) => {
1498 this.add_module_candidates(module, suggestions, filter_fn, None);
1499 }
1500 Scope::ModuleGlobs(..) => {
1501 }
1503 Scope::MacroUsePrelude => {
1504 suggestions.extend(this.macro_use_prelude.iter().filter_map(
1505 |(name, binding)| {
1506 let res = binding.res();
1507 filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1508 },
1509 ));
1510 }
1511 Scope::BuiltinAttrs => {
1512 let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
1513 if filter_fn(res) {
1514 suggestions.extend(
1515 BUILTIN_ATTRIBUTES
1516 .iter()
1517 .map(|attr| TypoSuggestion::typo_from_name(*attr, res)),
1518 );
1519 }
1520 }
1521 Scope::ExternPreludeItems => {
1522 suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
1524 let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1525 filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
1526 }));
1527 }
1528 Scope::ExternPreludeFlags => {}
1529 Scope::ToolPrelude => {
1530 let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1531 suggestions.extend(
1532 this.registered_tools
1533 .iter()
1534 .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
1535 );
1536 }
1537 Scope::StdLibPrelude => {
1538 if let Some(prelude) = this.prelude {
1539 let mut tmp_suggestions = Vec::new();
1540 this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1541 suggestions.extend(
1542 tmp_suggestions
1543 .into_iter()
1544 .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
1545 );
1546 }
1547 }
1548 Scope::BuiltinTypes => {
1549 suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1550 let res = Res::PrimTy(*prim_ty);
1551 filter_fn(res)
1552 .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1553 }))
1554 }
1555 }
1556
1557 ControlFlow::<()>::Continue(())
1558 });
1559 }
1560
1561 fn early_lookup_typo_candidate(
1563 &mut self,
1564 scope_set: ScopeSet<'ra>,
1565 parent_scope: &ParentScope<'ra>,
1566 ident: Ident,
1567 filter_fn: &impl Fn(Res) -> bool,
1568 ) -> Option<TypoSuggestion> {
1569 let mut suggestions = Vec::new();
1570 self.add_scope_set_candidates(
1571 &mut suggestions,
1572 scope_set,
1573 parent_scope,
1574 ident.span,
1575 filter_fn,
1576 );
1577
1578 suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
1580
1581 match find_best_match_for_name(
1582 &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1583 ident.name,
1584 None,
1585 ) {
1586 Some(found) if found != ident.name => {
1587 suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1588 }
1589 _ => None,
1590 }
1591 }
1592
1593 fn lookup_import_candidates_from_module<FilterFn>(
1594 &self,
1595 lookup_ident: Ident,
1596 namespace: Namespace,
1597 parent_scope: &ParentScope<'ra>,
1598 start_module: Module<'ra>,
1599 crate_path: ThinVec<ast::PathSegment>,
1600 filter_fn: FilterFn,
1601 ) -> Vec<ImportSuggestion>
1602 where
1603 FilterFn: Fn(Res) -> bool,
1604 {
1605 let mut candidates = Vec::new();
1606 let mut seen_modules = FxHashSet::default();
1607 let start_did = start_module.def_id();
1608 let mut worklist = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(start_module, ThinVec::<ast::PathSegment>::new(), true,
start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
true)]))vec![(
1609 start_module,
1610 ThinVec::<ast::PathSegment>::new(),
1611 true,
1612 start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1613 true,
1614 )];
1615 let mut worklist_via_import = ::alloc::vec::Vec::new()vec![];
1616
1617 while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1618 match worklist.pop() {
1619 None => worklist_via_import.pop(),
1620 Some(x) => Some(x),
1621 }
1622 {
1623 let in_module_is_extern = !in_module.def_id().is_local();
1624 in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
1625 if name_binding.is_assoc_item()
1627 && !this.features.import_trait_associated_functions()
1628 {
1629 return;
1630 }
1631
1632 if ident.name == kw::Underscore {
1633 return;
1634 }
1635
1636 let child_accessible =
1637 accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);
1638
1639 if in_module_is_extern && !child_accessible {
1641 return;
1642 }
1643
1644 let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1645
1646 if via_import && name_binding.is_possibly_imported_variant() {
1652 return;
1653 }
1654
1655 if let DeclKind::Import { source_decl, .. } = name_binding.kind
1657 && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1658 && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
1659 {
1660 return;
1661 }
1662
1663 let res = name_binding.res();
1664 let did = match res {
1665 Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
1666 _ => res.opt_def_id(),
1667 };
1668 let child_doc_visible = doc_visible
1669 && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));
1670
1671 if ident.name == lookup_ident.name
1675 && ns == namespace
1676 && in_module != parent_scope.module
1677 && ident.ctxt.is_root()
1678 && filter_fn(res)
1679 {
1680 let mut segms = if lookup_ident.span.at_least_rust_2018() {
1682 crate_path.clone()
1685 } else {
1686 ThinVec::new()
1687 };
1688 segms.append(&mut path_segments.clone());
1689
1690 segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1691 let path = Path { span: name_binding.span, segments: segms };
1692
1693 if child_accessible
1694 && let Some(idx) = candidates
1696 .iter()
1697 .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1698 {
1699 candidates.remove(idx);
1700 }
1701
1702 let is_stable = if is_stable
1703 && let Some(did) = did
1704 && this.is_stable(did, path.span)
1705 {
1706 true
1707 } else {
1708 false
1709 };
1710
1711 if is_stable
1716 && let Some(idx) = candidates
1717 .iter()
1718 .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1719 {
1720 candidates.remove(idx);
1721 }
1722
1723 if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1724 let note = if let Some(did) = did {
1727 let requires_note = !did.is_local()
1728 && {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(did, &this.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDiagnosticItem(sym::TryInto
| sym::TryFrom | sym::FromIterator)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(
1729 this.tcx,
1730 did,
1731 RustcDiagnosticItem(
1732 sym::TryInto | sym::TryFrom | sym::FromIterator
1733 )
1734 );
1735 requires_note.then(|| {
1736 ::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!(
1737 "'{}' is included in the prelude starting in Edition 2021",
1738 path_names_to_string(&path)
1739 )
1740 })
1741 } else {
1742 None
1743 };
1744
1745 candidates.push(ImportSuggestion {
1746 did,
1747 descr: res.descr(),
1748 path,
1749 accessible: child_accessible,
1750 doc_visible: child_doc_visible,
1751 note,
1752 via_import,
1753 is_stable,
1754 });
1755 }
1756 }
1757
1758 if let Some(def_id) = name_binding.res().module_like_def_id() {
1760 let mut path_segments = path_segments.clone();
1762 path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1763
1764 let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
1765 && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
1766 && import.parent_scope.expansion == parent_scope.expansion
1767 {
1768 true
1769 } else {
1770 false
1771 };
1772
1773 let is_extern_crate_that_also_appears_in_prelude =
1774 name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
1775
1776 if !is_extern_crate_that_also_appears_in_prelude || alias_import {
1777 if seen_modules.insert(def_id) {
1779 if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1780 (
1781 this.expect_module(def_id),
1782 path_segments,
1783 child_accessible,
1784 child_doc_visible,
1785 is_stable && this.is_stable(def_id, name_binding.span),
1786 ),
1787 );
1788 }
1789 }
1790 }
1791 })
1792 }
1793
1794 candidates
1795 }
1796
1797 fn is_stable(&self, did: DefId, span: Span) -> bool {
1798 if did.is_local() {
1799 return true;
1800 }
1801
1802 match self.tcx.lookup_stability(did) {
1803 Some(Stability {
1804 level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
1805 }) => {
1806 if span.allows_unstable(feature) {
1807 true
1808 } else if self.features.enabled(feature) {
1809 true
1810 } else if let Some(implied_by) = implied_by
1811 && self.features.enabled(implied_by)
1812 {
1813 true
1814 } else {
1815 false
1816 }
1817 }
1818 Some(_) => true,
1819 None => false,
1820 }
1821 }
1822
1823 pub(crate) fn lookup_import_candidates<FilterFn>(
1831 &mut self,
1832 lookup_ident: Ident,
1833 namespace: Namespace,
1834 parent_scope: &ParentScope<'ra>,
1835 filter_fn: FilterFn,
1836 ) -> Vec<ImportSuggestion>
1837 where
1838 FilterFn: Fn(Res) -> bool,
1839 {
1840 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))];
1841 let mut suggestions = self.lookup_import_candidates_from_module(
1842 lookup_ident,
1843 namespace,
1844 parent_scope,
1845 self.graph_root.to_module(),
1846 crate_path,
1847 &filter_fn,
1848 );
1849
1850 if lookup_ident.span.at_least_rust_2018() {
1851 for (ident, entry) in &self.extern_prelude {
1852 if entry.span().from_expansion() {
1853 continue;
1859 }
1860 let Some(crate_id) =
1861 self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
1862 else {
1863 continue;
1864 };
1865
1866 let crate_def_id = crate_id.as_def_id();
1867 let crate_root = self.expect_module(crate_def_id);
1868
1869 let needs_disambiguation =
1873 self.resolutions(parent_scope.module).borrow().iter().any(
1874 |(key, name_resolution)| {
1875 if key.ns == TypeNS
1876 && key.ident == *ident
1877 && let Some(decl) = name_resolution.borrow().best_decl()
1878 {
1879 match decl.res() {
1880 Res::Def(_, def_id) => def_id != crate_def_id,
1883 Res::PrimTy(_) => true,
1884 _ => false,
1885 }
1886 } else {
1887 false
1888 }
1889 },
1890 );
1891 let mut crate_path = ThinVec::new();
1892 if needs_disambiguation {
1893 crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
1894 }
1895 crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
1896
1897 suggestions.extend(self.lookup_import_candidates_from_module(
1898 lookup_ident,
1899 namespace,
1900 parent_scope,
1901 crate_root,
1902 crate_path,
1903 &filter_fn,
1904 ));
1905 }
1906 }
1907
1908 suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
1909 suggestions
1910 }
1911
1912 pub(crate) fn unresolved_macro_suggestions(
1913 &mut self,
1914 err: &mut Diag<'_>,
1915 macro_kind: MacroKind,
1916 parent_scope: &ParentScope<'ra>,
1917 ident: Ident,
1918 krate: &Crate,
1919 sugg_span: Option<Span>,
1920 ) {
1921 self.register_macros_for_all_crates();
1924
1925 let is_expected =
1926 &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
1927 let suggestion = self.early_lookup_typo_candidate(
1928 ScopeSet::Macro(macro_kind),
1929 parent_scope,
1930 ident,
1931 is_expected,
1932 );
1933 if !self.add_typo_suggestion(err, suggestion, ident.span) {
1934 self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
1935 }
1936
1937 let import_suggestions =
1938 self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1939 let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {
1940 DUMMY_NODE_ID => (None, FoundUse::No),
1941 node_id => UsePlacementFinder::check(krate, node_id),
1942 };
1943 show_candidates(
1944 self.tcx,
1945 err,
1946 span,
1947 &import_suggestions,
1948 Instead::No,
1949 found_use,
1950 DiagMode::Normal,
1951 ::alloc::vec::Vec::new()vec![],
1952 "",
1953 );
1954
1955 if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
1956 let label_span = ident.span.shrink_to_hi();
1957 let mut spans = MultiSpan::from_span(label_span);
1958 spans.push_span_label(label_span, "put a macro name here");
1959 err.subdiagnostic(MaybeMissingMacroRulesName { spans });
1960 return;
1961 }
1962
1963 if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1964 err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
1965 return;
1966 }
1967
1968 let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
1969 if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
1970 });
1971
1972 if let Some((def_id, unused_ident)) = unused_macro {
1973 let scope = self.local_macro_def_scopes[&def_id];
1974 let parent_nearest = parent_scope.module.nearest_parent_mod();
1975 let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();
1976 if !unused_macro_kinds.contains(macro_kind.into()) {
1977 match macro_kind {
1978 MacroKind::Bang => {
1979 err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
1980 }
1981 MacroKind::Attr => {
1982 err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
1983 }
1984 MacroKind::Derive => {
1985 err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
1986 }
1987 }
1988 return;
1989 }
1990 if Some(parent_nearest.to_def_id()) == scope.opt_def_id() {
1991 err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1992 err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1993 return;
1994 }
1995 }
1996
1997 if ident.name == kw::Default
1998 && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind
1999 {
2000 let span = self.def_span(def_id);
2001 let source_map = self.tcx.sess.source_map();
2002 let head_span = source_map.guess_head_span(span);
2003 err.subdiagnostic(ConsiderAddingADerive {
2004 span: head_span.shrink_to_lo(),
2005 suggestion: "#[derive(Default)]\n".to_string(),
2006 });
2007 }
2008 for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
2009 let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2010 ident,
2011 ScopeSet::All(ns),
2012 parent_scope,
2013 None,
2014 None,
2015 None,
2016 ) else {
2017 continue;
2018 };
2019
2020 let desc = match binding.res() {
2021 Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
2022 "a function-like macro".to_string()
2023 }
2024 Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
2025 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
})format!("an attribute: `#[{ident}]`")
2026 }
2027 Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
2028 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
ident))
})format!("a derive macro: `#[derive({ident})]`")
2029 }
2030 Res::Def(DefKind::Macro(kinds), _) => {
2031 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
kinds.descr()))
})format!("{} {}", kinds.article(), kinds.descr())
2032 }
2033 Res::ToolMod | Res::OpenMod(..) => {
2034 continue;
2036 }
2037 Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
2038 "only a trait, without a derive macro".to_string()
2039 }
2040 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!(
2041 "{} {}, not {} {}",
2042 res.article(),
2043 res.descr(),
2044 macro_kind.article(),
2045 macro_kind.descr_expected(),
2046 ),
2047 };
2048 if let crate::DeclKind::Import { import, .. } = binding.kind
2049 && !import.span.is_dummy()
2050 {
2051 let note = diagnostics::IdentImporterHereButItIsDesc {
2052 span: import.span,
2053 imported_ident: ident,
2054 imported_ident_desc: &desc,
2055 };
2056 err.subdiagnostic(note);
2057 self.record_use(ident, binding, Used::Other);
2060 return;
2061 }
2062 let note = diagnostics::IdentInScopeButItIsDesc {
2063 imported_ident: ident,
2064 imported_ident_desc: &desc,
2065 };
2066 err.subdiagnostic(note);
2067 return;
2068 }
2069
2070 if self.macro_names.contains(&IdentKey::new(ident)) {
2071 err.subdiagnostic(AddedMacroUse);
2072 return;
2073 }
2074 }
2075
2076 fn detect_derive_attribute(
2079 &self,
2080 err: &mut Diag<'_>,
2081 ident: Ident,
2082 parent_scope: &ParentScope<'ra>,
2083 sugg_span: Option<Span>,
2084 ) {
2085 let mut derives = ::alloc::vec::Vec::new()vec![];
2090 let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
2091 #[allow(rustc::potential_query_instability)]
2093 for (def_id, ext) in self
2094 .local_macro_map
2095 .iter()
2096 .map(|(local_id, ext)| (local_id.to_def_id(), ext))
2097 .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
2098 {
2099 for helper_attr in &ext.helper_attrs {
2100 let item_name = self.tcx.item_name(def_id);
2101 all_attrs.entry(*helper_attr).or_default().push(item_name);
2102 if helper_attr == &ident.name {
2103 derives.push(item_name);
2104 }
2105 }
2106 }
2107 let kind = MacroKind::Derive.descr();
2108 if !derives.is_empty() {
2109 let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
2111 derives.sort();
2112 derives.dedup();
2113 let msg = match &derives[..] {
2114 [derive] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", derive))
})format!(" `{derive}`"),
2115 [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!(
2116 "s {} and `{last}`",
2117 start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
2118 ),
2119 [] => {
::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!?"),
2120 };
2121 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!(
2122 "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
2123 missing a `derive` attribute",
2124 ident.name,
2125 );
2126 let sugg_span =
2127 if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind {
2128 let span = self.def_span(id);
2129 if span.from_expansion() {
2130 None
2131 } else {
2132 Some(span.shrink_to_lo())
2134 }
2135 } else {
2136 sugg_span
2138 };
2139 match sugg_span {
2140 Some(span) => {
2141 err.span_suggestion_verbose(
2142 span,
2143 msg,
2144 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#[derive({0})]\n",
derives.join(", ")))
})format!("#[derive({})]\n", derives.join(", ")),
2145 Applicability::MaybeIncorrect,
2146 );
2147 }
2148 None => {
2149 err.note(msg);
2150 }
2151 }
2152 } else {
2153 let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
2155 if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
2156 && let Some(macros) = all_attrs.get(&best_match)
2157 {
2158 let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
2159 macros.sort();
2160 macros.dedup();
2161 let msg = match ¯os[..] {
2162 [] => return,
2163 [name] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}` accepts", name))
})format!(" `{name}` accepts"),
2164 [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!(
2165 "s {} and `{end}` accept",
2166 start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
2167 ),
2168 };
2169 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");
2170 err.span_suggestion_verbose(
2171 ident.span,
2172 msg,
2173 best_match,
2174 Applicability::MaybeIncorrect,
2175 );
2176 }
2177 }
2178 }
2179
2180 pub(crate) fn add_typo_suggestion(
2181 &self,
2182 err: &mut Diag<'_>,
2183 suggestion: Option<TypoSuggestion>,
2184 span: Span,
2185 ) -> bool {
2186 let suggestion = match suggestion {
2187 None => return false,
2188 Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
2190 Some(suggestion) => suggestion,
2191 };
2192
2193 let mut did_label_def_span = false;
2194
2195 if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
2196 if span.overlaps(def_span) {
2197 return false;
2216 }
2217 let span = self.tcx.sess.source_map().guess_head_span(def_span);
2218 let candidate_descr = suggestion.res.descr();
2219 let candidate = suggestion.candidate;
2220 let label = match suggestion.target {
2221 SuggestionTarget::SimilarlyNamed => {
2222 diagnostics::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
2223 }
2224 SuggestionTarget::SingleItem => {
2225 diagnostics::DefinedHere::SingleItem { span, candidate_descr, candidate }
2226 }
2227 };
2228 did_label_def_span = true;
2229 err.subdiagnostic(label);
2230 }
2231
2232 let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
2233 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2234 && let Some(span) = suggestion.span
2235 && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
2236 && snippet == candidate
2237 {
2238 let candidate = suggestion.candidate;
2239 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!(
2242 "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
2243 );
2244 if !did_label_def_span {
2245 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
})format!("`{candidate}` defined here"));
2246 }
2247 (span, msg, snippet)
2248 } else {
2249 let msg = match suggestion.target {
2250 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!(
2251 "{} {} with a similar name exists",
2252 suggestion.res.article(),
2253 suggestion.res.descr()
2254 ),
2255 SuggestionTarget::SingleItem => {
2256 ::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())
2257 }
2258 };
2259 (span, msg, suggestion.candidate.to_ident_string())
2260 };
2261 err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2262 true
2263 }
2264
2265 fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2266 let res = b.res();
2267 if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2268 let (built_in, from) = match scope {
2269 Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2270 Scope::ExternPreludeFlags
2271 if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2272 || #[allow(non_exhaustive_omitted_patterns)] match res {
Res::OpenMod(..) => true,
_ => false,
}matches!(res, Res::OpenMod(..)) =>
2273 {
2274 ("", " passed with `--extern`")
2275 }
2276 _ => {
2277 if #[allow(non_exhaustive_omitted_patterns)] match res {
Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
_ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2278 ("", "")
2280 } else {
2281 (" built-in", "")
2282 }
2283 }
2284 };
2285
2286 let a = if built_in.is_empty() { res.article() } else { "a" };
2287 ::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())
2288 } else {
2289 let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2290 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
introduced))
})format!("the {thing} {introduced} here", thing = res.descr())
2291 }
2292 }
2293
2294 fn ambiguity_diagnostic(
2295 &self,
2296 ambiguity_error: &AmbiguityError<'ra>,
2297 ) -> diagnostics::Ambiguity {
2298 let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2299 *ambiguity_error;
2300 let extern_prelude_ambiguity = || {
2301 #[allow(non_exhaustive_omitted_patterns)] match scope2 {
Scope::ExternPreludeFlags => true,
_ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2303 && self
2304 .extern_prelude
2305 .get(&IdentKey::new(ident))
2306 .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2307 };
2308 let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2309 (b2, b1, scope2, scope1, true)
2311 } else {
2312 (b1, b2, scope1, scope2, false)
2313 };
2314
2315 let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2316 let what = self.decl_description(b, ident, scope);
2317 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}");
2318
2319 let thing = b.res().descr();
2320 let mut help_msgs = Vec::new();
2321 if b.is_glob_import()
2322 && (kind == AmbiguityKind::GlobVsGlob
2323 || kind == AmbiguityKind::GlobVsExpanded
2324 || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2325 {
2326 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
ident))
})format!(
2327 "consider adding an explicit import of `{ident}` to disambiguate"
2328 ))
2329 }
2330 if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2331 {
2332 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"))
2333 }
2334
2335 if kind != AmbiguityKind::GlobVsGlob {
2336 if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2337 if module == self.graph_root.to_module() {
2338 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2339 "use `crate::{ident}` to refer to this {thing} unambiguously"
2340 ));
2341 } else if module.is_normal() {
2342 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2343 "use `self::{ident}` to refer to this {thing} unambiguously"
2344 ));
2345 }
2346 }
2347 }
2348
2349 (
2350 Spanned { node: note_msg, span: b.span },
2351 help_msgs
2352 .iter()
2353 .enumerate()
2354 .map(|(i, help_msg)| {
2355 let or = if i == 0 { "" } else { "or " };
2356 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
})format!("{or}{help_msg}")
2357 })
2358 .collect::<Vec<_>>(),
2359 )
2360 };
2361 let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2362 let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2363 let help = if kind == AmbiguityKind::GlobVsGlob
2364 && b1
2365 .parent_module
2366 .and_then(|m| m.opt_def_id())
2367 .map(|d| !d.is_local())
2368 .unwrap_or_default()
2369 {
2370 Some(&[
2371 "consider updating this dependency to resolve this error",
2372 "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2373 ] as &[_])
2374 } else {
2375 None
2376 };
2377
2378 let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2379 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} or {1}",
vis1.to_string(CRATE_DEF_ID, self.tcx),
vis2.to_string(CRATE_DEF_ID, self.tcx)))
})format!(
2380 "{} or {}",
2381 vis1.to_string(CRATE_DEF_ID, self.tcx),
2382 vis2.to_string(CRATE_DEF_ID, self.tcx)
2383 )
2384 });
2385
2386 diagnostics::Ambiguity {
2387 ident,
2388 help,
2389 ambig_vis,
2390 kind: kind.descr(),
2391 b1_note,
2392 b1_help_msgs,
2393 b2_note,
2394 b2_help_msgs,
2395 is_error: false,
2396 }
2397 }
2398
2399 fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2402 let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
2403 decl.kind
2404 else {
2405 return None;
2406 };
2407
2408 let def_id = self.tcx.parent(ctor_def_id);
2409 self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) }
2411
2412 fn module_path_names(&self, module: Module<'ra>) -> Option<Vec<Symbol>> {
2416 let mut path = Vec::new();
2417 let mut def_id = module.opt_def_id()?;
2418 while let Some(parent) = self.tcx.opt_parent(def_id) {
2419 if let Some(name) = self.tcx.opt_item_name(def_id) {
2420 path.push(name);
2421 }
2422 if parent.is_top_level_module() {
2423 break;
2424 }
2425 def_id = parent;
2426 }
2427 path.reverse();
2428 path.insert(0, kw::Crate);
2429 Some(path)
2430 }
2431
2432 fn shorten_candidate_path(
2433 &self,
2434 suggestion: &mut ImportSuggestion,
2435 current_module: Module<'ra>,
2436 ) {
2437 self.shorten_import_path(suggestion.did, &mut suggestion.path, current_module);
2438 }
2439
2440 fn shorten_import_path(
2444 &self,
2445 did: Option<DefId>,
2446 path: &mut Path,
2447 current_module: Module<'ra>,
2448 ) {
2449 const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;
2450
2451 if did.is_none_or(|did| !did.is_local()) {
2453 return;
2454 }
2455
2456 let Some(current_mod_path) = self.module_path_names(current_module) else {
2458 return;
2459 };
2460
2461 let candidate_names = {
2465 let filtered_segments: Vec<_> =
2466 path.segments.iter().filter(|segment| segment.ident.name != kw::PathRoot).collect();
2467
2468 let mut candidate_names: Vec<Symbol> =
2469 filtered_segments.iter().map(|segment| segment.ident.name).collect();
2470 if candidate_names.first() != Some(&kw::Crate) {
2471 candidate_names.insert(0, kw::Crate);
2472 }
2473 if candidate_names.len() < 2 {
2474 return;
2475 }
2476 candidate_names
2477 };
2478
2479 let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];
2481
2482 let common_prefix_length = current_mod_path
2484 .iter()
2485 .zip(candidate_mod_names.iter())
2486 .take_while(|(current, candidate)| current == candidate)
2487 .count();
2488
2489 if common_prefix_length == 0 {
2491 return;
2492 }
2493
2494 let super_count = current_mod_path.len() - common_prefix_length;
2495
2496 let at_crate_root = current_mod_path.len() == 1;
2499
2500 let mut new_segments = if super_count == 0 && at_crate_root {
2501 ThinVec::new()
2502 } else {
2503 let prefix_keyword = match super_count {
2504 0 => kw::SelfLower,
2505 1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
2506 _ => return, };
2508 {
let len = [()].len();
let mut vec = ::thin_vec::ThinVec::with_capacity(len);
vec.push(ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword)));
vec
}thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword),)]
2509 };
2510 for &name in &candidate_names[common_prefix_length..] {
2511 new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
2512 }
2513
2514 if new_segments.len() >= path.segments.len() {
2516 return;
2517 }
2518
2519 *path = Path { span: path.span, segments: new_segments };
2520 }
2521
2522 fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2523 let PrivacyError {
2524 ident,
2525 decl,
2526 outermost_res,
2527 parent_scope,
2528 single_nested,
2529 dedup_span,
2530 ref source,
2531 } = *privacy_error;
2532
2533 let res = decl.res();
2534 let ctor_fields_span = self.ctor_fields_span(decl);
2535 let plain_descr = res.descr().to_string();
2536 let nonimport_descr =
2537 if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2538 let import_descr = nonimport_descr.clone() + " import";
2539 let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2540
2541 let ident_descr = get_descr(decl);
2543 let mut err =
2544 self.dcx().create_err(diagnostics::IsPrivate { span: ident.span, ident_descr, ident });
2545
2546 self.mention_default_field_values(source, ident, &mut err);
2547
2548 let shown_candidates = if let Some((this_res, outer_ident)) = outermost_res {
2549 let mut import_suggestions = self.lookup_import_candidates(
2550 outer_ident,
2551 this_res.ns().unwrap_or(Namespace::TypeNS),
2552 &parent_scope,
2553 &|res: Res| res == this_res,
2554 );
2555 for suggestion in &mut import_suggestions {
2557 self.shorten_candidate_path(suggestion, parent_scope.module);
2558 }
2559 let point_to_def = !show_candidates(
2560 self.tcx,
2561 &mut err,
2562 Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2563 &import_suggestions,
2564 Instead::Yes,
2565 FoundUse::Yes,
2566 DiagMode::Import { append: single_nested, unresolved_import: false },
2567 ::alloc::vec::Vec::new()vec![],
2568 "",
2569 );
2570 if point_to_def && ident.span != outer_ident.span {
2572 let label = diagnostics::OuterIdentIsNotPubliclyReexported {
2573 span: outer_ident.span,
2574 outer_ident_descr: this_res.descr(),
2575 outer_ident,
2576 };
2577 err.subdiagnostic(label);
2578 }
2579 !point_to_def
2580 } else {
2581 false
2582 };
2583
2584 let mut non_exhaustive = None;
2585 if let Some(def_id) = res.opt_def_id()
2589 && !def_id.is_local()
2590 && let Some(attr_span) = {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NonExhaustive(span)) => {
break 'done Some(*span);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
2591 {
2592 non_exhaustive = Some(attr_span);
2593 } else if let Some(span) = ctor_fields_span {
2594 let label = diagnostics::ConstructorPrivateIfAnyFieldPrivate { span };
2595 err.subdiagnostic(label);
2596 if let Res::Def(_, d) = res
2597 && let Some(fields) = self.field_visibility_spans.get(&d)
2598 {
2599 let spans = fields.iter().map(|span| *span).collect();
2600 let sugg = diagnostics::ConsiderMakingTheFieldPublic {
2601 spans,
2602 number_of_fields: fields.len(),
2603 };
2604 err.subdiagnostic(sugg);
2605 }
2606 }
2607
2608 let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2609 if let Some(mut def_id) = res.opt_def_id() {
2610 let mut path = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[def_id]))vec![def_id];
2612 while let Some(parent) = self.tcx.opt_parent(def_id) {
2613 def_id = parent;
2614 if !def_id.is_top_level_module() {
2615 path.push(def_id);
2616 } else {
2617 break;
2618 }
2619 }
2620 let path_names: Option<Vec<Ident>> = path
2622 .iter()
2623 .rev()
2624 .map(|def_id| {
2625 self.tcx.opt_item_name(*def_id).map(|name| {
2626 Ident::with_dummy_span(if def_id.is_top_level_module() {
2627 kw::Crate
2628 } else {
2629 name
2630 })
2631 })
2632 })
2633 .collect();
2634 if let Some(&def_id) = path.get(0)
2635 && let Some(path) = path_names
2636 {
2637 if let Some(def_id) = def_id.as_local() {
2638 if self.effective_visibilities.is_directly_public(def_id) {
2639 sugg_paths.push((path, false));
2640 }
2641 } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2642 {
2643 sugg_paths.push((path, false));
2644 }
2645 }
2646 }
2647
2648 let first_binding = decl;
2650 let mut next_binding = Some(decl);
2651 let mut next_ident = ident;
2652 while let Some(binding) = next_binding {
2653 let name = next_ident;
2654 next_binding = match binding.kind {
2655 _ if res == Res::Err => None,
2656 DeclKind::Import { source_decl, import, .. } => match import.kind {
2657 _ if source_decl.span.is_dummy() => None,
2658 ImportKind::Single { source, .. } => {
2659 next_ident = source;
2660 Some(source_decl)
2661 }
2662 ImportKind::Glob { .. }
2663 | ImportKind::MacroUse { .. }
2664 | ImportKind::MacroExport => Some(source_decl),
2665 ImportKind::ExternCrate { .. } => None,
2666 },
2667 _ => None,
2668 };
2669
2670 match binding.kind {
2671 DeclKind::Import { source_decl, import, .. } => {
2672 let through_reexport = !#[allow(non_exhaustive_omitted_patterns)] match source_decl.kind {
DeclKind::Def(_) => true,
_ => false,
}matches!(source_decl.kind, DeclKind::Def(_));
2673 let uses_relative_path = import
2674 .module_path
2675 .first()
2676 .is_some_and(|seg| #[allow(non_exhaustive_omitted_patterns)] match seg.ident.name {
kw::SelfLower | kw::Super => true,
_ => false,
}matches!(seg.ident.name, kw::SelfLower | kw::Super));
2677 let res_def_id = res.opt_def_id();
2678 let path = if uses_relative_path {
2679 let module_path = if let Some(ModuleOrUniformRoot::Module(module)) =
2682 import.imported_module.get()
2683 && module.is_local()
2684 && let Some(module_path) = self.module_path_names(module)
2685 && let Some(mut def_id) = module.opt_def_id()
2686 && res_def_id.is_none_or(|def_id| {
2687 self.is_accessible_from(
2688 self.tcx.visibility(def_id),
2689 parent_scope.module,
2690 )
2691 }) {
2692 let mut visible_from_use_site = true;
2696 while let Some(parent) = self.tcx.opt_parent(def_id) {
2697 if !self.is_accessible_from(
2698 self.tcx.visibility(def_id),
2699 parent_scope.module,
2700 ) {
2701 visible_from_use_site = false;
2702 break;
2703 }
2704 if parent.is_top_level_module() {
2705 break;
2706 }
2707 def_id = parent;
2708 }
2709 if visible_from_use_site { Some(module_path) } else { None }
2710 } else {
2711 None
2712 };
2713
2714 module_path.map(|module_path| {
2715 let mut path = Path {
2718 span: ident.span,
2719 segments: module_path
2720 .into_iter()
2721 .chain(std::iter::once(ident.name))
2722 .map(|name| {
2723 ast::PathSegment::from_ident(Ident::with_dummy_span(name))
2724 })
2725 .collect(),
2726 };
2727 self.shorten_import_path(res_def_id, &mut path, parent_scope.module);
2728 path.segments.iter().map(|seg| seg.ident).collect()
2729 })
2730 } else {
2731 Some(
2734 import
2735 .module_path
2736 .iter()
2737 .filter(|seg| seg.ident.name != kw::PathRoot)
2738 .map(|seg| seg.ident.clone())
2739 .chain(std::iter::once(ident))
2740 .collect::<Vec<_>>(),
2741 )
2742 };
2743 if let Some(path) = path {
2744 sugg_paths.push((path, through_reexport));
2745 }
2746 }
2747 DeclKind::Def(_) => {}
2748 }
2749 let first = binding == first_binding;
2750 let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2751 let mut note_span = MultiSpan::from_span(def_span);
2752 if !first && binding.vis().is_public() {
2753 let desc = match binding.kind {
2754 DeclKind::Import { .. } => "re-export",
2755 _ => "directly",
2756 };
2757 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}"));
2758 }
2759 if next_binding.is_none()
2762 && let Some(span) = non_exhaustive
2763 {
2764 note_span.push_span_label(
2765 span,
2766 "cannot be constructed because it is `#[non_exhaustive]`",
2767 );
2768 }
2769 let note = diagnostics::NoteAndRefersToTheItemDefinedHere {
2770 span: note_span,
2771 binding_descr: get_descr(binding),
2772 binding_name: name,
2773 first,
2774 dots: next_binding.is_some(),
2775 };
2776 err.subdiagnostic(note);
2777 }
2778 let can_replace_use = !shown_candidates
2786 && !single_nested
2787 && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
2788 if can_replace_use {
2789 sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2792 for (sugg, reexport) in sugg_paths {
2793 if sugg.len() <= 1 {
2794 continue;
2797 }
2798 let path = join_path_idents(sugg);
2799 let sugg = if reexport {
2800 diagnostics::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2801 } else {
2802 diagnostics::ImportIdent::Directly { span: dedup_span, ident, path }
2803 };
2804 err.subdiagnostic(sugg);
2805 break;
2806 }
2807 }
2808
2809 err.emit();
2810 }
2811
2812 fn mention_default_field_values(
2832 &self,
2833 source: &Option<ast::Expr>,
2834 ident: Ident,
2835 err: &mut Diag<'_>,
2836 ) {
2837 let Some(expr) = source else { return };
2838 let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2839 let Some(segment) = struct_expr.path.segments.last() else { return };
2842 let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2843 let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2844 return;
2845 };
2846 let Some(default_fields) = self.field_defaults(def_id) else { return };
2847 if struct_expr.fields.is_empty() {
2848 return;
2849 }
2850 let last_span = struct_expr.fields.iter().last().unwrap().span;
2851 let mut iter = struct_expr.fields.iter().peekable();
2852 let mut prev: Option<Span> = None;
2853 while let Some(field) = iter.next() {
2854 if field.expr.span.overlaps(ident.span) {
2855 err.span_label(field.ident.span, "while setting this field");
2856 if default_fields.contains(&field.ident.name) {
2857 let sugg = if last_span == field.span {
2858 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(field.span, "..".to_string())]))vec![(field.span, "..".to_string())]
2859 } else {
2860 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(match (prev, iter.peek()) {
(_, Some(next)) => field.span.with_hi(next.span.lo()),
(Some(prev), _) => field.span.with_lo(prev.hi()),
(None, None) => field.span,
}, String::new()),
(last_span.shrink_to_hi(), ", ..".to_string())]))vec![
2861 (
2862 match (prev, iter.peek()) {
2864 (_, Some(next)) => field.span.with_hi(next.span.lo()),
2865 (Some(prev), _) => field.span.with_lo(prev.hi()),
2866 (None, None) => field.span,
2867 },
2868 String::new(),
2869 ),
2870 (last_span.shrink_to_hi(), ", ..".to_string()),
2871 ]
2872 };
2873 err.multipart_suggestion(
2874 ::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!(
2875 "the type `{ident}` of field `{}` is private, but you can construct \
2876 the default value defined for it in `{}` using `..` in the struct \
2877 initializer expression",
2878 field.ident,
2879 self.tcx.item_name(def_id),
2880 ),
2881 sugg,
2882 Applicability::MachineApplicable,
2883 );
2884 break;
2885 }
2886 }
2887 prev = Some(field.span);
2888 }
2889 }
2890
2891 pub(crate) fn find_similarly_named_module_or_crate(
2892 &self,
2893 ident: Symbol,
2894 current_module: Module<'ra>,
2895 ) -> Option<Symbol> {
2896 let mut candidates = self
2897 .extern_prelude
2898 .keys()
2899 .map(|ident| ident.name)
2900 .chain(
2901 self.local_module_map
2902 .iter()
2903 .filter(|(_, module)| {
2904 let module = module.to_module();
2905 current_module.is_ancestor_of(module) && current_module != module
2906 })
2907 .flat_map(|(_, module)| module.name()),
2908 )
2909 .chain(
2910 self.extern_module_map
2911 .borrow()
2912 .iter()
2913 .filter(|(_, module)| {
2914 let module = module.to_module();
2915 current_module.is_ancestor_of(module) && current_module != module
2916 })
2917 .flat_map(|(_, module)| module.name()),
2918 )
2919 .filter(|c| !c.to_string().is_empty())
2920 .collect::<Vec<_>>();
2921 candidates.sort();
2922 candidates.dedup();
2923 find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2924 }
2925
2926 pub(crate) fn report_path_resolution_error(
2927 &mut self,
2928 path: &[Segment],
2929 opt_ns: Option<Namespace>, parent_scope: &ParentScope<'ra>,
2931 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2932 ignore_decl: Option<Decl<'ra>>,
2933 ignore_import: Option<Import<'ra>>,
2934 module: Option<ModuleOrUniformRoot<'ra>>,
2935 failed_segment_idx: usize,
2936 ident: Ident,
2937 diag_metadata: Option<&DiagMetadata<'_>>,
2938 ) -> (String, String, Option<Suggestion>) {
2939 let is_last = failed_segment_idx == path.len() - 1;
2940 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2941 let module_def_id = match module {
2942 Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
2943 _ => None,
2944 };
2945 let scope = match &path[..failed_segment_idx] {
2946 [.., prev] => {
2947 if prev.ident.name == kw::PathRoot {
2948 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the crate root"))
})format!("the crate root")
2949 } else {
2950 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", prev.ident))
})format!("`{}`", prev.ident)
2951 }
2952 }
2953 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this scope"))
})format!("this scope"),
2954 };
2955 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
scope))
})format!("cannot find `{ident}` in {scope}");
2956
2957 if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
2958 let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Mod, _) => true,
_ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2959 let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2960 candidates
2961 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2962 if let Some(candidate) = candidates.get(0) {
2963 let path = {
2964 let len = candidate.path.segments.len();
2966 let start_index = (0..=failed_segment_idx.min(len - 1))
2967 .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2968 .unwrap_or_default();
2969 let segments =
2970 (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2971 Path { segments, span: Span::default() }
2972 };
2973 (
2974 message,
2975 String::from("unresolved import"),
2976 Some((
2977 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, pprust::path_to_string(&path))]))vec![(ident.span, pprust::path_to_string(&path))],
2978 String::from("a similar path exists"),
2979 Applicability::MaybeIncorrect,
2980 )),
2981 )
2982 } else if ident.name == sym::core {
2983 (
2984 message,
2985 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
ident))
})format!("you might be missing crate `{ident}`"),
2986 Some((
2987 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, "std".to_string())]))vec![(ident.span, "std".to_string())],
2988 "try using `std` instead of `core`".to_string(),
2989 Applicability::MaybeIncorrect,
2990 )),
2991 )
2992 } else if ident.name == kw::Underscore {
2993 (
2994 "invalid crate or module name `_`".to_string(),
2995 "`_` is not a valid crate or module name".to_string(),
2996 None,
2997 )
2998 } else if self.tcx.sess.is_rust_2015() {
2999 (
3000 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}"),
3001 ::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}`"),
3002 Some((
3003 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(self.current_crate_outer_attr_insert_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern crate {0};\n",
ident))
}))]))vec![(
3004 self.current_crate_outer_attr_insert_span,
3005 format!("extern crate {ident};\n"),
3006 )],
3007 if was_invoked_from_cargo() {
3008 ::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!(
3009 "if you wanted to use a crate named `{ident}`, use `cargo add \
3010 {ident}` to add it to your `Cargo.toml` and import it in your \
3011 code",
3012 )
3013 } else {
3014 ::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!(
3015 "you might be missing a crate named `{ident}`, add it to your \
3016 project and import it in your code",
3017 )
3018 },
3019 Applicability::MaybeIncorrect,
3020 )),
3021 )
3022 } else {
3023 (message, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("could not find `{0}` in the crate root",
ident))
})format!("could not find `{ident}` in the crate root"), None)
3024 }
3025 } else if failed_segment_idx > 0 {
3026 let parent = path[failed_segment_idx - 1].ident.name;
3027 let parent = match parent {
3028 kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
3031 "the list of imported crates".to_owned()
3032 }
3033 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
3034 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", parent))
})format!("`{parent}`"),
3035 };
3036
3037 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}");
3038 if ns == TypeNS || ns == ValueNS {
3039 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
3040 let binding = if let Some(module) = module {
3041 self.cm()
3042 .resolve_ident_in_module(
3043 module,
3044 ident,
3045 ns_to_try,
3046 parent_scope,
3047 None,
3048 ignore_decl,
3049 ignore_import,
3050 )
3051 .ok()
3052 } else if let Some(ribs) = ribs
3053 && let Some(TypeNS | ValueNS) = opt_ns
3054 {
3055 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3056 match self.resolve_ident_in_lexical_scope(
3057 ident,
3058 ns_to_try,
3059 parent_scope,
3060 None,
3061 &ribs[ns_to_try],
3062 ignore_decl,
3063 diag_metadata,
3064 ) {
3065 Some(LateDecl::Decl(binding)) => Some(binding),
3067 _ => None,
3068 }
3069 } else {
3070 self.cm()
3071 .resolve_ident_in_scope_set(
3072 ident,
3073 ScopeSet::All(ns_to_try),
3074 parent_scope,
3075 None,
3076 ignore_decl,
3077 ignore_import,
3078 )
3079 .ok()
3080 };
3081 if let Some(binding) = binding {
3082 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!(
3083 "expected {}, found {} `{ident}` in {parent}",
3084 ns.descr(),
3085 binding.res().descr(),
3086 );
3087 };
3088 }
3089 (message, msg, None)
3090 } else if ident.name == kw::SelfUpper {
3091 if opt_ns.is_none() {
3095 (message, "`Self` cannot be used in imports".to_string(), None)
3096 } else {
3097 (
3098 message,
3099 "`Self` is only available in impls, traits, and type definitions".to_string(),
3100 None,
3101 )
3102 }
3103 } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
3104 let binding = if let Some(ribs) = ribs {
3106 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3107 self.resolve_ident_in_lexical_scope(
3108 ident,
3109 ValueNS,
3110 parent_scope,
3111 None,
3112 &ribs[ValueNS],
3113 ignore_decl,
3114 diag_metadata,
3115 )
3116 } else {
3117 None
3118 };
3119 let match_span = match binding {
3120 Some(LateDecl::RibDef(Res::Local(id))) => {
3129 Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
3130 }
3131 Some(LateDecl::Decl(name_binding)) => Some((
3143 name_binding.span,
3144 name_binding.res().article(),
3145 name_binding.res().descr(),
3146 )),
3147 _ => None,
3148 };
3149
3150 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find type `{0}` in {1}",
ident, scope))
})format!("cannot find type `{ident}` in {scope}");
3151 let label = if let Some((span, article, descr)) = match_span {
3152 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{1}` is declared as {2} {3} at `{0}`, not a type",
self.tcx.sess.source_map().span_to_short_string(span,
RemapPathScopeComponents::DIAGNOSTICS), ident, article,
descr))
})format!(
3153 "`{ident}` is declared as {article} {descr} at `{}`, not a type",
3154 self.tcx
3155 .sess
3156 .source_map()
3157 .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
3158 )
3159 } else {
3160 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
ident))
})format!("use of undeclared type `{ident}`")
3161 };
3162 (message, label, None)
3163 } else {
3164 let mut suggestion = None;
3165 if ident.name == sym::alloc {
3166 suggestion = Some((
3167 ::alloc::vec::Vec::new()vec![],
3168 String::from("add `extern crate alloc` to use the `alloc` crate"),
3169 Applicability::MaybeIncorrect,
3170 ))
3171 }
3172
3173 suggestion = suggestion.or_else(|| {
3174 self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
3175 |sugg| {
3176 (
3177 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(ident.span, sugg.to_string())]))vec![(ident.span, sugg.to_string())],
3178 String::from("there is a crate or module with a similar name"),
3179 Applicability::MaybeIncorrect,
3180 )
3181 },
3182 )
3183 });
3184 if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
3185 ident,
3186 ScopeSet::All(ValueNS),
3187 parent_scope,
3188 None,
3189 ignore_decl,
3190 ignore_import,
3191 ) {
3192 let descr = binding.res().descr();
3193 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}");
3194 (message, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} `{1}` is not a crate or module",
descr, ident))
})format!("{descr} `{ident}` is not a crate or module"), suggestion)
3195 } else {
3196 let suggestion = if suggestion.is_some() {
3197 suggestion
3198 } else if let Some(m) = self.undeclared_module_exists(ident) {
3199 self.undeclared_module_suggest_declare(ident, m)
3200 } else if was_invoked_from_cargo() {
3201 Some((
3202 ::alloc::vec::Vec::new()vec![],
3203 ::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!(
3204 "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
3205 to add it to your `Cargo.toml`",
3206 ),
3207 Applicability::MaybeIncorrect,
3208 ))
3209 } else {
3210 Some((
3211 ::alloc::vec::Vec::new()vec![],
3212 ::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}`",),
3213 Applicability::MaybeIncorrect,
3214 ))
3215 };
3216 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find module or crate `{0}` in {1}",
ident, scope))
})format!("cannot find module or crate `{ident}` in {scope}");
3217 (
3218 message,
3219 ::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}`"),
3220 suggestion,
3221 )
3222 }
3223 }
3224 }
3225
3226 fn undeclared_module_suggest_declare(
3227 &self,
3228 ident: Ident,
3229 path: std::path::PathBuf,
3230 ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
3231 Some((
3232 ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(self.current_crate_outer_attr_insert_span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("mod {0};\n", ident))
}))]))vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
3233 ::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!(
3234 "to make use of source file {}, use `mod {ident}` \
3235 in this file to declare the module",
3236 path.display()
3237 ),
3238 Applicability::MaybeIncorrect,
3239 ))
3240 }
3241
3242 fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
3243 let map = self.tcx.sess.source_map();
3244
3245 let src = map.span_to_filename(ident.span).into_local_path()?;
3246 let i = ident.as_str();
3247 let dir = src.parent()?;
3249 let src = src.file_stem()?.to_str()?;
3250 for file in [
3251 dir.join(i).with_extension("rs"),
3253 dir.join(i).join("mod.rs"),
3255 ] {
3256 if file.exists() {
3257 return Some(file);
3258 }
3259 }
3260 if !#[allow(non_exhaustive_omitted_patterns)] match src {
"main" | "lib" | "mod" => true,
_ => false,
}matches!(src, "main" | "lib" | "mod") {
3261 for file in [
3262 dir.join(src).join(i).with_extension("rs"),
3264 dir.join(src).join(i).join("mod.rs"),
3266 ] {
3267 if file.exists() {
3268 return Some(file);
3269 }
3270 }
3271 }
3272 None
3273 }
3274
3275 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_path_suggestion",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3276u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
match path[..] {
[first, second, ..] if
first.ident.name == kw::PathRoot &&
!second.ident.is_path_segment_keyword() => {}
[first, ..] if
first.ident.span.at_least_rust_2018() &&
!first.ident.is_path_segment_keyword() => {
path.insert(0, Segment::from_ident(Ident::dummy()));
}
_ => return None,
}
self.make_missing_self_suggestion(path.clone(),
parent_scope).or_else(||
self.make_missing_crate_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_missing_super_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_external_crate_suggestion(path, parent_scope))
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3277 pub(crate) fn make_path_suggestion(
3278 &mut self,
3279 mut path: Vec<Segment>,
3280 parent_scope: &ParentScope<'ra>,
3281 ) -> Option<(Vec<Segment>, Option<String>)> {
3282 match path[..] {
3283 [first, second, ..]
3286 if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
3287 [first, ..]
3289 if first.ident.span.at_least_rust_2018()
3290 && !first.ident.is_path_segment_keyword() =>
3291 {
3292 path.insert(0, Segment::from_ident(Ident::dummy()));
3294 }
3295 _ => return None,
3296 }
3297
3298 self.make_missing_self_suggestion(path.clone(), parent_scope)
3299 .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
3300 .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
3301 .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
3302 }
3303
3304 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_self_suggestion",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3311u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::SelfLower;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics/impls.rs:3320",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3320u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("result")
}> =
::tracing::__macro_support::FieldName::new("result");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3312 fn make_missing_self_suggestion(
3313 &mut self,
3314 mut path: Vec<Segment>,
3315 parent_scope: &ParentScope<'ra>,
3316 ) -> Option<(Vec<Segment>, Option<String>)> {
3317 path[0].ident.name = kw::SelfLower;
3319 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3320 debug!(?path, ?result);
3321 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3322 }
3323
3324 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_crate_suggestion",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3331u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Crate;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics/impls.rs:3340",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3340u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("result")
}> =
::tracing::__macro_support::FieldName::new("result");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path,
Some("`use` statements changed in Rust 2018; read more at \
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
clarity.html>".to_string())))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3332 fn make_missing_crate_suggestion(
3333 &mut self,
3334 mut path: Vec<Segment>,
3335 parent_scope: &ParentScope<'ra>,
3336 ) -> Option<(Vec<Segment>, Option<String>)> {
3337 path[0].ident.name = kw::Crate;
3339 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3340 debug!(?path, ?result);
3341 if let PathResult::Module(..) = result {
3342 Some((
3343 path,
3344 Some(
3345 "`use` statements changed in Rust 2018; read more at \
3346 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
3347 clarity.html>"
3348 .to_string(),
3349 ),
3350 ))
3351 } else {
3352 None
3353 }
3354 }
3355
3356 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_super_suggestion",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3363u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Super;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics/impls.rs:3372",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3372u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("result")
}> =
::tracing::__macro_support::FieldName::new("result");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3364 fn make_missing_super_suggestion(
3365 &mut self,
3366 mut path: Vec<Segment>,
3367 parent_scope: &ParentScope<'ra>,
3368 ) -> Option<(Vec<Segment>, Option<String>)> {
3369 path[0].ident.name = kw::Super;
3371 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3372 debug!(?path, ?result);
3373 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3374 }
3375
3376 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_external_crate_suggestion",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3386u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
if path[1].ident.span.is_rust_2015() { return None; }
let mut extern_crate_names =
self.extern_prelude.keys().map(|ident|
ident.name).collect::<Vec<_>>();
extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
for name in extern_crate_names.into_iter() {
path[0].ident.name = name;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope,
None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/diagnostics/impls.rs:3407",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3407u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("name")
}> =
::tracing::__macro_support::FieldName::new("name");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("result")
}> =
::tracing::__macro_support::FieldName::new("result");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&name)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&result)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
return Some((path, None));
}
}
None
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3387 fn make_external_crate_suggestion(
3388 &mut self,
3389 mut path: Vec<Segment>,
3390 parent_scope: &ParentScope<'ra>,
3391 ) -> Option<(Vec<Segment>, Option<String>)> {
3392 if path[1].ident.span.is_rust_2015() {
3393 return None;
3394 }
3395
3396 let mut extern_crate_names =
3400 self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
3401 extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
3402
3403 for name in extern_crate_names.into_iter() {
3404 path[0].ident.name = name;
3406 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3407 debug!(?path, ?name, ?result);
3408 if let PathResult::Module(..) = result {
3409 return Some((path, None));
3410 }
3411 }
3412
3413 None
3414 }
3415
3416 pub(crate) fn check_for_module_export_macro(
3429 &mut self,
3430 import: Import<'ra>,
3431 module: ModuleOrUniformRoot<'ra>,
3432 ident: Ident,
3433 ) -> Option<(Option<Suggestion>, Option<String>)> {
3434 let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3435 return None;
3436 };
3437
3438 while let Some(parent) = crate_module.parent {
3439 crate_module = parent;
3440 }
3441
3442 if module == ModuleOrUniformRoot::Module(crate_module) {
3443 return None;
3445 }
3446
3447 let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3448 let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3449 let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3450 return None;
3451 };
3452 if !kinds.contains(MacroKinds::BANG) {
3453 return None;
3454 }
3455 let module_name = crate_module.name().unwrap_or(kw::Crate);
3456 let import_snippet = match import.kind {
3457 ImportKind::Single { source, target, .. } if source != target => {
3458 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}", source, target))
})format!("{source} as {target}")
3459 }
3460 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}"),
3461 };
3462
3463 let mut corrections: Vec<(Span, String)> = Vec::new();
3464 if !import.is_nested() {
3465 corrections.push((import.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}", module_name,
import_snippet))
})format!("{module_name}::{import_snippet}")));
3468 } else {
3469 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3473 self.tcx.sess,
3474 import.span,
3475 import.use_span,
3476 );
3477 {
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/impls.rs:3477",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3477u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("found_closing_brace")
}> =
::tracing::__macro_support::FieldName::new("found_closing_brace");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("binding_span")
}> =
::tracing::__macro_support::FieldName::new("binding_span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&found_closing_brace
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&binding_span)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(found_closing_brace, ?binding_span);
3478
3479 let mut removal_span = binding_span;
3480
3481 if found_closing_brace
3489 && let Some(previous_span) =
3490 extend_span_to_previous_binding(self.tcx.sess, binding_span)
3491 {
3492 {
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/impls.rs:3492",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3492u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("previous_span")
}> =
::tracing::__macro_support::FieldName::new("previous_span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&previous_span)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?previous_span);
3493 removal_span = removal_span.with_lo(previous_span.lo());
3494 }
3495 {
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/impls.rs:3495",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3495u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("removal_span")
}> =
::tracing::__macro_support::FieldName::new("removal_span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&removal_span)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?removal_span);
3496
3497 corrections.push((removal_span, "".to_string()));
3499
3500 let (has_nested, after_crate_name) =
3507 find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3508 {
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/impls.rs:3508",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3508u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("has_nested")
}> =
::tracing::__macro_support::FieldName::new("has_nested");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("after_crate_name")
}> =
::tracing::__macro_support::FieldName::new("after_crate_name");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&has_nested
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&after_crate_name)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(has_nested, ?after_crate_name);
3509
3510 let source_map = self.tcx.sess.source_map();
3511
3512 let is_definitely_crate = import
3514 .module_path
3515 .first()
3516 .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3517
3518 let start_point = source_map.start_point(after_crate_name);
3520 if is_definitely_crate
3521 && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3522 {
3523 corrections.push((
3524 start_point,
3525 if has_nested {
3526 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
import_snippet))
})format!("{start_snippet}{import_snippet}, ")
3528 } else {
3529 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
start_snippet))
})format!("{{{import_snippet}, {start_snippet}")
3532 },
3533 ));
3534
3535 if !has_nested {
3537 corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3538 }
3539 } else {
3540 corrections.push((
3542 import.use_span.shrink_to_lo(),
3543 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
import_snippet))
})format!("use {module_name}::{import_snippet};\n"),
3544 ));
3545 }
3546 }
3547
3548 let suggestion = Some((
3549 corrections,
3550 String::from("a macro with this name exists at the root of the crate"),
3551 Applicability::MaybeIncorrect,
3552 ));
3553 Some((
3554 suggestion,
3555 Some(
3556 "this could be because a macro annotated with `#[macro_export]` will be exported \
3557 at the root of the crate instead of the module where it is defined"
3558 .to_string(),
3559 ),
3560 ))
3561 }
3562
3563 pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3565 let local_items;
3566 let symbols = if module.is_local() {
3567 local_items = self
3568 .stripped_cfg_items
3569 .iter()
3570 .filter_map(|item| {
3571 let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
3572 ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
3573 Some(def_id)
3574 }
3575 _ => None,
3576 })?;
3577 Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3578 })
3579 .collect::<Vec<_>>();
3580 local_items.as_slice()
3581 } else {
3582 self.tcx.stripped_cfg_items(module.krate)
3583 };
3584
3585 for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3586 if ident.name != *segment {
3587 continue;
3588 }
3589
3590 let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3591
3592 fn comes_from_same_module_for_glob(
3593 r: &Resolver<'_, '_>,
3594 parent_module: DefId,
3595 module: DefId,
3596 visited: &mut FxHashMap<DefId, bool>,
3597 ) -> bool {
3598 if let Some(&cached) = visited.get(&parent_module) {
3599 return cached;
3603 }
3604 visited.insert(parent_module, false);
3605 let mut res = false;
3606 let m = r.expect_module(parent_module);
3607 if m.is_local() {
3608 for importer in m.glob_importers.borrow().iter() {
3609 if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
3610 {
3611 if next_parent_module == module
3612 || comes_from_same_module_for_glob(
3613 r,
3614 next_parent_module,
3615 module,
3616 visited,
3617 )
3618 {
3619 res = true;
3620 break;
3621 }
3622 }
3623 }
3624 }
3625 visited.insert(parent_module, res);
3626 res
3627 }
3628
3629 let comes_from_same_module = parent_module == module
3630 || comes_from_same_module_for_glob(
3631 self,
3632 parent_module,
3633 module,
3634 &mut Default::default(),
3635 );
3636 if !comes_from_same_module {
3637 continue;
3638 }
3639
3640 let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3641 diagnostics::ItemWas::BehindFeature { feature, span: cfg.1 }
3642 } else {
3643 diagnostics::ItemWas::CfgOut { span: cfg.1 }
3644 };
3645 let note = diagnostics::FoundItemConfigureOut { span: ident.span, item_was };
3646 err.subdiagnostic(note);
3647 }
3648 }
3649
3650 pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3651 match def_id.as_local() {
3652 Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3653 None => {
3654 self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3655 let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3656 let vis = self.tcx.visibility(ctor_def_id);
3657 let field_visibilities = self
3658 .tcx
3659 .associated_item_def_ids(def_id)
3660 .iter()
3661 .map(|&field_id| self.tcx.visibility(field_id))
3662 .collect();
3663 StructCtor { res, vis, field_visibilities }
3664 })
3665 }
3666 }
3667 }
3668
3669 fn on_unknown_data(&self, def_id: DefId) -> Option<&Directive> {
3671 match def_id.as_local() {
3672 Some(local) => Some(self.on_unknown_data.get(&local)?.directive.as_ref()),
3673 None => {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(OnUnknown { directive }) => {
break 'done Some(directive);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(self.tcx, def_id, OnUnknown{ directive } => directive)?.as_deref(),
3674 }
3675 }
3676}
3677
3678fn find_span_of_binding_until_next_binding(
3692 sess: &Session,
3693 binding_span: Span,
3694 use_span: Span,
3695) -> (bool, Span) {
3696 let source_map = sess.source_map();
3697
3698 let binding_until_end = binding_span.with_hi(use_span.hi());
3701
3702 let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3705
3706 let mut found_closing_brace = false;
3713 let after_binding_until_next_binding =
3714 source_map.span_take_while(after_binding_until_end, |&ch| {
3715 if ch == '}' {
3716 found_closing_brace = true;
3717 }
3718 ch == ' ' || ch == ','
3719 });
3720
3721 let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3726
3727 (found_closing_brace, span)
3728}
3729
3730fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3743 let source_map = sess.source_map();
3744
3745 let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3749
3750 let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3751 let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3752 if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3753 return None;
3754 }
3755
3756 let prev_comma = prev_comma.first().unwrap();
3757 let prev_starting_brace = prev_starting_brace.first().unwrap();
3758
3759 if prev_comma.len() > prev_starting_brace.len() {
3763 return None;
3764 }
3765
3766 Some(binding_span.with_lo(BytePos(
3767 binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3770 )))
3771}
3772
3773#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("find_span_immediately_after_crate_name",
"rustc_resolve::diagnostics::impls",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/diagnostics/impls.rs"),
::tracing_core::__macro_support::Option::Some(3786u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::diagnostics::impls"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("use_span")
}> =
::tracing::__macro_support::FieldName::new("use_span");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_span)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: (bool, Span) = loop {};
return __tracing_attr_fake_return;
}
{
let source_map = sess.source_map();
let mut num_colons = 0;
let until_second_colon =
source_map.span_take_while(use_span,
|c|
{
if *c == ':' { num_colons += 1; }
!#[allow(non_exhaustive_omitted_patterns)] match c {
':' if num_colons == 2 => true,
_ => false,
}
});
let from_second_colon =
use_span.with_lo(until_second_colon.hi() + BytePos(1));
let mut found_a_non_whitespace_character = false;
let after_second_colon =
source_map.span_take_while(from_second_colon,
|c|
{
if found_a_non_whitespace_character { return false; }
if !c.is_whitespace() {
found_a_non_whitespace_character = true;
}
true
});
let next_left_bracket =
source_map.span_through_char(from_second_colon, '{');
(next_left_bracket == after_second_colon, from_second_colon)
}
}
}#[instrument(level = "debug", skip(sess))]
3787fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3788 let source_map = sess.source_map();
3789
3790 let mut num_colons = 0;
3792 let until_second_colon = source_map.span_take_while(use_span, |c| {
3794 if *c == ':' {
3795 num_colons += 1;
3796 }
3797 !matches!(c, ':' if num_colons == 2)
3798 });
3799 let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3801
3802 let mut found_a_non_whitespace_character = false;
3803 let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3805 if found_a_non_whitespace_character {
3806 return false;
3807 }
3808 if !c.is_whitespace() {
3809 found_a_non_whitespace_character = true;
3810 }
3811 true
3812 });
3813
3814 let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3816
3817 (next_left_bracket == after_second_colon, from_second_colon)
3818}
3819
3820enum Instead {
3823 Yes,
3824 No,
3825}
3826
3827enum FoundUse {
3829 Yes,
3830 No,
3831}
3832
3833pub(crate) enum DiagMode {
3835 Normal,
3836 Pattern,
3838 Import {
3840 unresolved_import: bool,
3842 append: bool,
3845 },
3846}
3847
3848pub(crate) fn import_candidates(
3849 tcx: TyCtxt<'_>,
3850 err: &mut Diag<'_>,
3851 use_placement_span: Option<Span>,
3853 candidates: &[ImportSuggestion],
3854 mode: DiagMode,
3855 append: &str,
3856) {
3857 show_candidates(
3858 tcx,
3859 err,
3860 use_placement_span,
3861 candidates,
3862 Instead::Yes,
3863 FoundUse::Yes,
3864 mode,
3865 ::alloc::vec::Vec::new()vec![],
3866 append,
3867 );
3868}
3869
3870type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3871
3872fn show_candidates(
3877 tcx: TyCtxt<'_>,
3878 err: &mut Diag<'_>,
3879 use_placement_span: Option<Span>,
3881 candidates: &[ImportSuggestion],
3882 instead: Instead,
3883 found_use: FoundUse,
3884 mode: DiagMode,
3885 path: Vec<Segment>,
3886 append: &str,
3887) -> bool {
3888 if candidates.is_empty() {
3889 return false;
3890 }
3891
3892 let mut showed = false;
3893 let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3894 let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3895
3896 candidates.iter().for_each(|c| {
3897 if c.accessible {
3898 if c.doc_visible {
3900 accessible_path_strings.push((
3901 pprust::path_to_string(&c.path),
3902 c.descr,
3903 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3904 &c.note,
3905 c.via_import,
3906 ))
3907 }
3908 } else {
3909 inaccessible_path_strings.push((
3910 pprust::path_to_string(&c.path),
3911 c.descr,
3912 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3913 &c.note,
3914 c.via_import,
3915 ))
3916 }
3917 });
3918
3919 for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3922 path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3923 path_strings.dedup_by(|a, b| a.0 == b.0);
3924 let core_path_strings =
3925 path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3926 let std_path_strings =
3927 path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3928 let foreign_crate_path_strings =
3929 path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3930
3931 if std_path_strings.len() == core_path_strings.len() {
3934 path_strings.extend(std_path_strings);
3936 } else {
3937 path_strings.extend(std_path_strings);
3938 path_strings.extend(core_path_strings);
3939 }
3940 path_strings.extend(foreign_crate_path_strings);
3942 }
3943
3944 if !accessible_path_strings.is_empty() {
3945 let (determiner, kind, s, name, through) =
3946 if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3947 (
3948 "this",
3949 *descr,
3950 "",
3951 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", name))
})format!(" `{name}`"),
3952 if *via_import { " through its public re-export" } else { "" },
3953 )
3954 } else {
3955 let kinds = accessible_path_strings
3958 .iter()
3959 .map(|(_, descr, _, _, _)| *descr)
3960 .collect::<UnordSet<&str>>();
3961 let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3962 let s = if kind.ends_with('s') { "es" } else { "s" };
3963
3964 ("one of these", kind, s, String::new(), "")
3965 };
3966
3967 let instead = if let Instead::Yes = instead { " instead" } else { "" };
3968 let mut msg = if let DiagMode::Pattern = mode {
3969 ::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!(
3970 "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3971 pattern",
3972 )
3973 } else {
3974 ::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}")
3975 };
3976
3977 for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3978 err.note(note.clone());
3979 }
3980
3981 let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3982 msg.push(':');
3983
3984 for candidate in accessible_path_strings {
3985 msg.push('\n');
3986 msg.push_str(&candidate.0);
3987 }
3988 };
3989
3990 if let Some(span) = use_placement_span {
3991 let (add_use, trailing) = match mode {
3992 DiagMode::Pattern => {
3993 err.span_suggestions(
3994 span,
3995 msg,
3996 accessible_path_strings.into_iter().map(|a| a.0),
3997 Applicability::MaybeIncorrect,
3998 );
3999 return true;
4000 }
4001 DiagMode::Import { .. } => ("", ""),
4002 DiagMode::Normal => ("use ", ";\n"),
4003 };
4004 for candidate in &mut accessible_path_strings {
4005 let additional_newline = if let FoundUse::No = found_use
4008 && let DiagMode::Normal = mode
4009 {
4010 "\n"
4011 } else {
4012 ""
4013 };
4014 candidate.0 =
4015 ::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);
4016 }
4017
4018 match mode {
4019 DiagMode::Import { append: true, .. } => {
4020 append_candidates(&mut msg, accessible_path_strings);
4021 err.span_help(span, msg);
4022 }
4023 _ => {
4024 err.span_suggestions_with_style(
4025 span,
4026 msg,
4027 accessible_path_strings.into_iter().map(|a| a.0),
4028 Applicability::MaybeIncorrect,
4029 SuggestionStyle::ShowAlways,
4030 );
4031 }
4032 }
4033
4034 if let [first, .., last] = &path[..] {
4035 let sp = first.ident.span.until(last.ident.span);
4036 if sp.can_be_used_for_suggestions() && !sp.is_empty() {
4039 err.span_suggestion_verbose(
4040 sp,
4041 ::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),
4042 "",
4043 Applicability::Unspecified,
4044 );
4045 }
4046 }
4047 } else {
4048 append_candidates(&mut msg, accessible_path_strings);
4049 err.help(msg);
4050 }
4051 showed = true;
4052 }
4053 if !inaccessible_path_strings.is_empty()
4054 && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
DiagMode::Import { unresolved_import: false, .. } => true,
_ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
4055 {
4056 let prefix =
4057 if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
4058 if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
4059 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!(
4060 "{prefix}{descr} `{name}`{} exists but is inaccessible",
4061 if let DiagMode::Pattern = mode { ", which" } else { "" }
4062 );
4063
4064 if let Some(source_span) = source_span {
4065 let span = tcx.sess.source_map().guess_head_span(*source_span);
4066 let mut multi_span = MultiSpan::from_span(span);
4067 multi_span.push_span_label(span, "not accessible");
4068 err.span_note(multi_span, msg);
4069 } else {
4070 err.note(msg);
4071 }
4072 if let Some(note) = (*note).as_deref() {
4073 err.note(note.to_string());
4074 }
4075 } else {
4076 let descr = inaccessible_path_strings
4077 .iter()
4078 .map(|&(_, descr, _, _, _)| descr)
4079 .all_equal_value()
4080 .unwrap_or("item");
4081 let plural_descr =
4082 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") };
4083
4084 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");
4085 let mut has_colon = false;
4086
4087 let mut spans = Vec::new();
4088 for (name, _, source_span, _, _) in &inaccessible_path_strings {
4089 if let Some(source_span) = source_span {
4090 let span = tcx.sess.source_map().guess_head_span(*source_span);
4091 spans.push((name, span));
4092 } else {
4093 if !has_colon {
4094 msg.push(':');
4095 has_colon = true;
4096 }
4097 msg.push('\n');
4098 msg.push_str(name);
4099 }
4100 }
4101
4102 let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
4103 for (name, span) in spans {
4104 multi_span.push_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
})format!("`{name}`: not accessible"));
4105 }
4106
4107 for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4108 err.note(note.clone());
4109 }
4110
4111 err.span_note(multi_span, msg);
4112 }
4113 showed = true;
4114 }
4115 showed
4116}
4117
4118#[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)]
4119struct UsePlacementFinder {
4120 target_module: NodeId,
4121 first_legal_span: Option<Span>,
4122 first_use_span: Option<Span>,
4123}
4124
4125impl UsePlacementFinder {
4126 fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
4127 let mut finder =
4128 UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
4129 finder.visit_crate(krate);
4130 if let Some(use_span) = finder.first_use_span {
4131 (Some(use_span), FoundUse::Yes)
4132 } else {
4133 (finder.first_legal_span, FoundUse::No)
4134 }
4135 }
4136}
4137
4138impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
4139 fn visit_crate(&mut self, c: &Crate) {
4140 if self.target_module == CRATE_NODE_ID {
4141 let inject = c.spans.inject_use_span;
4142 if is_span_suitable_for_use_injection(inject) {
4143 self.first_legal_span = Some(inject);
4144 }
4145 self.first_use_span = search_for_any_use_in_items(&c.items);
4146 } else {
4147 visit::walk_crate(self, c);
4148 }
4149 }
4150
4151 fn visit_item(&mut self, item: &'tcx ast::Item) {
4152 if self.target_module == item.id {
4153 if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
4154 let inject = mod_spans.inject_use_span;
4155 if is_span_suitable_for_use_injection(inject) {
4156 self.first_legal_span = Some(inject);
4157 }
4158 self.first_use_span = search_for_any_use_in_items(items);
4159 }
4160 } else {
4161 visit::walk_item(self, item);
4162 }
4163 }
4164}
4165
4166#[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)]
4167struct BindingVisitor {
4168 identifiers: Vec<Symbol>,
4169 spans: FxHashMap<Symbol, Vec<Span>>,
4170}
4171
4172impl<'tcx> Visitor<'tcx> for BindingVisitor {
4173 fn visit_pat(&mut self, pat: &ast::Pat) {
4174 if let ast::PatKind::Ident(_, ident, _) = pat.kind {
4175 self.identifiers.push(ident.name);
4176 self.spans.entry(ident.name).or_default().push(ident.span);
4177 }
4178 visit::walk_pat(self, pat);
4179 }
4180}
4181
4182fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
4183 for item in items {
4184 if let ItemKind::Use(..) = item.kind
4185 && is_span_suitable_for_use_injection(item.span)
4186 {
4187 let mut lo = item.span.lo();
4188 for attr in &item.attrs {
4189 if attr.span.eq_ctxt(item.span) {
4190 lo = std::cmp::min(lo, attr.span.lo());
4191 }
4192 }
4193 return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
4194 }
4195 }
4196 None
4197}
4198
4199fn is_span_suitable_for_use_injection(s: Span) -> bool {
4200 !s.from_expansion()
4203}
4204
4205#[derive(#[automatically_derived]
impl ::core::fmt::Debug for OnUnknownData {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "OnUnknownData",
"directive", &&self.directive)
}
}Debug, #[automatically_derived]
impl ::core::clone::Clone for OnUnknownData {
#[inline]
fn clone(&self) -> OnUnknownData {
OnUnknownData {
directive: ::core::clone::Clone::clone(&self.directive),
}
}
}Clone, #[automatically_derived]
impl ::core::default::Default for OnUnknownData {
#[inline]
fn default() -> OnUnknownData {
OnUnknownData { directive: ::core::default::Default::default() }
}
}Default)]
4206pub(crate) struct OnUnknownData {
4207 pub(crate) directive: Box<Directive>,
4208}
4209
4210impl OnUnknownData {
4211 pub(crate) fn from_attrs(
4212 r: &Resolver<'_, '_>,
4213 attrs: &[ast::Attribute],
4214 ) -> Option<OnUnknownData> {
4215 if r.features.diagnostic_on_unknown()
4216 && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) =
4217 AttributeParser::parse_limited(
4218 r.tcx.sess,
4219 attrs,
4220 &[sym::diagnostic, sym::on_unknown],
4221 )
4222 {
4223 Some(Self { directive: directive? })
4224 } else {
4225 None
4226 }
4227 }
4228}