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