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