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 &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 &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 &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::ToolAttributePrelude => {
1530 let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1531 suggestions.extend(
1532 this.registered_attr_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 &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 &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).iter().any(|(key, name_resolution)| {
1874 if key.ns == TypeNS
1875 && key.ident == *ident
1876 && let Some(decl) = name_resolution.borrow().best_decl()
1877 {
1878 match decl.res() {
1879 Res::Def(_, def_id) => def_id != crate_def_id,
1882 Res::PrimTy(_) => true,
1883 _ => false,
1884 }
1885 } else {
1886 false
1887 }
1888 });
1889 let mut crate_path = ThinVec::new();
1890 if needs_disambiguation {
1891 crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
1892 }
1893 crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
1894
1895 suggestions.extend(self.lookup_import_candidates_from_module(
1896 lookup_ident,
1897 namespace,
1898 parent_scope,
1899 crate_root,
1900 crate_path,
1901 &filter_fn,
1902 ));
1903 }
1904 }
1905
1906 suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
1907 suggestions
1908 }
1909
1910 pub(crate) fn unresolved_macro_suggestions(
1911 &mut self,
1912 err: &mut Diag<'_>,
1913 macro_kind: MacroKind,
1914 parent_scope: &ParentScope<'ra>,
1915 ident: Ident,
1916 krate: &Crate,
1917 sugg_span: Option<Span>,
1918 ) {
1919 self.register_macros_for_all_crates();
1922
1923 let is_expected =
1924 &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
1925 let suggestion = self.early_lookup_typo_candidate(
1926 ScopeSet::Macro(macro_kind),
1927 parent_scope,
1928 ident,
1929 is_expected,
1930 );
1931 if !self.add_typo_suggestion(err, suggestion, ident.span) {
1932 self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
1933 }
1934
1935 let import_suggestions =
1936 self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1937 let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {
1938 DUMMY_NODE_ID => (None, FoundUse::No),
1939 node_id => UsePlacementFinder::check(krate, node_id),
1940 };
1941 show_candidates(
1942 self.tcx,
1943 err,
1944 span,
1945 &import_suggestions,
1946 Instead::No,
1947 found_use,
1948 DiagMode::Normal,
1949 ::alloc::vec::Vec::new()vec![],
1950 "",
1951 );
1952
1953 if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
1954 let label_span = ident.span.shrink_to_hi();
1955 let mut spans = MultiSpan::from_span(label_span);
1956 spans.push_span_label(label_span, "put a macro name here");
1957 err.subdiagnostic(MaybeMissingMacroRulesName { spans });
1958 return;
1959 }
1960
1961 if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1962 err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
1963 return;
1964 }
1965
1966 let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
1967 if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
1968 });
1969
1970 if let Some((def_id, unused_ident)) = unused_macro {
1971 let scope = self.local_macro_def_scopes[&def_id];
1972 let parent_nearest = parent_scope.module.nearest_parent_mod();
1973 let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();
1974 if !unused_macro_kinds.contains(macro_kind.into()) {
1975 match macro_kind {
1976 MacroKind::Bang => {
1977 err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
1978 }
1979 MacroKind::Attr => {
1980 err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
1981 }
1982 MacroKind::Derive => {
1983 err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
1984 }
1985 }
1986 return;
1987 }
1988 if Some(parent_nearest.to_def_id()) == scope.opt_def_id() {
1989 err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1990 err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1991 return;
1992 }
1993 }
1994
1995 if ident.name == kw::Default
1996 && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind
1997 {
1998 let span = self.def_span(def_id);
1999 let source_map = self.tcx.sess.source_map();
2000 let head_span = source_map.guess_head_span(span);
2001 err.subdiagnostic(ConsiderAddingADerive {
2002 span: head_span.shrink_to_lo(),
2003 suggestion: "#[derive(Default)]\n".to_string(),
2004 });
2005 }
2006 for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
2007 let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2008 ident,
2009 ScopeSet::All(ns),
2010 parent_scope,
2011 None,
2012 None,
2013 None,
2014 ) else {
2015 continue;
2016 };
2017
2018 let desc = match binding.res() {
2019 Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
2020 "a function-like macro".to_string()
2021 }
2022 Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
2023 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
})format!("an attribute: `#[{ident}]`")
2024 }
2025 Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
2026 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
ident))
})format!("a derive macro: `#[derive({ident})]`")
2027 }
2028 Res::Def(DefKind::Macro(kinds), _) => {
2029 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
kinds.descr()))
})format!("{} {}", kinds.article(), kinds.descr())
2030 }
2031 Res::ToolMod | Res::OpenMod(..) => {
2032 continue;
2034 }
2035 Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
2036 "only a trait, without a derive macro".to_string()
2037 }
2038 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!(
2039 "{} {}, not {} {}",
2040 res.article(),
2041 res.descr(),
2042 macro_kind.article(),
2043 macro_kind.descr_expected(),
2044 ),
2045 };
2046 if let crate::DeclKind::Import { import, .. } = binding.kind
2047 && !import.span.is_dummy()
2048 {
2049 let note = diagnostics::IdentImporterHereButItIsDesc {
2050 span: import.span,
2051 imported_ident: ident,
2052 imported_ident_desc: &desc,
2053 };
2054 err.subdiagnostic(note);
2055 self.record_use(ident, binding, Used::Other);
2058 return;
2059 }
2060 let note = diagnostics::IdentInScopeButItIsDesc {
2061 imported_ident: ident,
2062 imported_ident_desc: &desc,
2063 };
2064 err.subdiagnostic(note);
2065 return;
2066 }
2067
2068 if self.macro_names.contains(&IdentKey::new(ident)) {
2069 err.subdiagnostic(AddedMacroUse);
2070 return;
2071 }
2072 }
2073
2074 fn detect_derive_attribute(
2077 &self,
2078 err: &mut Diag<'_>,
2079 ident: Ident,
2080 parent_scope: &ParentScope<'ra>,
2081 sugg_span: Option<Span>,
2082 ) {
2083 let mut derives = ::alloc::vec::Vec::new()vec![];
2088 let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
2089 #[allow(rustc::potential_query_instability)]
2091 for (def_id, ext) in self
2092 .local_macro_map
2093 .iter()
2094 .map(|(local_id, ext)| (local_id.to_def_id(), ext))
2095 .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
2096 {
2097 for helper_attr in &ext.helper_attrs {
2098 let item_name = self.tcx.item_name(def_id);
2099 all_attrs.entry(*helper_attr).or_default().push(item_name);
2100 if helper_attr == &ident.name {
2101 derives.push(item_name);
2102 }
2103 }
2104 }
2105 let kind = MacroKind::Derive.descr();
2106 if !derives.is_empty() {
2107 let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
2109 derives.sort();
2110 derives.dedup();
2111 let msg = match &derives[..] {
2112 [derive] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", derive))
})format!(" `{derive}`"),
2113 [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!(
2114 "s {} and `{last}`",
2115 start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
2116 ),
2117 [] => {
::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!?"),
2118 };
2119 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!(
2120 "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
2121 missing a `derive` attribute",
2122 ident.name,
2123 );
2124 let sugg_span =
2125 if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind {
2126 let span = self.def_span(id);
2127 if span.from_expansion() {
2128 None
2129 } else {
2130 Some(span.shrink_to_lo())
2132 }
2133 } else {
2134 sugg_span
2136 };
2137 match sugg_span {
2138 Some(span) => {
2139 err.span_suggestion_verbose(
2140 span,
2141 msg,
2142 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#[derive({0})]\n",
derives.join(", ")))
})format!("#[derive({})]\n", derives.join(", ")),
2143 Applicability::MaybeIncorrect,
2144 );
2145 }
2146 None => {
2147 err.note(msg);
2148 }
2149 }
2150 } else {
2151 let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
2153 if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
2154 && let Some(macros) = all_attrs.get(&best_match)
2155 {
2156 let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
2157 macros.sort();
2158 macros.dedup();
2159 let msg = match ¯os[..] {
2160 [] => return,
2161 [name] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}` accepts", name))
})format!(" `{name}` accepts"),
2162 [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!(
2163 "s {} and `{end}` accept",
2164 start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
2165 ),
2166 };
2167 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");
2168 err.span_suggestion_verbose(
2169 ident.span,
2170 msg,
2171 best_match,
2172 Applicability::MaybeIncorrect,
2173 );
2174 }
2175 }
2176 }
2177
2178 pub(crate) fn add_typo_suggestion(
2179 &self,
2180 err: &mut Diag<'_>,
2181 suggestion: Option<TypoSuggestion>,
2182 span: Span,
2183 ) -> bool {
2184 let suggestion = match suggestion {
2185 None => return false,
2186 Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
2188 Some(suggestion) => suggestion,
2189 };
2190
2191 let mut did_label_def_span = false;
2192
2193 if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
2194 if span.overlaps(def_span) {
2195 return false;
2214 }
2215 let span = self.tcx.sess.source_map().guess_head_span(def_span);
2216 let candidate_descr = suggestion.res.descr();
2217 let candidate = suggestion.candidate;
2218 let label = match suggestion.target {
2219 SuggestionTarget::SimilarlyNamed => {
2220 diagnostics::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
2221 }
2222 SuggestionTarget::SingleItem => {
2223 diagnostics::DefinedHere::SingleItem { span, candidate_descr, candidate }
2224 }
2225 };
2226 did_label_def_span = true;
2227 err.subdiagnostic(label);
2228 }
2229
2230 let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
2231 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2232 && let Some(span) = suggestion.span
2233 && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
2234 && snippet == candidate
2235 {
2236 let candidate = suggestion.candidate;
2237 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!(
2240 "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
2241 );
2242 if !did_label_def_span {
2243 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
})format!("`{candidate}` defined here"));
2244 }
2245 (span, msg, snippet)
2246 } else {
2247 let msg = match suggestion.target {
2248 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!(
2249 "{} {} with a similar name exists",
2250 suggestion.res.article(),
2251 suggestion.res.descr()
2252 ),
2253 SuggestionTarget::SingleItem => {
2254 ::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())
2255 }
2256 };
2257 (span, msg, suggestion.candidate.to_ident_string())
2258 };
2259 err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2260 true
2261 }
2262
2263 fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2264 let res = b.res();
2265 if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2266 let (built_in, from) = match scope {
2267 Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2268 Scope::ExternPreludeFlags
2269 if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2270 || #[allow(non_exhaustive_omitted_patterns)] match res {
Res::OpenMod(..) => true,
_ => false,
}matches!(res, Res::OpenMod(..)) =>
2271 {
2272 ("", " passed with `--extern`")
2273 }
2274 _ => {
2275 if #[allow(non_exhaustive_omitted_patterns)] match res {
Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
_ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2276 ("", "")
2278 } else {
2279 (" built-in", "")
2280 }
2281 }
2282 };
2283
2284 let a = if built_in.is_empty() { res.article() } else { "a" };
2285 ::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())
2286 } else {
2287 let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2288 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
introduced))
})format!("the {thing} {introduced} here", thing = res.descr())
2289 }
2290 }
2291
2292 fn ambiguity_diagnostic(
2293 &self,
2294 ambiguity_error: &AmbiguityError<'ra>,
2295 ) -> diagnostics::Ambiguity {
2296 let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2297 *ambiguity_error;
2298 let extern_prelude_ambiguity = || {
2299 #[allow(non_exhaustive_omitted_patterns)] match scope2 {
Scope::ExternPreludeFlags => true,
_ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2301 && self
2302 .extern_prelude
2303 .get(&IdentKey::new(ident))
2304 .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2305 };
2306 let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2307 (b2, b1, scope2, scope1, true)
2309 } else {
2310 (b1, b2, scope1, scope2, false)
2311 };
2312
2313 let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2314 let what = self.decl_description(b, ident, scope);
2315 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}");
2316
2317 let thing = b.res().descr();
2318 let mut help_msgs = Vec::new();
2319 if b.is_glob_import()
2320 && (kind == AmbiguityKind::GlobVsGlob
2321 || kind == AmbiguityKind::GlobVsExpanded
2322 || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2323 {
2324 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
ident))
})format!(
2325 "consider adding an explicit import of `{ident}` to disambiguate"
2326 ))
2327 }
2328 if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2329 {
2330 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"))
2331 }
2332
2333 if kind != AmbiguityKind::GlobVsGlob {
2334 if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2335 if module == self.graph_root.to_module() {
2336 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2337 "use `crate::{ident}` to refer to this {thing} unambiguously"
2338 ));
2339 } else if module.is_normal() {
2340 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2341 "use `self::{ident}` to refer to this {thing} unambiguously"
2342 ));
2343 }
2344 }
2345 }
2346
2347 (
2348 Spanned { node: note_msg, span: b.span },
2349 help_msgs
2350 .iter()
2351 .enumerate()
2352 .map(|(i, help_msg)| {
2353 let or = if i == 0 { "" } else { "or " };
2354 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
})format!("{or}{help_msg}")
2355 })
2356 .collect::<Vec<_>>(),
2357 )
2358 };
2359 let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2360 let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2361 let help = if kind == AmbiguityKind::GlobVsGlob
2362 && b1
2363 .parent_module
2364 .and_then(|m| m.opt_def_id())
2365 .map(|d| !d.is_local())
2366 .unwrap_or_default()
2367 {
2368 Some(&[
2369 "consider updating this dependency to resolve this error",
2370 "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2371 ] as &[_])
2372 } else {
2373 None
2374 };
2375
2376 let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2377 ::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!(
2378 "{} or {}",
2379 vis1.to_string(CRATE_DEF_ID, self.tcx),
2380 vis2.to_string(CRATE_DEF_ID, self.tcx)
2381 )
2382 });
2383
2384 diagnostics::Ambiguity {
2385 ident,
2386 help,
2387 ambig_vis,
2388 kind: kind.descr(),
2389 b1_note,
2390 b1_help_msgs,
2391 b2_note,
2392 b2_help_msgs,
2393 is_error: false,
2394 }
2395 }
2396
2397 fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2400 let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
2401 decl.kind
2402 else {
2403 return None;
2404 };
2405
2406 let def_id = self.tcx.parent(ctor_def_id);
2407 self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) }
2409
2410 fn module_path_names(&self, module: Module<'ra>) -> Option<Vec<Symbol>> {
2414 let mut path = Vec::new();
2415 let mut def_id = module.opt_def_id()?;
2416 while let Some(parent) = self.tcx.opt_parent(def_id) {
2417 if let Some(name) = self.tcx.opt_item_name(def_id) {
2418 path.push(name);
2419 }
2420 if parent.is_top_level_module() {
2421 break;
2422 }
2423 def_id = parent;
2424 }
2425 path.reverse();
2426 path.insert(0, kw::Crate);
2427 Some(path)
2428 }
2429
2430 fn shorten_candidate_path(
2431 &self,
2432 suggestion: &mut ImportSuggestion,
2433 current_module: Module<'ra>,
2434 ) {
2435 self.shorten_import_path(suggestion.did, &mut suggestion.path, current_module);
2436 }
2437
2438 fn shorten_import_path(
2442 &self,
2443 did: Option<DefId>,
2444 path: &mut Path,
2445 current_module: Module<'ra>,
2446 ) {
2447 const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;
2448
2449 if did.is_none_or(|did| !did.is_local()) {
2451 return;
2452 }
2453
2454 let Some(current_mod_path) = self.module_path_names(current_module) else {
2456 return;
2457 };
2458
2459 let candidate_names = {
2463 let filtered_segments: Vec<_> =
2464 path.segments.iter().filter(|segment| segment.ident.name != kw::PathRoot).collect();
2465
2466 let mut candidate_names: Vec<Symbol> =
2467 filtered_segments.iter().map(|segment| segment.ident.name).collect();
2468 if candidate_names.first() != Some(&kw::Crate) {
2469 candidate_names.insert(0, kw::Crate);
2470 }
2471 if candidate_names.len() < 2 {
2472 return;
2473 }
2474 candidate_names
2475 };
2476
2477 let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];
2479
2480 let common_prefix_length = current_mod_path
2482 .iter()
2483 .zip(candidate_mod_names.iter())
2484 .take_while(|(current, candidate)| current == candidate)
2485 .count();
2486
2487 if common_prefix_length == 0 {
2489 return;
2490 }
2491
2492 let super_count = current_mod_path.len() - common_prefix_length;
2493
2494 let at_crate_root = current_mod_path.len() == 1;
2497
2498 let mut new_segments = if super_count == 0 && at_crate_root {
2499 ThinVec::new()
2500 } else {
2501 let prefix_keyword = match super_count {
2502 0 => kw::SelfLower,
2503 1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
2504 _ => return, };
2506 {
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),)]
2507 };
2508 for &name in &candidate_names[common_prefix_length..] {
2509 new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
2510 }
2511
2512 if new_segments.len() >= path.segments.len() {
2514 return;
2515 }
2516
2517 *path = Path { span: path.span, segments: new_segments };
2518 }
2519
2520 fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2521 let PrivacyError {
2522 ident,
2523 decl,
2524 outermost_res,
2525 parent_scope,
2526 single_nested,
2527 dedup_span,
2528 ref source,
2529 } = *privacy_error;
2530
2531 let res = decl.res();
2532 let ctor_fields_span = self.ctor_fields_span(decl);
2533 let plain_descr = res.descr().to_string();
2534 let nonimport_descr =
2535 if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2536 let import_descr = nonimport_descr.clone() + " import";
2537 let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2538
2539 let ident_descr = get_descr(decl);
2541 let mut err =
2542 self.dcx().create_err(diagnostics::IsPrivate { span: ident.span, ident_descr, ident });
2543
2544 self.mention_default_field_values(source, ident, &mut err);
2545
2546 let shown_candidates = if let Some((this_res, outer_ident)) = outermost_res {
2547 let mut import_suggestions = self.lookup_import_candidates(
2548 outer_ident,
2549 this_res.ns().unwrap_or(Namespace::TypeNS),
2550 &parent_scope,
2551 &|res: Res| res == this_res,
2552 );
2553 for suggestion in &mut import_suggestions {
2555 self.shorten_candidate_path(suggestion, parent_scope.module);
2556 }
2557 let point_to_def = !show_candidates(
2558 self.tcx,
2559 &mut err,
2560 Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2561 &import_suggestions,
2562 Instead::Yes,
2563 FoundUse::Yes,
2564 DiagMode::Import { append: single_nested, unresolved_import: false },
2565 ::alloc::vec::Vec::new()vec![],
2566 "",
2567 );
2568 if point_to_def && ident.span != outer_ident.span {
2570 let label = diagnostics::OuterIdentIsNotPubliclyReexported {
2571 span: outer_ident.span,
2572 outer_ident_descr: this_res.descr(),
2573 outer_ident,
2574 };
2575 err.subdiagnostic(label);
2576 }
2577 !point_to_def
2578 } else {
2579 false
2580 };
2581
2582 let mut non_exhaustive = None;
2583 if let Some(def_id) = res.opt_def_id()
2587 && !def_id.is_local()
2588 && 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)
2589 {
2590 non_exhaustive = Some(attr_span);
2591 } else if let Some(span) = ctor_fields_span {
2592 let label = diagnostics::ConstructorPrivateIfAnyFieldPrivate { span };
2593 err.subdiagnostic(label);
2594 if let Res::Def(_, d) = res
2595 && let Some(fields) = self.field_visibility_spans.get(&d)
2596 {
2597 let spans = fields.iter().map(|span| *span).collect();
2598 let sugg = diagnostics::ConsiderMakingTheFieldPublic {
2599 spans,
2600 number_of_fields: fields.len(),
2601 };
2602 err.subdiagnostic(sugg);
2603 }
2604 }
2605
2606 let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2607 if let Some(mut def_id) = res.opt_def_id() {
2608 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];
2610 while let Some(parent) = self.tcx.opt_parent(def_id) {
2611 def_id = parent;
2612 if !def_id.is_top_level_module() {
2613 path.push(def_id);
2614 } else {
2615 break;
2616 }
2617 }
2618 let path_names: Option<Vec<Ident>> = path
2620 .iter()
2621 .rev()
2622 .map(|def_id| {
2623 self.tcx.opt_item_name(*def_id).map(|name| {
2624 Ident::with_dummy_span(if def_id.is_top_level_module() {
2625 kw::Crate
2626 } else {
2627 name
2628 })
2629 })
2630 })
2631 .collect();
2632 if let Some(&def_id) = path.get(0)
2633 && let Some(path) = path_names
2634 {
2635 if let Some(def_id) = def_id.as_local() {
2636 if self.effective_visibilities.is_directly_public(def_id) {
2637 sugg_paths.push((path, false));
2638 }
2639 } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2640 {
2641 sugg_paths.push((path, false));
2642 }
2643 }
2644 }
2645
2646 let first_binding = decl;
2648 let mut next_binding = Some(decl);
2649 let mut next_ident = ident;
2650 while let Some(binding) = next_binding {
2651 let name = next_ident;
2652 next_binding = match binding.kind {
2653 _ if res == Res::Err => None,
2654 DeclKind::Import { source_decl, import, .. } => match import.kind {
2655 _ if source_decl.span.is_dummy() => None,
2656 ImportKind::Single { source, .. } => {
2657 next_ident = source;
2658 Some(source_decl)
2659 }
2660 ImportKind::Glob { .. }
2661 | ImportKind::MacroUse { .. }
2662 | ImportKind::MacroExport => Some(source_decl),
2663 ImportKind::ExternCrate { .. } => None,
2664 },
2665 _ => None,
2666 };
2667
2668 match binding.kind {
2669 DeclKind::Import { source_decl, import, .. } => {
2670 let through_reexport = !#[allow(non_exhaustive_omitted_patterns)] match source_decl.kind {
DeclKind::Def(_) => true,
_ => false,
}matches!(source_decl.kind, DeclKind::Def(_));
2671 let uses_relative_path = import
2672 .module_path
2673 .first()
2674 .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));
2675 let res_def_id = res.opt_def_id();
2676 let path = if uses_relative_path {
2677 let module_path = if let Some(ModuleOrUniformRoot::Module(module)) =
2680 import.imported_module.get()
2681 && module.is_local()
2682 && let Some(module_path) = self.module_path_names(module)
2683 && let Some(mut def_id) = module.opt_def_id()
2684 && res_def_id.is_none_or(|def_id| {
2685 self.is_accessible_from(
2686 self.tcx.visibility(def_id),
2687 parent_scope.module,
2688 )
2689 }) {
2690 let mut visible_from_use_site = true;
2694 while let Some(parent) = self.tcx.opt_parent(def_id) {
2695 if !self.is_accessible_from(
2696 self.tcx.visibility(def_id),
2697 parent_scope.module,
2698 ) {
2699 visible_from_use_site = false;
2700 break;
2701 }
2702 if parent.is_top_level_module() {
2703 break;
2704 }
2705 def_id = parent;
2706 }
2707 if visible_from_use_site { Some(module_path) } else { None }
2708 } else {
2709 None
2710 };
2711
2712 module_path.map(|module_path| {
2713 let mut path = Path {
2716 span: ident.span,
2717 segments: module_path
2718 .into_iter()
2719 .chain(std::iter::once(ident.name))
2720 .map(|name| {
2721 ast::PathSegment::from_ident(Ident::with_dummy_span(name))
2722 })
2723 .collect(),
2724 };
2725 self.shorten_import_path(res_def_id, &mut path, parent_scope.module);
2726 path.segments.iter().map(|seg| seg.ident).collect()
2727 })
2728 } else {
2729 Some(
2732 import
2733 .module_path
2734 .iter()
2735 .filter(|seg| seg.ident.name != kw::PathRoot)
2736 .map(|seg| seg.ident.clone())
2737 .chain(std::iter::once(ident))
2738 .collect::<Vec<_>>(),
2739 )
2740 };
2741 if let Some(path) = path {
2742 sugg_paths.push((path, through_reexport));
2743 }
2744 }
2745 DeclKind::Def(_) => {}
2746 }
2747 let first = binding == first_binding;
2748 let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2749 let mut note_span = MultiSpan::from_span(def_span);
2750 if !first && binding.vis().is_public() {
2751 let desc = match binding.kind {
2752 DeclKind::Import { .. } => "re-export",
2753 _ => "directly",
2754 };
2755 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}"));
2756 }
2757 if next_binding.is_none()
2760 && let Some(span) = non_exhaustive
2761 {
2762 note_span.push_span_label(
2763 span,
2764 "cannot be constructed because it is `#[non_exhaustive]`",
2765 );
2766 }
2767 let note = diagnostics::NoteAndRefersToTheItemDefinedHere {
2768 span: note_span,
2769 binding_descr: get_descr(binding),
2770 binding_name: name,
2771 first,
2772 dots: next_binding.is_some(),
2773 };
2774 err.subdiagnostic(note);
2775 }
2776 let can_replace_use = !shown_candidates
2784 && !single_nested
2785 && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
2786 if can_replace_use {
2787 sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2790 for (sugg, reexport) in sugg_paths {
2791 if sugg.len() <= 1 {
2792 continue;
2795 }
2796 let path = join_path_idents(sugg);
2797 let sugg = if reexport {
2798 diagnostics::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2799 } else {
2800 diagnostics::ImportIdent::Directly { span: dedup_span, ident, path }
2801 };
2802 err.subdiagnostic(sugg);
2803 break;
2804 }
2805 }
2806
2807 err.emit();
2808 }
2809
2810 fn mention_default_field_values(
2830 &self,
2831 source: &Option<ast::Expr>,
2832 ident: Ident,
2833 err: &mut Diag<'_>,
2834 ) {
2835 let Some(expr) = source else { return };
2836 let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2837 let Some(segment) = struct_expr.path.segments.last() else { return };
2840 let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2841 let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2842 return;
2843 };
2844 let Some(default_fields) = self.field_defaults(def_id) else { return };
2845 if struct_expr.fields.is_empty() {
2846 return;
2847 }
2848 let last_span = struct_expr.fields.iter().last().unwrap().span;
2849 let mut iter = struct_expr.fields.iter().peekable();
2850 let mut prev: Option<Span> = None;
2851 while let Some(field) = iter.next() {
2852 if field.expr.span.overlaps(ident.span) {
2853 err.span_label(field.ident.span, "while setting this field");
2854 if default_fields.contains(&field.ident.name) {
2855 let sugg = if last_span == field.span {
2856 ::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())]
2857 } else {
2858 ::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![
2859 (
2860 match (prev, iter.peek()) {
2862 (_, Some(next)) => field.span.with_hi(next.span.lo()),
2863 (Some(prev), _) => field.span.with_lo(prev.hi()),
2864 (None, None) => field.span,
2865 },
2866 String::new(),
2867 ),
2868 (last_span.shrink_to_hi(), ", ..".to_string()),
2869 ]
2870 };
2871 err.multipart_suggestion(
2872 ::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!(
2873 "the type `{ident}` of field `{}` is private, but you can construct \
2874 the default value defined for it in `{}` using `..` in the struct \
2875 initializer expression",
2876 field.ident,
2877 self.tcx.item_name(def_id),
2878 ),
2879 sugg,
2880 Applicability::MachineApplicable,
2881 );
2882 break;
2883 }
2884 }
2885 prev = Some(field.span);
2886 }
2887 }
2888
2889 pub(crate) fn find_similarly_named_module_or_crate(
2890 &self,
2891 ident: Symbol,
2892 current_module: Module<'ra>,
2893 ) -> Option<Symbol> {
2894 let mut candidates = self
2895 .extern_prelude
2896 .keys()
2897 .map(|ident| ident.name)
2898 .chain(
2899 self.local_module_map
2900 .iter()
2901 .filter(|(_, module)| {
2902 let module = module.to_module();
2903 current_module.is_ancestor_of(module) && current_module != module
2904 })
2905 .flat_map(|(_, module)| module.name()),
2906 )
2907 .chain(
2908 self.extern_module_map
2909 .borrow()
2910 .iter()
2911 .filter(|(_, module)| {
2912 let module = module.to_module();
2913 current_module.is_ancestor_of(module) && current_module != module
2914 })
2915 .flat_map(|(_, module)| module.name()),
2916 )
2917 .filter(|c| !c.to_string().is_empty())
2918 .collect::<Vec<_>>();
2919 candidates.sort();
2920 candidates.dedup();
2921 find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2922 }
2923
2924 pub(crate) fn report_path_resolution_error(
2925 &mut self,
2926 path: &[Segment],
2927 opt_ns: Option<Namespace>, parent_scope: &ParentScope<'ra>,
2929 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2930 ignore_decl: Option<Decl<'ra>>,
2931 ignore_import: Option<Import<'ra>>,
2932 module: Option<ModuleOrUniformRoot<'ra>>,
2933 failed_segment_idx: usize,
2934 ident: Ident,
2935 diag_metadata: Option<&DiagMetadata<'_>>,
2936 ) -> (String, String, Option<Suggestion>) {
2937 let is_last = failed_segment_idx == path.len() - 1;
2938 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2939 let module_def_id = match module {
2940 Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
2941 _ => None,
2942 };
2943 let scope = match &path[..failed_segment_idx] {
2944 [.., prev] => {
2945 if prev.ident.name == kw::PathRoot {
2946 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the crate root"))
})format!("the crate root")
2947 } else {
2948 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", prev.ident))
})format!("`{}`", prev.ident)
2949 }
2950 }
2951 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this scope"))
})format!("this scope"),
2952 };
2953 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
scope))
})format!("cannot find `{ident}` in {scope}");
2954
2955 if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
2956 let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Mod, _) => true,
_ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2957 let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2958 candidates
2959 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2960 if let Some(candidate) = candidates.get(0) {
2961 let path = {
2962 let len = candidate.path.segments.len();
2964 let start_index = (0..=failed_segment_idx.min(len - 1))
2965 .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2966 .unwrap_or_default();
2967 let segments =
2968 (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2969 Path { segments, span: Span::default() }
2970 };
2971 (
2972 message,
2973 String::from("unresolved import"),
2974 Some((
2975 ::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))],
2976 String::from("a similar path exists"),
2977 Applicability::MaybeIncorrect,
2978 )),
2979 )
2980 } else if ident.name == sym::core {
2981 (
2982 message,
2983 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
ident))
})format!("you might be missing crate `{ident}`"),
2984 Some((
2985 ::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())],
2986 "try using `std` instead of `core`".to_string(),
2987 Applicability::MaybeIncorrect,
2988 )),
2989 )
2990 } else if ident.name == kw::Underscore {
2991 (
2992 "invalid crate or module name `_`".to_string(),
2993 "`_` is not a valid crate or module name".to_string(),
2994 None,
2995 )
2996 } else if self.tcx.sess.is_rust_2015() {
2997 (
2998 ::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}"),
2999 ::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}`"),
3000 Some((
3001 ::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![(
3002 self.current_crate_outer_attr_insert_span,
3003 format!("extern crate {ident};\n"),
3004 )],
3005 if was_invoked_from_cargo() {
3006 ::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!(
3007 "if you wanted to use a crate named `{ident}`, use `cargo add \
3008 {ident}` to add it to your `Cargo.toml` and import it in your \
3009 code",
3010 )
3011 } else {
3012 ::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!(
3013 "you might be missing a crate named `{ident}`, add it to your \
3014 project and import it in your code",
3015 )
3016 },
3017 Applicability::MaybeIncorrect,
3018 )),
3019 )
3020 } else {
3021 (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)
3022 }
3023 } else if failed_segment_idx > 0 {
3024 let parent = path[failed_segment_idx - 1].ident.name;
3025 let parent = match parent {
3026 kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
3029 "the list of imported crates".to_owned()
3030 }
3031 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
3032 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", parent))
})format!("`{parent}`"),
3033 };
3034
3035 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}");
3036 if ns == TypeNS || ns == ValueNS {
3037 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
3038 let binding = if let Some(module) = module {
3039 self.cm()
3040 .resolve_ident_in_module(
3041 module,
3042 ident,
3043 ns_to_try,
3044 parent_scope,
3045 None,
3046 ignore_decl,
3047 ignore_import,
3048 )
3049 .ok()
3050 } else if let Some(ribs) = ribs
3051 && let Some(TypeNS | ValueNS) = opt_ns
3052 {
3053 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3054 match self.resolve_ident_in_lexical_scope(
3055 ident,
3056 ns_to_try,
3057 parent_scope,
3058 None,
3059 &ribs[ns_to_try],
3060 ignore_decl,
3061 diag_metadata,
3062 ) {
3063 Some(LateDecl::Decl(binding)) => Some(binding),
3065 _ => None,
3066 }
3067 } else {
3068 self.cm()
3069 .resolve_ident_in_scope_set(
3070 ident,
3071 ScopeSet::All(ns_to_try),
3072 parent_scope,
3073 None,
3074 ignore_decl,
3075 ignore_import,
3076 )
3077 .ok()
3078 };
3079 if let Some(binding) = binding {
3080 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!(
3081 "expected {}, found {} `{ident}` in {parent}",
3082 ns.descr(),
3083 binding.res().descr(),
3084 );
3085 };
3086 }
3087 (message, msg, None)
3088 } else if ident.name == kw::SelfUpper {
3089 if opt_ns.is_none() {
3093 (message, "`Self` cannot be used in imports".to_string(), None)
3094 } else {
3095 (
3096 message,
3097 "`Self` is only available in impls, traits, and type definitions".to_string(),
3098 None,
3099 )
3100 }
3101 } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
3102 let binding = if let Some(ribs) = ribs {
3104 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3105 self.resolve_ident_in_lexical_scope(
3106 ident,
3107 ValueNS,
3108 parent_scope,
3109 None,
3110 &ribs[ValueNS],
3111 ignore_decl,
3112 diag_metadata,
3113 )
3114 } else {
3115 None
3116 };
3117 let match_span = match binding {
3118 Some(LateDecl::RibDef(Res::Local(id))) => {
3127 Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
3128 }
3129 Some(LateDecl::Decl(name_binding)) => Some((
3141 name_binding.span,
3142 name_binding.res().article(),
3143 name_binding.res().descr(),
3144 )),
3145 _ => None,
3146 };
3147
3148 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}");
3149 let label = if let Some((span, article, descr)) = match_span {
3150 ::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!(
3151 "`{ident}` is declared as {article} {descr} at `{}`, not a type",
3152 self.tcx
3153 .sess
3154 .source_map()
3155 .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
3156 )
3157 } else {
3158 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
ident))
})format!("use of undeclared type `{ident}`")
3159 };
3160 (message, label, None)
3161 } else {
3162 let mut suggestion = None;
3163 if ident.name == sym::alloc {
3164 suggestion = Some((
3165 ::alloc::vec::Vec::new()vec![],
3166 String::from("add `extern crate alloc` to use the `alloc` crate"),
3167 Applicability::MaybeIncorrect,
3168 ))
3169 }
3170
3171 suggestion = suggestion.or_else(|| {
3172 self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
3173 |sugg| {
3174 (
3175 ::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())],
3176 String::from("there is a crate or module with a similar name"),
3177 Applicability::MaybeIncorrect,
3178 )
3179 },
3180 )
3181 });
3182 if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
3183 ident,
3184 ScopeSet::All(ValueNS),
3185 parent_scope,
3186 None,
3187 ignore_decl,
3188 ignore_import,
3189 ) {
3190 let descr = binding.res().descr();
3191 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}");
3192 (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)
3193 } else {
3194 let suggestion = if suggestion.is_some() {
3195 suggestion
3196 } else if let Some(m) = self.undeclared_module_exists(ident) {
3197 self.undeclared_module_suggest_declare(ident, m)
3198 } else if was_invoked_from_cargo() {
3199 Some((
3200 ::alloc::vec::Vec::new()vec![],
3201 ::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!(
3202 "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
3203 to add it to your `Cargo.toml`",
3204 ),
3205 Applicability::MaybeIncorrect,
3206 ))
3207 } else {
3208 Some((
3209 ::alloc::vec::Vec::new()vec![],
3210 ::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}`",),
3211 Applicability::MaybeIncorrect,
3212 ))
3213 };
3214 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}");
3215 (
3216 message,
3217 ::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}`"),
3218 suggestion,
3219 )
3220 }
3221 }
3222 }
3223
3224 fn undeclared_module_suggest_declare(
3225 &self,
3226 ident: Ident,
3227 path: std::path::PathBuf,
3228 ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
3229 Some((
3230 ::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"))],
3231 ::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!(
3232 "to make use of source file {}, use `mod {ident}` \
3233 in this file to declare the module",
3234 path.display()
3235 ),
3236 Applicability::MaybeIncorrect,
3237 ))
3238 }
3239
3240 fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
3241 let map = self.tcx.sess.source_map();
3242
3243 let src = map.span_to_filename(ident.span).into_local_path()?;
3244 let i = ident.as_str();
3245 let dir = src.parent()?;
3247 let src = src.file_stem()?.to_str()?;
3248 for file in [
3249 dir.join(i).with_extension("rs"),
3251 dir.join(i).join("mod.rs"),
3253 ] {
3254 if file.exists() {
3255 return Some(file);
3256 }
3257 }
3258 if !#[allow(non_exhaustive_omitted_patterns)] match src {
"main" | "lib" | "mod" => true,
_ => false,
}matches!(src, "main" | "lib" | "mod") {
3259 for file in [
3260 dir.join(src).join(i).with_extension("rs"),
3262 dir.join(src).join(i).join("mod.rs"),
3264 ] {
3265 if file.exists() {
3266 return Some(file);
3267 }
3268 }
3269 }
3270 None
3271 }
3272
3273 #[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(3274u32),
::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))]
3275 pub(crate) fn make_path_suggestion(
3276 &mut self,
3277 mut path: Vec<Segment>,
3278 parent_scope: &ParentScope<'ra>,
3279 ) -> Option<(Vec<Segment>, Option<String>)> {
3280 match path[..] {
3281 [first, second, ..]
3284 if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
3285 [first, ..]
3287 if first.ident.span.at_least_rust_2018()
3288 && !first.ident.is_path_segment_keyword() =>
3289 {
3290 path.insert(0, Segment::from_ident(Ident::dummy()));
3292 }
3293 _ => return None,
3294 }
3295
3296 self.make_missing_self_suggestion(path.clone(), parent_scope)
3297 .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
3298 .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
3299 .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
3300 }
3301
3302 #[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(3309u32),
::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:3318",
"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(3318u32),
::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))]
3310 fn make_missing_self_suggestion(
3311 &self,
3312 mut path: Vec<Segment>,
3313 parent_scope: &ParentScope<'ra>,
3314 ) -> Option<(Vec<Segment>, Option<String>)> {
3315 path[0].ident.name = kw::SelfLower;
3317 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3318 debug!(?path, ?result);
3319 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3320 }
3321
3322 #[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(3329u32),
::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:3338",
"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(3338u32),
::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))]
3330 fn make_missing_crate_suggestion(
3331 &self,
3332 mut path: Vec<Segment>,
3333 parent_scope: &ParentScope<'ra>,
3334 ) -> Option<(Vec<Segment>, Option<String>)> {
3335 path[0].ident.name = kw::Crate;
3337 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3338 debug!(?path, ?result);
3339 if let PathResult::Module(..) = result {
3340 Some((
3341 path,
3342 Some(
3343 "`use` statements changed in Rust 2018; read more at \
3344 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
3345 clarity.html>"
3346 .to_string(),
3347 ),
3348 ))
3349 } else {
3350 None
3351 }
3352 }
3353
3354 #[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(3361u32),
::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:3370",
"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(3370u32),
::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))]
3362 fn make_missing_super_suggestion(
3363 &self,
3364 mut path: Vec<Segment>,
3365 parent_scope: &ParentScope<'ra>,
3366 ) -> Option<(Vec<Segment>, Option<String>)> {
3367 path[0].ident.name = kw::Super;
3369 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3370 debug!(?path, ?result);
3371 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3372 }
3373
3374 #[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(3384u32),
::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:3405",
"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(3405u32),
::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))]
3385 fn make_external_crate_suggestion(
3386 &self,
3387 mut path: Vec<Segment>,
3388 parent_scope: &ParentScope<'ra>,
3389 ) -> Option<(Vec<Segment>, Option<String>)> {
3390 if path[1].ident.span.is_rust_2015() {
3391 return None;
3392 }
3393
3394 let mut extern_crate_names =
3398 self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
3399 extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
3400
3401 for name in extern_crate_names.into_iter() {
3402 path[0].ident.name = name;
3404 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3405 debug!(?path, ?name, ?result);
3406 if let PathResult::Module(..) = result {
3407 return Some((path, None));
3408 }
3409 }
3410
3411 None
3412 }
3413
3414 pub(crate) fn check_for_module_export_macro(
3427 &mut self,
3428 import: Import<'ra>,
3429 module: ModuleOrUniformRoot<'ra>,
3430 ident: Ident,
3431 ) -> Option<(Option<Suggestion>, Option<String>)> {
3432 let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3433 return None;
3434 };
3435
3436 while let Some(parent) = crate_module.parent {
3437 crate_module = parent;
3438 }
3439
3440 if module == ModuleOrUniformRoot::Module(crate_module) {
3441 return None;
3443 }
3444
3445 let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3446 let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3447 let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3448 return None;
3449 };
3450 if !kinds.contains(MacroKinds::BANG) {
3451 return None;
3452 }
3453 let module_name = crate_module.name().unwrap_or(kw::Crate);
3454 let import_snippet = match import.kind {
3455 ImportKind::Single { source, target, .. } if source != target => {
3456 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}", source, target))
})format!("{source} as {target}")
3457 }
3458 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}"),
3459 };
3460
3461 let mut corrections: Vec<(Span, String)> = Vec::new();
3462 if !import.is_nested() {
3463 corrections.push((import.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}", module_name,
import_snippet))
})format!("{module_name}::{import_snippet}")));
3466 } else {
3467 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3471 self.tcx.sess,
3472 import.span,
3473 import.use_span,
3474 );
3475 {
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:3475",
"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(3475u32),
::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);
3476
3477 let mut removal_span = binding_span;
3478
3479 if found_closing_brace
3487 && let Some(previous_span) =
3488 extend_span_to_previous_binding(self.tcx.sess, binding_span)
3489 {
3490 {
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:3490",
"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(3490u32),
::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);
3491 removal_span = removal_span.with_lo(previous_span.lo());
3492 }
3493 {
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:3493",
"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(3493u32),
::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);
3494
3495 corrections.push((removal_span, "".to_string()));
3497
3498 let (has_nested, after_crate_name) =
3505 find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3506 {
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:3506",
"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(3506u32),
::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);
3507
3508 let source_map = self.tcx.sess.source_map();
3509
3510 let is_definitely_crate = import
3512 .module_path
3513 .first()
3514 .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3515
3516 let start_point = source_map.start_point(after_crate_name);
3518 if is_definitely_crate
3519 && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3520 {
3521 corrections.push((
3522 start_point,
3523 if has_nested {
3524 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
import_snippet))
})format!("{start_snippet}{import_snippet}, ")
3526 } else {
3527 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
start_snippet))
})format!("{{{import_snippet}, {start_snippet}")
3530 },
3531 ));
3532
3533 if !has_nested {
3535 corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3536 }
3537 } else {
3538 corrections.push((
3540 import.use_span.shrink_to_lo(),
3541 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
import_snippet))
})format!("use {module_name}::{import_snippet};\n"),
3542 ));
3543 }
3544 }
3545
3546 let suggestion = Some((
3547 corrections,
3548 String::from("a macro with this name exists at the root of the crate"),
3549 Applicability::MaybeIncorrect,
3550 ));
3551 Some((
3552 suggestion,
3553 Some(
3554 "this could be because a macro annotated with `#[macro_export]` will be exported \
3555 at the root of the crate instead of the module where it is defined"
3556 .to_string(),
3557 ),
3558 ))
3559 }
3560
3561 pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3563 let local_items;
3564 let symbols = if module.is_local() {
3565 local_items = self
3566 .stripped_cfg_items
3567 .iter()
3568 .filter_map(|item| {
3569 let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
3570 ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
3571 Some(def_id)
3572 }
3573 _ => None,
3574 })?;
3575 Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3576 })
3577 .collect::<Vec<_>>();
3578 local_items.as_slice()
3579 } else {
3580 self.tcx.stripped_cfg_items(module.krate)
3581 };
3582
3583 for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3584 if ident.name != *segment {
3585 continue;
3586 }
3587
3588 let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3589
3590 fn comes_from_same_module_for_glob(
3591 r: &Resolver<'_, '_>,
3592 parent_module: DefId,
3593 module: DefId,
3594 visited: &mut FxHashMap<DefId, bool>,
3595 ) -> bool {
3596 if let Some(&cached) = visited.get(&parent_module) {
3597 return cached;
3601 }
3602 visited.insert(parent_module, false);
3603 let mut res = false;
3604 let m = r.expect_module(parent_module);
3605 if m.is_local() {
3606 for importer in m.glob_importers.borrow().iter() {
3607 if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
3608 {
3609 if next_parent_module == module
3610 || comes_from_same_module_for_glob(
3611 r,
3612 next_parent_module,
3613 module,
3614 visited,
3615 )
3616 {
3617 res = true;
3618 break;
3619 }
3620 }
3621 }
3622 }
3623 visited.insert(parent_module, res);
3624 res
3625 }
3626
3627 let comes_from_same_module = parent_module == module
3628 || comes_from_same_module_for_glob(
3629 self,
3630 parent_module,
3631 module,
3632 &mut Default::default(),
3633 );
3634 if !comes_from_same_module {
3635 continue;
3636 }
3637
3638 let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3639 diagnostics::ItemWas::BehindFeature { feature, span: cfg.1 }
3640 } else {
3641 diagnostics::ItemWas::CfgOut { span: cfg.1 }
3642 };
3643 let note = diagnostics::FoundItemConfigureOut { span: ident.span, item_was };
3644 err.subdiagnostic(note);
3645 }
3646 }
3647
3648 pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3649 match def_id.as_local() {
3650 Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3651 None => {
3652 self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3653 let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3654 let vis = self.tcx.visibility(ctor_def_id);
3655 let field_visibilities = self
3656 .tcx
3657 .associated_item_def_ids(def_id)
3658 .iter()
3659 .map(|&field_id| self.tcx.visibility(field_id))
3660 .collect();
3661 StructCtor { res, vis, field_visibilities }
3662 })
3663 }
3664 }
3665 }
3666
3667 pub(crate) fn on_unknown_data(&self, def_id: DefId) -> Option<&Directive> {
3669 match def_id.as_local() {
3670 Some(local) => Some(self.on_unknown_data.get(&local)?.directive.as_ref()),
3671 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(),
3672 }
3673 }
3674}
3675
3676fn find_span_of_binding_until_next_binding(
3690 sess: &Session,
3691 binding_span: Span,
3692 use_span: Span,
3693) -> (bool, Span) {
3694 let source_map = sess.source_map();
3695
3696 let binding_until_end = binding_span.with_hi(use_span.hi());
3699
3700 let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3703
3704 let mut found_closing_brace = false;
3711 let after_binding_until_next_binding =
3712 source_map.span_take_while(after_binding_until_end, |&ch| {
3713 if ch == '}' {
3714 found_closing_brace = true;
3715 }
3716 ch == ' ' || ch == ','
3717 });
3718
3719 let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3724
3725 (found_closing_brace, span)
3726}
3727
3728fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3741 let source_map = sess.source_map();
3742
3743 let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3747
3748 let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3749 let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3750 if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3751 return None;
3752 }
3753
3754 let prev_comma = prev_comma.first().unwrap();
3755 let prev_starting_brace = prev_starting_brace.first().unwrap();
3756
3757 if prev_comma.len() > prev_starting_brace.len() {
3761 return None;
3762 }
3763
3764 Some(binding_span.with_lo(BytePos(
3765 binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3768 )))
3769}
3770
3771#[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(3784u32),
::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))]
3785fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3786 let source_map = sess.source_map();
3787
3788 let mut num_colons = 0;
3790 let until_second_colon = source_map.span_take_while(use_span, |c| {
3792 if *c == ':' {
3793 num_colons += 1;
3794 }
3795 !matches!(c, ':' if num_colons == 2)
3796 });
3797 let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3799
3800 let mut found_a_non_whitespace_character = false;
3801 let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3803 if found_a_non_whitespace_character {
3804 return false;
3805 }
3806 if !c.is_whitespace() {
3807 found_a_non_whitespace_character = true;
3808 }
3809 true
3810 });
3811
3812 let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3814
3815 (next_left_bracket == after_second_colon, from_second_colon)
3816}
3817
3818enum Instead {
3821 Yes,
3822 No,
3823}
3824
3825enum FoundUse {
3827 Yes,
3828 No,
3829}
3830
3831pub(crate) enum DiagMode {
3833 Normal,
3834 Pattern,
3836 Import {
3838 unresolved_import: bool,
3840 append: bool,
3843 },
3844}
3845
3846pub(crate) fn import_candidates(
3847 tcx: TyCtxt<'_>,
3848 err: &mut Diag<'_>,
3849 use_placement_span: Option<Span>,
3851 candidates: &[ImportSuggestion],
3852 mode: DiagMode,
3853 append: &str,
3854) {
3855 show_candidates(
3856 tcx,
3857 err,
3858 use_placement_span,
3859 candidates,
3860 Instead::Yes,
3861 FoundUse::Yes,
3862 mode,
3863 ::alloc::vec::Vec::new()vec![],
3864 append,
3865 );
3866}
3867
3868type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3869
3870fn show_candidates(
3875 tcx: TyCtxt<'_>,
3876 err: &mut Diag<'_>,
3877 use_placement_span: Option<Span>,
3879 candidates: &[ImportSuggestion],
3880 instead: Instead,
3881 found_use: FoundUse,
3882 mode: DiagMode,
3883 path: Vec<Segment>,
3884 append: &str,
3885) -> bool {
3886 if candidates.is_empty() {
3887 return false;
3888 }
3889
3890 let mut showed = false;
3891 let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3892 let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3893
3894 candidates.iter().for_each(|c| {
3895 if c.accessible {
3896 if c.doc_visible {
3898 accessible_path_strings.push((
3899 pprust::path_to_string(&c.path),
3900 c.descr,
3901 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3902 &c.note,
3903 c.via_import,
3904 ))
3905 }
3906 } else {
3907 inaccessible_path_strings.push((
3908 pprust::path_to_string(&c.path),
3909 c.descr,
3910 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3911 &c.note,
3912 c.via_import,
3913 ))
3914 }
3915 });
3916
3917 for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3920 path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3921 path_strings.dedup_by(|a, b| a.0 == b.0);
3922 let core_path_strings =
3923 path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3924 let std_path_strings =
3925 path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3926 let foreign_crate_path_strings =
3927 path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3928
3929 if std_path_strings.len() == core_path_strings.len() {
3932 path_strings.extend(std_path_strings);
3934 } else {
3935 path_strings.extend(std_path_strings);
3936 path_strings.extend(core_path_strings);
3937 }
3938 path_strings.extend(foreign_crate_path_strings);
3940 }
3941
3942 if !accessible_path_strings.is_empty() {
3943 let (determiner, kind, s, name, through) =
3944 if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3945 (
3946 "this",
3947 *descr,
3948 "",
3949 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", name))
})format!(" `{name}`"),
3950 if *via_import { " through its public re-export" } else { "" },
3951 )
3952 } else {
3953 let kinds = accessible_path_strings
3956 .iter()
3957 .map(|(_, descr, _, _, _)| *descr)
3958 .collect::<UnordSet<&str>>();
3959 let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3960 let s = if kind.ends_with('s') { "es" } else { "s" };
3961
3962 ("one of these", kind, s, String::new(), "")
3963 };
3964
3965 let instead = if let Instead::Yes = instead { " instead" } else { "" };
3966 let mut msg = if let DiagMode::Pattern = mode {
3967 ::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!(
3968 "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3969 pattern",
3970 )
3971 } else {
3972 ::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}")
3973 };
3974
3975 for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3976 err.note(note.clone());
3977 }
3978
3979 let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3980 msg.push(':');
3981
3982 for candidate in accessible_path_strings {
3983 msg.push('\n');
3984 msg.push_str(&candidate.0);
3985 }
3986 };
3987
3988 if let Some(span) = use_placement_span {
3989 let (add_use, trailing) = match mode {
3990 DiagMode::Pattern => {
3991 err.span_suggestions(
3992 span,
3993 msg,
3994 accessible_path_strings.into_iter().map(|a| a.0),
3995 Applicability::MaybeIncorrect,
3996 );
3997 return true;
3998 }
3999 DiagMode::Import { .. } => ("", ""),
4000 DiagMode::Normal => ("use ", ";\n"),
4001 };
4002 for candidate in &mut accessible_path_strings {
4003 let additional_newline = if let FoundUse::No = found_use
4006 && let DiagMode::Normal = mode
4007 {
4008 "\n"
4009 } else {
4010 ""
4011 };
4012 candidate.0 =
4013 ::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);
4014 }
4015
4016 match mode {
4017 DiagMode::Import { append: true, .. } => {
4018 append_candidates(&mut msg, accessible_path_strings);
4019 err.span_help(span, msg);
4020 }
4021 _ => {
4022 err.span_suggestions_with_style(
4023 span,
4024 msg,
4025 accessible_path_strings.into_iter().map(|a| a.0),
4026 Applicability::MaybeIncorrect,
4027 SuggestionStyle::ShowAlways,
4028 );
4029 }
4030 }
4031
4032 if let [first, .., last] = &path[..] {
4033 let sp = first.ident.span.until(last.ident.span);
4034 if sp.can_be_used_for_suggestions() && !sp.is_empty() {
4037 err.span_suggestion_verbose(
4038 sp,
4039 ::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),
4040 "",
4041 Applicability::Unspecified,
4042 );
4043 }
4044 }
4045 } else {
4046 append_candidates(&mut msg, accessible_path_strings);
4047 err.help(msg);
4048 }
4049 showed = true;
4050 }
4051 if !inaccessible_path_strings.is_empty()
4052 && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
DiagMode::Import { unresolved_import: false, .. } => true,
_ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
4053 {
4054 let prefix =
4055 if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
4056 if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
4057 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!(
4058 "{prefix}{descr} `{name}`{} exists but is inaccessible",
4059 if let DiagMode::Pattern = mode { ", which" } else { "" }
4060 );
4061
4062 if let Some(source_span) = source_span {
4063 let span = tcx.sess.source_map().guess_head_span(*source_span);
4064 let mut multi_span = MultiSpan::from_span(span);
4065 multi_span.push_span_label(span, "not accessible");
4066 err.span_note(multi_span, msg);
4067 } else {
4068 err.note(msg);
4069 }
4070 if let Some(note) = (*note).as_deref() {
4071 err.note(note.to_string());
4072 }
4073 } else {
4074 let descr = inaccessible_path_strings
4075 .iter()
4076 .map(|&(_, descr, _, _, _)| descr)
4077 .all_equal_value()
4078 .unwrap_or("item");
4079 let plural_descr =
4080 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") };
4081
4082 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");
4083 let mut has_colon = false;
4084
4085 let mut spans = Vec::new();
4086 for (name, _, source_span, _, _) in &inaccessible_path_strings {
4087 if let Some(source_span) = source_span {
4088 let span = tcx.sess.source_map().guess_head_span(*source_span);
4089 spans.push((name, span));
4090 } else {
4091 if !has_colon {
4092 msg.push(':');
4093 has_colon = true;
4094 }
4095 msg.push('\n');
4096 msg.push_str(name);
4097 }
4098 }
4099
4100 let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
4101 for (name, span) in spans {
4102 multi_span.push_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
})format!("`{name}`: not accessible"));
4103 }
4104
4105 for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4106 err.note(note.clone());
4107 }
4108
4109 err.span_note(multi_span, msg);
4110 }
4111 showed = true;
4112 }
4113 showed
4114}
4115
4116#[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)]
4117struct UsePlacementFinder {
4118 target_module: NodeId,
4119 first_legal_span: Option<Span>,
4120 first_use_span: Option<Span>,
4121}
4122
4123impl UsePlacementFinder {
4124 fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
4125 let mut finder =
4126 UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
4127 finder.visit_crate(krate);
4128 if let Some(use_span) = finder.first_use_span {
4129 (Some(use_span), FoundUse::Yes)
4130 } else {
4131 (finder.first_legal_span, FoundUse::No)
4132 }
4133 }
4134}
4135
4136impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
4137 fn visit_crate(&mut self, c: &Crate) {
4138 if self.target_module == CRATE_NODE_ID {
4139 let inject = c.spans.inject_use_span;
4140 if is_span_suitable_for_use_injection(inject) {
4141 self.first_legal_span = Some(inject);
4142 }
4143 self.first_use_span = search_for_any_use_in_items(&c.items);
4144 } else {
4145 visit::walk_crate(self, c);
4146 }
4147 }
4148
4149 fn visit_item(&mut self, item: &'tcx ast::Item) {
4150 if self.target_module == item.id {
4151 if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
4152 let inject = mod_spans.inject_use_span;
4153 if is_span_suitable_for_use_injection(inject) {
4154 self.first_legal_span = Some(inject);
4155 }
4156 self.first_use_span = search_for_any_use_in_items(items);
4157 }
4158 } else {
4159 visit::walk_item(self, item);
4160 }
4161 }
4162}
4163
4164#[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)]
4165struct BindingVisitor {
4166 identifiers: Vec<Symbol>,
4167 spans: FxHashMap<Symbol, Vec<Span>>,
4168}
4169
4170impl<'tcx> Visitor<'tcx> for BindingVisitor {
4171 fn visit_pat(&mut self, pat: &ast::Pat) {
4172 if let ast::PatKind::Ident(_, ident, _) = pat.kind {
4173 self.identifiers.push(ident.name);
4174 self.spans.entry(ident.name).or_default().push(ident.span);
4175 }
4176 visit::walk_pat(self, pat);
4177 }
4178}
4179
4180fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
4181 for item in items {
4182 if let ItemKind::Use(..) = item.kind
4183 && is_span_suitable_for_use_injection(item.span)
4184 {
4185 let mut lo = item.span.lo();
4186 for attr in &item.attrs {
4187 if attr.span.eq_ctxt(item.span) {
4188 lo = std::cmp::min(lo, attr.span.lo());
4189 }
4190 }
4191 return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
4192 }
4193 }
4194 None
4195}
4196
4197fn is_span_suitable_for_use_injection(s: Span) -> bool {
4198 !s.from_expansion()
4201}
4202
4203#[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)]
4204pub(crate) struct OnUnknownData {
4205 pub(crate) directive: Box<Directive>,
4206}
4207
4208impl OnUnknownData {
4209 pub(crate) fn from_attrs(
4210 r: &Resolver<'_, '_>,
4211 attrs: &[ast::Attribute],
4212 ) -> Option<OnUnknownData> {
4213 if r.features.diagnostic_on_unknown()
4214 && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) =
4215 AttributeParser::parse_limited_sym(
4216 r.tcx.sess,
4217 attrs,
4218 &[sym::diagnostic, sym::on_unknown],
4219 )
4220 {
4221 Some(Self { directive: directive? })
4222 } else {
4223 None
4224 }
4225 }
4226}