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