3 use rustc_ast
::{self as ast, Path}
;
4 use rustc_ast_pretty
::pprust
;
5 use rustc_data_structures
::fx
::FxHashSet
;
6 use rustc_errors
::{struct_span_err, Applicability, DiagnosticBuilder}
;
7 use rustc_feature
::BUILTIN_ATTRIBUTES
;
8 use rustc_hir
::def
::Namespace
::{self, *}
;
9 use rustc_hir
::def
::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind}
;
10 use rustc_hir
::def_id
::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}
;
11 use rustc_hir
::PrimTy
;
12 use rustc_middle
::bug
;
13 use rustc_middle
::ty
::DefIdTree
;
14 use rustc_session
::Session
;
15 use rustc_span
::hygiene
::MacroKind
;
16 use rustc_span
::lev_distance
::find_best_match_for_name
;
17 use rustc_span
::source_map
::SourceMap
;
18 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
19 use rustc_span
::{BytePos, MultiSpan, Span}
;
22 use crate::imports
::{Import, ImportKind, ImportResolver}
;
23 use crate::path_names_to_string
;
24 use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}
;
26 BindingError
, CrateLint
, HasGenericParams
, MacroRulesScope
, Module
, ModuleOrUniformRoot
,
28 use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError}
;
29 use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment}
;
31 type Res
= def
::Res
<ast
::NodeId
>;
33 /// A vector of spans and replacements, a message and applicability.
34 crate type Suggestion
= (Vec
<(Span
, String
)>, String
, Applicability
);
36 /// Potential candidate for an undeclared or out-of-scope label - contains the ident of a
37 /// similarly named label and whether or not it is reachable.
38 crate type LabelSuggestion
= (Ident
, bool
);
40 crate enum SuggestionTarget
{
41 /// The target has a similar name as the name used by the programmer (probably a typo)
43 /// The target is the only valid item that can be used in the corresponding context
47 crate struct TypoSuggestion
{
48 pub candidate
: Symbol
,
50 pub target
: SuggestionTarget
,
54 crate fn typo_from_res(candidate
: Symbol
, res
: Res
) -> TypoSuggestion
{
55 Self { candidate, res, target: SuggestionTarget::SimilarlyNamed }
57 crate fn single_item_from_res(candidate
: Symbol
, res
: Res
) -> TypoSuggestion
{
58 Self { candidate, res, target: SuggestionTarget::SingleItem }
62 /// A free importable items suggested in case of resolution failure.
63 crate struct ImportSuggestion
{
64 pub did
: Option
<DefId
>,
65 pub descr
: &'
static str,
68 /// An extra note that should be issued if this item is suggested
69 pub note
: Option
<String
>,
72 /// Adjust the impl span so that just the `impl` keyword is taken by removing
73 /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
74 /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
76 /// *Attention*: the method used is very fragile since it essentially duplicates the work of the
77 /// parser. If you need to use this function or something similar, please consider updating the
78 /// `source_map` functions and this function to something more robust.
79 fn reduce_impl_span_to_impl_keyword(sm
: &SourceMap
, impl_span
: Span
) -> Span
{
80 let impl_span
= sm
.span_until_char(impl_span
, '
<'
);
81 sm
.span_until_whitespace(impl_span
)
84 impl<'a
> Resolver
<'a
> {
85 crate fn add_module_candidates(
88 names
: &mut Vec
<TypoSuggestion
>,
89 filter_fn
: &impl Fn(Res
) -> bool
,
91 for (key
, resolution
) in self.resolutions(module
).borrow().iter() {
92 if let Some(binding
) = resolution
.borrow().binding
{
93 let res
= binding
.res();
95 names
.push(TypoSuggestion
::typo_from_res(key
.ident
.name
, res
));
101 /// Combines an error with provided span and emits it.
103 /// This takes the error provided, combines it with the span and any additional spans inside the
104 /// error and emits it.
105 crate fn report_error(&self, span
: Span
, resolution_error
: ResolutionError
<'_
>) {
106 self.into_struct_error(span
, resolution_error
).emit();
109 crate fn into_struct_error(
112 resolution_error
: ResolutionError
<'_
>,
113 ) -> DiagnosticBuilder
<'_
> {
114 match resolution_error
{
115 ResolutionError
::GenericParamsFromOuterFunction(outer_res
, has_generic_params
) => {
116 let mut err
= struct_span_err
!(
120 "can't use generic parameters from outer function",
122 err
.span_label(span
, "use of generic parameter from outer function".to_string());
124 let sm
= self.session
.source_map();
126 Res
::SelfTy { trait_: maybe_trait_defid, alias_to: maybe_impl_defid }
=> {
127 if let Some(impl_span
) =
128 maybe_impl_defid
.and_then(|(def_id
, _
)| self.opt_span(def_id
))
131 reduce_impl_span_to_impl_keyword(sm
, impl_span
),
132 "`Self` type implicitly declared here, by this `impl`",
135 match (maybe_trait_defid
, maybe_impl_defid
) {
137 err
.span_label(span
, "can't use `Self` here");
140 err
.span_label(span
, "use a type here instead");
142 (None
, None
) => bug
!("`impl` without trait nor type?"),
146 Res
::Def(DefKind
::TyParam
, def_id
) => {
147 if let Some(span
) = self.opt_span(def_id
) {
148 err
.span_label(span
, "type parameter from outer function");
151 Res
::Def(DefKind
::ConstParam
, def_id
) => {
152 if let Some(span
) = self.opt_span(def_id
) {
153 err
.span_label(span
, "const parameter from outer function");
158 "GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
159 DefKind::TyParam or DefKind::ConstParam"
164 if has_generic_params
== HasGenericParams
::Yes
{
165 // Try to retrieve the span of the function signature and generate a new
166 // message with a local type or const parameter.
167 let sugg_msg
= "try using a local generic parameter instead";
168 if let Some((sugg_span
, snippet
)) = sm
.generate_local_type_param_snippet(span
) {
169 // Suggest the modification to the user
174 Applicability
::MachineApplicable
,
176 } else if let Some(sp
) = sm
.generate_fn_name_span(span
) {
179 "try adding a local generic parameter in this method instead"
183 err
.help("try using a local generic parameter instead");
189 ResolutionError
::NameAlreadyUsedInParameterList(name
, first_use_span
) => {
190 let mut err
= struct_span_err
!(
194 "the name `{}` is already used for a generic \
195 parameter in this item's generic parameters",
198 err
.span_label(span
, "already used");
199 err
.span_label(first_use_span
, format
!("first use of `{}`", name
));
202 ResolutionError
::MethodNotMemberOfTrait(method
, trait_
, candidate
) => {
203 let mut err
= struct_span_err
!(
207 "method `{}` is not a member of trait `{}`",
211 err
.span_label(span
, format
!("not a member of trait `{}`", trait_
));
212 if let Some(candidate
) = candidate
{
215 "there is an associated function with a similar name",
216 candidate
.to_ident_string(),
217 Applicability
::MaybeIncorrect
,
222 ResolutionError
::TypeNotMemberOfTrait(type_
, trait_
, candidate
) => {
223 let mut err
= struct_span_err
!(
227 "type `{}` is not a member of trait `{}`",
231 err
.span_label(span
, format
!("not a member of trait `{}`", trait_
));
232 if let Some(candidate
) = candidate
{
235 "there is an associated type with a similar name",
236 candidate
.to_ident_string(),
237 Applicability
::MaybeIncorrect
,
242 ResolutionError
::ConstNotMemberOfTrait(const_
, trait_
, candidate
) => {
243 let mut err
= struct_span_err
!(
247 "const `{}` is not a member of trait `{}`",
251 err
.span_label(span
, format
!("not a member of trait `{}`", trait_
));
252 if let Some(candidate
) = candidate
{
255 "there is an associated constant with a similar name",
256 candidate
.to_ident_string(),
257 Applicability
::MaybeIncorrect
,
262 ResolutionError
::VariableNotBoundInPattern(binding_error
) => {
263 let BindingError { name, target, origin, could_be_path }
= binding_error
;
265 let target_sp
= target
.iter().copied().collect
::<Vec
<_
>>();
266 let origin_sp
= origin
.iter().copied().collect
::<Vec
<_
>>();
268 let msp
= MultiSpan
::from_spans(target_sp
.clone());
269 let mut err
= struct_span_err
!(
273 "variable `{}` is not bound in all patterns",
276 for sp
in target_sp
{
277 err
.span_label(sp
, format
!("pattern doesn't bind `{}`", name
));
279 for sp
in origin_sp
{
280 err
.span_label(sp
, "variable not in all patterns");
283 let help_msg
= format
!(
284 "if you meant to match on a variant or a `const` item, consider \
285 making the path in the pattern qualified: `?::{}`",
288 err
.span_help(span
, &help_msg
);
292 ResolutionError
::VariableBoundWithDifferentMode(variable_name
, first_binding_span
) => {
293 let mut err
= struct_span_err
!(
297 "variable `{}` is bound inconsistently across alternatives separated by `|`",
300 err
.span_label(span
, "bound in different ways");
301 err
.span_label(first_binding_span
, "first binding");
304 ResolutionError
::IdentifierBoundMoreThanOnceInParameterList(identifier
) => {
305 let mut err
= struct_span_err
!(
309 "identifier `{}` is bound more than once in this parameter list",
312 err
.span_label(span
, "used as parameter more than once");
315 ResolutionError
::IdentifierBoundMoreThanOnceInSamePattern(identifier
) => {
316 let mut err
= struct_span_err
!(
320 "identifier `{}` is bound more than once in the same pattern",
323 err
.span_label(span
, "used in a pattern more than once");
326 ResolutionError
::UndeclaredLabel { name, suggestion }
=> {
327 let mut err
= struct_span_err
!(
331 "use of undeclared label `{}`",
335 err
.span_label(span
, format
!("undeclared label `{}`", name
));
338 // A reachable label with a similar name exists.
339 Some((ident
, true)) => {
340 err
.span_label(ident
.span
, "a label with a similar name is reachable");
343 "try using similarly named label",
344 ident
.name
.to_string(),
345 Applicability
::MaybeIncorrect
,
348 // An unreachable label with a similar name exists.
349 Some((ident
, false)) => {
352 "a label with a similar name exists but is unreachable",
355 // No similarly-named labels exist.
361 ResolutionError
::SelfImportsOnlyAllowedWithin { root, span_with_rename }
=> {
362 let mut err
= struct_span_err
!(
367 "`self` imports are only allowed within a { } list"
370 // None of the suggestions below would help with a case like `use self`.
372 // use foo::bar::self -> foo::bar
373 // use foo::bar::self as abc -> foo::bar as abc
376 "consider importing the module directly",
378 Applicability
::MachineApplicable
,
381 // use foo::bar::self -> foo::bar::{self}
382 // use foo::bar::self as abc -> foo::bar::{self as abc}
384 (span_with_rename
.shrink_to_lo(), "{".to_string()),
385 (span_with_rename
.shrink_to_hi(), "}".to_string()),
387 err
.multipart_suggestion(
388 "alternatively, use the multi-path `use` syntax to import `self`",
390 Applicability
::MachineApplicable
,
395 ResolutionError
::SelfImportCanOnlyAppearOnceInTheList
=> {
396 let mut err
= struct_span_err
!(
400 "`self` import can only appear once in an import list"
402 err
.span_label(span
, "can only appear once in an import list");
405 ResolutionError
::SelfImportOnlyInImportListWithNonEmptyPrefix
=> {
406 let mut err
= struct_span_err
!(
410 "`self` import can only appear in an import list with \
413 err
.span_label(span
, "can only appear in an import list with a non-empty prefix");
416 ResolutionError
::FailedToResolve { label, suggestion }
=> {
418 struct_span_err
!(self.session
, span
, E0433
, "failed to resolve: {}", &label
);
419 err
.span_label(span
, label
);
421 if let Some((suggestions
, msg
, applicability
)) = suggestion
{
422 if suggestions
.is_empty() {
426 err
.multipart_suggestion(&msg
, suggestions
, applicability
);
431 ResolutionError
::CannotCaptureDynamicEnvironmentInFnItem
=> {
432 let mut err
= struct_span_err
!(
437 "can't capture dynamic environment in a fn item"
439 err
.help("use the `|| { ... }` closure form instead");
442 ResolutionError
::AttemptToUseNonConstantValueInConstant(ident
, sugg
, current
) => {
443 let mut err
= struct_span_err
!(
447 "attempt to use a non-constant value in a constant"
450 // ^^^ given this Span
451 // ------- get this Span to have an applicable suggestion
454 // only do this if the const and usage of the non-constant value are on the same line
455 // the further the two are apart, the higher the chance of the suggestion being wrong
460 .span_extend_to_prev_str(ident
.span
, current
, true, false);
463 Some(sp
) if !self.session
.source_map().is_multiline(sp
) => {
464 let sp
= sp
.with_lo(BytePos(sp
.lo().0 - (current
.len() as u32)));
467 &format
!("consider using `{}` instead of `{}`", sugg
, current
),
468 format
!("{} {}", sugg
, ident
),
469 Applicability
::MaybeIncorrect
,
471 err
.span_label(span
, "non-constant value");
474 err
.span_label(ident
.span
, &format
!("this would need to be a `{}`", sugg
));
480 ResolutionError
::BindingShadowsSomethingUnacceptable
{
481 shadowing_binding_descr
,
485 shadowed_binding_descr
,
486 shadowed_binding_span
,
488 let mut err
= struct_span_err
!(
492 "{}s cannot shadow {}s",
493 shadowing_binding_descr
,
494 shadowed_binding_descr
,
498 format
!("cannot be named the same as {} {}", article
, shadowed_binding_descr
),
501 format
!("the {} `{}` is {} here", shadowed_binding_descr
, name
, participle
);
502 err
.span_label(shadowed_binding_span
, msg
);
505 ResolutionError
::ForwardDeclaredGenericParam
=> {
506 let mut err
= struct_span_err
!(
510 "generic parameters with a default cannot use \
511 forward declared identifiers"
515 "defaulted generic parameters cannot be forward declared".to_string(),
519 ResolutionError
::ParamInTyOfConstParam(name
) => {
520 let mut err
= struct_span_err
!(
524 "the type of const parameters must not depend on other generic parameters"
528 format
!("the type must not depend on the parameter `{}`", name
),
532 ResolutionError
::ParamInNonTrivialAnonConst { name, is_type }
=> {
533 let mut err
= self.session
.struct_span_err(
535 "generic parameters may not be used in const operations",
537 err
.span_label(span
, &format
!("cannot perform const operation using `{}`", name
));
540 err
.note("type parameters may not be used in const expressions");
543 "const parameters may only be used as standalone arguments, i.e. `{}`",
548 if self.session
.is_nightly_build() {
550 "use `#![feature(generic_const_exprs)]` to allow generic const expressions",
556 ResolutionError
::SelfInGenericParamDefault
=> {
557 let mut err
= struct_span_err
!(
561 "generic parameters cannot use `Self` in their defaults"
563 err
.span_label(span
, "`Self` in generic parameter default".to_string());
566 ResolutionError
::UnreachableLabel { name, definition_span, suggestion }
=> {
567 let mut err
= struct_span_err
!(
571 "use of unreachable label `{}`",
575 err
.span_label(definition_span
, "unreachable label defined here");
576 err
.span_label(span
, format
!("unreachable label `{}`", name
));
578 "labels are unreachable through functions, closures, async blocks and modules",
582 // A reachable label with a similar name exists.
583 Some((ident
, true)) => {
584 err
.span_label(ident
.span
, "a label with a similar name is reachable");
587 "try using similarly named label",
588 ident
.name
.to_string(),
589 Applicability
::MaybeIncorrect
,
592 // An unreachable label with a similar name exists.
593 Some((ident
, false)) => {
596 "a label with a similar name exists but is also unreachable",
599 // No similarly-named labels exist.
605 ResolutionError
::TraitImplMismatch
{
612 let mut err
= self.session
.struct_span_err_with_code(
615 "item `{}` is an associated {}, which doesn't match its trait `{}`",
616 name
, kind
, trait_path
,
620 err
.span_label(span
, "does not match trait");
621 err
.span_label(trait_item_span
, "item in trait");
627 crate fn report_vis_error(&self, vis_resolution_error
: VisResolutionError
<'_
>) {
628 match vis_resolution_error
{
629 VisResolutionError
::Relative2018(span
, path
) => {
630 let mut err
= self.session
.struct_span_err(
632 "relative paths are not supported in visibilities on 2018 edition",
637 format
!("crate::{}", pprust
::path_to_string(&path
)),
638 Applicability
::MaybeIncorrect
,
642 VisResolutionError
::AncestorOnly(span
) => struct_span_err
!(
646 "visibilities can only be restricted to ancestor modules"
648 VisResolutionError
::FailedToResolve(span
, label
, suggestion
) => {
649 self.into_struct_error(span
, ResolutionError
::FailedToResolve { label, suggestion }
)
651 VisResolutionError
::ExpectedFound(span
, path_str
, res
) => {
652 let mut err
= struct_span_err
!(
656 "expected module, found {} `{}`",
660 err
.span_label(span
, "not a module");
663 VisResolutionError
::Indeterminate(span
) => struct_span_err
!(
667 "cannot determine resolution for the visibility"
669 VisResolutionError
::ModuleOnly(span
) => {
670 self.session
.struct_span_err(span
, "visibility must resolve to a module")
676 /// Lookup typo candidate in scope for a macro or import.
677 fn early_lookup_typo_candidate(
679 scope_set
: ScopeSet
<'a
>,
680 parent_scope
: &ParentScope
<'a
>,
682 filter_fn
: &impl Fn(Res
) -> bool
,
683 ) -> Option
<TypoSuggestion
> {
684 let mut suggestions
= Vec
::new();
685 let ctxt
= ident
.span
.ctxt();
686 self.visit_scopes(scope_set
, parent_scope
, ctxt
, |this
, scope
, use_prelude
, _
| {
688 Scope
::DeriveHelpers(expn_id
) => {
689 let res
= Res
::NonMacroAttr(NonMacroAttrKind
::DeriveHelper
);
696 .map(|ident
| TypoSuggestion
::typo_from_res(ident
.name
, res
)),
700 Scope
::DeriveHelpersCompat
=> {
701 let res
= Res
::NonMacroAttr(NonMacroAttrKind
::DeriveHelperCompat
);
703 for derive
in parent_scope
.derives
{
704 let parent_scope
= &ParentScope { derives: &[], ..*parent_scope }
;
705 if let Ok((Some(ext
), _
)) = this
.resolve_macro_path(
707 Some(MacroKind
::Derive
),
715 .map(|name
| TypoSuggestion
::typo_from_res(*name
, res
)),
721 Scope
::MacroRules(macro_rules_scope
) => {
722 if let MacroRulesScope
::Binding(macro_rules_binding
) = macro_rules_scope
.get() {
723 let res
= macro_rules_binding
.binding
.res();
725 suggestions
.push(TypoSuggestion
::typo_from_res(
726 macro_rules_binding
.ident
.name
,
732 Scope
::CrateRoot
=> {
733 let root_ident
= Ident
::new(kw
::PathRoot
, ident
.span
);
734 let root_module
= this
.resolve_crate_root(root_ident
);
735 this
.add_module_candidates(root_module
, &mut suggestions
, filter_fn
);
737 Scope
::Module(module
, _
) => {
738 this
.add_module_candidates(module
, &mut suggestions
, filter_fn
);
740 Scope
::RegisteredAttrs
=> {
741 let res
= Res
::NonMacroAttr(NonMacroAttrKind
::Registered
);
744 this
.registered_attrs
746 .map(|ident
| TypoSuggestion
::typo_from_res(ident
.name
, res
)),
750 Scope
::MacroUsePrelude
=> {
751 suggestions
.extend(this
.macro_use_prelude
.iter().filter_map(
753 let res
= binding
.res();
754 filter_fn(res
).then_some(TypoSuggestion
::typo_from_res(*name
, res
))
758 Scope
::BuiltinAttrs
=> {
759 let res
= Res
::NonMacroAttr(NonMacroAttrKind
::Builtin(kw
::Empty
));
764 .map(|attr
| TypoSuggestion
::typo_from_res(attr
.name
, res
)),
768 Scope
::ExternPrelude
=> {
769 suggestions
.extend(this
.extern_prelude
.iter().filter_map(|(ident
, _
)| {
770 let res
= Res
::Def(DefKind
::Mod
, DefId
::local(CRATE_DEF_INDEX
));
771 filter_fn(res
).then_some(TypoSuggestion
::typo_from_res(ident
.name
, res
))
774 Scope
::ToolPrelude
=> {
775 let res
= Res
::NonMacroAttr(NonMacroAttrKind
::Tool
);
777 this
.registered_tools
779 .map(|ident
| TypoSuggestion
::typo_from_res(ident
.name
, res
)),
782 Scope
::StdLibPrelude
=> {
783 if let Some(prelude
) = this
.prelude
{
784 let mut tmp_suggestions
= Vec
::new();
785 this
.add_module_candidates(prelude
, &mut tmp_suggestions
, filter_fn
);
789 .filter(|s
| use_prelude
|| this
.is_builtin_macro(s
.res
)),
793 Scope
::BuiltinTypes
=> {
794 suggestions
.extend(PrimTy
::ALL
.iter().filter_map(|prim_ty
| {
795 let res
= Res
::PrimTy(*prim_ty
);
796 filter_fn(res
).then_some(TypoSuggestion
::typo_from_res(prim_ty
.name(), res
))
804 // Make sure error reporting is deterministic.
805 suggestions
.sort_by(|a
, b
| a
.candidate
.as_str().partial_cmp(b
.candidate
.as_str()).unwrap());
807 match find_best_match_for_name(
808 &suggestions
.iter().map(|suggestion
| suggestion
.candidate
).collect
::<Vec
<Symbol
>>(),
812 Some(found
) if found
!= ident
.name
=> {
813 suggestions
.into_iter().find(|suggestion
| suggestion
.candidate
== found
)
819 fn lookup_import_candidates_from_module
<FilterFn
>(
822 namespace
: Namespace
,
823 parent_scope
: &ParentScope
<'a
>,
824 start_module
: Module
<'a
>,
827 ) -> Vec
<ImportSuggestion
>
829 FilterFn
: Fn(Res
) -> bool
,
831 let mut candidates
= Vec
::new();
832 let mut seen_modules
= FxHashSet
::default();
833 let mut worklist
= vec
![(start_module
, Vec
::<ast
::PathSegment
>::new(), true)];
834 let mut worklist_via_import
= vec
![];
836 while let Some((in_module
, path_segments
, accessible
)) = match worklist
.pop() {
837 None
=> worklist_via_import
.pop(),
840 let in_module_is_extern
= !in_module
.def_id().is_local();
841 // We have to visit module children in deterministic order to avoid
842 // instabilities in reported imports (#43552).
843 in_module
.for_each_child(self, |this
, ident
, ns
, name_binding
| {
844 // avoid non-importable candidates
845 if !name_binding
.is_importable() {
849 let child_accessible
=
850 accessible
&& this
.is_accessible_from(name_binding
.vis
, parent_scope
.module
);
852 // do not venture inside inaccessible items of other crates
853 if in_module_is_extern
&& !child_accessible
{
857 let via_import
= name_binding
.is_import() && !name_binding
.is_extern_crate();
859 // There is an assumption elsewhere that paths of variants are in the enum's
860 // declaration and not imported. With this assumption, the variant component is
861 // chopped and the rest of the path is assumed to be the enum's own path. For
862 // errors where a variant is used as the type instead of the enum, this causes
863 // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
864 if via_import
&& name_binding
.is_possibly_imported_variant() {
868 // #90113: Do not count an inaccessible reexported item as a candidate.
869 if let NameBindingKind
::Import { binding, .. }
= name_binding
.kind
{
870 if this
.is_accessible_from(binding
.vis
, parent_scope
.module
)
871 && !this
.is_accessible_from(name_binding
.vis
, parent_scope
.module
)
877 // collect results based on the filter function
878 // avoid suggesting anything from the same module in which we are resolving
879 // avoid suggesting anything with a hygienic name
880 if ident
.name
== lookup_ident
.name
882 && !ptr
::eq(in_module
, parent_scope
.module
)
883 && !ident
.span
.normalize_to_macros_2_0().from_expansion()
885 let res
= name_binding
.res();
888 let mut segms
= path_segments
.clone();
889 if lookup_ident
.span
.rust_2018() {
890 // crate-local absolute paths start with `crate::` in edition 2018
891 // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
892 segms
.insert(0, ast
::PathSegment
::from_ident(crate_name
));
895 segms
.push(ast
::PathSegment
::from_ident(ident
));
896 let path
= Path { span: name_binding.span, segments: segms, tokens: None }
;
897 let did
= match res
{
898 Res
::Def(DefKind
::Ctor(..), did
) => this
.parent(did
),
899 _
=> res
.opt_def_id(),
902 if child_accessible
{
903 // Remove invisible match if exists
904 if let Some(idx
) = candidates
906 .position(|v
: &ImportSuggestion
| v
.did
== did
&& !v
.accessible
)
908 candidates
.remove(idx
);
912 if candidates
.iter().all(|v
: &ImportSuggestion
| v
.did
!= did
) {
913 // See if we're recommending TryFrom, TryInto, or FromIterator and add
914 // a note about editions
915 let note
= if let Some(did
) = did
{
916 let requires_note
= !did
.is_local()
917 && this
.cstore().item_attrs_untracked(did
, this
.session
).any(
919 if attr
.has_name(sym
::rustc_diagnostic_item
) {
920 [sym
::TryInto
, sym
::TryFrom
, sym
::FromIterator
]
922 .contains(&attr
.value_str())
929 requires_note
.then(|| {
931 "'{}' is included in the prelude starting in Edition 2021",
932 path_names_to_string(&path
)
939 candidates
.push(ImportSuggestion
{
943 accessible
: child_accessible
,
950 // collect submodules to explore
951 if let Some(module
) = name_binding
.module() {
953 let mut path_segments
= path_segments
.clone();
954 path_segments
.push(ast
::PathSegment
::from_ident(ident
));
956 let is_extern_crate_that_also_appears_in_prelude
=
957 name_binding
.is_extern_crate() && lookup_ident
.span
.rust_2018();
959 if !is_extern_crate_that_also_appears_in_prelude
{
960 // add the module to the lookup
961 if seen_modules
.insert(module
.def_id()) {
962 if via_import { &mut worklist_via_import }
else { &mut worklist }
963 .push((module
, path_segments
, child_accessible
));
970 // If only some candidates are accessible, take just them
971 if !candidates
.iter().all(|v
: &ImportSuggestion
| !v
.accessible
) {
972 candidates
= candidates
.into_iter().filter(|x
| x
.accessible
).collect();
978 /// When name resolution fails, this method can be used to look up candidate
979 /// entities with the expected name. It allows filtering them using the
980 /// supplied predicate (which should be used to only accept the types of
981 /// definitions expected, e.g., traits). The lookup spans across all crates.
983 /// N.B., the method does not look into imports, but this is not a problem,
984 /// since we report the definitions (thus, the de-aliased imports).
985 crate fn lookup_import_candidates
<FilterFn
>(
988 namespace
: Namespace
,
989 parent_scope
: &ParentScope
<'a
>,
991 ) -> Vec
<ImportSuggestion
>
993 FilterFn
: Fn(Res
) -> bool
,
995 let mut suggestions
= self.lookup_import_candidates_from_module(
1000 Ident
::with_dummy_span(kw
::Crate
),
1004 if lookup_ident
.span
.rust_2018() {
1005 let extern_prelude_names
= self.extern_prelude
.clone();
1006 for (ident
, _
) in extern_prelude_names
.into_iter() {
1007 if ident
.span
.from_expansion() {
1008 // Idents are adjusted to the root context before being
1009 // resolved in the extern prelude, so reporting this to the
1010 // user is no help. This skips the injected
1011 // `extern crate std` in the 2018 edition, which would
1012 // otherwise cause duplicate suggestions.
1015 if let Some(crate_id
) = self.crate_loader
.maybe_process_path_extern(ident
.name
) {
1016 let crate_root
= self.expect_module(crate_id
.as_def_id());
1017 suggestions
.extend(self.lookup_import_candidates_from_module(
1032 crate fn unresolved_macro_suggestions(
1034 err
: &mut DiagnosticBuilder
<'a
>,
1035 macro_kind
: MacroKind
,
1036 parent_scope
: &ParentScope
<'a
>,
1039 let is_expected
= &|res
: Res
| res
.macro_kind() == Some(macro_kind
);
1040 let suggestion
= self.early_lookup_typo_candidate(
1041 ScopeSet
::Macro(macro_kind
),
1046 self.add_typo_suggestion(err
, suggestion
, ident
.span
);
1048 let import_suggestions
=
1049 self.lookup_import_candidates(ident
, Namespace
::MacroNS
, parent_scope
, is_expected
);
1055 &import_suggestions
,
1060 if macro_kind
== MacroKind
::Derive
&& (ident
.name
== sym
::Send
|| ident
.name
== sym
::Sync
) {
1061 let msg
= format
!("unsafe traits like `{}` should be implemented explicitly", ident
);
1062 err
.span_note(ident
.span
, &msg
);
1065 if self.macro_names
.contains(&ident
.normalize_to_macros_2_0()) {
1066 err
.help("have you added the `#[macro_use]` on the module/import?");
1069 for ns
in [Namespace
::MacroNS
, Namespace
::TypeNS
, Namespace
::ValueNS
] {
1070 if let Ok(binding
) = self.early_resolve_ident_in_lexical_scope(
1072 ScopeSet
::All(ns
, false),
1078 let desc
= match binding
.res() {
1079 Res
::Def(DefKind
::Macro(MacroKind
::Bang
), _
) => {
1080 "a function-like macro".to_string()
1082 Res
::Def(DefKind
::Macro(MacroKind
::Attr
), _
) | Res
::NonMacroAttr(..) => {
1083 format
!("an attribute: `#[{}]`", ident
)
1085 Res
::Def(DefKind
::Macro(MacroKind
::Derive
), _
) => {
1086 format
!("a derive macro: `#[derive({})]`", ident
)
1089 // Don't confuse the user with tool modules.
1092 Res
::Def(DefKind
::Trait
, _
) if macro_kind
== MacroKind
::Derive
=> {
1093 "only a trait, without a derive macro".to_string()
1099 macro_kind
.article(),
1100 macro_kind
.descr_expected(),
1103 if let crate::NameBindingKind
::Import { import, .. }
= binding
.kind
{
1104 if !import
.span
.is_dummy() {
1107 &format
!("`{}` is imported here, but it is {}", ident
, desc
),
1109 // Silence the 'unused import' warning we might get,
1110 // since this diagnostic already covers that import.
1111 self.record_use(ident
, binding
, false);
1115 err
.note(&format
!("`{}` is in scope, but it is {}", ident
, desc
));
1121 crate fn add_typo_suggestion(
1123 err
: &mut DiagnosticBuilder
<'_
>,
1124 suggestion
: Option
<TypoSuggestion
>,
1127 let suggestion
= match suggestion
{
1128 None
=> return false,
1129 // We shouldn't suggest underscore.
1130 Some(suggestion
) if suggestion
.candidate
== kw
::Underscore
=> return false,
1131 Some(suggestion
) => suggestion
,
1133 let def_span
= suggestion
.res
.opt_def_id().and_then(|def_id
| match def_id
.krate
{
1134 LOCAL_CRATE
=> self.opt_span(def_id
),
1138 .guess_head_span(self.cstore().get_span_untracked(def_id
, self.session
)),
1141 if let Some(def_span
) = def_span
{
1142 if span
.overlaps(def_span
) {
1143 // Don't suggest typo suggestion for itself like in the following:
1144 // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
1145 // --> $DIR/issue-64792-bad-unicode-ctor.rs:3:14
1148 // | ----------- `X` defined here
1150 // LL | const Y: X = X("ö");
1151 // | -------------^^^^^^- similarly named constant `Y` defined here
1153 // help: use struct literal syntax instead
1155 // LL | const Y: X = X {};
1157 // help: a constant with a similar name exists
1159 // LL | const Y: X = Y("ö");
1163 let prefix
= match suggestion
.target
{
1164 SuggestionTarget
::SimilarlyNamed
=> "similarly named ",
1165 SuggestionTarget
::SingleItem
=> "",
1169 self.session
.source_map().guess_head_span(def_span
),
1171 "{}{} `{}` defined here",
1173 suggestion
.res
.descr(),
1174 suggestion
.candidate
.as_str(),
1178 let msg
= match suggestion
.target
{
1179 SuggestionTarget
::SimilarlyNamed
=> format
!(
1180 "{} {} with a similar name exists",
1181 suggestion
.res
.article(),
1182 suggestion
.res
.descr()
1184 SuggestionTarget
::SingleItem
=> {
1185 format
!("maybe you meant this {}", suggestion
.res
.descr())
1188 err
.span_suggestion(
1191 suggestion
.candidate
.to_string(),
1192 Applicability
::MaybeIncorrect
,
1197 fn binding_description(&self, b
: &NameBinding
<'_
>, ident
: Ident
, from_prelude
: bool
) -> String
{
1199 if b
.span
.is_dummy() || self.session
.source_map().span_to_snippet(b
.span
).is_err() {
1200 // These already contain the "built-in" prefix or look bad with it.
1202 !matches
!(b
.res(), Res
::NonMacroAttr(..) | Res
::PrimTy(..) | Res
::ToolMod
);
1203 let (built_in
, from
) = if from_prelude
{
1204 ("", " from prelude")
1205 } else if b
.is_extern_crate()
1207 && self.session
.opts
.externs
.get(ident
.as_str()).is_some()
1209 ("", " passed with `--extern`")
1210 } else if add_built_in
{
1216 let a
= if built_in
.is_empty() { res.article() }
else { "a" }
;
1217 format
!("{a}{built_in} {thing}{from}", thing
= res
.descr())
1219 let introduced
= if b
.is_import() { "imported" }
else { "defined" }
;
1220 format
!("the {thing} {introduced} here", thing
= res
.descr())
1224 crate fn report_ambiguity_error(&self, ambiguity_error
: &AmbiguityError
<'_
>) {
1225 let AmbiguityError { kind, ident, b1, b2, misc1, misc2 }
= *ambiguity_error
;
1226 let (b1
, b2
, misc1
, misc2
, swapped
) = if b2
.span
.is_dummy() && !b1
.span
.is_dummy() {
1227 // We have to print the span-less alternative first, otherwise formatting looks bad.
1228 (b2
, b1
, misc2
, misc1
, true)
1230 (b1
, b2
, misc1
, misc2
, false)
1233 let mut err
= struct_span_err
!(self.session
, ident
.span
, E0659
, "`{ident}` is ambiguous");
1234 err
.span_label(ident
.span
, "ambiguous name");
1235 err
.note(&format
!("ambiguous because of {}", kind
.descr()));
1237 let mut could_refer_to
= |b
: &NameBinding
<'_
>, misc
: AmbiguityErrorMisc
, also
: &str| {
1238 let what
= self.binding_description(b
, ident
, misc
== AmbiguityErrorMisc
::FromPrelude
);
1239 let note_msg
= format
!("`{ident}` could{also} refer to {what}");
1241 let thing
= b
.res().descr();
1242 let mut help_msgs
= Vec
::new();
1243 if b
.is_glob_import()
1244 && (kind
== AmbiguityKind
::GlobVsGlob
1245 || kind
== AmbiguityKind
::GlobVsExpanded
1246 || kind
== AmbiguityKind
::GlobVsOuter
&& swapped
!= also
.is_empty())
1248 help_msgs
.push(format
!(
1249 "consider adding an explicit import of `{ident}` to disambiguate"
1252 if b
.is_extern_crate() && ident
.span
.rust_2018() {
1253 help_msgs
.push(format
!("use `::{ident}` to refer to this {thing} unambiguously"))
1255 if misc
== AmbiguityErrorMisc
::SuggestCrate
{
1257 .push(format
!("use `crate::{ident}` to refer to this {thing} unambiguously"))
1258 } else if misc
== AmbiguityErrorMisc
::SuggestSelf
{
1260 .push(format
!("use `self::{ident}` to refer to this {thing} unambiguously"))
1263 err
.span_note(b
.span
, ¬e_msg
);
1264 for (i
, help_msg
) in help_msgs
.iter().enumerate() {
1265 let or
= if i
== 0 { "" }
else { "or " }
;
1266 err
.help(&format
!("{}{}", or
, help_msg
));
1270 could_refer_to(b1
, misc1
, "");
1271 could_refer_to(b2
, misc2
, " also");
1275 /// If the binding refers to a tuple struct constructor with fields,
1276 /// returns the span of its fields.
1277 fn ctor_fields_span(&self, binding
: &NameBinding
<'_
>) -> Option
<Span
> {
1278 if let NameBindingKind
::Res(
1279 Res
::Def(DefKind
::Ctor(CtorOf
::Struct
, CtorKind
::Fn
), ctor_def_id
),
1283 let def_id
= self.parent(ctor_def_id
).expect("no parent for a constructor");
1284 let fields
= self.field_names
.get(&def_id
)?
;
1285 return fields
.iter().map(|name
| name
.span
).reduce(Span
::to
); // None for `struct Foo()`
1290 crate fn report_privacy_error(&self, privacy_error
: &PrivacyError
<'_
>) {
1291 let PrivacyError { ident, binding, .. }
= *privacy_error
;
1293 let res
= binding
.res();
1294 let ctor_fields_span
= self.ctor_fields_span(binding
);
1295 let plain_descr
= res
.descr().to_string();
1296 let nonimport_descr
=
1297 if ctor_fields_span
.is_some() { plain_descr + " constructor" }
else { plain_descr }
;
1298 let import_descr
= nonimport_descr
.clone() + " import";
1300 |b
: &NameBinding
<'_
>| if b
.is_import() { &import_descr }
else { &nonimport_descr }
;
1302 // Print the primary message.
1303 let descr
= get_descr(binding
);
1305 struct_span_err
!(self.session
, ident
.span
, E0603
, "{} `{}` is private", descr
, ident
);
1306 err
.span_label(ident
.span
, &format
!("private {}", descr
));
1307 if let Some(span
) = ctor_fields_span
{
1308 err
.span_label(span
, "a constructor is private if any of the fields is private");
1311 // Print the whole import chain to make it easier to see what happens.
1312 let first_binding
= binding
;
1313 let mut next_binding
= Some(binding
);
1314 let mut next_ident
= ident
;
1315 while let Some(binding
) = next_binding
{
1316 let name
= next_ident
;
1317 next_binding
= match binding
.kind
{
1318 _
if res
== Res
::Err
=> None
,
1319 NameBindingKind
::Import { binding, import, .. }
=> match import
.kind
{
1320 _
if binding
.span
.is_dummy() => None
,
1321 ImportKind
::Single { source, .. }
=> {
1322 next_ident
= source
;
1325 ImportKind
::Glob { .. }
| ImportKind
::MacroUse
=> Some(binding
),
1326 ImportKind
::ExternCrate { .. }
=> None
,
1331 let first
= ptr
::eq(binding
, first_binding
);
1333 "{and_refers_to}the {item} `{name}`{which} is defined here{dots}",
1334 and_refers_to
= if first { "" }
else { "...and refers to " }
,
1335 item
= get_descr(binding
),
1336 which
= if first { "" }
else { " which" }
,
1337 dots
= if next_binding
.is_some() { "..." }
else { "" }
,
1339 let def_span
= self.session
.source_map().guess_head_span(binding
.span
);
1340 let mut note_span
= MultiSpan
::from_span(def_span
);
1341 if !first
&& binding
.vis
.is_public() {
1342 note_span
.push_span_label(def_span
, "consider importing it directly".into());
1344 err
.span_note(note_span
, &msg
);
1350 crate fn find_similarly_named_module_or_crate(
1353 current_module
: &Module
<'a
>,
1354 ) -> Option
<Symbol
> {
1355 let mut candidates
= self
1358 .map(|(ident
, _
)| ident
.name
)
1362 .filter(|(_
, module
)| {
1363 current_module
.is_ancestor_of(module
) && !ptr
::eq(current_module
, *module
)
1365 .flat_map(|(_
, module
)| module
.kind
.name()),
1367 .filter(|c
| !c
.to_string().is_empty())
1368 .collect
::<Vec
<_
>>();
1371 match find_best_match_for_name(&candidates
, ident
, None
) {
1372 Some(sugg
) if sugg
== ident
=> None
,
1378 impl<'a
, 'b
> ImportResolver
<'a
, 'b
> {
1379 /// Adds suggestions for a path that cannot be resolved.
1380 pub(crate) fn make_path_suggestion(
1383 mut path
: Vec
<Segment
>,
1384 parent_scope
: &ParentScope
<'b
>,
1385 ) -> Option
<(Vec
<Segment
>, Vec
<String
>)> {
1386 debug
!("make_path_suggestion: span={:?} path={:?}", span
, path
);
1388 match (path
.get(0), path
.get(1)) {
1389 // `{{root}}::ident::...` on both editions.
1390 // On 2015 `{{root}}` is usually added implicitly.
1391 (Some(fst
), Some(snd
))
1392 if fst
.ident
.name
== kw
::PathRoot
&& !snd
.ident
.is_path_segment_keyword() => {}
1393 // `ident::...` on 2018.
1395 if fst
.ident
.span
.rust_2018() && !fst
.ident
.is_path_segment_keyword() =>
1397 // Insert a placeholder that's later replaced by `self`/`super`/etc.
1398 path
.insert(0, Segment
::from_ident(Ident
::empty()));
1403 self.make_missing_self_suggestion(span
, path
.clone(), parent_scope
)
1404 .or_else(|| self.make_missing_crate_suggestion(span
, path
.clone(), parent_scope
))
1405 .or_else(|| self.make_missing_super_suggestion(span
, path
.clone(), parent_scope
))
1406 .or_else(|| self.make_external_crate_suggestion(span
, path
, parent_scope
))
1409 /// Suggest a missing `self::` if that resolves to an correct module.
1413 /// LL | use foo::Bar;
1414 /// | ^^^ did you mean `self::foo`?
1416 fn make_missing_self_suggestion(
1419 mut path
: Vec
<Segment
>,
1420 parent_scope
: &ParentScope
<'b
>,
1421 ) -> Option
<(Vec
<Segment
>, Vec
<String
>)> {
1422 // Replace first ident with `self` and check if that is valid.
1423 path
[0].ident
.name
= kw
::SelfLower
;
1424 let result
= self.r
.resolve_path(&path
, None
, parent_scope
, false, span
, CrateLint
::No
);
1425 debug
!("make_missing_self_suggestion: path={:?} result={:?}", path
, result
);
1426 if let PathResult
::Module(..) = result { Some((path, Vec::new())) }
else { None }
1429 /// Suggests a missing `crate::` if that resolves to an correct module.
1433 /// LL | use foo::Bar;
1434 /// | ^^^ did you mean `crate::foo`?
1436 fn make_missing_crate_suggestion(
1439 mut path
: Vec
<Segment
>,
1440 parent_scope
: &ParentScope
<'b
>,
1441 ) -> Option
<(Vec
<Segment
>, Vec
<String
>)> {
1442 // Replace first ident with `crate` and check if that is valid.
1443 path
[0].ident
.name
= kw
::Crate
;
1444 let result
= self.r
.resolve_path(&path
, None
, parent_scope
, false, span
, CrateLint
::No
);
1445 debug
!("make_missing_crate_suggestion: path={:?} result={:?}", path
, result
);
1446 if let PathResult
::Module(..) = result
{
1450 "`use` statements changed in Rust 2018; read more at \
1451 <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
1461 /// Suggests a missing `super::` if that resolves to an correct module.
1465 /// LL | use foo::Bar;
1466 /// | ^^^ did you mean `super::foo`?
1468 fn make_missing_super_suggestion(
1471 mut path
: Vec
<Segment
>,
1472 parent_scope
: &ParentScope
<'b
>,
1473 ) -> Option
<(Vec
<Segment
>, Vec
<String
>)> {
1474 // Replace first ident with `crate` and check if that is valid.
1475 path
[0].ident
.name
= kw
::Super
;
1476 let result
= self.r
.resolve_path(&path
, None
, parent_scope
, false, span
, CrateLint
::No
);
1477 debug
!("make_missing_super_suggestion: path={:?} result={:?}", path
, result
);
1478 if let PathResult
::Module(..) = result { Some((path, Vec::new())) }
else { None }
1481 /// Suggests a missing external crate name if that resolves to an correct module.
1485 /// LL | use foobar::Baz;
1486 /// | ^^^^^^ did you mean `baz::foobar`?
1489 /// Used when importing a submodule of an external crate but missing that crate's
1490 /// name as the first part of path.
1491 fn make_external_crate_suggestion(
1494 mut path
: Vec
<Segment
>,
1495 parent_scope
: &ParentScope
<'b
>,
1496 ) -> Option
<(Vec
<Segment
>, Vec
<String
>)> {
1497 if path
[1].ident
.span
.rust_2015() {
1501 // Sort extern crate names in *reverse* order to get
1502 // 1) some consistent ordering for emitted diagnostics, and
1503 // 2) `std` suggestions before `core` suggestions.
1504 let mut extern_crate_names
=
1505 self.r
.extern_prelude
.iter().map(|(ident
, _
)| ident
.name
).collect
::<Vec
<_
>>();
1506 extern_crate_names
.sort_by(|a
, b
| b
.as_str().partial_cmp(a
.as_str()).unwrap());
1508 for name
in extern_crate_names
.into_iter() {
1509 // Replace first ident with a crate name and check if that is valid.
1510 path
[0].ident
.name
= name
;
1511 let result
= self.r
.resolve_path(&path
, None
, parent_scope
, false, span
, CrateLint
::No
);
1513 "make_external_crate_suggestion: name={:?} path={:?} result={:?}",
1516 if let PathResult
::Module(..) = result
{
1517 return Some((path
, Vec
::new()));
1524 /// Suggests importing a macro from the root of the crate rather than a module within
1528 /// help: a macro with this name exists at the root of the crate
1530 /// LL | use issue_59764::makro;
1531 /// | ^^^^^^^^^^^^^^^^^^
1533 /// = note: this could be because a macro annotated with `#[macro_export]` will be exported
1534 /// at the root of the crate instead of the module where it is defined
1536 pub(crate) fn check_for_module_export_macro(
1538 import
: &'b Import
<'b
>,
1539 module
: ModuleOrUniformRoot
<'b
>,
1541 ) -> Option
<(Option
<Suggestion
>, Vec
<String
>)> {
1542 let ModuleOrUniformRoot
::Module(mut crate_module
) = module
else {
1546 while let Some(parent
) = crate_module
.parent
{
1547 crate_module
= parent
;
1550 if ModuleOrUniformRoot
::same_def(ModuleOrUniformRoot
::Module(crate_module
), module
) {
1551 // Don't make a suggestion if the import was already from the root of the
1556 let resolutions
= self.r
.resolutions(crate_module
).borrow();
1557 let resolution
= resolutions
.get(&self.r
.new_key(ident
, MacroNS
))?
;
1558 let binding
= resolution
.borrow().binding()?
;
1559 if let Res
::Def(DefKind
::Macro(MacroKind
::Bang
), _
) = binding
.res() {
1560 let module_name
= crate_module
.kind
.name().unwrap();
1561 let import_snippet
= match import
.kind
{
1562 ImportKind
::Single { source, target, .. }
if source
!= target
=> {
1563 format
!("{} as {}", source
, target
)
1565 _
=> format
!("{}", ident
),
1568 let mut corrections
: Vec
<(Span
, String
)> = Vec
::new();
1569 if !import
.is_nested() {
1570 // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
1571 // intermediate segments.
1572 corrections
.push((import
.span
, format
!("{}::{}", module_name
, import_snippet
)));
1574 // Find the binding span (and any trailing commas and spaces).
1575 // ie. `use a::b::{c, d, e};`
1577 let (found_closing_brace
, binding_span
) = find_span_of_binding_until_next_binding(
1583 "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
1584 found_closing_brace
, binding_span
1587 let mut removal_span
= binding_span
;
1588 if found_closing_brace
{
1589 // If the binding span ended with a closing brace, as in the below example:
1590 // ie. `use a::b::{c, d};`
1592 // Then expand the span of characters to remove to include the previous
1593 // binding's trailing comma.
1594 // ie. `use a::b::{c, d};`
1596 if let Some(previous_span
) =
1597 extend_span_to_previous_binding(self.r
.session
, binding_span
)
1599 debug
!("check_for_module_export_macro: previous_span={:?}", previous_span
);
1600 removal_span
= removal_span
.with_lo(previous_span
.lo());
1603 debug
!("check_for_module_export_macro: removal_span={:?}", removal_span
);
1605 // Remove the `removal_span`.
1606 corrections
.push((removal_span
, "".to_string()));
1608 // Find the span after the crate name and if it has nested imports immediatately
1609 // after the crate name already.
1610 // ie. `use a::b::{c, d};`
1612 // or `use a::{b, c, d}};`
1614 let (has_nested
, after_crate_name
) = find_span_immediately_after_crate_name(
1620 "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
1621 has_nested
, after_crate_name
1624 let source_map
= self.r
.session
.source_map();
1626 // Add the import to the start, with a `{` if required.
1627 let start_point
= source_map
.start_point(after_crate_name
);
1628 if let Ok(start_snippet
) = source_map
.span_to_snippet(start_point
) {
1632 // In this case, `start_snippet` must equal '{'.
1633 format
!("{}{}, ", start_snippet
, import_snippet
)
1635 // In this case, add a `{`, then the moved import, then whatever
1636 // was there before.
1637 format
!("{{{}, {}", import_snippet
, start_snippet
)
1642 // Add a `};` to the end if nested, matching the `{` added at the start.
1644 corrections
.push((source_map
.end_point(after_crate_name
), "};".to_string()));
1648 let suggestion
= Some((
1650 String
::from("a macro with this name exists at the root of the crate"),
1651 Applicability
::MaybeIncorrect
,
1654 "this could be because a macro annotated with `#[macro_export]` will be exported \
1655 at the root of the crate instead of the module where it is defined"
1658 Some((suggestion
, note
))
1665 /// Given a `binding_span` of a binding within a use statement:
1668 /// use foo::{a, b, c};
1672 /// then return the span until the next binding or the end of the statement:
1675 /// use foo::{a, b, c};
1678 pub(crate) fn find_span_of_binding_until_next_binding(
1683 let source_map
= sess
.source_map();
1685 // Find the span of everything after the binding.
1686 // ie. `a, e};` or `a};`
1687 let binding_until_end
= binding_span
.with_hi(use_span
.hi());
1689 // Find everything after the binding but not including the binding.
1690 // ie. `, e};` or `};`
1691 let after_binding_until_end
= binding_until_end
.with_lo(binding_span
.hi());
1693 // Keep characters in the span until we encounter something that isn't a comma or
1697 // Also note whether a closing brace character was encountered. If there
1698 // was, then later go backwards to remove any trailing commas that are left.
1699 let mut found_closing_brace
= false;
1700 let after_binding_until_next_binding
=
1701 source_map
.span_take_while(after_binding_until_end
, |&ch
| {
1703 found_closing_brace
= true;
1705 ch
== ' '
|| ch
== '
,'
1708 // Combine the two spans.
1709 // ie. `a, ` or `a`.
1711 // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
1712 let span
= binding_span
.with_hi(after_binding_until_next_binding
.hi());
1714 (found_closing_brace
, span
)
1717 /// Given a `binding_span`, return the span through to the comma or opening brace of the previous
1721 /// use foo::a::{a, b, c};
1722 /// ^^--- binding span
1726 /// use foo::{a, b, c};
1727 /// --- binding span
1729 pub(crate) fn extend_span_to_previous_binding(sess
: &Session
, binding_span
: Span
) -> Option
<Span
> {
1730 let source_map
= sess
.source_map();
1732 // `prev_source` will contain all of the source that came before the span.
1733 // Then split based on a command and take the first (ie. closest to our span)
1734 // snippet. In the example, this is a space.
1735 let prev_source
= source_map
.span_to_prev_source(binding_span
).ok()?
;
1737 let prev_comma
= prev_source
.rsplit('
,'
).collect
::<Vec
<_
>>();
1738 let prev_starting_brace
= prev_source
.rsplit('
{'
).collect
::<Vec
<_
>>();
1739 if prev_comma
.len() <= 1 || prev_starting_brace
.len() <= 1 {
1743 let prev_comma
= prev_comma
.first().unwrap();
1744 let prev_starting_brace
= prev_starting_brace
.first().unwrap();
1746 // If the amount of source code before the comma is greater than
1747 // the amount of source code before the starting brace then we've only
1748 // got one item in the nested item (eg. `issue_52891::{self}`).
1749 if prev_comma
.len() > prev_starting_brace
.len() {
1753 Some(binding_span
.with_lo(BytePos(
1754 // Take away the number of bytes for the characters we've found and an
1755 // extra for the comma.
1756 binding_span
.lo().0 - (prev_comma
.as_bytes().len() as u32) - 1,
1760 /// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
1761 /// it is a nested use tree.
1764 /// use foo::a::{b, c};
1765 /// ^^^^^^^^^^ // false
1767 /// use foo::{a, b, c};
1768 /// ^^^^^^^^^^ // true
1770 /// use foo::{a, b::{c, d}};
1771 /// ^^^^^^^^^^^^^^^ // true
1773 fn find_span_immediately_after_crate_name(
1775 module_name
: Symbol
,
1779 "find_span_immediately_after_crate_name: module_name={:?} use_span={:?}",
1780 module_name
, use_span
1782 let source_map
= sess
.source_map();
1784 // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
1785 let mut num_colons
= 0;
1786 // Find second colon.. `use issue_59764:`
1787 let until_second_colon
= source_map
.span_take_while(use_span
, |c
| {
1791 !matches
!(c
, '
:'
if num_colons
== 2)
1793 // Find everything after the second colon.. `foo::{baz, makro};`
1794 let from_second_colon
= use_span
.with_lo(until_second_colon
.hi() + BytePos(1));
1796 let mut found_a_non_whitespace_character
= false;
1797 // Find the first non-whitespace character in `from_second_colon`.. `f`
1798 let after_second_colon
= source_map
.span_take_while(from_second_colon
, |c
| {
1799 if found_a_non_whitespace_character
{
1802 if !c
.is_whitespace() {
1803 found_a_non_whitespace_character
= true;
1808 // Find the first `{` in from_second_colon.. `foo::{`
1809 let next_left_bracket
= source_map
.span_through_char(from_second_colon
, '
{'
);
1811 (next_left_bracket
== after_second_colon
, from_second_colon
)
1814 /// When an entity with a given name is not available in scope, we search for
1815 /// entities with that name in all crates. This method allows outputting the
1816 /// results of this search in a programmer-friendly way
1817 crate fn show_candidates(
1818 definitions
: &rustc_hir
::definitions
::Definitions
,
1820 err
: &mut DiagnosticBuilder
<'_
>,
1821 // This is `None` if all placement locations are inside expansions
1822 use_placement_span
: Option
<Span
>,
1823 candidates
: &[ImportSuggestion
],
1827 if candidates
.is_empty() {
1831 let mut accessible_path_strings
: Vec
<(String
, &str, Option
<DefId
>, &Option
<String
>)> =
1833 let mut inaccessible_path_strings
: Vec
<(String
, &str, Option
<DefId
>, &Option
<String
>)> =
1836 candidates
.iter().for_each(|c
| {
1837 (if c
.accessible { &mut accessible_path_strings }
else { &mut inaccessible_path_strings }
)
1838 .push((path_names_to_string(&c
.path
), c
.descr
, c
.did
, &c
.note
))
1841 // we want consistent results across executions, but candidates are produced
1842 // by iterating through a hash map, so make sure they are ordered:
1843 for path_strings
in [&mut accessible_path_strings
, &mut inaccessible_path_strings
] {
1844 path_strings
.sort_by(|a
, b
| a
.0.cmp(&b
.0));
1845 let core_path_strings
=
1846 path_strings
.drain_filter(|p
| p
.0.starts_with("core::")).collect
::<Vec
<_
>>();
1847 path_strings
.extend(core_path_strings
);
1848 path_strings
.dedup_by(|a
, b
| a
.0 == b
.0);
1851 if !accessible_path_strings
.is_empty() {
1852 let (determiner
, kind
) = if accessible_path_strings
.len() == 1 {
1853 ("this", accessible_path_strings
[0].1)
1855 ("one of these", "items")
1858 let instead
= if instead { " instead" }
else { "" }
;
1859 let mut msg
= format
!("consider importing {} {}{}", determiner
, kind
, instead
);
1861 for note
in accessible_path_strings
.iter().flat_map(|cand
| cand
.3.as_ref()) {
1865 if let Some(span
) = use_placement_span
{
1866 for candidate
in &mut accessible_path_strings
{
1867 // produce an additional newline to separate the new use statement
1868 // from the directly following item.
1869 let additional_newline
= if found_use { "" }
else { "\n" }
;
1870 candidate
.0 = format
!("use {};\n{}", &candidate
.0, additional_newline
);
1873 err
.span_suggestions(
1876 accessible_path_strings
.into_iter().map(|a
| a
.0),
1877 Applicability
::Unspecified
,
1882 for candidate
in accessible_path_strings
{
1884 msg
.push_str(&candidate
.0);
1890 assert
!(!inaccessible_path_strings
.is_empty());
1892 if inaccessible_path_strings
.len() == 1 {
1893 let (name
, descr
, def_id
, note
) = &inaccessible_path_strings
[0];
1894 let msg
= format
!("{} `{}` exists but is inaccessible", descr
, name
);
1896 if let Some(local_def_id
) = def_id
.and_then(|did
| did
.as_local()) {
1897 let span
= definitions
.def_span(local_def_id
);
1898 let span
= session
.source_map().guess_head_span(span
);
1899 let mut multi_span
= MultiSpan
::from_span(span
);
1900 multi_span
.push_span_label(span
, "not accessible".to_string());
1901 err
.span_note(multi_span
, &msg
);
1905 if let Some(note
) = (*note
).as_deref() {
1909 let (_
, descr_first
, _
, _
) = &inaccessible_path_strings
[0];
1910 let descr
= if inaccessible_path_strings
1913 .all(|(_
, descr
, _
, _
)| descr
== descr_first
)
1915 descr_first
.to_string()
1920 let mut msg
= format
!("these {}s exist but are inaccessible", descr
);
1921 let mut has_colon
= false;
1923 let mut spans
= Vec
::new();
1924 for (name
, _
, def_id
, _
) in &inaccessible_path_strings
{
1925 if let Some(local_def_id
) = def_id
.and_then(|did
| did
.as_local()) {
1926 let span
= definitions
.def_span(local_def_id
);
1927 let span
= session
.source_map().guess_head_span(span
);
1928 spans
.push((name
, span
));
1939 let mut multi_span
= MultiSpan
::from_spans(spans
.iter().map(|(_
, sp
)| *sp
).collect());
1940 for (name
, span
) in spans
{
1941 multi_span
.push_span_label(span
, format
!("`{}`: not accessible", name
));
1944 for note
in inaccessible_path_strings
.iter().flat_map(|cand
| cand
.3.as_ref()) {
1948 err
.span_note(multi_span
, &msg
);