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_data_structures::fx::{FxHashMap, FxHashSet};
13use rustc_data_structures::unord::{UnordMap, UnordSet};
14use rustc_errors::codes::*;
15use rustc_errors::{
16 Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
17 struct_span_code_err,
18};
19use rustc_feature::BUILTIN_ATTRIBUTES;
20use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
21use rustc_hir::def::Namespace::{self, *};
22use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
23use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
24use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr};
25use rustc_middle::bug;
26use rustc_middle::ty::{TyCtxt, Visibility};
27use rustc_session::Session;
28use rustc_session::lint::builtin::{
29 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
30 AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
31};
32use rustc_session::utils::was_invoked_from_cargo;
33use rustc_span::edit_distance::find_best_match_for_name;
34use rustc_span::edition::Edition;
35use rustc_span::hygiene::MacroKind;
36use rustc_span::source_map::SourceMap;
37use rustc_span::{
38 BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,
39};
40use thin_vec::{ThinVec, thin_vec};
41use tracing::{debug, instrument};
42
43use crate::diagnostics::{
44 self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
45 ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
46 MaybeMissingMacroRulesName,
47};
48use crate::hygiene::Macros20NormalizedSyntaxContext;
49use crate::imports::{Import, ImportKind};
50use crate::late::{DiagMetadata, PatternSource, Rib};
51use crate::{
52 AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
53 DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey,
54 LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
55 PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
56 VisResolutionError, path_names_to_string,
57};
58
59pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);
61
62pub(crate) type LabelSuggestion = (Ident, bool);
65
66#[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)]
67pub(crate) struct StructCtor {
68 pub res: Res,
69 pub vis: Visibility<DefId>,
70 pub field_visibilities: Vec<Visibility<DefId>>,
71}
72
73impl StructCtor {
74 pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
75 self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
76 }
77}
78
79#[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)]
80pub(crate) enum SuggestionTarget {
81 SimilarlyNamed,
83 SingleItem,
85}
86
87#[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)]
88pub(crate) struct TypoSuggestion {
89 pub candidate: Symbol,
90 pub span: Option<Span>,
93 pub res: Res,
94 pub target: SuggestionTarget,
95}
96
97impl TypoSuggestion {
98 pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
99 Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
100 }
101 pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
102 Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
103 }
104 pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
105 Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
106 }
107}
108
109#[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, #[automatically_derived]
impl ::core::clone::Clone for ImportSuggestion {
#[inline]
fn clone(&self) -> ImportSuggestion {
ImportSuggestion {
did: ::core::clone::Clone::clone(&self.did),
descr: ::core::clone::Clone::clone(&self.descr),
path: ::core::clone::Clone::clone(&self.path),
accessible: ::core::clone::Clone::clone(&self.accessible),
doc_visible: ::core::clone::Clone::clone(&self.doc_visible),
via_import: ::core::clone::Clone::clone(&self.via_import),
note: ::core::clone::Clone::clone(&self.note),
is_stable: ::core::clone::Clone::clone(&self.is_stable),
}
}
}Clone)]
111pub(crate) struct ImportSuggestion {
112 pub did: Option<DefId>,
113 pub descr: &'static str,
114 pub path: Path,
115 pub accessible: bool,
116 pub doc_visible: bool,
118 pub via_import: bool,
119 pub note: Option<String>,
121 pub is_stable: bool,
122}
123
124fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
132 let impl_span = sm.span_until_char(impl_span, '<');
133 sm.span_until_whitespace(impl_span)
134}
135
136impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
137 pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
138 self.tcx.dcx()
139 }
140
141 pub(crate) fn report_errors(&mut self, krate: &Crate) {
142 self.report_delayed_vis_resolution_errors();
143 self.report_with_use_injections(krate);
144
145 for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
146 self.lint_buffer.buffer_lint(
147 MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
148 CRATE_NODE_ID,
149 span_use,
150 diagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths {
151 definition: span_def,
152 },
153 );
154 }
155
156 for ambiguity_error in &self.ambiguity_errors {
157 let mut diag = self.ambiguity_diagnostic(ambiguity_error);
158
159 if let Some(ambiguity_warning) = ambiguity_error.warning {
160 let node_id = match ambiguity_error.b1.0.kind {
161 DeclKind::Import { import, .. } => import.root_id,
162 DeclKind::Def(_) => CRATE_NODE_ID,
163 };
164
165 let lint = match ambiguity_warning {
166 _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
167 AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
168 AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
169 };
170
171 self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
172 } else {
173 diag.is_error = true;
174 self.dcx().emit_err(diag);
175 }
176 }
177
178 let mut reported_spans = FxHashSet::default();
179 for error in mem::take(&mut self.privacy_errors) {
180 if reported_spans.insert(error.dedup_span) {
181 self.report_privacy_error(&error);
182 }
183 }
184 }
185
186 fn report_delayed_vis_resolution_errors(&mut self) {
187 for DelayedVisResolutionError { vis, parent_scope, error } in
188 mem::take(&mut self.delayed_vis_resolution_errors)
189 {
190 match self.try_resolve_visibility(&parent_scope, &vis, true) {
191 Ok(_) => self.report_vis_error(error),
192 Err(error) => self.report_vis_error(error),
193 };
194 }
195 }
196
197 fn report_with_use_injections(&mut self, krate: &Crate) {
198 for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in
199 mem::take(&mut self.use_injections)
200 {
201 let (span, found_use) = if node_id != DUMMY_NODE_ID {
202 UsePlacementFinder::check(krate, node_id)
203 } else {
204 (None, FoundUse::No)
205 };
206
207 if !candidates.is_empty() {
208 show_candidates(
209 self.tcx,
210 &mut err,
211 span,
212 &candidates,
213 if instead { Instead::Yes } else { Instead::No },
214 found_use,
215 DiagMode::Normal,
216 path,
217 "",
218 );
219 err.emit();
220 } else if let Some((span, msg, sugg, appl)) = suggestion {
221 err.span_suggestion_verbose(span, msg, sugg, appl);
222 err.emit();
223 } else if let [segment] = path.as_slice()
224 && is_call
225 {
226 err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
227 } else {
228 err.emit();
229 }
230 }
231 }
232
233 pub(crate) fn report_conflict(
234 &mut self,
235 ident: IdentKey,
236 ns: Namespace,
237 old_binding: Decl<'ra>,
238 new_binding: Decl<'ra>,
239 ) {
240 if old_binding.span.lo() > new_binding.span.lo() {
242 return self.report_conflict(ident, ns, new_binding, old_binding);
243 }
244
245 let container = match old_binding.parent_module.unwrap().expect_local().kind {
246 ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id),
249 ModuleKind::Block => "block",
250 };
251
252 let (name, span) =
253 (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));
254
255 if self.name_already_seen.get(&name) == Some(&span) {
256 return;
257 }
258
259 let old_kind = match (ns, old_binding.res()) {
260 (ValueNS, _) => "value",
261 (MacroNS, _) => "macro",
262 (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
263 (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
264 (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
265 (TypeNS, _) => "type",
266 };
267
268 let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
269 (true, true) => E0259,
270 (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
271 true => E0254,
272 false => E0260,
273 },
274 _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
275 (false, false) => E0428,
276 (true, true) => E0252,
277 _ => E0255,
278 },
279 };
280
281 let label = match new_binding.is_import_user_facing() {
282 true => diagnostics::NameDefinedMultipleTimeLabel::Reimported { span, name },
283 false => diagnostics::NameDefinedMultipleTimeLabel::Redefined { span, name },
284 };
285
286 let old_binding_label =
287 (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
288 let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
289 match old_binding.is_import_user_facing() {
290 true => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Import {
291 span,
292 old_kind,
293 name,
294 },
295 false => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Definition {
296 span,
297 old_kind,
298 name,
299 },
300 }
301 });
302
303 let mut err = self
304 .dcx()
305 .create_err(diagnostics::NameDefinedMultipleTime {
306 span,
307 name,
308 descr: ns.descr(),
309 container,
310 label,
311 old_binding_label,
312 })
313 .with_code(code);
314
315 use DeclKind::Import;
317 let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
318 !binding.span.is_dummy()
319 && !#[allow(non_exhaustive_omitted_patterns)] match import.kind {
ImportKind::MacroUse { .. } | ImportKind::MacroExport => true,
_ => false,
}matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
320 };
321 let import = match (&new_binding.kind, &old_binding.kind) {
322 (Import { import: new, .. }, Import { import: old, .. })
325 if {
326 (new.has_attributes || old.has_attributes)
327 && can_suggest(old_binding, *old)
328 && can_suggest(new_binding, *new)
329 } =>
330 {
331 if old.has_attributes {
332 Some((*new, new_binding.span, true))
333 } else {
334 Some((*old, old_binding.span, true))
335 }
336 }
337 (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
339 Some((*import, new_binding.span, other.is_import()))
340 }
341 (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
342 Some((*import, old_binding.span, other.is_import()))
343 }
344 _ => None,
345 };
346
347 let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
349 let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
350 let from_item =
351 self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
352 let should_remove_import = duplicate
356 && !has_dummy_span
357 && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);
358
359 match import {
360 Some((import, span, true)) if should_remove_import && import.is_nested() => {
361 self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
362 }
363 Some((import, _, true)) if should_remove_import && !import.is_glob() => {
364 err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport {
367 span: import.use_span_with_attributes,
368 });
369 }
370 Some((import, span, _)) => {
371 self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
372 }
373 _ => {}
374 }
375
376 err.emit();
377 self.name_already_seen.insert(name, span);
378 }
379
380 fn add_suggestion_for_rename_of_use(
390 &self,
391 err: &mut Diag<'_>,
392 name: Symbol,
393 import: Import<'_>,
394 binding_span: Span,
395 ) {
396 let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
397 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Other{0}", name))
})format!("Other{name}")
398 } else {
399 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("other_{0}", name))
})format!("other_{name}")
400 };
401
402 let mut suggestion = None;
403 let mut span = binding_span;
404 match import.kind {
405 ImportKind::Single { source, .. } => {
406 if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
407 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
408 && pos as usize <= snippet.len()
409 {
410 span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
411 binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
412 );
413 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" as {0}", suggested_name))
})format!(" as {suggested_name}"));
414 }
415 }
416 ImportKind::ExternCrate { source, target, .. } => {
417 suggestion = Some(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern crate {0} as {1};",
source.unwrap_or(target.name), suggested_name))
})format!(
418 "extern crate {} as {};",
419 source.unwrap_or(target.name),
420 suggested_name,
421 ))
422 }
423 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
424 }
425
426 if let Some(suggestion) = suggestion {
427 err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
428 } else {
429 err.subdiagnostic(ChangeImportBinding { span });
430 }
431 }
432
433 fn add_suggestion_for_duplicate_nested_use(
456 &self,
457 err: &mut Diag<'_>,
458 import: Import<'_>,
459 binding_span: Span,
460 ) {
461 if !import.is_nested() {
::core::panicking::panic("assertion failed: import.is_nested()")
};assert!(import.is_nested());
462
463 let (found_closing_brace, span) =
471 find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);
472
473 if found_closing_brace {
476 if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
477 err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport { span });
478 } else {
479 err.subdiagnostic(diagnostics::RemoveUnnecessaryImport {
482 span: import.use_span_with_attributes,
483 });
484 }
485
486 return;
487 }
488
489 err.subdiagnostic(diagnostics::RemoveUnnecessaryImport { span });
490 }
491
492 pub(crate) fn lint_if_path_starts_with_module(
493 &mut self,
494 finalize: Finalize,
495 path: &[Segment],
496 second_binding: Option<Decl<'_>>,
497 ) {
498 let Finalize { node_id, root_span, .. } = finalize;
499
500 let first_name = match path.get(0) {
501 Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
503 seg.ident.name
504 }
505 _ => return,
506 };
507
508 if first_name != kw::PathRoot {
511 return;
512 }
513
514 match path.get(1) {
515 Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
517 Some(_) => {}
519 None => return,
523 }
524
525 if let Some(binding) = second_binding
529 && let DeclKind::Import { import, .. } = binding.kind
530 && let ImportKind::ExternCrate { source: None, .. } = import.kind
532 {
533 return;
534 }
535
536 self.lint_buffer.dyn_buffer_lint_any(
537 ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
538 node_id,
539 root_span,
540 move |dcx, level, sess| {
541 let (replacement, applicability) = match sess
542 .downcast_ref::<Session>()
543 .expect("expected a `Session`")
544 .source_map()
545 .span_to_snippet(root_span)
546 {
547 Ok(ref s) => {
548 let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };
551
552 (::alloc::__export::must_use({
::alloc::fmt::format(format_args!("crate{0}{1}", opt_colon, s))
})format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
553 }
554 Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
555 };
556 diagnostics::AbsPathWithModule {
557 sugg: diagnostics::AbsPathWithModuleSugg {
558 span: root_span,
559 applicability,
560 replacement,
561 },
562 }
563 .into_diag(dcx, level)
564 },
565 );
566 }
567
568 pub(crate) fn add_module_candidates(
569 &self,
570 module: Module<'ra>,
571 names: &mut Vec<TypoSuggestion>,
572 filter_fn: &impl Fn(Res) -> bool,
573 ctxt: Option<SyntaxContext>,
574 ) {
575 module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
576 let res = binding.res();
577 if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
578 names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
579 }
580 });
581 }
582
583 pub(crate) fn report_error(
588 &mut self,
589 span: Span,
590 resolution_error: ResolutionError<'ra>,
591 ) -> ErrorGuaranteed {
592 self.into_struct_error(span, resolution_error).emit()
593 }
594
595 pub(crate) fn into_struct_error(
596 &mut self,
597 span: Span,
598 resolution_error: ResolutionError<'ra>,
599 ) -> Diag<'_> {
600 match resolution_error {
601 ResolutionError::GenericParamsFromOuterItem {
602 outer_res,
603 has_generic_params,
604 def_kind,
605 inner_item,
606 current_self_ty,
607 } => {
608 use diagnostics::GenericParamsFromOuterItemLabel as Label;
609 let static_or_const = match def_kind {
610 DefKind::Static { .. } => {
611 Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Static)
612 }
613 DefKind::Const { .. } => {
614 Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Const)
615 }
616 _ => None,
617 };
618 let is_self =
619 #[allow(non_exhaustive_omitted_patterns)] match outer_res {
Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => true,
_ => false,
}matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
620 let mut err = diagnostics::GenericParamsFromOuterItem {
621 span,
622 label: None,
623 refer_to_type_directly: None,
624 use_let: None,
625 sugg: None,
626 static_or_const,
627 is_self,
628 item: inner_item.as_ref().map(|(label_span, _, kind)| {
629 diagnostics::GenericParamsFromOuterItemInnerItem {
630 span: *label_span,
631 descr: kind.descr().to_string(),
632 is_self,
633 }
634 }),
635 };
636
637 let sm = self.tcx.sess.source_map();
638 let def_id = match outer_res {
641 Res::SelfTyParam { .. } => {
642 err.label = Some(Label::SelfTyParam(span));
643 None
644 }
645 Res::SelfTyAlias { alias_to: def_id, .. } => {
646 err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
647 sm,
648 self.def_span(def_id),
649 )));
650 err.refer_to_type_directly = current_self_ty
651 .map(|snippet| diagnostics::UseTypeDirectly { span, snippet });
652 None
653 }
654 Res::Def(DefKind::TyParam, def_id) => {
655 err.label = Some(Label::TyParam(self.def_span(def_id)));
656 Some(def_id)
657 }
658 Res::Def(DefKind::ConstParam, def_id) => {
659 err.label = Some(Label::ConstParam(self.def_span(def_id)));
660 Some(def_id)
661 }
662 _ => {
663 ::rustc_middle::util::bug::bug_fmt(format_args!("GenericParamsFromOuterItem should only be used with Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or DefKind::ConstParam"));bug!(
664 "GenericParamsFromOuterItem should only be used with \
665 Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
666 DefKind::ConstParam"
667 );
668 }
669 };
670
671 if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() {
672 err.use_let = Some(diagnostics::GenericParamsFromOuterItemUseLet {
673 span: sm.span_until_whitespace(*item_span),
674 });
675 }
676
677 if let Some(def_id) = def_id
678 && let HasGenericParams::Yes(span) = has_generic_params
679 && !#[allow(non_exhaustive_omitted_patterns)] match inner_item {
Some((_, _, ItemKind::Delegation(..))) => true,
_ => false,
}matches!(inner_item, Some((_, _, ItemKind::Delegation(..))))
680 {
681 let name = self.tcx.item_name(def_id);
682 let (span, snippet) = if span.is_empty() {
683 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("<{0}>", name))
})format!("<{name}>");
684 (span, snippet)
685 } else {
686 let span = sm.span_through_char(span, '<').shrink_to_hi();
687 let snippet = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}, ", name))
})format!("{name}, ");
688 (span, snippet)
689 };
690 err.sugg = Some(diagnostics::GenericParamsFromOuterItemSugg { span, snippet });
691 }
692
693 self.dcx().create_err(err)
694 }
695 ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
696 self.dcx().create_err(diagnostics::NameAlreadyUsedInParameterList {
697 span,
698 first_use_span,
699 name,
700 })
701 }
702 ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
703 self.dcx().create_err(diagnostics::MethodNotMemberOfTrait {
704 span,
705 method,
706 trait_,
707 sub: candidate.map(|c| diagnostics::AssociatedFnWithSimilarNameExists {
708 span: method.span,
709 candidate: c,
710 }),
711 })
712 }
713 ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
714 self.dcx().create_err(diagnostics::TypeNotMemberOfTrait {
715 span,
716 type_,
717 trait_,
718 sub: candidate.map(|c| diagnostics::AssociatedTypeWithSimilarNameExists {
719 span: type_.span,
720 candidate: c,
721 }),
722 })
723 }
724 ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
725 self.dcx().create_err(diagnostics::ConstNotMemberOfTrait {
726 span,
727 const_,
728 trait_,
729 sub: candidate.map(|c| diagnostics::AssociatedConstWithSimilarNameExists {
730 span: const_.span,
731 candidate: c,
732 }),
733 })
734 }
735 ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
736 let BindingError { name, target, origin, could_be_path } = binding_error;
737
738 let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
739 target_sp.sort();
740 target_sp.dedup();
741 let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
742 origin_sp.sort();
743 origin_sp.dedup();
744
745 let msp = MultiSpan::from_spans(target_sp.clone());
746 let mut err = self.dcx().create_err(diagnostics::VariableIsNotBoundInAllPatterns {
747 multispan: msp,
748 name,
749 });
750 for sp in target_sp {
751 err.subdiagnostic(diagnostics::PatternDoesntBindName { span: sp, name });
752 }
753 for sp in &origin_sp {
754 err.subdiagnostic(diagnostics::VariableNotInAllPatterns { span: *sp });
755 }
756 let mut suggested_typo = false;
757 if !target.iter().all(|pat| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
758 && !origin.iter().all(|(_, pat)| #[allow(non_exhaustive_omitted_patterns)] match pat.kind {
ast::PatKind::Ident(..) => true,
_ => false,
}matches!(pat.kind, ast::PatKind::Ident(..)))
759 {
760 let mut target_visitor = BindingVisitor::default();
763 for pat in &target {
764 target_visitor.visit_pat(pat);
765 }
766 target_visitor.identifiers.sort();
767 target_visitor.identifiers.dedup();
768 let mut origin_visitor = BindingVisitor::default();
769 for (_, pat) in &origin {
770 origin_visitor.visit_pat(pat);
771 }
772 origin_visitor.identifiers.sort();
773 origin_visitor.identifiers.dedup();
774 if let Some(typo) =
776 find_best_match_for_name(&target_visitor.identifiers, name.name, None)
777 && !origin_visitor.identifiers.contains(&typo)
778 {
779 err.subdiagnostic(diagnostics::PatternBindingTypo {
780 spans: origin_sp,
781 typo,
782 });
783 suggested_typo = true;
784 }
785 }
786 if could_be_path {
787 let import_suggestions = self.lookup_import_candidates(
788 name,
789 Namespace::ValueNS,
790 &parent_scope,
791 &|res: Res| {
792 #[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!(
793 res,
794 Res::Def(
795 DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
796 | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
797 | DefKind::Const { .. }
798 | DefKind::AssocConst { .. },
799 _,
800 )
801 )
802 },
803 );
804
805 if import_suggestions.is_empty() && !suggested_typo {
806 let kind_matches: [fn(DefKind) -> bool; 4] = [
807 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Variant, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
808 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => true,
_ => false,
}matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
809 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::Const { .. } => true,
_ => false,
}matches!(kind, DefKind::Const { .. }),
810 |kind| #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::AssocConst { .. } => true,
_ => false,
}matches!(kind, DefKind::AssocConst { .. }),
811 ];
812 let mut local_names = ::alloc::vec::Vec::new()vec![];
813 self.add_module_candidates(
814 parent_scope.module,
815 &mut local_names,
816 &|res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(_, _) => true,
_ => false,
}matches!(res, Res::Def(_, _)),
817 None,
818 );
819 let local_names: FxHashSet<_> = local_names
820 .into_iter()
821 .filter_map(|s| match s.res {
822 Res::Def(_, def_id) => Some(def_id),
823 _ => None,
824 })
825 .collect();
826
827 let mut local_suggestions = ::alloc::vec::Vec::new()vec![];
828 let mut suggestions = ::alloc::vec::Vec::new()vec![];
829 for matches_kind in kind_matches {
830 if let Some(suggestion) = self.early_lookup_typo_candidate(
831 ScopeSet::All(Namespace::ValueNS),
832 &parent_scope,
833 name,
834 &|res: Res| match res {
835 Res::Def(k, _) => matches_kind(k),
836 _ => false,
837 },
838 ) && let Res::Def(kind, mut def_id) = suggestion.res
839 {
840 if let DefKind::Ctor(_, _) = kind {
841 def_id = self.tcx.parent(def_id);
842 }
843 let kind = kind.descr(def_id);
844 if local_names.contains(&def_id) {
845 local_suggestions.push((
848 suggestion.candidate,
849 suggestion.candidate.to_string(),
850 kind,
851 ));
852 } else {
853 suggestions.push((
854 suggestion.candidate,
855 self.def_path_str(def_id),
856 kind,
857 ));
858 }
859 }
860 }
861 let suggestions = if !local_suggestions.is_empty() {
862 local_suggestions
865 } else {
866 suggestions
867 };
868 for (name, sugg, kind) in suggestions {
869 err.span_suggestion_verbose(
870 span,
871 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might have meant to use the similarly named {0} `{1}`",
kind, name))
})format!(
872 "you might have meant to use the similarly named {kind} `{name}`",
873 ),
874 sugg,
875 Applicability::MaybeIncorrect,
876 );
877 suggested_typo = true;
878 }
879 }
880 if import_suggestions.is_empty() && !suggested_typo {
881 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!(
882 "if you meant to match on a unit struct, unit variant or a `const` \
883 item, consider making the path in the pattern qualified: \
884 `path::to::ModOrType::{name}`",
885 );
886 err.span_help(span, help_msg);
887 }
888 show_candidates(
889 self.tcx,
890 &mut err,
891 Some(span),
892 &import_suggestions,
893 Instead::No,
894 FoundUse::Yes,
895 DiagMode::Pattern,
896 ::alloc::vec::Vec::new()vec![],
897 "",
898 );
899 }
900 err
901 }
902 ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
903 self.dcx().create_err(diagnostics::VariableBoundWithDifferentMode {
904 span,
905 first_binding_span,
906 variable_name,
907 })
908 }
909 ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
910 self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInParameterList {
911 span,
912 identifier,
913 })
914 }
915 ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
916 self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInSamePattern {
917 span,
918 identifier,
919 })
920 }
921 ResolutionError::UndeclaredLabel { name, suggestion } => {
922 let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
923 {
924 Some((ident, true)) => (
926 (
927 Some(diagnostics::LabelWithSimilarNameReachable(ident.span)),
928 Some(diagnostics::TryUsingSimilarlyNamedLabel {
929 span,
930 ident_name: ident.name,
931 }),
932 ),
933 None,
934 ),
935 Some((ident, false)) => (
937 (None, None),
938 Some(diagnostics::UnreachableLabelWithSimilarNameExists {
939 ident_span: ident.span,
940 }),
941 ),
942 None => ((None, None), None),
944 };
945 self.dcx().create_err(diagnostics::UndeclaredLabel {
946 span,
947 name,
948 sub_reachable,
949 sub_reachable_suggestion,
950 sub_unreachable,
951 })
952 }
953 ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
954 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}");
955 err.span_label(span, label);
956
957 if let Some((suggestions, msg, applicability)) = suggestion {
958 if suggestions.is_empty() {
959 err.help(msg);
960 return err;
961 }
962 err.multipart_suggestion(msg, suggestions, applicability);
963 }
964
965 let module = match module {
966 Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
967 _ => CRATE_DEF_ID.to_def_id(),
968 };
969 self.find_cfg_stripped(&mut err, &segment, module);
970
971 err
972 }
973 ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
974 self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem { span })
975 }
976 ResolutionError::AttemptToUseNonConstantValueInConstant {
977 ident,
978 suggestion,
979 current,
980 type_span,
981 } => {
982 let sp = self
991 .tcx
992 .sess
993 .source_map()
994 .span_extend_to_prev_str(ident.span, current, true, false);
995
996 let (with, with_label, without) = match sp {
997 Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
998 let sp = sp
999 .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
1000 .until(ident.span);
1001
1002 let is_simple_binding =
1010 self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {
1011 let after_keyword = snippet[current.len()..].trim();
1012 after_keyword.is_empty() || after_keyword == "mut"
1013 });
1014
1015 if is_simple_binding {
1016 (
1017 Some(diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion {
1018 span: sp,
1019 suggestion,
1020 current,
1021 type_span,
1022 }),
1023 Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1024 None,
1025 )
1026 } else {
1027 (
1028 None,
1029 Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
1030 None,
1031 )
1032 }
1033 }
1034 _ => (
1035 None,
1036 None,
1037 Some(
1038 diagnostics::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
1039 ident_span: ident.span,
1040 suggestion,
1041 },
1042 ),
1043 ),
1044 };
1045
1046 self.dcx().create_err(diagnostics::AttemptToUseNonConstantValueInConstant {
1047 span,
1048 with,
1049 with_label,
1050 without,
1051 })
1052 }
1053 ResolutionError::BindingShadowsSomethingUnacceptable {
1054 shadowing_binding,
1055 name,
1056 participle,
1057 article,
1058 shadowed_binding,
1059 shadowed_binding_span,
1060 } => self.dcx().create_err(diagnostics::BindingShadowsSomethingUnacceptable {
1061 span,
1062 shadowing_binding,
1063 shadowed_binding,
1064 article,
1065 sub_suggestion: match (shadowing_binding, shadowed_binding) {
1066 (
1067 PatternSource::Match,
1068 Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
1069 ) => Some(diagnostics::BindingShadowsSomethingUnacceptableSuggestion {
1070 span,
1071 name,
1072 }),
1073 _ => None,
1074 },
1075 shadowed_binding_span,
1076 participle,
1077 name,
1078 }),
1079 ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
1080 ForwardGenericParamBanReason::Default => {
1081 self.dcx().create_err(diagnostics::ForwardDeclaredGenericParam { param, span })
1082 }
1083 ForwardGenericParamBanReason::ConstParamTy => self
1084 .dcx()
1085 .create_err(diagnostics::ForwardDeclaredGenericInConstParamTy { param, span }),
1086 },
1087 ResolutionError::ParamInTyOfConstParam { name } => {
1088 self.dcx().create_err(diagnostics::ParamInTyOfConstParam { span, name })
1089 }
1090 ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {
1091 self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst {
1092 span,
1093 name,
1094 param_kind: is_type,
1095 help: self.tcx.sess.is_nightly_build(),
1096 is_gca,
1097 help_gca: is_gca,
1098 })
1099 }
1100 ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => {
1101 self.dcx().create_err(diagnostics::ParamInEnumDiscriminant {
1102 span,
1103 name,
1104 param_kind: is_type,
1105 })
1106 }
1107 ResolutionError::ForwardDeclaredSelf(reason) => match reason {
1108 ForwardGenericParamBanReason::Default => {
1109 self.dcx().create_err(diagnostics::SelfInGenericParamDefault { span })
1110 }
1111 ForwardGenericParamBanReason::ConstParamTy => {
1112 self.dcx().create_err(diagnostics::SelfInConstGenericTy { span })
1113 }
1114 },
1115 ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
1116 let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
1117 match suggestion {
1118 Some((ident, true)) => (
1120 (
1121 Some(diagnostics::UnreachableLabelSubLabel {
1122 ident_span: ident.span,
1123 }),
1124 Some(diagnostics::UnreachableLabelSubSuggestion {
1125 span,
1126 ident_name: ident.name,
1129 }),
1130 ),
1131 None,
1132 ),
1133 Some((ident, false)) => (
1135 (None, None),
1136 Some(diagnostics::UnreachableLabelSubLabelUnreachable {
1137 ident_span: ident.span,
1138 }),
1139 ),
1140 None => ((None, None), None),
1142 };
1143 self.dcx().create_err(diagnostics::UnreachableLabel {
1144 span,
1145 name,
1146 definition_span,
1147 sub_suggestion,
1148 sub_suggestion_label,
1149 sub_unreachable_label,
1150 })
1151 }
1152 ResolutionError::TraitImplMismatch {
1153 name,
1154 kind,
1155 code,
1156 trait_item_span,
1157 trait_path,
1158 } => self
1159 .dcx()
1160 .create_err(diagnostics::TraitImplMismatch {
1161 span,
1162 name,
1163 kind,
1164 trait_path,
1165 trait_item_span,
1166 })
1167 .with_code(code),
1168 ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {
1169 self.dcx().create_err(diagnostics::TraitImplDuplicate {
1170 span,
1171 name,
1172 trait_item_span,
1173 old_span,
1174 })
1175 }
1176 ResolutionError::InvalidAsmSym => {
1177 self.dcx().create_err(diagnostics::InvalidAsmSym { span })
1178 }
1179 ResolutionError::LowercaseSelf => {
1180 self.dcx().create_err(diagnostics::LowercaseSelf { span })
1181 }
1182 ResolutionError::BindingInNeverPattern => {
1183 self.dcx().create_err(diagnostics::BindingInNeverPattern { span })
1184 }
1185 }
1186 }
1187
1188 pub(crate) fn report_vis_error(
1189 &mut self,
1190 vis_resolution_error: VisResolutionError,
1191 ) -> ErrorGuaranteed {
1192 match vis_resolution_error {
1193 VisResolutionError::Relative2018(span, path) => {
1194 self.dcx().create_err(diagnostics::Relative2018 {
1195 span,
1196 path_span: path.span,
1197 path_str: pprust::path_to_string(&path),
1200 })
1201 }
1202 VisResolutionError::AncestorOnly(span) => {
1203 self.dcx().create_err(diagnostics::AncestorOnly(span))
1204 }
1205 VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self
1206 .into_struct_error(
1207 span,
1208 ResolutionError::FailedToResolve {
1209 segment,
1210 label,
1211 suggestion,
1212 module: None,
1213 message,
1214 },
1215 ),
1216 VisResolutionError::ExpectedFound(span, path_str, res) => {
1217 self.dcx().create_err(diagnostics::ExpectedModuleFound { span, res, path_str })
1218 }
1219 VisResolutionError::Indeterminate(span) => {
1220 self.dcx().create_err(diagnostics::Indeterminate(span))
1221 }
1222 VisResolutionError::ModuleOnly(span) => {
1223 self.dcx().create_err(diagnostics::ModuleOnly(span))
1224 }
1225 }
1226 .emit()
1227 }
1228
1229 pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {
1230 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];
1232 while let Some(parent) = self.tcx.opt_parent(def_id) {
1233 def_id = parent;
1234 path.push(def_id);
1235 if def_id.is_top_level_module() {
1236 break;
1237 }
1238 }
1239 path.into_iter()
1241 .rev()
1242 .map(|def_id| {
1243 self.tcx
1244 .opt_item_name(def_id)
1245 .map(|name| {
1246 match (
1247 def_id.is_top_level_module(),
1248 def_id.is_local(),
1249 self.tcx.sess.edition(),
1250 ) {
1251 (true, true, Edition::Edition2015) => String::new(),
1252 (true, true, _) => kw::Crate.to_string(),
1253 (true, false, _) | (false, _, _) => name.to_string(),
1254 }
1255 })
1256 .unwrap_or_else(|| "_".to_string())
1257 })
1258 .collect::<Vec<String>>()
1259 .join("::")
1260 }
1261
1262 pub(crate) fn add_scope_set_candidates(
1263 &mut self,
1264 suggestions: &mut Vec<TypoSuggestion>,
1265 scope_set: ScopeSet<'ra>,
1266 ps: &ParentScope<'ra>,
1267 sp: Span,
1268 filter_fn: &impl Fn(Res) -> bool,
1269 ) {
1270 let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
1271 self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
1272 match scope {
1273 Scope::DeriveHelpers(expn_id) => {
1274 let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
1275 if filter_fn(res) {
1276 suggestions.extend(
1277 this.helper_attrs.get(&expn_id).into_iter().flatten().map(
1278 |&(ident, orig_ident_span, _)| {
1279 TypoSuggestion::new(ident.name, orig_ident_span, res)
1280 },
1281 ),
1282 );
1283 }
1284 }
1285 Scope::DeriveHelpersCompat => {
1286 }
1288 Scope::MacroRules(macro_rules_scope) => {
1289 if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
1290 let res = macro_rules_def.decl.res();
1291 if filter_fn(res) {
1292 suggestions.push(TypoSuggestion::new(
1293 macro_rules_def.ident.name,
1294 macro_rules_def.orig_ident_span,
1295 res,
1296 ))
1297 }
1298 }
1299 }
1300 Scope::ModuleNonGlobs(module, _) => {
1301 this.add_module_candidates(module, suggestions, filter_fn, None);
1302 }
1303 Scope::ModuleGlobs(..) => {
1304 }
1306 Scope::MacroUsePrelude => {
1307 suggestions.extend(this.macro_use_prelude.iter().filter_map(
1308 |(name, binding)| {
1309 let res = binding.res();
1310 filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
1311 },
1312 ));
1313 }
1314 Scope::BuiltinAttrs => {
1315 let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
1316 if filter_fn(res) {
1317 suggestions.extend(
1318 BUILTIN_ATTRIBUTES
1319 .iter()
1320 .filter(|attr| {
1323 !#[allow(non_exhaustive_omitted_patterns)] match **attr {
sym::cfg_trace | sym::cfg_attr_trace => true,
_ => false,
}matches!(**attr, sym::cfg_trace | sym::cfg_attr_trace)
1324 })
1325 .map(|attr| TypoSuggestion::typo_from_name(*attr, res)),
1326 );
1327 }
1328 }
1329 Scope::ExternPreludeItems => {
1330 suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
1332 let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
1333 filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
1334 }));
1335 }
1336 Scope::ExternPreludeFlags => {}
1337 Scope::ToolPrelude => {
1338 let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
1339 suggestions.extend(
1340 this.registered_tools
1341 .iter()
1342 .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
1343 );
1344 }
1345 Scope::StdLibPrelude => {
1346 if let Some(prelude) = this.prelude {
1347 let mut tmp_suggestions = Vec::new();
1348 this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
1349 suggestions.extend(
1350 tmp_suggestions
1351 .into_iter()
1352 .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
1353 );
1354 }
1355 }
1356 Scope::BuiltinTypes => {
1357 suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
1358 let res = Res::PrimTy(*prim_ty);
1359 filter_fn(res)
1360 .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
1361 }))
1362 }
1363 }
1364
1365 ControlFlow::<()>::Continue(())
1366 });
1367 }
1368
1369 fn early_lookup_typo_candidate(
1371 &mut self,
1372 scope_set: ScopeSet<'ra>,
1373 parent_scope: &ParentScope<'ra>,
1374 ident: Ident,
1375 filter_fn: &impl Fn(Res) -> bool,
1376 ) -> Option<TypoSuggestion> {
1377 let mut suggestions = Vec::new();
1378 self.add_scope_set_candidates(
1379 &mut suggestions,
1380 scope_set,
1381 parent_scope,
1382 ident.span,
1383 filter_fn,
1384 );
1385
1386 suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
1388
1389 match find_best_match_for_name(
1390 &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
1391 ident.name,
1392 None,
1393 ) {
1394 Some(found) if found != ident.name => {
1395 suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
1396 }
1397 _ => None,
1398 }
1399 }
1400
1401 fn lookup_import_candidates_from_module<FilterFn>(
1402 &self,
1403 lookup_ident: Ident,
1404 namespace: Namespace,
1405 parent_scope: &ParentScope<'ra>,
1406 start_module: Module<'ra>,
1407 crate_path: ThinVec<ast::PathSegment>,
1408 filter_fn: FilterFn,
1409 ) -> Vec<ImportSuggestion>
1410 where
1411 FilterFn: Fn(Res) -> bool,
1412 {
1413 let mut candidates = Vec::new();
1414 let mut seen_modules = FxHashSet::default();
1415 let start_did = start_module.def_id();
1416 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![(
1417 start_module,
1418 ThinVec::<ast::PathSegment>::new(),
1419 true,
1420 start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
1421 true,
1422 )];
1423 let mut worklist_via_import = ::alloc::vec::Vec::new()vec![];
1424
1425 while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
1426 match worklist.pop() {
1427 None => worklist_via_import.pop(),
1428 Some(x) => Some(x),
1429 }
1430 {
1431 let in_module_is_extern = !in_module.def_id().is_local();
1432 in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
1433 if name_binding.is_assoc_item()
1435 && !this.tcx.features().import_trait_associated_functions()
1436 {
1437 return;
1438 }
1439
1440 if ident.name == kw::Underscore {
1441 return;
1442 }
1443
1444 let child_accessible =
1445 accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);
1446
1447 if in_module_is_extern && !child_accessible {
1449 return;
1450 }
1451
1452 let via_import = name_binding.is_import() && !name_binding.is_extern_crate();
1453
1454 if via_import && name_binding.is_possibly_imported_variant() {
1460 return;
1461 }
1462
1463 if let DeclKind::Import { source_decl, .. } = name_binding.kind
1465 && this.is_accessible_from(source_decl.vis(), parent_scope.module)
1466 && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
1467 {
1468 return;
1469 }
1470
1471 let res = name_binding.res();
1472 let did = match res {
1473 Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
1474 _ => res.opt_def_id(),
1475 };
1476 let child_doc_visible = doc_visible
1477 && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));
1478
1479 if ident.name == lookup_ident.name
1483 && ns == namespace
1484 && in_module != parent_scope.module
1485 && ident.ctxt.is_root()
1486 && filter_fn(res)
1487 {
1488 let mut segms = if lookup_ident.span.at_least_rust_2018() {
1490 crate_path.clone()
1493 } else {
1494 ThinVec::new()
1495 };
1496 segms.append(&mut path_segments.clone());
1497
1498 segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1499 let path = Path { span: name_binding.span, segments: segms, tokens: None };
1500
1501 if child_accessible
1502 && let Some(idx) = candidates
1504 .iter()
1505 .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
1506 {
1507 candidates.remove(idx);
1508 }
1509
1510 let is_stable = if is_stable
1511 && let Some(did) = did
1512 && this.is_stable(did, path.span)
1513 {
1514 true
1515 } else {
1516 false
1517 };
1518
1519 if is_stable
1524 && let Some(idx) = candidates
1525 .iter()
1526 .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
1527 {
1528 candidates.remove(idx);
1529 }
1530
1531 if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
1532 let note = if let Some(did) = did {
1535 let requires_note = !did.is_local()
1536 && {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(did, &this.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcDiagnosticItem(sym::TryInto
| sym::TryFrom | sym::FromIterator)) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(
1537 this.tcx,
1538 did,
1539 RustcDiagnosticItem(
1540 sym::TryInto | sym::TryFrom | sym::FromIterator
1541 )
1542 );
1543 requires_note.then(|| {
1544 ::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!(
1545 "'{}' is included in the prelude starting in Edition 2021",
1546 path_names_to_string(&path)
1547 )
1548 })
1549 } else {
1550 None
1551 };
1552
1553 candidates.push(ImportSuggestion {
1554 did,
1555 descr: res.descr(),
1556 path,
1557 accessible: child_accessible,
1558 doc_visible: child_doc_visible,
1559 note,
1560 via_import,
1561 is_stable,
1562 });
1563 }
1564 }
1565
1566 if let Some(def_id) = name_binding.res().module_like_def_id() {
1568 let mut path_segments = path_segments.clone();
1570 path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
1571
1572 let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
1573 && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
1574 && import.parent_scope.expansion == parent_scope.expansion
1575 {
1576 true
1577 } else {
1578 false
1579 };
1580
1581 let is_extern_crate_that_also_appears_in_prelude =
1582 name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();
1583
1584 if !is_extern_crate_that_also_appears_in_prelude || alias_import {
1585 if seen_modules.insert(def_id) {
1587 if via_import { &mut worklist_via_import } else { &mut worklist }.push(
1588 (
1589 this.expect_module(def_id),
1590 path_segments,
1591 child_accessible,
1592 child_doc_visible,
1593 is_stable && this.is_stable(def_id, name_binding.span),
1594 ),
1595 );
1596 }
1597 }
1598 }
1599 })
1600 }
1601
1602 candidates
1603 }
1604
1605 fn is_stable(&self, did: DefId, span: Span) -> bool {
1606 if did.is_local() {
1607 return true;
1608 }
1609
1610 match self.tcx.lookup_stability(did) {
1611 Some(Stability {
1612 level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
1613 }) => {
1614 if span.allows_unstable(feature) {
1615 true
1616 } else if self.tcx.features().enabled(feature) {
1617 true
1618 } else if let Some(implied_by) = implied_by
1619 && self.tcx.features().enabled(implied_by)
1620 {
1621 true
1622 } else {
1623 false
1624 }
1625 }
1626 Some(_) => true,
1627 None => false,
1628 }
1629 }
1630
1631 pub(crate) fn lookup_import_candidates<FilterFn>(
1639 &mut self,
1640 lookup_ident: Ident,
1641 namespace: Namespace,
1642 parent_scope: &ParentScope<'ra>,
1643 filter_fn: FilterFn,
1644 ) -> Vec<ImportSuggestion>
1645 where
1646 FilterFn: Fn(Res) -> bool,
1647 {
1648 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))];
1649 let mut suggestions = self.lookup_import_candidates_from_module(
1650 lookup_ident,
1651 namespace,
1652 parent_scope,
1653 self.graph_root.to_module(),
1654 crate_path,
1655 &filter_fn,
1656 );
1657
1658 if lookup_ident.span.at_least_rust_2018() {
1659 for (ident, entry) in &self.extern_prelude {
1660 if entry.span().from_expansion() {
1661 continue;
1667 }
1668 let Some(crate_id) =
1669 self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
1670 else {
1671 continue;
1672 };
1673
1674 let crate_def_id = crate_id.as_def_id();
1675 let crate_root = self.expect_module(crate_def_id);
1676
1677 let needs_disambiguation =
1681 self.resolutions(parent_scope.module).borrow().iter().any(
1682 |(key, name_resolution)| {
1683 if key.ns == TypeNS
1684 && key.ident == *ident
1685 && let Some(decl) = name_resolution.borrow().best_decl()
1686 {
1687 match decl.res() {
1688 Res::Def(_, def_id) => def_id != crate_def_id,
1691 Res::PrimTy(_) => true,
1692 _ => false,
1693 }
1694 } else {
1695 false
1696 }
1697 },
1698 );
1699 let mut crate_path = ThinVec::new();
1700 if needs_disambiguation {
1701 crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
1702 }
1703 crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));
1704
1705 suggestions.extend(self.lookup_import_candidates_from_module(
1706 lookup_ident,
1707 namespace,
1708 parent_scope,
1709 crate_root,
1710 crate_path,
1711 &filter_fn,
1712 ));
1713 }
1714 }
1715
1716 suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
1717 suggestions
1718 }
1719
1720 pub(crate) fn unresolved_macro_suggestions(
1721 &mut self,
1722 err: &mut Diag<'_>,
1723 macro_kind: MacroKind,
1724 parent_scope: &ParentScope<'ra>,
1725 ident: Ident,
1726 krate: &Crate,
1727 sugg_span: Option<Span>,
1728 ) {
1729 self.register_macros_for_all_crates();
1732
1733 let is_expected =
1734 &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
1735 let suggestion = self.early_lookup_typo_candidate(
1736 ScopeSet::Macro(macro_kind),
1737 parent_scope,
1738 ident,
1739 is_expected,
1740 );
1741 if !self.add_typo_suggestion(err, suggestion, ident.span) {
1742 self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
1743 }
1744
1745 let import_suggestions =
1746 self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
1747 let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {
1748 DUMMY_NODE_ID => (None, FoundUse::No),
1749 node_id => UsePlacementFinder::check(krate, node_id),
1750 };
1751 show_candidates(
1752 self.tcx,
1753 err,
1754 span,
1755 &import_suggestions,
1756 Instead::No,
1757 found_use,
1758 DiagMode::Normal,
1759 ::alloc::vec::Vec::new()vec![],
1760 "",
1761 );
1762
1763 if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
1764 let label_span = ident.span.shrink_to_hi();
1765 let mut spans = MultiSpan::from_span(label_span);
1766 spans.push_span_label(label_span, "put a macro name here");
1767 err.subdiagnostic(MaybeMissingMacroRulesName { spans });
1768 return;
1769 }
1770
1771 if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
1772 err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
1773 return;
1774 }
1775
1776 let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
1777 if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
1778 });
1779
1780 if let Some((def_id, unused_ident)) = unused_macro {
1781 let scope = self.local_macro_def_scopes[&def_id];
1782 let parent_nearest = parent_scope.module.nearest_parent_mod();
1783 let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();
1784 if !unused_macro_kinds.contains(macro_kind.into()) {
1785 match macro_kind {
1786 MacroKind::Bang => {
1787 err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
1788 }
1789 MacroKind::Attr => {
1790 err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
1791 }
1792 MacroKind::Derive => {
1793 err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
1794 }
1795 }
1796 return;
1797 }
1798 if Some(parent_nearest) == scope.opt_def_id() {
1799 err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
1800 err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
1801 return;
1802 }
1803 }
1804
1805 if ident.name == kw::Default
1806 && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind
1807 {
1808 let span = self.def_span(def_id);
1809 let source_map = self.tcx.sess.source_map();
1810 let head_span = source_map.guess_head_span(span);
1811 err.subdiagnostic(ConsiderAddingADerive {
1812 span: head_span.shrink_to_lo(),
1813 suggestion: "#[derive(Default)]\n".to_string(),
1814 });
1815 }
1816 for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
1817 let Ok(binding) = self.cm().resolve_ident_in_scope_set(
1818 ident,
1819 ScopeSet::All(ns),
1820 parent_scope,
1821 None,
1822 None,
1823 None,
1824 ) else {
1825 continue;
1826 };
1827
1828 let desc = match binding.res() {
1829 Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
1830 "a function-like macro".to_string()
1831 }
1832 Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
1833 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("an attribute: `#[{0}]`", ident))
})format!("an attribute: `#[{ident}]`")
1834 }
1835 Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
1836 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("a derive macro: `#[derive({0})]`",
ident))
})format!("a derive macro: `#[derive({ident})]`")
1837 }
1838 Res::Def(DefKind::Macro(kinds), _) => {
1839 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} {1}", kinds.article(),
kinds.descr()))
})format!("{} {}", kinds.article(), kinds.descr())
1840 }
1841 Res::ToolMod | Res::OpenMod(..) => {
1842 continue;
1844 }
1845 Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
1846 "only a trait, without a derive macro".to_string()
1847 }
1848 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!(
1849 "{} {}, not {} {}",
1850 res.article(),
1851 res.descr(),
1852 macro_kind.article(),
1853 macro_kind.descr_expected(),
1854 ),
1855 };
1856 if let crate::DeclKind::Import { import, .. } = binding.kind
1857 && !import.span.is_dummy()
1858 {
1859 let note = diagnostics::IdentImporterHereButItIsDesc {
1860 span: import.span,
1861 imported_ident: ident,
1862 imported_ident_desc: &desc,
1863 };
1864 err.subdiagnostic(note);
1865 self.record_use(ident, binding, Used::Other);
1868 return;
1869 }
1870 let note = diagnostics::IdentInScopeButItIsDesc {
1871 imported_ident: ident,
1872 imported_ident_desc: &desc,
1873 };
1874 err.subdiagnostic(note);
1875 return;
1876 }
1877
1878 if self.macro_names.contains(&IdentKey::new(ident)) {
1879 err.subdiagnostic(AddedMacroUse);
1880 return;
1881 }
1882 }
1883
1884 fn detect_derive_attribute(
1887 &self,
1888 err: &mut Diag<'_>,
1889 ident: Ident,
1890 parent_scope: &ParentScope<'ra>,
1891 sugg_span: Option<Span>,
1892 ) {
1893 let mut derives = ::alloc::vec::Vec::new()vec![];
1898 let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
1899 #[allow(rustc::potential_query_instability)]
1901 for (def_id, ext) in self
1902 .local_macro_map
1903 .iter()
1904 .map(|(local_id, ext)| (local_id.to_def_id(), ext))
1905 .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
1906 {
1907 for helper_attr in &ext.helper_attrs {
1908 let item_name = self.tcx.item_name(def_id);
1909 all_attrs.entry(*helper_attr).or_default().push(item_name);
1910 if helper_attr == &ident.name {
1911 derives.push(item_name);
1912 }
1913 }
1914 }
1915 let kind = MacroKind::Derive.descr();
1916 if !derives.is_empty() {
1917 let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
1919 derives.sort();
1920 derives.dedup();
1921 let msg = match &derives[..] {
1922 [derive] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", derive))
})format!(" `{derive}`"),
1923 [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!(
1924 "s {} and `{last}`",
1925 start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
1926 ),
1927 [] => {
::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!?"),
1928 };
1929 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!(
1930 "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
1931 missing a `derive` attribute",
1932 ident.name,
1933 );
1934 let sugg_span =
1935 if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind {
1936 let span = self.def_span(id);
1937 if span.from_expansion() {
1938 None
1939 } else {
1940 Some(span.shrink_to_lo())
1942 }
1943 } else {
1944 sugg_span
1946 };
1947 match sugg_span {
1948 Some(span) => {
1949 err.span_suggestion_verbose(
1950 span,
1951 msg,
1952 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("#[derive({0})]\n",
derives.join(", ")))
})format!("#[derive({})]\n", derives.join(", ")),
1953 Applicability::MaybeIncorrect,
1954 );
1955 }
1956 None => {
1957 err.note(msg);
1958 }
1959 }
1960 } else {
1961 let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
1963 if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
1964 && let Some(macros) = all_attrs.get(&best_match)
1965 {
1966 let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
1967 macros.sort();
1968 macros.dedup();
1969 let msg = match ¯os[..] {
1970 [] => return,
1971 [name] => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}` accepts", name))
})format!(" `{name}` accepts"),
1972 [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!(
1973 "s {} and `{end}` accept",
1974 start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
1975 ),
1976 };
1977 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");
1978 err.span_suggestion_verbose(
1979 ident.span,
1980 msg,
1981 best_match,
1982 Applicability::MaybeIncorrect,
1983 );
1984 }
1985 }
1986 }
1987
1988 pub(crate) fn add_typo_suggestion(
1989 &self,
1990 err: &mut Diag<'_>,
1991 suggestion: Option<TypoSuggestion>,
1992 span: Span,
1993 ) -> bool {
1994 let suggestion = match suggestion {
1995 None => return false,
1996 Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
1998 Some(suggestion) => suggestion,
1999 };
2000
2001 let mut did_label_def_span = false;
2002
2003 if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
2004 if span.overlaps(def_span) {
2005 return false;
2024 }
2025 let span = self.tcx.sess.source_map().guess_head_span(def_span);
2026 let candidate_descr = suggestion.res.descr();
2027 let candidate = suggestion.candidate;
2028 let label = match suggestion.target {
2029 SuggestionTarget::SimilarlyNamed => {
2030 diagnostics::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
2031 }
2032 SuggestionTarget::SingleItem => {
2033 diagnostics::DefinedHere::SingleItem { span, candidate_descr, candidate }
2034 }
2035 };
2036 did_label_def_span = true;
2037 err.subdiagnostic(label);
2038 }
2039
2040 let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
2041 && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
2042 && let Some(span) = suggestion.span
2043 && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
2044 && snippet == candidate
2045 {
2046 let candidate = suggestion.candidate;
2047 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!(
2050 "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
2051 );
2052 if !did_label_def_span {
2053 err.span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}` defined here", candidate))
})format!("`{candidate}` defined here"));
2054 }
2055 (span, msg, snippet)
2056 } else {
2057 let msg = match suggestion.target {
2058 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!(
2059 "{} {} with a similar name exists",
2060 suggestion.res.article(),
2061 suggestion.res.descr()
2062 ),
2063 SuggestionTarget::SingleItem => {
2064 ::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())
2065 }
2066 };
2067 (span, msg, suggestion.candidate.to_ident_string())
2068 };
2069 err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
2070 true
2071 }
2072
2073 fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
2074 let res = b.res();
2075 if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
2076 let (built_in, from) = match scope {
2077 Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
2078 Scope::ExternPreludeFlags
2079 if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
2080 || #[allow(non_exhaustive_omitted_patterns)] match res {
Res::OpenMod(..) => true,
_ => false,
}matches!(res, Res::OpenMod(..)) =>
2081 {
2082 ("", " passed with `--extern`")
2083 }
2084 _ => {
2085 if #[allow(non_exhaustive_omitted_patterns)] match res {
Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod => true,
_ => false,
}matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
2086 ("", "")
2088 } else {
2089 (" built-in", "")
2090 }
2091 }
2092 };
2093
2094 let a = if built_in.is_empty() { res.article() } else { "a" };
2095 ::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())
2096 } else {
2097 let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
2098 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the {0} {1} here", res.descr(),
introduced))
})format!("the {thing} {introduced} here", thing = res.descr())
2099 }
2100 }
2101
2102 fn ambiguity_diagnostic(
2103 &self,
2104 ambiguity_error: &AmbiguityError<'ra>,
2105 ) -> diagnostics::Ambiguity {
2106 let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
2107 *ambiguity_error;
2108 let extern_prelude_ambiguity = || {
2109 #[allow(non_exhaustive_omitted_patterns)] match scope2 {
Scope::ExternPreludeFlags => true,
_ => false,
}matches!(scope2, Scope::ExternPreludeFlags)
2111 && self
2112 .extern_prelude
2113 .get(&IdentKey::new(ident))
2114 .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
2115 };
2116 let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
2117 (b2, b1, scope2, scope1, true)
2119 } else {
2120 (b1, b2, scope1, scope2, false)
2121 };
2122
2123 let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
2124 let what = self.decl_description(b, ident, scope);
2125 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}");
2126
2127 let thing = b.res().descr();
2128 let mut help_msgs = Vec::new();
2129 if b.is_glob_import()
2130 && (kind == AmbiguityKind::GlobVsGlob
2131 || kind == AmbiguityKind::GlobVsExpanded
2132 || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
2133 {
2134 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("consider adding an explicit import of `{0}` to disambiguate",
ident))
})format!(
2135 "consider adding an explicit import of `{ident}` to disambiguate"
2136 ))
2137 }
2138 if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
2139 {
2140 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"))
2141 }
2142
2143 if kind != AmbiguityKind::GlobVsGlob {
2144 if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
2145 if module == self.graph_root.to_module() {
2146 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `crate::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2147 "use `crate::{ident}` to refer to this {thing} unambiguously"
2148 ));
2149 } else if module.is_normal() {
2150 help_msgs.push(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use `self::{0}` to refer to this {1} unambiguously",
ident, thing))
})format!(
2151 "use `self::{ident}` to refer to this {thing} unambiguously"
2152 ));
2153 }
2154 }
2155 }
2156
2157 (
2158 Spanned { node: note_msg, span: b.span },
2159 help_msgs
2160 .iter()
2161 .enumerate()
2162 .map(|(i, help_msg)| {
2163 let or = if i == 0 { "" } else { "or " };
2164 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", or, help_msg))
})format!("{or}{help_msg}")
2165 })
2166 .collect::<Vec<_>>(),
2167 )
2168 };
2169 let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
2170 let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
2171 let help = if kind == AmbiguityKind::GlobVsGlob
2172 && b1
2173 .parent_module
2174 .and_then(|m| m.opt_def_id())
2175 .map(|d| !d.is_local())
2176 .unwrap_or_default()
2177 {
2178 Some(&[
2179 "consider updating this dependency to resolve this error",
2180 "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
2181 ] as &[_])
2182 } else {
2183 None
2184 };
2185
2186 let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
2187 ::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!(
2188 "{} or {}",
2189 vis1.to_string(CRATE_DEF_ID, self.tcx),
2190 vis2.to_string(CRATE_DEF_ID, self.tcx)
2191 )
2192 });
2193
2194 diagnostics::Ambiguity {
2195 ident,
2196 help,
2197 ambig_vis,
2198 kind: kind.descr(),
2199 b1_note,
2200 b1_help_msgs,
2201 b2_note,
2202 b2_help_msgs,
2203 is_error: false,
2204 }
2205 }
2206
2207 fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
2210 let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
2211 decl.kind
2212 else {
2213 return None;
2214 };
2215
2216 let def_id = self.tcx.parent(ctor_def_id);
2217 self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) }
2219
2220 fn module_path_names(&self, module: Module<'ra>) -> Option<Vec<Symbol>> {
2224 let mut path = Vec::new();
2225 let mut def_id = module.opt_def_id()?;
2226 while let Some(parent) = self.tcx.opt_parent(def_id) {
2227 if let Some(name) = self.tcx.opt_item_name(def_id) {
2228 path.push(name);
2229 }
2230 if parent.is_top_level_module() {
2231 break;
2232 }
2233 def_id = parent;
2234 }
2235 path.reverse();
2236 path.insert(0, kw::Crate);
2237 Some(path)
2238 }
2239
2240 fn shorten_candidate_path(
2244 &self,
2245 suggestion: &mut ImportSuggestion,
2246 current_module: Module<'ra>,
2247 ) {
2248 const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;
2249
2250 if suggestion.did.is_none_or(|did| !did.is_local()) {
2252 return;
2253 }
2254
2255 let Some(current_mod_path) = self.module_path_names(current_module) else {
2257 return;
2258 };
2259
2260 let candidate_names = {
2264 let filtered_segments: Vec<_> = suggestion
2265 .path
2266 .segments
2267 .iter()
2268 .filter(|segment| segment.ident.name != kw::PathRoot)
2269 .collect();
2270
2271 let mut candidate_names: Vec<Symbol> =
2272 filtered_segments.iter().map(|segment| segment.ident.name).collect();
2273 if candidate_names.first() != Some(&kw::Crate) {
2274 candidate_names.insert(0, kw::Crate);
2275 }
2276 if candidate_names.len() < 2 {
2277 return;
2278 }
2279 candidate_names
2280 };
2281
2282 let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];
2284
2285 let common_prefix_length = current_mod_path
2287 .iter()
2288 .zip(candidate_mod_names.iter())
2289 .take_while(|(current, candidate)| current == candidate)
2290 .count();
2291
2292 if common_prefix_length == 0 {
2294 return;
2295 }
2296
2297 let super_count = current_mod_path.len() - common_prefix_length;
2298
2299 let at_crate_root = current_mod_path.len() == 1;
2302
2303 let mut new_segments = if super_count == 0 && at_crate_root {
2304 ThinVec::new()
2305 } else {
2306 let prefix_keyword = match super_count {
2307 0 => kw::SelfLower,
2308 1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
2309 _ => return, };
2311 {
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),)]
2312 };
2313 for &name in &candidate_names[common_prefix_length..] {
2314 new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
2315 }
2316
2317 if new_segments.len() >= suggestion.path.segments.len() {
2319 return;
2320 }
2321
2322 suggestion.path = Path { span: suggestion.path.span, segments: new_segments, tokens: None };
2323 }
2324
2325 fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
2326 let PrivacyError {
2327 ident,
2328 decl,
2329 outermost_res,
2330 parent_scope,
2331 single_nested,
2332 dedup_span,
2333 ref source,
2334 } = *privacy_error;
2335
2336 let res = decl.res();
2337 let ctor_fields_span = self.ctor_fields_span(decl);
2338 let plain_descr = res.descr().to_string();
2339 let nonimport_descr =
2340 if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
2341 let import_descr = nonimport_descr.clone() + " import";
2342 let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };
2343
2344 let ident_descr = get_descr(decl);
2346 let mut err =
2347 self.dcx().create_err(diagnostics::IsPrivate { span: ident.span, ident_descr, ident });
2348
2349 self.mention_default_field_values(source, ident, &mut err);
2350
2351 let shown_candidates = if let Some((this_res, outer_ident)) = outermost_res {
2352 let mut import_suggestions = self.lookup_import_candidates(
2353 outer_ident,
2354 this_res.ns().unwrap_or(Namespace::TypeNS),
2355 &parent_scope,
2356 &|res: Res| res == this_res,
2357 );
2358 for suggestion in &mut import_suggestions {
2360 self.shorten_candidate_path(suggestion, parent_scope.module);
2361 }
2362 let point_to_def = !show_candidates(
2363 self.tcx,
2364 &mut err,
2365 Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
2366 &import_suggestions,
2367 Instead::Yes,
2368 FoundUse::Yes,
2369 DiagMode::Import { append: single_nested, unresolved_import: false },
2370 ::alloc::vec::Vec::new()vec![],
2371 "",
2372 );
2373 if point_to_def && ident.span != outer_ident.span {
2375 let label = diagnostics::OuterIdentIsNotPubliclyReexported {
2376 span: outer_ident.span,
2377 outer_ident_descr: this_res.descr(),
2378 outer_ident,
2379 };
2380 err.subdiagnostic(label);
2381 }
2382 !point_to_def
2383 } else {
2384 false
2385 };
2386
2387 let mut non_exhaustive = None;
2388 if let Some(def_id) = res.opt_def_id()
2392 && !def_id.is_local()
2393 && let Some(attr_span) = {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(NonExhaustive(span)) => {
break 'done Some(*span);
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
2394 {
2395 non_exhaustive = Some(attr_span);
2396 } else if let Some(span) = ctor_fields_span {
2397 let label = diagnostics::ConstructorPrivateIfAnyFieldPrivate { span };
2398 err.subdiagnostic(label);
2399 if let Res::Def(_, d) = res
2400 && let Some(fields) = self.field_visibility_spans.get(&d)
2401 {
2402 let spans = fields.iter().map(|span| *span).collect();
2403 let sugg = diagnostics::ConsiderMakingTheFieldPublic {
2404 spans,
2405 number_of_fields: fields.len(),
2406 };
2407 err.subdiagnostic(sugg);
2408 }
2409 }
2410
2411 let mut sugg_paths: Vec<(Vec<Ident>, bool)> = ::alloc::vec::Vec::new()vec![];
2412 if let Some(mut def_id) = res.opt_def_id() {
2413 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];
2415 while let Some(parent) = self.tcx.opt_parent(def_id) {
2416 def_id = parent;
2417 if !def_id.is_top_level_module() {
2418 path.push(def_id);
2419 } else {
2420 break;
2421 }
2422 }
2423 let path_names: Option<Vec<Ident>> = path
2425 .iter()
2426 .rev()
2427 .map(|def_id| {
2428 self.tcx.opt_item_name(*def_id).map(|name| {
2429 Ident::with_dummy_span(if def_id.is_top_level_module() {
2430 kw::Crate
2431 } else {
2432 name
2433 })
2434 })
2435 })
2436 .collect();
2437 if let Some(&def_id) = path.get(0)
2438 && let Some(path) = path_names
2439 {
2440 if let Some(def_id) = def_id.as_local() {
2441 if self.effective_visibilities.is_directly_public(def_id) {
2442 sugg_paths.push((path, false));
2443 }
2444 } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
2445 {
2446 sugg_paths.push((path, false));
2447 }
2448 }
2449 }
2450
2451 let first_binding = decl;
2453 let mut next_binding = Some(decl);
2454 let mut next_ident = ident;
2455 while let Some(binding) = next_binding {
2456 let name = next_ident;
2457 next_binding = match binding.kind {
2458 _ if res == Res::Err => None,
2459 DeclKind::Import { source_decl, import, .. } => match import.kind {
2460 _ if source_decl.span.is_dummy() => None,
2461 ImportKind::Single { source, .. } => {
2462 next_ident = source;
2463 Some(source_decl)
2464 }
2465 ImportKind::Glob { .. }
2466 | ImportKind::MacroUse { .. }
2467 | ImportKind::MacroExport => Some(source_decl),
2468 ImportKind::ExternCrate { .. } => None,
2469 },
2470 _ => None,
2471 };
2472
2473 match binding.kind {
2474 DeclKind::Import { source_decl, import, .. } => {
2475 let path = import
2478 .module_path
2479 .iter()
2480 .filter(|seg| seg.ident.name != kw::PathRoot)
2481 .map(|seg| seg.ident.clone())
2482 .chain(std::iter::once(ident))
2483 .collect::<Vec<_>>();
2484 let through_reexport = !#[allow(non_exhaustive_omitted_patterns)] match source_decl.kind {
DeclKind::Def(_) => true,
_ => false,
}matches!(source_decl.kind, DeclKind::Def(_));
2485 sugg_paths.push((path, through_reexport));
2486 }
2487 DeclKind::Def(_) => {}
2488 }
2489 let first = binding == first_binding;
2490 let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
2491 let mut note_span = MultiSpan::from_span(def_span);
2492 if !first && binding.vis().is_public() {
2493 let desc = match binding.kind {
2494 DeclKind::Import { .. } => "re-export",
2495 _ => "directly",
2496 };
2497 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}"));
2498 }
2499 if next_binding.is_none()
2502 && let Some(span) = non_exhaustive
2503 {
2504 note_span.push_span_label(
2505 span,
2506 "cannot be constructed because it is `#[non_exhaustive]`",
2507 );
2508 }
2509 let note = diagnostics::NoteAndRefersToTheItemDefinedHere {
2510 span: note_span,
2511 binding_descr: get_descr(binding),
2512 binding_name: name,
2513 first,
2514 dots: next_binding.is_some(),
2515 };
2516 err.subdiagnostic(note);
2517 }
2518 let can_replace_use = !shown_candidates
2526 && !single_nested
2527 && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
2528 if can_replace_use {
2529 sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
2532 for (sugg, reexport) in sugg_paths {
2533 if sugg.len() <= 1 {
2534 continue;
2537 }
2538 let path = join_path_idents(sugg);
2539 let sugg = if reexport {
2540 diagnostics::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
2541 } else {
2542 diagnostics::ImportIdent::Directly { span: dedup_span, ident, path }
2543 };
2544 err.subdiagnostic(sugg);
2545 break;
2546 }
2547 }
2548
2549 err.emit();
2550 }
2551
2552 fn mention_default_field_values(
2572 &self,
2573 source: &Option<ast::Expr>,
2574 ident: Ident,
2575 err: &mut Diag<'_>,
2576 ) {
2577 let Some(expr) = source else { return };
2578 let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
2579 let Some(segment) = struct_expr.path.segments.last() else { return };
2582 let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
2583 let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
2584 return;
2585 };
2586 let Some(default_fields) = self.field_defaults(def_id) else { return };
2587 if struct_expr.fields.is_empty() {
2588 return;
2589 }
2590 let last_span = struct_expr.fields.iter().last().unwrap().span;
2591 let mut iter = struct_expr.fields.iter().peekable();
2592 let mut prev: Option<Span> = None;
2593 while let Some(field) = iter.next() {
2594 if field.expr.span.overlaps(ident.span) {
2595 err.span_label(field.ident.span, "while setting this field");
2596 if default_fields.contains(&field.ident.name) {
2597 let sugg = if last_span == field.span {
2598 ::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())]
2599 } else {
2600 ::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![
2601 (
2602 match (prev, iter.peek()) {
2604 (_, Some(next)) => field.span.with_hi(next.span.lo()),
2605 (Some(prev), _) => field.span.with_lo(prev.hi()),
2606 (None, None) => field.span,
2607 },
2608 String::new(),
2609 ),
2610 (last_span.shrink_to_hi(), ", ..".to_string()),
2611 ]
2612 };
2613 err.multipart_suggestion(
2614 ::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!(
2615 "the type `{ident}` of field `{}` is private, but you can construct \
2616 the default value defined for it in `{}` using `..` in the struct \
2617 initializer expression",
2618 field.ident,
2619 self.tcx.item_name(def_id),
2620 ),
2621 sugg,
2622 Applicability::MachineApplicable,
2623 );
2624 break;
2625 }
2626 }
2627 prev = Some(field.span);
2628 }
2629 }
2630
2631 pub(crate) fn find_similarly_named_module_or_crate(
2632 &self,
2633 ident: Symbol,
2634 current_module: Module<'ra>,
2635 ) -> Option<Symbol> {
2636 let mut candidates = self
2637 .extern_prelude
2638 .keys()
2639 .map(|ident| ident.name)
2640 .chain(
2641 self.local_module_map
2642 .iter()
2643 .filter(|(_, module)| {
2644 let module = module.to_module();
2645 current_module.is_ancestor_of(module) && current_module != module
2646 })
2647 .flat_map(|(_, module)| module.name()),
2648 )
2649 .chain(
2650 self.extern_module_map
2651 .borrow()
2652 .iter()
2653 .filter(|(_, module)| {
2654 let module = module.to_module();
2655 current_module.is_ancestor_of(module) && current_module != module
2656 })
2657 .flat_map(|(_, module)| module.name()),
2658 )
2659 .filter(|c| !c.to_string().is_empty())
2660 .collect::<Vec<_>>();
2661 candidates.sort();
2662 candidates.dedup();
2663 find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
2664 }
2665
2666 pub(crate) fn report_path_resolution_error(
2667 &mut self,
2668 path: &[Segment],
2669 opt_ns: Option<Namespace>, parent_scope: &ParentScope<'ra>,
2671 ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
2672 ignore_decl: Option<Decl<'ra>>,
2673 ignore_import: Option<Import<'ra>>,
2674 module: Option<ModuleOrUniformRoot<'ra>>,
2675 failed_segment_idx: usize,
2676 ident: Ident,
2677 diag_metadata: Option<&DiagMetadata<'_>>,
2678 ) -> (String, String, Option<Suggestion>) {
2679 let is_last = failed_segment_idx == path.len() - 1;
2680 let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
2681 let module_def_id = match module {
2682 Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
2683 _ => None,
2684 };
2685 let scope = match &path[..failed_segment_idx] {
2686 [.., prev] => {
2687 if prev.ident.name == kw::PathRoot {
2688 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the crate root"))
})format!("the crate root")
2689 } else {
2690 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", prev.ident))
})format!("`{}`", prev.ident)
2691 }
2692 }
2693 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("this scope"))
})format!("this scope"),
2694 };
2695 let message = ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("cannot find `{0}` in {1}", ident,
scope))
})format!("cannot find `{ident}` in {scope}");
2696
2697 if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
2698 let is_mod = |res| #[allow(non_exhaustive_omitted_patterns)] match res {
Res::Def(DefKind::Mod, _) => true,
_ => false,
}matches!(res, Res::Def(DefKind::Mod, _));
2699 let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
2700 candidates
2701 .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
2702 if let Some(candidate) = candidates.get(0) {
2703 let path = {
2704 let len = candidate.path.segments.len();
2706 let start_index = (0..=failed_segment_idx.min(len - 1))
2707 .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
2708 .unwrap_or_default();
2709 let segments =
2710 (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
2711 Path { segments, span: Span::default(), tokens: None }
2712 };
2713 (
2714 message,
2715 String::from("unresolved import"),
2716 Some((
2717 ::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))],
2718 String::from("a similar path exists"),
2719 Applicability::MaybeIncorrect,
2720 )),
2721 )
2722 } else if ident.name == sym::core {
2723 (
2724 message,
2725 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("you might be missing crate `{0}`",
ident))
})format!("you might be missing crate `{ident}`"),
2726 Some((
2727 ::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())],
2728 "try using `std` instead of `core`".to_string(),
2729 Applicability::MaybeIncorrect,
2730 )),
2731 )
2732 } else if ident.name == kw::Underscore {
2733 (
2734 "invalid crate or module name `_`".to_string(),
2735 "`_` is not a valid crate or module name".to_string(),
2736 None,
2737 )
2738 } else if self.tcx.sess.is_rust_2015() {
2739 (
2740 ::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}"),
2741 ::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}`"),
2742 Some((
2743 ::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![(
2744 self.current_crate_outer_attr_insert_span,
2745 format!("extern crate {ident};\n"),
2746 )],
2747 if was_invoked_from_cargo() {
2748 ::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!(
2749 "if you wanted to use a crate named `{ident}`, use `cargo add \
2750 {ident}` to add it to your `Cargo.toml` and import it in your \
2751 code",
2752 )
2753 } else {
2754 ::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!(
2755 "you might be missing a crate named `{ident}`, add it to your \
2756 project and import it in your code",
2757 )
2758 },
2759 Applicability::MaybeIncorrect,
2760 )),
2761 )
2762 } else {
2763 (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)
2764 }
2765 } else if failed_segment_idx > 0 {
2766 let parent = path[failed_segment_idx - 1].ident.name;
2767 let parent = match parent {
2768 kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
2771 "the list of imported crates".to_owned()
2772 }
2773 kw::PathRoot | kw::Crate => "the crate root".to_owned(),
2774 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", parent))
})format!("`{parent}`"),
2775 };
2776
2777 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}");
2778 if ns == TypeNS || ns == ValueNS {
2779 let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
2780 let binding = if let Some(module) = module {
2781 self.cm()
2782 .resolve_ident_in_module(
2783 module,
2784 ident,
2785 ns_to_try,
2786 parent_scope,
2787 None,
2788 ignore_decl,
2789 ignore_import,
2790 )
2791 .ok()
2792 } else if let Some(ribs) = ribs
2793 && let Some(TypeNS | ValueNS) = opt_ns
2794 {
2795 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2796 match self.resolve_ident_in_lexical_scope(
2797 ident,
2798 ns_to_try,
2799 parent_scope,
2800 None,
2801 &ribs[ns_to_try],
2802 ignore_decl,
2803 diag_metadata,
2804 ) {
2805 Some(LateDecl::Decl(binding)) => Some(binding),
2807 _ => None,
2808 }
2809 } else {
2810 self.cm()
2811 .resolve_ident_in_scope_set(
2812 ident,
2813 ScopeSet::All(ns_to_try),
2814 parent_scope,
2815 None,
2816 ignore_decl,
2817 ignore_import,
2818 )
2819 .ok()
2820 };
2821 if let Some(binding) = binding {
2822 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!(
2823 "expected {}, found {} `{ident}` in {parent}",
2824 ns.descr(),
2825 binding.res().descr(),
2826 );
2827 };
2828 }
2829 (message, msg, None)
2830 } else if ident.name == kw::SelfUpper {
2831 if opt_ns.is_none() {
2835 (message, "`Self` cannot be used in imports".to_string(), None)
2836 } else {
2837 (
2838 message,
2839 "`Self` is only available in impls, traits, and type definitions".to_string(),
2840 None,
2841 )
2842 }
2843 } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
2844 let binding = if let Some(ribs) = ribs {
2846 if !ignore_import.is_none() {
::core::panicking::panic("assertion failed: ignore_import.is_none()")
};assert!(ignore_import.is_none());
2847 self.resolve_ident_in_lexical_scope(
2848 ident,
2849 ValueNS,
2850 parent_scope,
2851 None,
2852 &ribs[ValueNS],
2853 ignore_decl,
2854 diag_metadata,
2855 )
2856 } else {
2857 None
2858 };
2859 let match_span = match binding {
2860 Some(LateDecl::RibDef(Res::Local(id))) => {
2869 Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
2870 }
2871 Some(LateDecl::Decl(name_binding)) => Some((
2883 name_binding.span,
2884 name_binding.res().article(),
2885 name_binding.res().descr(),
2886 )),
2887 _ => None,
2888 };
2889
2890 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}");
2891 let label = if let Some((span, article, descr)) = match_span {
2892 ::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!(
2893 "`{ident}` is declared as {article} {descr} at `{}`, not a type",
2894 self.tcx
2895 .sess
2896 .source_map()
2897 .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
2898 )
2899 } else {
2900 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use of undeclared type `{0}`",
ident))
})format!("use of undeclared type `{ident}`")
2901 };
2902 (message, label, None)
2903 } else {
2904 let mut suggestion = None;
2905 if ident.name == sym::alloc {
2906 suggestion = Some((
2907 ::alloc::vec::Vec::new()vec![],
2908 String::from("add `extern crate alloc` to use the `alloc` crate"),
2909 Applicability::MaybeIncorrect,
2910 ))
2911 }
2912
2913 suggestion = suggestion.or_else(|| {
2914 self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
2915 |sugg| {
2916 (
2917 ::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())],
2918 String::from("there is a crate or module with a similar name"),
2919 Applicability::MaybeIncorrect,
2920 )
2921 },
2922 )
2923 });
2924 if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
2925 ident,
2926 ScopeSet::All(ValueNS),
2927 parent_scope,
2928 None,
2929 ignore_decl,
2930 ignore_import,
2931 ) {
2932 let descr = binding.res().descr();
2933 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}");
2934 (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)
2935 } else {
2936 let suggestion = if suggestion.is_some() {
2937 suggestion
2938 } else if let Some(m) = self.undeclared_module_exists(ident) {
2939 self.undeclared_module_suggest_declare(ident, m)
2940 } else if was_invoked_from_cargo() {
2941 Some((
2942 ::alloc::vec::Vec::new()vec![],
2943 ::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!(
2944 "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
2945 to add it to your `Cargo.toml`",
2946 ),
2947 Applicability::MaybeIncorrect,
2948 ))
2949 } else {
2950 Some((
2951 ::alloc::vec::Vec::new()vec![],
2952 ::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}`",),
2953 Applicability::MaybeIncorrect,
2954 ))
2955 };
2956 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}");
2957 (
2958 message,
2959 ::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}`"),
2960 suggestion,
2961 )
2962 }
2963 }
2964 }
2965
2966 fn undeclared_module_suggest_declare(
2967 &self,
2968 ident: Ident,
2969 path: std::path::PathBuf,
2970 ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
2971 Some((
2972 ::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"))],
2973 ::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!(
2974 "to make use of source file {}, use `mod {ident}` \
2975 in this file to declare the module",
2976 path.display()
2977 ),
2978 Applicability::MaybeIncorrect,
2979 ))
2980 }
2981
2982 fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
2983 let map = self.tcx.sess.source_map();
2984
2985 let src = map.span_to_filename(ident.span).into_local_path()?;
2986 let i = ident.as_str();
2987 let dir = src.parent()?;
2989 let src = src.file_stem()?.to_str()?;
2990 for file in [
2991 dir.join(i).with_extension("rs"),
2993 dir.join(i).join("mod.rs"),
2995 ] {
2996 if file.exists() {
2997 return Some(file);
2998 }
2999 }
3000 if !#[allow(non_exhaustive_omitted_patterns)] match src {
"main" | "lib" | "mod" => true,
_ => false,
}matches!(src, "main" | "lib" | "mod") {
3001 for file in [
3002 dir.join(src).join(i).with_extension("rs"),
3004 dir.join(src).join(i).join("mod.rs"),
3006 ] {
3007 if file.exists() {
3008 return Some(file);
3009 }
3010 }
3011 }
3012 None
3013 }
3014
3015 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_path_suggestion",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3016u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
match path[..] {
[first, second, ..] if
first.ident.name == kw::PathRoot &&
!second.ident.is_path_segment_keyword() => {}
[first, ..] if
first.ident.span.at_least_rust_2018() &&
!first.ident.is_path_segment_keyword() => {
path.insert(0, Segment::from_ident(Ident::dummy()));
}
_ => return None,
}
self.make_missing_self_suggestion(path.clone(),
parent_scope).or_else(||
self.make_missing_crate_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_missing_super_suggestion(path.clone(),
parent_scope)).or_else(||
self.make_external_crate_suggestion(path, parent_scope))
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3017 pub(crate) fn make_path_suggestion(
3018 &mut self,
3019 mut path: Vec<Segment>,
3020 parent_scope: &ParentScope<'ra>,
3021 ) -> Option<(Vec<Segment>, Option<String>)> {
3022 match path[..] {
3023 [first, second, ..]
3026 if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
3027 [first, ..]
3029 if first.ident.span.at_least_rust_2018()
3030 && !first.ident.is_path_segment_keyword() =>
3031 {
3032 path.insert(0, Segment::from_ident(Ident::dummy()));
3034 }
3035 _ => return None,
3036 }
3037
3038 self.make_missing_self_suggestion(path.clone(), parent_scope)
3039 .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
3040 .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
3041 .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
3042 }
3043
3044 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_self_suggestion",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3051u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::SelfLower;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3060",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3060u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3052 fn make_missing_self_suggestion(
3053 &mut self,
3054 mut path: Vec<Segment>,
3055 parent_scope: &ParentScope<'ra>,
3056 ) -> Option<(Vec<Segment>, Option<String>)> {
3057 path[0].ident.name = kw::SelfLower;
3059 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3060 debug!(?path, ?result);
3061 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3062 }
3063
3064 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_crate_suggestion",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3071u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Crate;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3080",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3080u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path,
Some("`use` statements changed in Rust 2018; read more at \
<https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
clarity.html>".to_string())))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3072 fn make_missing_crate_suggestion(
3073 &mut self,
3074 mut path: Vec<Segment>,
3075 parent_scope: &ParentScope<'ra>,
3076 ) -> Option<(Vec<Segment>, Option<String>)> {
3077 path[0].ident.name = kw::Crate;
3079 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3080 debug!(?path, ?result);
3081 if let PathResult::Module(..) = result {
3082 Some((
3083 path,
3084 Some(
3085 "`use` statements changed in Rust 2018; read more at \
3086 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
3087 clarity.html>"
3088 .to_string(),
3089 ),
3090 ))
3091 } else {
3092 None
3093 }
3094 }
3095
3096 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_missing_super_suggestion",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3103u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
path[0].ident.name = kw::Super;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope, None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3112",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3112u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path", "result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
Some((path, None))
} else { None }
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3104 fn make_missing_super_suggestion(
3105 &mut self,
3106 mut path: Vec<Segment>,
3107 parent_scope: &ParentScope<'ra>,
3108 ) -> Option<(Vec<Segment>, Option<String>)> {
3109 path[0].ident.name = kw::Super;
3111 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3112 debug!(?path, ?result);
3113 if let PathResult::Module(..) = result { Some((path, None)) } else { None }
3114 }
3115
3116 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_external_crate_suggestion",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3126u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Vec<Segment>, Option<String>)> = loop {};
return __tracing_attr_fake_return;
}
{
if path[1].ident.span.is_rust_2015() { return None; }
let mut extern_crate_names =
self.extern_prelude.keys().map(|ident|
ident.name).collect::<Vec<_>>();
extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
for name in extern_crate_names.into_iter() {
path[0].ident.name = name;
let result =
self.cm().maybe_resolve_path(&path, None, parent_scope,
None);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3147",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3147u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["path", "name",
"result"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&path) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&name) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&result) as
&dyn Value))])
});
} else { ; }
};
if let PathResult::Module(..) = result {
return Some((path, None));
}
}
None
}
}
}#[instrument(level = "debug", skip(self, parent_scope))]
3127 fn make_external_crate_suggestion(
3128 &mut self,
3129 mut path: Vec<Segment>,
3130 parent_scope: &ParentScope<'ra>,
3131 ) -> Option<(Vec<Segment>, Option<String>)> {
3132 if path[1].ident.span.is_rust_2015() {
3133 return None;
3134 }
3135
3136 let mut extern_crate_names =
3140 self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
3141 extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));
3142
3143 for name in extern_crate_names.into_iter() {
3144 path[0].ident.name = name;
3146 let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
3147 debug!(?path, ?name, ?result);
3148 if let PathResult::Module(..) = result {
3149 return Some((path, None));
3150 }
3151 }
3152
3153 None
3154 }
3155
3156 pub(crate) fn check_for_module_export_macro(
3169 &mut self,
3170 import: Import<'ra>,
3171 module: ModuleOrUniformRoot<'ra>,
3172 ident: Ident,
3173 ) -> Option<(Option<Suggestion>, Option<String>)> {
3174 let ModuleOrUniformRoot::Module(mut crate_module) = module else {
3175 return None;
3176 };
3177
3178 while let Some(parent) = crate_module.parent {
3179 crate_module = parent;
3180 }
3181
3182 if module == ModuleOrUniformRoot::Module(crate_module) {
3183 return None;
3185 }
3186
3187 let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
3188 let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
3189 let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
3190 return None;
3191 };
3192 if !kinds.contains(MacroKinds::BANG) {
3193 return None;
3194 }
3195 let module_name = crate_module.name().unwrap_or(kw::Crate);
3196 let import_snippet = match import.kind {
3197 ImportKind::Single { source, target, .. } if source != target => {
3198 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}", source, target))
})format!("{source} as {target}")
3199 }
3200 _ => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", ident))
})format!("{ident}"),
3201 };
3202
3203 let mut corrections: Vec<(Span, String)> = Vec::new();
3204 if !import.is_nested() {
3205 corrections.push((import.span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::{1}", module_name,
import_snippet))
})format!("{module_name}::{import_snippet}")));
3208 } else {
3209 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
3213 self.tcx.sess,
3214 import.span,
3215 import.use_span,
3216 );
3217 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3217",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3217u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["found_closing_brace",
"binding_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&found_closing_brace
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&binding_span)
as &dyn Value))])
});
} else { ; }
};debug!(found_closing_brace, ?binding_span);
3218
3219 let mut removal_span = binding_span;
3220
3221 if found_closing_brace
3229 && let Some(previous_span) =
3230 extend_span_to_previous_binding(self.tcx.sess, binding_span)
3231 {
3232 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3232",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3232u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["previous_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&previous_span)
as &dyn Value))])
});
} else { ; }
};debug!(?previous_span);
3233 removal_span = removal_span.with_lo(previous_span.lo());
3234 }
3235 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3235",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3235u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["removal_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&removal_span)
as &dyn Value))])
});
} else { ; }
};debug!(?removal_span);
3236
3237 corrections.push((removal_span, "".to_string()));
3239
3240 let (has_nested, after_crate_name) =
3247 find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
3248 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_resolve/src/error_helper.rs:3248",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3248u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["has_nested",
"after_crate_name"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&has_nested as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&after_crate_name)
as &dyn Value))])
});
} else { ; }
};debug!(has_nested, ?after_crate_name);
3249
3250 let source_map = self.tcx.sess.source_map();
3251
3252 let is_definitely_crate = import
3254 .module_path
3255 .first()
3256 .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);
3257
3258 let start_point = source_map.start_point(after_crate_name);
3260 if is_definitely_crate
3261 && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
3262 {
3263 corrections.push((
3264 start_point,
3265 if has_nested {
3266 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}, ", start_snippet,
import_snippet))
})format!("{start_snippet}{import_snippet}, ")
3268 } else {
3269 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{{{0}, {1}", import_snippet,
start_snippet))
})format!("{{{import_snippet}, {start_snippet}")
3272 },
3273 ));
3274
3275 if !has_nested {
3277 corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
3278 }
3279 } else {
3280 corrections.push((
3282 import.use_span.shrink_to_lo(),
3283 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("use {0}::{1};\n", module_name,
import_snippet))
})format!("use {module_name}::{import_snippet};\n"),
3284 ));
3285 }
3286 }
3287
3288 let suggestion = Some((
3289 corrections,
3290 String::from("a macro with this name exists at the root of the crate"),
3291 Applicability::MaybeIncorrect,
3292 ));
3293 Some((
3294 suggestion,
3295 Some(
3296 "this could be because a macro annotated with `#[macro_export]` will be exported \
3297 at the root of the crate instead of the module where it is defined"
3298 .to_string(),
3299 ),
3300 ))
3301 }
3302
3303 pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
3305 let local_items;
3306 let symbols = if module.is_local() {
3307 local_items = self
3308 .stripped_cfg_items
3309 .iter()
3310 .filter_map(|item| {
3311 let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
3312 ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
3313 Some(def_id)
3314 }
3315 _ => None,
3316 })?;
3317 Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
3318 })
3319 .collect::<Vec<_>>();
3320 local_items.as_slice()
3321 } else {
3322 self.tcx.stripped_cfg_items(module.krate)
3323 };
3324
3325 for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
3326 if ident.name != *segment {
3327 continue;
3328 }
3329
3330 let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();
3331
3332 fn comes_from_same_module_for_glob(
3333 r: &Resolver<'_, '_>,
3334 parent_module: DefId,
3335 module: DefId,
3336 visited: &mut FxHashMap<DefId, bool>,
3337 ) -> bool {
3338 if let Some(&cached) = visited.get(&parent_module) {
3339 return cached;
3343 }
3344 visited.insert(parent_module, false);
3345 let mut res = false;
3346 let m = r.expect_module(parent_module);
3347 if m.is_local() {
3348 for importer in m.glob_importers.borrow().iter() {
3349 if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
3350 {
3351 if next_parent_module == module
3352 || comes_from_same_module_for_glob(
3353 r,
3354 next_parent_module,
3355 module,
3356 visited,
3357 )
3358 {
3359 res = true;
3360 break;
3361 }
3362 }
3363 }
3364 }
3365 visited.insert(parent_module, res);
3366 res
3367 }
3368
3369 let comes_from_same_module = parent_module == module
3370 || comes_from_same_module_for_glob(
3371 self,
3372 parent_module,
3373 module,
3374 &mut Default::default(),
3375 );
3376 if !comes_from_same_module {
3377 continue;
3378 }
3379
3380 let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
3381 diagnostics::ItemWas::BehindFeature { feature, span: cfg.1 }
3382 } else {
3383 diagnostics::ItemWas::CfgOut { span: cfg.1 }
3384 };
3385 let note = diagnostics::FoundItemConfigureOut { span: ident.span, item_was };
3386 err.subdiagnostic(note);
3387 }
3388 }
3389
3390 pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
3391 match def_id.as_local() {
3392 Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
3393 None => {
3394 self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
3395 let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
3396 let vis = self.tcx.visibility(ctor_def_id);
3397 let field_visibilities = self
3398 .tcx
3399 .associated_item_def_ids(def_id)
3400 .iter()
3401 .map(|&field_id| self.tcx.visibility(field_id))
3402 .collect();
3403 StructCtor { res, vis, field_visibilities }
3404 })
3405 }
3406 }
3407 }
3408}
3409
3410fn find_span_of_binding_until_next_binding(
3424 sess: &Session,
3425 binding_span: Span,
3426 use_span: Span,
3427) -> (bool, Span) {
3428 let source_map = sess.source_map();
3429
3430 let binding_until_end = binding_span.with_hi(use_span.hi());
3433
3434 let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
3437
3438 let mut found_closing_brace = false;
3445 let after_binding_until_next_binding =
3446 source_map.span_take_while(after_binding_until_end, |&ch| {
3447 if ch == '}' {
3448 found_closing_brace = true;
3449 }
3450 ch == ' ' || ch == ','
3451 });
3452
3453 let span = binding_span.with_hi(after_binding_until_next_binding.hi());
3458
3459 (found_closing_brace, span)
3460}
3461
3462fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
3475 let source_map = sess.source_map();
3476
3477 let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
3481
3482 let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
3483 let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
3484 if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
3485 return None;
3486 }
3487
3488 let prev_comma = prev_comma.first().unwrap();
3489 let prev_starting_brace = prev_starting_brace.first().unwrap();
3490
3491 if prev_comma.len() > prev_starting_brace.len() {
3495 return None;
3496 }
3497
3498 Some(binding_span.with_lo(BytePos(
3499 binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
3502 )))
3503}
3504
3505#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("find_span_immediately_after_crate_name",
"rustc_resolve::error_helper", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_resolve/src/error_helper.rs"),
::tracing_core::__macro_support::Option::Some(3518u32),
::tracing_core::__macro_support::Option::Some("rustc_resolve::error_helper"),
::tracing_core::field::FieldSet::new(&["use_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&use_span)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: (bool, Span) = loop {};
return __tracing_attr_fake_return;
}
{
let source_map = sess.source_map();
let mut num_colons = 0;
let until_second_colon =
source_map.span_take_while(use_span,
|c|
{
if *c == ':' { num_colons += 1; }
!#[allow(non_exhaustive_omitted_patterns)] match c {
':' if num_colons == 2 => true,
_ => false,
}
});
let from_second_colon =
use_span.with_lo(until_second_colon.hi() + BytePos(1));
let mut found_a_non_whitespace_character = false;
let after_second_colon =
source_map.span_take_while(from_second_colon,
|c|
{
if found_a_non_whitespace_character { return false; }
if !c.is_whitespace() {
found_a_non_whitespace_character = true;
}
true
});
let next_left_bracket =
source_map.span_through_char(from_second_colon, '{');
(next_left_bracket == after_second_colon, from_second_colon)
}
}
}#[instrument(level = "debug", skip(sess))]
3519fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
3520 let source_map = sess.source_map();
3521
3522 let mut num_colons = 0;
3524 let until_second_colon = source_map.span_take_while(use_span, |c| {
3526 if *c == ':' {
3527 num_colons += 1;
3528 }
3529 !matches!(c, ':' if num_colons == 2)
3530 });
3531 let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
3533
3534 let mut found_a_non_whitespace_character = false;
3535 let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
3537 if found_a_non_whitespace_character {
3538 return false;
3539 }
3540 if !c.is_whitespace() {
3541 found_a_non_whitespace_character = true;
3542 }
3543 true
3544 });
3545
3546 let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
3548
3549 (next_left_bracket == after_second_colon, from_second_colon)
3550}
3551
3552enum Instead {
3555 Yes,
3556 No,
3557}
3558
3559enum FoundUse {
3561 Yes,
3562 No,
3563}
3564
3565pub(crate) enum DiagMode {
3567 Normal,
3568 Pattern,
3570 Import {
3572 unresolved_import: bool,
3574 append: bool,
3577 },
3578}
3579
3580pub(crate) fn import_candidates(
3581 tcx: TyCtxt<'_>,
3582 err: &mut Diag<'_>,
3583 use_placement_span: Option<Span>,
3585 candidates: &[ImportSuggestion],
3586 mode: DiagMode,
3587 append: &str,
3588) {
3589 show_candidates(
3590 tcx,
3591 err,
3592 use_placement_span,
3593 candidates,
3594 Instead::Yes,
3595 FoundUse::Yes,
3596 mode,
3597 ::alloc::vec::Vec::new()vec![],
3598 append,
3599 );
3600}
3601
3602type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);
3603
3604fn show_candidates(
3609 tcx: TyCtxt<'_>,
3610 err: &mut Diag<'_>,
3611 use_placement_span: Option<Span>,
3613 candidates: &[ImportSuggestion],
3614 instead: Instead,
3615 found_use: FoundUse,
3616 mode: DiagMode,
3617 path: Vec<Segment>,
3618 append: &str,
3619) -> bool {
3620 if candidates.is_empty() {
3621 return false;
3622 }
3623
3624 let mut showed = false;
3625 let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
3626 let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();
3627
3628 candidates.iter().for_each(|c| {
3629 if c.accessible {
3630 if c.doc_visible {
3632 accessible_path_strings.push((
3633 pprust::path_to_string(&c.path),
3634 c.descr,
3635 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3636 &c.note,
3637 c.via_import,
3638 ))
3639 }
3640 } else {
3641 inaccessible_path_strings.push((
3642 pprust::path_to_string(&c.path),
3643 c.descr,
3644 c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
3645 &c.note,
3646 c.via_import,
3647 ))
3648 }
3649 });
3650
3651 for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
3654 path_strings.sort_by(|a, b| a.0.cmp(&b.0));
3655 path_strings.dedup_by(|a, b| a.0 == b.0);
3656 let core_path_strings =
3657 path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
3658 let std_path_strings =
3659 path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
3660 let foreign_crate_path_strings =
3661 path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();
3662
3663 if std_path_strings.len() == core_path_strings.len() {
3666 path_strings.extend(std_path_strings);
3668 } else {
3669 path_strings.extend(std_path_strings);
3670 path_strings.extend(core_path_strings);
3671 }
3672 path_strings.extend(foreign_crate_path_strings);
3674 }
3675
3676 if !accessible_path_strings.is_empty() {
3677 let (determiner, kind, s, name, through) =
3678 if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
3679 (
3680 "this",
3681 *descr,
3682 "",
3683 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" `{0}`", name))
})format!(" `{name}`"),
3684 if *via_import { " through its public re-export" } else { "" },
3685 )
3686 } else {
3687 let kinds = accessible_path_strings
3690 .iter()
3691 .map(|(_, descr, _, _, _)| *descr)
3692 .collect::<UnordSet<&str>>();
3693 let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
3694 let s = if kind.ends_with('s') { "es" } else { "s" };
3695
3696 ("one of these", kind, s, String::new(), "")
3697 };
3698
3699 let instead = if let Instead::Yes = instead { " instead" } else { "" };
3700 let mut msg = if let DiagMode::Pattern = mode {
3701 ::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!(
3702 "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
3703 pattern",
3704 )
3705 } else {
3706 ::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}")
3707 };
3708
3709 for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3710 err.note(note.clone());
3711 }
3712
3713 let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
3714 msg.push(':');
3715
3716 for candidate in accessible_path_strings {
3717 msg.push('\n');
3718 msg.push_str(&candidate.0);
3719 }
3720 };
3721
3722 if let Some(span) = use_placement_span {
3723 let (add_use, trailing) = match mode {
3724 DiagMode::Pattern => {
3725 err.span_suggestions(
3726 span,
3727 msg,
3728 accessible_path_strings.into_iter().map(|a| a.0),
3729 Applicability::MaybeIncorrect,
3730 );
3731 return true;
3732 }
3733 DiagMode::Import { .. } => ("", ""),
3734 DiagMode::Normal => ("use ", ";\n"),
3735 };
3736 for candidate in &mut accessible_path_strings {
3737 let additional_newline = if let FoundUse::No = found_use
3740 && let DiagMode::Normal = mode
3741 {
3742 "\n"
3743 } else {
3744 ""
3745 };
3746 candidate.0 =
3747 ::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);
3748 }
3749
3750 match mode {
3751 DiagMode::Import { append: true, .. } => {
3752 append_candidates(&mut msg, accessible_path_strings);
3753 err.span_help(span, msg);
3754 }
3755 _ => {
3756 err.span_suggestions_with_style(
3757 span,
3758 msg,
3759 accessible_path_strings.into_iter().map(|a| a.0),
3760 Applicability::MaybeIncorrect,
3761 SuggestionStyle::ShowAlways,
3762 );
3763 }
3764 }
3765
3766 if let [first, .., last] = &path[..] {
3767 let sp = first.ident.span.until(last.ident.span);
3768 if sp.can_be_used_for_suggestions() && !sp.is_empty() {
3771 err.span_suggestion_verbose(
3772 sp,
3773 ::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),
3774 "",
3775 Applicability::Unspecified,
3776 );
3777 }
3778 }
3779 } else {
3780 append_candidates(&mut msg, accessible_path_strings);
3781 err.help(msg);
3782 }
3783 showed = true;
3784 }
3785 if !inaccessible_path_strings.is_empty()
3786 && (!#[allow(non_exhaustive_omitted_patterns)] match mode {
DiagMode::Import { unresolved_import: false, .. } => true,
_ => false,
}matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
3787 {
3788 let prefix =
3789 if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
3790 if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
3791 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!(
3792 "{prefix}{descr} `{name}`{} exists but is inaccessible",
3793 if let DiagMode::Pattern = mode { ", which" } else { "" }
3794 );
3795
3796 if let Some(source_span) = source_span {
3797 let span = tcx.sess.source_map().guess_head_span(*source_span);
3798 let mut multi_span = MultiSpan::from_span(span);
3799 multi_span.push_span_label(span, "not accessible");
3800 err.span_note(multi_span, msg);
3801 } else {
3802 err.note(msg);
3803 }
3804 if let Some(note) = (*note).as_deref() {
3805 err.note(note.to_string());
3806 }
3807 } else {
3808 let descr = inaccessible_path_strings
3809 .iter()
3810 .map(|&(_, descr, _, _, _)| descr)
3811 .all_equal_value()
3812 .unwrap_or("item");
3813 let plural_descr =
3814 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") };
3815
3816 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");
3817 let mut has_colon = false;
3818
3819 let mut spans = Vec::new();
3820 for (name, _, source_span, _, _) in &inaccessible_path_strings {
3821 if let Some(source_span) = source_span {
3822 let span = tcx.sess.source_map().guess_head_span(*source_span);
3823 spans.push((name, span));
3824 } else {
3825 if !has_colon {
3826 msg.push(':');
3827 has_colon = true;
3828 }
3829 msg.push('\n');
3830 msg.push_str(name);
3831 }
3832 }
3833
3834 let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
3835 for (name, span) in spans {
3836 multi_span.push_span_label(span, ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`: not accessible", name))
})format!("`{name}`: not accessible"));
3837 }
3838
3839 for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
3840 err.note(note.clone());
3841 }
3842
3843 err.span_note(multi_span, msg);
3844 }
3845 showed = true;
3846 }
3847 showed
3848}
3849
3850#[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)]
3851struct UsePlacementFinder {
3852 target_module: NodeId,
3853 first_legal_span: Option<Span>,
3854 first_use_span: Option<Span>,
3855}
3856
3857impl UsePlacementFinder {
3858 fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
3859 let mut finder =
3860 UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
3861 finder.visit_crate(krate);
3862 if let Some(use_span) = finder.first_use_span {
3863 (Some(use_span), FoundUse::Yes)
3864 } else {
3865 (finder.first_legal_span, FoundUse::No)
3866 }
3867 }
3868}
3869
3870impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
3871 fn visit_crate(&mut self, c: &Crate) {
3872 if self.target_module == CRATE_NODE_ID {
3873 let inject = c.spans.inject_use_span;
3874 if is_span_suitable_for_use_injection(inject) {
3875 self.first_legal_span = Some(inject);
3876 }
3877 self.first_use_span = search_for_any_use_in_items(&c.items);
3878 } else {
3879 visit::walk_crate(self, c);
3880 }
3881 }
3882
3883 fn visit_item(&mut self, item: &'tcx ast::Item) {
3884 if self.target_module == item.id {
3885 if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
3886 let inject = mod_spans.inject_use_span;
3887 if is_span_suitable_for_use_injection(inject) {
3888 self.first_legal_span = Some(inject);
3889 }
3890 self.first_use_span = search_for_any_use_in_items(items);
3891 }
3892 } else {
3893 visit::walk_item(self, item);
3894 }
3895 }
3896}
3897
3898#[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)]
3899struct BindingVisitor {
3900 identifiers: Vec<Symbol>,
3901 spans: FxHashMap<Symbol, Vec<Span>>,
3902}
3903
3904impl<'tcx> Visitor<'tcx> for BindingVisitor {
3905 fn visit_pat(&mut self, pat: &ast::Pat) {
3906 if let ast::PatKind::Ident(_, ident, _) = pat.kind {
3907 self.identifiers.push(ident.name);
3908 self.spans.entry(ident.name).or_default().push(ident.span);
3909 }
3910 visit::walk_pat(self, pat);
3911 }
3912}
3913
3914fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
3915 for item in items {
3916 if let ItemKind::Use(..) = item.kind
3917 && is_span_suitable_for_use_injection(item.span)
3918 {
3919 let mut lo = item.span.lo();
3920 for attr in &item.attrs {
3921 if attr.span.eq_ctxt(item.span) {
3922 lo = std::cmp::min(lo, attr.span.lo());
3923 }
3924 }
3925 return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
3926 }
3927 }
3928 None
3929}
3930
3931fn is_span_suitable_for_use_injection(s: Span) -> bool {
3932 !s.from_expansion()
3935}