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(
2440 &self,
2441 suggestion: &mut ImportSuggestion,
2442 current_module: Module<'ra>,
2443 ) {
2444 const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;
2445
2446 if suggestion.did.is_none_or(|did| !did.is_local()) {
2448 return;
2449 }
2450
2451 let Some(current_mod_path) = self.module_path_names(current_module) else {
2453 return;
2454 };
2455
2456 let candidate_names = {
2460 let filtered_segments: Vec<_> = suggestion
2461 .path
2462 .segments
2463 .iter()
2464 .filter(|segment| segment.ident.name != kw::PathRoot)
2465 .collect();
2466
2467 let mut candidate_names: Vec<Symbol> =
2468 filtered_segments.iter().map(|segment| segment.ident.name).collect();
2469 if candidate_names.first() != Some(&kw::Crate) {
2470 candidate_names.insert(0, kw::Crate);
2471 }
2472 if candidate_names.len() < 2 {
2473 return;
2474 }
2475 candidate_names
2476 };
2477
2478 let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];
2480
2481 let common_prefix_length = current_mod_path
2483 .iter()
2484 .zip(candidate_mod_names.iter())
2485 .take_while(|(current, candidate)| current == candidate)
2486 .count();
2487
2488 if common_prefix_length == 0 {
2490 return;
2491 }
2492
2493 let super_count = current_mod_path.len() - common_prefix_length;
2494
2495 let at_crate_root = current_mod_path.len() == 1;
2498
2499 let mut new_segments = if super_count == 0 && at_crate_root {
2500 ThinVec::new()
2501 } else {
2502 let prefix_keyword = match super_count {
2503 0 => kw::SelfLower,
2504 1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
2505 _ => return, };
2507 {
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),)]
2508 };
2509 for &name in &candidate_names[common_prefix_length..] {
2510 new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
2511 }
2512
2513 if new_segments.len() >= suggestion.path.segments.len() {
2515 return;
2516 }
2517
2518 suggestion.path = Path { span: suggestion.path.span, segments: new_segments };
2519 }
2520
2521 fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2522 let PrivacyError {
2523 ident,
2524 decl,
2525 outermost_res,
2526 parent_scope,
2527 single_nested,
2528 dedup_span,
2529 ref source,
2530 } = *privacy_error;
2531
2532 let res = decl.res();
2533 let ctor_fields_span = self.ctor_fields_span(decl);
2534 let plain_descr = res.descr().to_string();
2535 let nonimport_descr =
2536 if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2537 let import_descr = nonimport_descr.clone() + " import";
2538 let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2539
2540 let ident_descr = get_descr(decl);
2542 let mut err =
2543 self.dcx().create_err(diagnostics::IsPrivate { span: ident.span, ident_descr, ident });
2544
2545 self.mention_default_field_values(source, ident, &mut err);
2546
2547 let shown_candidates = if let Some((this_res, outer_ident)) = outermost_res {
2548 let mut import_suggestions = self.lookup_import_candidates(
2549 outer_ident,
2550 this_res.ns().unwrap_or(Namespace::TypeNS),
2551 &parent_scope,
2552 &|res: Res| res == this_res,
2553 );
2554 for suggestion in &mut import_suggestions {
2556 self.shorten_candidate_path(suggestion, parent_scope.module);
2557 }
2558 let point_to_def = !show_candidates(
2559 self.tcx,
2560 &mut err,
2561 Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2562 &import_suggestions,
2563 Instead::Yes,
2564 FoundUse::Yes,
2565 DiagMode::Import { append: single_nested, unresolved_import: false },
2566 ::alloc::vec::Vec::new()vec![],
2567 "",
2568 );
2569 if point_to_def && ident.span != outer_ident.span {
2571 let label = diagnostics::OuterIdentIsNotPubliclyReexported {
2572 span: outer_ident.span,
2573 outer_ident_descr: this_res.descr(),
2574 outer_ident,
2575 };
2576 err.subdiagnostic(label);
2577 }
2578 !point_to_def
2579 } else {
2580 false
2581 };
2582
2583 let mut non_exhaustive = None;
2584 if let Some(def_id) = res.opt_def_id()
2588 && !def_id.is_local()
2589 && 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)
2590 {
2591 non_exhaustive = Some(attr_span);
2592 } else if let Some(span) = ctor_fields_span {
2593 let label = diagnostics::ConstructorPrivateIfAnyFieldPrivate { span };
2594 err.subdiagnostic(label);
2595 if let Res::Def(_, d) = res
2596 && let Some(fields) = self.field_visibility_spans.get(&d)
2597 {
2598 let spans = fields.iter().map(|span| *span).collect();
2599 let sugg = diagnostics::ConsiderMakingTheFieldPublic {
2600 spans,
2601 number_of_fields: fields.len(),
2602 };
2603 err.subdiagnostic(sugg);
2604 }
2605 }
2606
2607 let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2608 if let Some(mut def_id) = res.opt_def_id() {
2609 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];
2611 while let Some(parent) = self.tcx.opt_parent(def_id) {
2612 def_id = parent;
2613 if !def_id.is_top_level_module() {
2614 path.push(def_id);
2615 } else {
2616 break;
2617 }
2618 }
2619 let path_names: Option<Vec<Ident>> = path
2621 .iter()
2622 .rev()
2623 .map(|def_id| {
2624 self.tcx.opt_item_name(*def_id).map(|name| {
2625 Ident::with_dummy_span(if def_id.is_top_level_module() {
2626 kw::Crate
2627 } else {
2628 name
2629 })
2630 })
2631 })
2632 .collect();
2633 if let Some(&def_id) = path.get(0)
2634 && let Some(path) = path_names
2635 {
2636 if let Some(def_id) = def_id.as_local() {
2637 if self.effective_visibilities.is_directly_public(def_id) {
2638 sugg_paths.push((path, false));
2639 }
2640 } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2641 {
2642 sugg_paths.push((path, false));
2643 }
2644 }
2645 }
2646
2647 let first_binding = decl;
2649 let mut next_binding = Some(decl);
2650 let mut next_ident = ident;
2651 while let Some(binding) = next_binding {
2652 let name = next_ident;
2653 next_binding = match binding.kind {
2654 _ if res == Res::Err => None,
2655 DeclKind::Import { source_decl, import, .. } => match import.kind {
2656 _ if source_decl.span.is_dummy() => None,
2657 ImportKind::Single { source, .. } => {
2658 next_ident = source;
2659 Some(source_decl)
2660 }
2661 ImportKind::Glob { .. }
2662 | ImportKind::MacroUse { .. }
2663 | ImportKind::MacroExport => Some(source_decl),
2664 ImportKind::ExternCrate { .. } => None,
2665 },
2666 _ => None,
2667 };
2668
2669 match binding.kind {
2670 DeclKind::Import { source_decl, import, .. } => {
2671 let path = import
2674 .module_path
2675 .iter()
2676 .filter(|seg| seg.ident.name != kw::PathRoot)
2677 .map(|seg| seg.ident.clone())
2678 .chain(std::iter::once(ident))
2679 .collect::<Vec<_>>();
2680 let through_reexport = !#[allow(non_exhaustive_omitted_patterns)] match source_decl.kind {
DeclKind::Def(_) => true,
_ => false,
}matches!(source_decl.kind, DeclKind::Def(_));
2681 sugg_paths.push((path, through_reexport));
2682 }
2683 DeclKind::Def(_) => {}
2684 }
2685 let first = binding == first_binding;
2686 let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2687 let mut note_span = MultiSpan::from_span(def_span);
2688 if !first && binding.vis().is_public() {
2689 let desc = match binding.kind {
2690 DeclKind::Import { .. } => "re-export",
2691 _ => "directly",
2692 };
2693 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}"));
2694 }
2695 if next_binding.is_none()
2698 && let Some(span) = non_exhaustive
2699 {
2700 note_span.push_span_label(
2701 span,
2702 "cannot be constructed because it is `#[non_exhaustive]`",
2703 );
2704 }
2705 let note = diagnostics::NoteAndRefersToTheItemDefinedHere {
2706 span: note_span,
2707 binding_descr: get_descr(binding),
2708 binding_name: name,
2709 first,
2710 dots: next_binding.is_some(),
2711 };
2712 err.subdiagnostic(note);
2713 }
2714 let can_replace_use = !shown_candidates
2722 && !single_nested
2723 && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
2724 if can_replace_use {
2725 sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2728 for (sugg, reexport) in sugg_paths {
2729 if sugg.len() <= 1 {
2730 continue;
2733 }
2734 let path = join_path_idents(sugg);
2735 let sugg = if reexport {
2736 diagnostics::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2737 } else {
2738 diagnostics::ImportIdent::Directly { span: dedup_span, ident, path }
2739 };
2740 err.subdiagnostic(sugg);
2741 break;
2742 }
2743 }
2744
2745 err.emit();
2746 }
2747
2748 fn mention_default_field_values(
2768 &self,
2769 source: &Option<ast::Expr>,
2770 ident: Ident,
2771 err: &mut Diag<'_>,
2772 ) {
2773 let Some(expr) = source else { return };
2774 let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2775 let Some(segment) = struct_expr.path.segments.last() else { return };
2778 let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2779 let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2780 return;
2781 };
2782 let Some(default_fields) = self.field_defaults(def_id) else { return };
2783 if struct_expr.fields.is_empty() {
2784 return;
2785 }
2786 let last_span = struct_expr.fields.iter().last().unwrap().span;
2787 let mut iter = struct_expr.fields.iter().peekable();
2788 let mut prev: Option<Span> = None;
2789 while let Some(field) = iter.next() {
2790 if field.expr.span.overlaps(ident.span) {
2791 err.span_label(field.ident.span, "while setting this field");
2792 if default_fields.contains(&field.ident.name) {
2793 let sugg = if last_span == field.span {
2794 ::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())]
2795 } else {
2796 ::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![
2797 (
2798 match (prev, iter.peek()) {
2800 (_, Some(next)) => field.span.with_hi(next.span.lo()),
2801 (Some(prev), _) => field.span.with_lo(prev.hi()),
2802 (None, None) => field.span,
2803 },
2804 String::new(),
2805 ),
2806 (last_span.shrink_to_hi(), ", ..".to_string()),
2807 ]
2808 };
2809 err.multipart_suggestion(
2810 ::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!(
2811 "the type `{ident}` of field `{}` is private, but you can construct \
2812 the default value defined for it in `{}` using `..` in the struct \
2813 initializer expression",
2814 field.ident,
2815 self.tcx.item_name(def_id),
2816 ),
2817 sugg,
2818 Applicability::MachineApplicable,
2819 );
2820 break;
2821 }
2822 }
2823 prev = Some(field.span);
2824 }
2825 }
2826
2827 pub(crate) fn find_similarly_named_module_or_crate(
2828 &self,
2829 ident: Symbol,
2830 current_module: Module<'ra>,
2831 ) -> Option<Symbol> {
2832 let mut candidates = self
2833 .extern_prelude
2834 .keys()
2835 .map(|ident| ident.name)
2836 .chain(
2837 self.local_module_map
2838 .iter()
2839 .filter(|(_, module)| {
2840 let module = module.to_module();
2841 current_module.is_ancestor_of(module) && current_module != module
2842 })
2843 .flat_map(|(_, module)| module.name()),
2844 )
2845 .chain(
2846 self.extern_module_map
2847 .borrow()
2848 .iter()
2849 .filter(|(_, module)| {
2850 let module = module.to_module();
2851 current_module.is_ancestor_of(module) && current_module != module
2852 })
2853 .flat_map(|(_, module)| module.name()),
2854 )
2855 .filter(|c| !c.to_string().is_empty())
2856 .collect::<Vec<_>>();
2857 candidates.sort();
2858 candidates.dedup();
2859 find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2860 }
2861
2862 pub(crate) fn report_path_resolution_error(
2863 &mut self,
2864 path: &[Segment],
2865 opt_ns: Option<Namespace>, parent_scope: &ParentScope<'ra>,
2867 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2868 ignore_decl: Option<Decl<'ra>>,
2869 ignore_import: Option<Import<'ra>>,
2870 module: Option<ModuleOrUniformRoot<'ra>>,
2871 failed_segment_idx: usize,
2872 ident: Ident,
2873 diag_metadata: Option<&DiagMetadata<'_>>,
2874 ) -> (String, String, Option<Suggestion>) {
2875 let is_last = failed_segment_idx == path.len() - 1;
2876 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2877 let module_def_id = match module {
2878 Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
2879 _ => None,
2880 };
2881 let scope = match &path[..failed_segment_idx] {
2882 [.., prev] => {
2883 if prev.ident.name == kw::PathRoot {
2884 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the crate root"))
})format!("the crate root")
2885 } else {
2886 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", prev.ident))
})format!("`{}`", prev.ident)
2887 }
2888 }
2889 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this scope"))
})format!("this scope"),
2890 };
2891 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
scope))
})format!("cannot find `{ident}` in {scope}");
2892
2893 if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
2894 let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Mod, _) => true,
_ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2895 let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2896 candidates
2897 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2898 if let Some(candidate) = candidates.get(0) {
2899 let path = {
2900 let len = candidate.path.segments.len();
2902 let start_index = (0..=failed_segment_idx.min(len - 1))
2903 .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2904 .unwrap_or_default();
2905 let segments =
2906 (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2907 Path { segments, span: Span::default() }
2908 };
2909 (
2910 message,
2911 String::from("unresolved import"),
2912 Some((
2913 ::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))],
2914 String::from("a similar path exists"),
2915 Applicability::MaybeIncorrect,
2916 )),
2917 )
2918 } else if ident.name == sym::core {
2919 (
2920 message,
2921 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
ident))
})format!("you might be missing crate `{ident}`"),
2922 Some((
2923 ::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())],
2924 "try using `std` instead of `core`".to_string(),
2925 Applicability::MaybeIncorrect,
2926 )),
2927 )
2928 } else if ident.name == kw::Underscore {
2929 (
2930 "invalid crate or module name `_`".to_string(),
2931 "`_` is not a valid crate or module name".to_string(),
2932 None,
2933 )
2934 } else if self.tcx.sess.is_rust_2015() {
2935 (
2936 ::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}"),
2937 ::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}`"),
2938 Some((
2939 ::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![(
2940 self.current_crate_outer_attr_insert_span,
2941 format!("extern crate {ident};\n"),
2942 )],
2943 if was_invoked_from_cargo() {
2944 ::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!(
2945 "if you wanted to use a crate named `{ident}`, use `cargo add \
2946 {ident}` to add it to your `Cargo.toml` and import it in your \
2947 code",
2948 )
2949 } else {
2950 ::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!(
2951 "you might be missing a crate named `{ident}`, add it to your \
2952 project and import it in your code",
2953 )
2954 },
2955 Applicability::MaybeIncorrect,
2956 )),
2957 )
2958 } else {
2959 (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)
2960 }
2961 } else if failed_segment_idx > 0 {
2962 let parent = path[failed_segment_idx - 1].ident.name;
2963 let parent = match parent {
2964 kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
2967 "the list of imported crates".to_owned()
2968 }
2969 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
2970 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", parent))
})format!("`{parent}`"),
2971 };
2972
2973 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}");
2974 if ns == TypeNS || ns == ValueNS {
2975 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
2976 let binding = if let Some(module) = module {
2977 self.cm()
2978 .resolve_ident_in_module(
2979 module,
2980 ident,
2981 ns_to_try,
2982 parent_scope,
2983 None,
2984 ignore_decl,
2985 ignore_import,
2986 )
2987 .ok()
2988 } else if let Some(ribs) = ribs
2989 && let Some(TypeNS | ValueNS) = opt_ns
2990 {
2991 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2992 match self.resolve_ident_in_lexical_scope(
2993 ident,
2994 ns_to_try,
2995 parent_scope,
2996 None,
2997 &ribs[ns_to_try],
2998 ignore_decl,
2999 diag_metadata,
3000 ) {
3001 Some(LateDecl::Decl(binding)) => Some(binding),
3003 _ => None,
3004 }
3005 } else {
3006 self.cm()
3007 .resolve_ident_in_scope_set(
3008 ident,
3009 ScopeSet::All(ns_to_try),
3010 parent_scope,
3011 None,
3012 ignore_decl,
3013 ignore_import,
3014 )
3015 .ok()
3016 };
3017 if let Some(binding) = binding {
3018 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!(
3019 "expected {}, found {} `{ident}` in {parent}",
3020 ns.descr(),
3021 binding.res().descr(),
3022 );
3023 };
3024 }
3025 (message, msg, None)
3026 } else if ident.name == kw::SelfUpper {
3027 if opt_ns.is_none() {
3031 (message, "`Self` cannot be used in imports".to_string(), None)
3032 } else {
3033 (
3034 message,
3035 "`Self` is only available in impls, traits, and type definitions".to_string(),
3036 None,
3037 )
3038 }
3039 } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
3040 let binding = if let Some(ribs) = ribs {
3042 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
3043 self.resolve_ident_in_lexical_scope(
3044 ident,
3045 ValueNS,
3046 parent_scope,
3047 None,
3048 &ribs[ValueNS],
3049 ignore_decl,
3050 diag_metadata,
3051 )
3052 } else {
3053 None
3054 };
3055 let match_span = match binding {
3056 Some(LateDecl::RibDef(Res::Local(id))) => {
3065 Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
3066 }
3067 Some(LateDecl::Decl(name_binding)) => Some((
3079 name_binding.span,
3080 name_binding.res().article(),
3081 name_binding.res().descr(),
3082 )),
3083 _ => None,
3084 };
3085
3086 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}");
3087 let label = if let Some((span, article, descr)) = match_span {
3088 ::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!(
3089 "`{ident}` is declared as {article} {descr} at `{}`, not a type",
3090 self.tcx
3091 .sess
3092 .source_map()
3093 .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
3094 )
3095 } else {
3096 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
ident))
})format!("use of undeclared type `{ident}`")
3097 };
3098 (message, label, None)
3099 } else {
3100 let mut suggestion = None;
3101 if ident.name == sym::alloc {
3102 suggestion = Some((
3103 ::alloc::vec::Vec::new()vec![],
3104 String::from("add `extern crate alloc` to use the `alloc` crate"),
3105 Applicability::MaybeIncorrect,
3106 ))
3107 }
3108
3109 suggestion = suggestion.or_else(|| {
3110 self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
3111 |sugg| {
3112 (
3113 ::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())],
3114 String::from("there is a crate or module with a similar name"),
3115 Applicability::MaybeIncorrect,
3116 )
3117 },
3118 )
3119 });
3120 if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
3121 ident,
3122 ScopeSet::All(ValueNS),
3123 parent_scope,
3124 None,
3125 ignore_decl,
3126 ignore_import,
3127 ) {
3128 let descr = binding.res().descr();
3129 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}");
3130 (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)
3131 } else {
3132 let suggestion = if suggestion.is_some() {
3133 suggestion
3134 } else if let Some(m) = self.undeclared_module_exists(ident) {
3135 self.undeclared_module_suggest_declare(ident, m)
3136 } else if was_invoked_from_cargo() {
3137 Some((
3138 ::alloc::vec::Vec::new()vec![],
3139 ::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!(
3140 "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
3141 to add it to your `Cargo.toml`",
3142 ),
3143 Applicability::MaybeIncorrect,
3144 ))
3145 } else {
3146 Some((
3147 ::alloc::vec::Vec::new()vec![],
3148 ::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}`",),
3149 Applicability::MaybeIncorrect,
3150 ))
3151 };
3152 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}");
3153 (
3154 message,
3155 ::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}`"),
3156 suggestion,
3157 )
3158 }
3159 }
3160 }
3161
3162 fn undeclared_module_suggest_declare(
3163 &self,
3164 ident: Ident,
3165 path: std::path::PathBuf,
3166 ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
3167 Some((
3168 ::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"))],
3169 ::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!(
3170 "to make use of source file {}, use `mod {ident}` \
3171 in this file to declare the module",
3172 path.display()
3173 ),
3174 Applicability::MaybeIncorrect,
3175 ))
3176 }
3177
3178 fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
3179 let map = self.tcx.sess.source_map();
3180
3181 let src = map.span_to_filename(ident.span).into_local_path()?;
3182 let i = ident.as_str();
3183 let dir = src.parent()?;
3185 let src = src.file_stem()?.to_str()?;
3186 for file in [
3187 dir.join(i).with_extension("rs"),
3189 dir.join(i).join("mod.rs"),
3191 ] {
3192 if file.exists() {
3193 return Some(file);
3194 }
3195 }
3196 if !#[allow(non_exhaustive_omitted_patterns)] match src {
"main" | "lib" | "mod" => true,
_ => false,
}matches!(src, "main" | "lib" | "mod") {
3197 for file in [
3198 dir.join(src).join(i).with_extension("rs"),
3200 dir.join(src).join(i).join("mod.rs"),
3202 ] {
3203 if file.exists() {
3204 return Some(file);
3205 }
3206 }
3207 }
3208 None
3209 }
3210
3211 #[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3212u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3213 pub(crate) fn make_path_suggestion(
3214 &mut self,
3215 mut path: Vec<Segment>,
3216 parent_scope: &ParentScope<'ra>,
3217 ) -> Option<(Vec<Segment>, Option<String>)> {
3218 match path[..] {
3219 [first, second, ..]
3222 if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
3223 [first, ..]
3225 if first.ident.span.at_least_rust_2018()
3226 && !first.ident.is_path_segment_keyword() =>
3227 {
3228 path.insert(0, Segment::from_ident(Ident::dummy()));
3230 }
3231 _ => return None,
3232 }
3233
3234 self.make_missing_self_suggestion(path.clone(), parent_scope)
3235 .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
3236 .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
3237 .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
3238 }
3239
3240 #[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3247u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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/error_helper.rs:3256",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3256u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3248 fn make_missing_self_suggestion(
3249 &mut self,
3250 mut path: Vec<Segment>,
3251 parent_scope: &ParentScope<'ra>,
3252 ) -> Option<(Vec<Segment>, Option<String>)> {
3253 path[0].ident.name = kw::SelfLower;
3255 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3256 debug!(?path, ?result);
3257 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3258 }
3259
3260 #[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3267u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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/error_helper.rs:3276",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3276u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3268 fn make_missing_crate_suggestion(
3269 &mut self,
3270 mut path: Vec<Segment>,
3271 parent_scope: &ParentScope<'ra>,
3272 ) -> Option<(Vec<Segment>, Option<String>)> {
3273 path[0].ident.name = kw::Crate;
3275 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3276 debug!(?path, ?result);
3277 if let PathResult::Module(..) = result {
3278 Some((
3279 path,
3280 Some(
3281 "`use` statements changed in Rust 2018; read more at \
3282 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
3283 clarity.html>"
3284 .to_string(),
3285 ),
3286 ))
3287 } else {
3288 None
3289 }
3290 }
3291
3292 #[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3299u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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/error_helper.rs:3308",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3308u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3300 fn make_missing_super_suggestion(
3301 &mut self,
3302 mut path: Vec<Segment>,
3303 parent_scope: &ParentScope<'ra>,
3304 ) -> Option<(Vec<Segment>, Option<String>)> {
3305 path[0].ident.name = kw::Super;
3307 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3308 debug!(?path, ?result);
3309 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3310 }
3311
3312 #[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3322u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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/error_helper.rs:3343",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3343u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3323 fn make_external_crate_suggestion(
3324 &mut self,
3325 mut path: Vec<Segment>,
3326 parent_scope: &ParentScope<'ra>,
3327 ) -> Option<(Vec<Segment>, Option<String>)> {
3328 if path[1].ident.span.is_rust_2015() {
3329 return None;
3330 }
3331
3332 let mut extern_crate_names =
3336 self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
3337 extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
3338
3339 for name in extern_crate_names.into_iter() {
3340 path[0].ident.name = name;
3342 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3343 debug!(?path, ?name, ?result);
3344 if let PathResult::Module(..) = result {
3345 return Some((path, None));
3346 }
3347 }
3348
3349 None
3350 }
3351
3352 pub(crate) fn check_for_module_export_macro(
3365 &mut self,
3366 import: Import<'ra>,
3367 module: ModuleOrUniformRoot<'ra>,
3368 ident: Ident,
3369 ) -> Option<(Option<Suggestion>, Option<String>)> {
3370 let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3371 return None;
3372 };
3373
3374 while let Some(parent) = crate_module.parent {
3375 crate_module = parent;
3376 }
3377
3378 if module == ModuleOrUniformRoot::Module(crate_module) {
3379 return None;
3381 }
3382
3383 let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3384 let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3385 let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3386 return None;
3387 };
3388 if !kinds.contains(MacroKinds::BANG) {
3389 return None;
3390 }
3391 let module_name = crate_module.name().unwrap_or(kw::Crate);
3392 let import_snippet = match import.kind {
3393 ImportKind::Single { source, target, .. } if source != target => {
3394 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}", source, target))
})format!("{source} as {target}")
3395 }
3396 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}"),
3397 };
3398
3399 let mut corrections: Vec<(Span, String)> = Vec::new();
3400 if !import.is_nested() {
3401 corrections.push((import.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}", module_name,
import_snippet))
})format!("{module_name}::{import_snippet}")));
3404 } else {
3405 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3409 self.tcx.sess,
3410 import.span,
3411 import.use_span,
3412 );
3413 {
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/error_helper.rs:3413",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3413u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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);
3414
3415 let mut removal_span = binding_span;
3416
3417 if found_closing_brace
3425 && let Some(previous_span) =
3426 extend_span_to_previous_binding(self.tcx.sess, binding_span)
3427 {
3428 {
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/error_helper.rs:3428",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3428u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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);
3429 removal_span = removal_span.with_lo(previous_span.lo());
3430 }
3431 {
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/error_helper.rs:3431",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3431u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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);
3432
3433 corrections.push((removal_span, "".to_string()));
3435
3436 let (has_nested, after_crate_name) =
3443 find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3444 {
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/error_helper.rs:3444",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3444u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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);
3445
3446 let source_map = self.tcx.sess.source_map();
3447
3448 let is_definitely_crate = import
3450 .module_path
3451 .first()
3452 .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3453
3454 let start_point = source_map.start_point(after_crate_name);
3456 if is_definitely_crate
3457 && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3458 {
3459 corrections.push((
3460 start_point,
3461 if has_nested {
3462 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
import_snippet))
})format!("{start_snippet}{import_snippet}, ")
3464 } else {
3465 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
start_snippet))
})format!("{{{import_snippet}, {start_snippet}")
3468 },
3469 ));
3470
3471 if !has_nested {
3473 corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3474 }
3475 } else {
3476 corrections.push((
3478 import.use_span.shrink_to_lo(),
3479 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
import_snippet))
})format!("use {module_name}::{import_snippet};\n"),
3480 ));
3481 }
3482 }
3483
3484 let suggestion = Some((
3485 corrections,
3486 String::from("a macro with this name exists at the root of the crate"),
3487 Applicability::MaybeIncorrect,
3488 ));
3489 Some((
3490 suggestion,
3491 Some(
3492 "this could be because a macro annotated with `#[macro_export]` will be exported \
3493 at the root of the crate instead of the module where it is defined"
3494 .to_string(),
3495 ),
3496 ))
3497 }
3498
3499 pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3501 let local_items;
3502 let symbols = if module.is_local() {
3503 local_items = self
3504 .stripped_cfg_items
3505 .iter()
3506 .filter_map(|item| {
3507 let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
3508 ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
3509 Some(def_id)
3510 }
3511 _ => None,
3512 })?;
3513 Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3514 })
3515 .collect::<Vec<_>>();
3516 local_items.as_slice()
3517 } else {
3518 self.tcx.stripped_cfg_items(module.krate)
3519 };
3520
3521 for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3522 if ident.name != *segment {
3523 continue;
3524 }
3525
3526 let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3527
3528 fn comes_from_same_module_for_glob(
3529 r: &Resolver<'_, '_>,
3530 parent_module: DefId,
3531 module: DefId,
3532 visited: &mut FxHashMap<DefId, bool>,
3533 ) -> bool {
3534 if let Some(&cached) = visited.get(&parent_module) {
3535 return cached;
3539 }
3540 visited.insert(parent_module, false);
3541 let mut res = false;
3542 let m = r.expect_module(parent_module);
3543 if m.is_local() {
3544 for importer in m.glob_importers.borrow().iter() {
3545 if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
3546 {
3547 if next_parent_module == module
3548 || comes_from_same_module_for_glob(
3549 r,
3550 next_parent_module,
3551 module,
3552 visited,
3553 )
3554 {
3555 res = true;
3556 break;
3557 }
3558 }
3559 }
3560 }
3561 visited.insert(parent_module, res);
3562 res
3563 }
3564
3565 let comes_from_same_module = parent_module == module
3566 || comes_from_same_module_for_glob(
3567 self,
3568 parent_module,
3569 module,
3570 &mut Default::default(),
3571 );
3572 if !comes_from_same_module {
3573 continue;
3574 }
3575
3576 let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3577 diagnostics::ItemWas::BehindFeature { feature, span: cfg.1 }
3578 } else {
3579 diagnostics::ItemWas::CfgOut { span: cfg.1 }
3580 };
3581 let note = diagnostics::FoundItemConfigureOut { span: ident.span, item_was };
3582 err.subdiagnostic(note);
3583 }
3584 }
3585
3586 pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3587 match def_id.as_local() {
3588 Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3589 None => {
3590 self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3591 let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3592 let vis = self.tcx.visibility(ctor_def_id);
3593 let field_visibilities = self
3594 .tcx
3595 .associated_item_def_ids(def_id)
3596 .iter()
3597 .map(|&field_id| self.tcx.visibility(field_id))
3598 .collect();
3599 StructCtor { res, vis, field_visibilities }
3600 })
3601 }
3602 }
3603 }
3604
3605 fn on_unknown_data(&self, def_id: DefId) -> Option<&Directive> {
3607 match def_id.as_local() {
3608 Some(local) => Some(self.on_unknown_data.get(&local)?.directive.as_ref()),
3609 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(),
3610 }
3611 }
3612}
3613
3614fn find_span_of_binding_until_next_binding(
3628 sess: &Session,
3629 binding_span: Span,
3630 use_span: Span,
3631) -> (bool, Span) {
3632 let source_map = sess.source_map();
3633
3634 let binding_until_end = binding_span.with_hi(use_span.hi());
3637
3638 let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3641
3642 let mut found_closing_brace = false;
3649 let after_binding_until_next_binding =
3650 source_map.span_take_while(after_binding_until_end, |&ch| {
3651 if ch == '}' {
3652 found_closing_brace = true;
3653 }
3654 ch == ' ' || ch == ','
3655 });
3656
3657 let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3662
3663 (found_closing_brace, span)
3664}
3665
3666fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3679 let source_map = sess.source_map();
3680
3681 let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3685
3686 let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3687 let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3688 if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3689 return None;
3690 }
3691
3692 let prev_comma = prev_comma.first().unwrap();
3693 let prev_starting_brace = prev_starting_brace.first().unwrap();
3694
3695 if prev_comma.len() > prev_starting_brace.len() {
3699 return None;
3700 }
3701
3702 Some(binding_span.with_lo(BytePos(
3703 binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3706 )))
3707}
3708
3709#[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::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3722u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::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))]
3723fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3724 let source_map = sess.source_map();
3725
3726 let mut num_colons = 0;
3728 let until_second_colon = source_map.span_take_while(use_span, |c| {
3730 if *c == ':' {
3731 num_colons += 1;
3732 }
3733 !matches!(c, ':' if num_colons == 2)
3734 });
3735 let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3737
3738 let mut found_a_non_whitespace_character = false;
3739 let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3741 if found_a_non_whitespace_character {
3742 return false;
3743 }
3744 if !c.is_whitespace() {
3745 found_a_non_whitespace_character = true;
3746 }
3747 true
3748 });
3749
3750 let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3752
3753 (next_left_bracket == after_second_colon, from_second_colon)
3754}
3755
3756enum Instead {
3759 Yes,
3760 No,
3761}
3762
3763enum FoundUse {
3765 Yes,
3766 No,
3767}
3768
3769pub(crate) enum DiagMode {
3771 Normal,
3772 Pattern,
3774 Import {
3776 unresolved_import: bool,
3778 append: bool,
3781 },
3782}
3783
3784pub(crate) fn import_candidates(
3785 tcx: TyCtxt<'_>,
3786 err: &mut Diag<'_>,
3787 use_placement_span: Option<Span>,
3789 candidates: &[ImportSuggestion],
3790 mode: DiagMode,
3791 append: &str,
3792) {
3793 show_candidates(
3794 tcx,
3795 err,
3796 use_placement_span,
3797 candidates,
3798 Instead::Yes,
3799 FoundUse::Yes,
3800 mode,
3801 ::alloc::vec::Vec::new()vec![],
3802 append,
3803 );
3804}
3805
3806type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3807
3808fn show_candidates(
3813 tcx: TyCtxt<'_>,
3814 err: &mut Diag<'_>,
3815 use_placement_span: Option<Span>,
3817 candidates: &[ImportSuggestion],
3818 instead: Instead,
3819 found_use: FoundUse,
3820 mode: DiagMode,
3821 path: Vec<Segment>,
3822 append: &str,
3823) -> bool {
3824 if candidates.is_empty() {
3825 return false;
3826 }
3827
3828 let mut showed = false;
3829 let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3830 let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3831
3832 candidates.iter().for_each(|c| {
3833 if c.accessible {
3834 if c.doc_visible {
3836 accessible_path_strings.push((
3837 pprust::path_to_string(&c.path),
3838 c.descr,
3839 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3840 &c.note,
3841 c.via_import,
3842 ))
3843 }
3844 } else {
3845 inaccessible_path_strings.push((
3846 pprust::path_to_string(&c.path),
3847 c.descr,
3848 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3849 &c.note,
3850 c.via_import,
3851 ))
3852 }
3853 });
3854
3855 for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3858 path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3859 path_strings.dedup_by(|a, b| a.0 == b.0);
3860 let core_path_strings =
3861 path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3862 let std_path_strings =
3863 path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3864 let foreign_crate_path_strings =
3865 path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3866
3867 if std_path_strings.len() == core_path_strings.len() {
3870 path_strings.extend(std_path_strings);
3872 } else {
3873 path_strings.extend(std_path_strings);
3874 path_strings.extend(core_path_strings);
3875 }
3876 path_strings.extend(foreign_crate_path_strings);
3878 }
3879
3880 if !accessible_path_strings.is_empty() {
3881 let (determiner, kind, s, name, through) =
3882 if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3883 (
3884 "this",
3885 *descr,
3886 "",
3887 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", name))
})format!(" `{name}`"),
3888 if *via_import { " through its public re-export" } else { "" },
3889 )
3890 } else {
3891 let kinds = accessible_path_strings
3894 .iter()
3895 .map(|(_, descr, _, _, _)| *descr)
3896 .collect::<UnordSet<&str>>();
3897 let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3898 let s = if kind.ends_with('s') { "es" } else { "s" };
3899
3900 ("one of these", kind, s, String::new(), "")
3901 };
3902
3903 let instead = if let Instead::Yes = instead { " instead" } else { "" };
3904 let mut msg = if let DiagMode::Pattern = mode {
3905 ::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!(
3906 "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3907 pattern",
3908 )
3909 } else {
3910 ::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}")
3911 };
3912
3913 for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3914 err.note(note.clone());
3915 }
3916
3917 let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3918 msg.push(':');
3919
3920 for candidate in accessible_path_strings {
3921 msg.push('\n');
3922 msg.push_str(&candidate.0);
3923 }
3924 };
3925
3926 if let Some(span) = use_placement_span {
3927 let (add_use, trailing) = match mode {
3928 DiagMode::Pattern => {
3929 err.span_suggestions(
3930 span,
3931 msg,
3932 accessible_path_strings.into_iter().map(|a| a.0),
3933 Applicability::MaybeIncorrect,
3934 );
3935 return true;
3936 }
3937 DiagMode::Import { .. } => ("", ""),
3938 DiagMode::Normal => ("use ", ";\n"),
3939 };
3940 for candidate in &mut accessible_path_strings {
3941 let additional_newline = if let FoundUse::No = found_use
3944 && let DiagMode::Normal = mode
3945 {
3946 "\n"
3947 } else {
3948 ""
3949 };
3950 candidate.0 =
3951 ::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);
3952 }
3953
3954 match mode {
3955 DiagMode::Import { append: true, .. } => {
3956 append_candidates(&mut msg, accessible_path_strings);
3957 err.span_help(span, msg);
3958 }
3959 _ => {
3960 err.span_suggestions_with_style(
3961 span,
3962 msg,
3963 accessible_path_strings.into_iter().map(|a| a.0),
3964 Applicability::MaybeIncorrect,
3965 SuggestionStyle::ShowAlways,
3966 );
3967 }
3968 }
3969
3970 if let [first, .., last] = &path[..] {
3971 let sp = first.ident.span.until(last.ident.span);
3972 if sp.can_be_used_for_suggestions() && !sp.is_empty() {
3975 err.span_suggestion_verbose(
3976 sp,
3977 ::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),
3978 "",
3979 Applicability::Unspecified,
3980 );
3981 }
3982 }
3983 } else {
3984 append_candidates(&mut msg, accessible_path_strings);
3985 err.help(msg);
3986 }
3987 showed = true;
3988 }
3989 if !inaccessible_path_strings.is_empty()
3990 && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
DiagMode::Import { unresolved_import: false, .. } => true,
_ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
3991 {
3992 let prefix =
3993 if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
3994 if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
3995 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!(
3996 "{prefix}{descr} `{name}`{} exists but is inaccessible",
3997 if let DiagMode::Pattern = mode { ", which" } else { "" }
3998 );
3999
4000 if let Some(source_span) = source_span {
4001 let span = tcx.sess.source_map().guess_head_span(*source_span);
4002 let mut multi_span = MultiSpan::from_span(span);
4003 multi_span.push_span_label(span, "not accessible");
4004 err.span_note(multi_span, msg);
4005 } else {
4006 err.note(msg);
4007 }
4008 if let Some(note) = (*note).as_deref() {
4009 err.note(note.to_string());
4010 }
4011 } else {
4012 let descr = inaccessible_path_strings
4013 .iter()
4014 .map(|&(_, descr, _, _, _)| descr)
4015 .all_equal_value()
4016 .unwrap_or("item");
4017 let plural_descr =
4018 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") };
4019
4020 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");
4021 let mut has_colon = false;
4022
4023 let mut spans = Vec::new();
4024 for (name, _, source_span, _, _) in &inaccessible_path_strings {
4025 if let Some(source_span) = source_span {
4026 let span = tcx.sess.source_map().guess_head_span(*source_span);
4027 spans.push((name, span));
4028 } else {
4029 if !has_colon {
4030 msg.push(':');
4031 has_colon = true;
4032 }
4033 msg.push('\n');
4034 msg.push_str(name);
4035 }
4036 }
4037
4038 let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
4039 for (name, span) in spans {
4040 multi_span.push_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
})format!("`{name}`: not accessible"));
4041 }
4042
4043 for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
4044 err.note(note.clone());
4045 }
4046
4047 err.span_note(multi_span, msg);
4048 }
4049 showed = true;
4050 }
4051 showed
4052}
4053
4054#[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)]
4055struct UsePlacementFinder {
4056 target_module: NodeId,
4057 first_legal_span: Option<Span>,
4058 first_use_span: Option<Span>,
4059}
4060
4061impl UsePlacementFinder {
4062 fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
4063 let mut finder =
4064 UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
4065 finder.visit_crate(krate);
4066 if let Some(use_span) = finder.first_use_span {
4067 (Some(use_span), FoundUse::Yes)
4068 } else {
4069 (finder.first_legal_span, FoundUse::No)
4070 }
4071 }
4072}
4073
4074impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
4075 fn visit_crate(&mut self, c: &Crate) {
4076 if self.target_module == CRATE_NODE_ID {
4077 let inject = c.spans.inject_use_span;
4078 if is_span_suitable_for_use_injection(inject) {
4079 self.first_legal_span = Some(inject);
4080 }
4081 self.first_use_span = search_for_any_use_in_items(&c.items);
4082 } else {
4083 visit::walk_crate(self, c);
4084 }
4085 }
4086
4087 fn visit_item(&mut self, item: &'tcx ast::Item) {
4088 if self.target_module == item.id {
4089 if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
4090 let inject = mod_spans.inject_use_span;
4091 if is_span_suitable_for_use_injection(inject) {
4092 self.first_legal_span = Some(inject);
4093 }
4094 self.first_use_span = search_for_any_use_in_items(items);
4095 }
4096 } else {
4097 visit::walk_item(self, item);
4098 }
4099 }
4100}
4101
4102#[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)]
4103struct BindingVisitor {
4104 identifiers: Vec<Symbol>,
4105 spans: FxHashMap<Symbol, Vec<Span>>,
4106}
4107
4108impl<'tcx> Visitor<'tcx> for BindingVisitor {
4109 fn visit_pat(&mut self, pat: &ast::Pat) {
4110 if let ast::PatKind::Ident(_, ident, _) = pat.kind {
4111 self.identifiers.push(ident.name);
4112 self.spans.entry(ident.name).or_default().push(ident.span);
4113 }
4114 visit::walk_pat(self, pat);
4115 }
4116}
4117
4118fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
4119 for item in items {
4120 if let ItemKind::Use(..) = item.kind
4121 && is_span_suitable_for_use_injection(item.span)
4122 {
4123 let mut lo = item.span.lo();
4124 for attr in &item.attrs {
4125 if attr.span.eq_ctxt(item.span) {
4126 lo = std::cmp::min(lo, attr.span.lo());
4127 }
4128 }
4129 return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
4130 }
4131 }
4132 None
4133}
4134
4135fn is_span_suitable_for_use_injection(s: Span) -> bool {
4136 !s.from_expansion()
4139}
4140
4141#[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)]
4142pub(crate) struct OnUnknownData {
4143 pub(crate) directive: Box<Directive>,
4144}
4145
4146impl OnUnknownData {
4147 pub(crate) fn from_attrs(
4148 r: &Resolver<'_, '_>,
4149 attrs: &[ast::Attribute],
4150 ) -> Option<OnUnknownData> {
4151 if r.features.diagnostic_on_unknown()
4152 && let Some(Attribute::Parsed(AttributeKind::OnUnknown { directive, .. })) =
4153 AttributeParser::parse_limited(
4154 r.tcx.sess,
4155 attrs,
4156 &[sym::diagnostic, sym::on_unknown],
4157 )
4158 {
4159 Some(Self { directive: directive? })
4160 } else {
4161 None
4162 }
4163 }
4164}