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