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