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