]> git.lizzy.rs Git - rust.git/blob - src/librustc_resolve/diagnostics.rs
resolve: Populate external modules in more automatic and lazy way
[rust.git] / src / librustc_resolve / diagnostics.rs
1 use std::cmp::Reverse;
2
3 use errors::{Applicability, DiagnosticBuilder, DiagnosticId};
4 use log::debug;
5 use rustc::bug;
6 use rustc::hir::def::{self, DefKind, NonMacroAttrKind};
7 use rustc::hir::def::Namespace::{self, *};
8 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
9 use rustc::session::Session;
10 use rustc::ty::{self, DefIdTree};
11 use rustc::util::nodemap::FxHashSet;
12 use syntax::ast::{self, Ident, Path};
13 use syntax::ext::base::MacroKind;
14 use syntax::feature_gate::BUILTIN_ATTRIBUTES;
15 use syntax::source_map::SourceMap;
16 use syntax::struct_span_err;
17 use syntax::symbol::{Symbol, kw};
18 use syntax::util::lev_distance::find_best_match_for_name;
19 use syntax_pos::{BytePos, Span, MultiSpan};
20
21 use crate::resolve_imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver};
22 use crate::{path_names_to_string, KNOWN_TOOLS};
23 use crate::{BindingError, CrateLint, LegacyScope, Module, ModuleOrUniformRoot};
24 use crate::{PathResult, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Segment};
25
26 type Res = def::Res<ast::NodeId>;
27
28 /// A vector of spans and replacements, a message and applicability.
29 crate type Suggestion = (Vec<(Span, String)>, String, Applicability);
30
31 crate struct TypoSuggestion {
32     pub candidate: Symbol,
33     pub res: Res,
34 }
35
36 impl TypoSuggestion {
37     crate fn from_res(candidate: Symbol, res: Res) -> TypoSuggestion {
38         TypoSuggestion { candidate, res }
39     }
40 }
41
42 /// A free importable items suggested in case of resolution failure.
43 crate struct ImportSuggestion {
44     pub did: Option<DefId>,
45     pub path: Path,
46 }
47
48 /// Adjust the impl span so that just the `impl` keyword is taken by removing
49 /// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
50 /// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
51 ///
52 /// *Attention*: the method used is very fragile since it essentially duplicates the work of the
53 /// parser. If you need to use this function or something similar, please consider updating the
54 /// `source_map` functions and this function to something more robust.
55 fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span {
56     let impl_span = cm.span_until_char(impl_span, '<');
57     let impl_span = cm.span_until_whitespace(impl_span);
58     impl_span
59 }
60
61 crate fn add_typo_suggestion(
62     err: &mut DiagnosticBuilder<'_>, suggestion: Option<TypoSuggestion>, span: Span
63 ) -> bool {
64     if let Some(suggestion) = suggestion {
65         let msg = format!(
66             "{} {} with a similar name exists", suggestion.res.article(), suggestion.res.descr()
67         );
68         err.span_suggestion(
69             span, &msg, suggestion.candidate.to_string(), Applicability::MaybeIncorrect
70         );
71         return true;
72     }
73     false
74 }
75
76 crate fn add_module_candidates<'a>(
77     resolver: &mut Resolver<'a>,
78     module: Module<'a>,
79     names: &mut Vec<TypoSuggestion>,
80     filter_fn: &impl Fn(Res) -> bool,
81 ) {
82     for (&(ident, _), resolution) in resolver.resolutions(module).borrow().iter() {
83         if let Some(binding) = resolution.borrow().binding {
84             let res = binding.res();
85             if filter_fn(res) {
86                 names.push(TypoSuggestion::from_res(ident.name, res));
87             }
88         }
89     }
90 }
91
92 impl<'a> Resolver<'a> {
93     /// Combines an error with provided span and emits it.
94     ///
95     /// This takes the error provided, combines it with the span and any additional spans inside the
96     /// error and emits it.
97     crate fn report_error(&self, span: Span, resolution_error: ResolutionError<'_>) {
98         self.into_struct_error(span, resolution_error).emit();
99     }
100
101     crate fn into_struct_error(
102         &self, span: Span, resolution_error: ResolutionError<'_>
103     ) -> DiagnosticBuilder<'_> {
104         match resolution_error {
105             ResolutionError::GenericParamsFromOuterFunction(outer_res) => {
106                 let mut err = struct_span_err!(self.session,
107                     span,
108                     E0401,
109                     "can't use generic parameters from outer function",
110                 );
111                 err.span_label(span, format!("use of generic parameter from outer function"));
112
113                 let cm = self.session.source_map();
114                 match outer_res {
115                     Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => {
116                         if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| {
117                             self.definitions.opt_span(def_id)
118                         }) {
119                             err.span_label(
120                                 reduce_impl_span_to_impl_keyword(cm, impl_span),
121                                 "`Self` type implicitly declared here, by this `impl`",
122                             );
123                         }
124                         match (maybe_trait_defid, maybe_impl_defid) {
125                             (Some(_), None) => {
126                                 err.span_label(span, "can't use `Self` here");
127                             }
128                             (_, Some(_)) => {
129                                 err.span_label(span, "use a type here instead");
130                             }
131                             (None, None) => bug!("`impl` without trait nor type?"),
132                         }
133                         return err;
134                     },
135                     Res::Def(DefKind::TyParam, def_id) => {
136                         if let Some(span) = self.definitions.opt_span(def_id) {
137                             err.span_label(span, "type parameter from outer function");
138                         }
139                     }
140                     Res::Def(DefKind::ConstParam, def_id) => {
141                         if let Some(span) = self.definitions.opt_span(def_id) {
142                             err.span_label(span, "const parameter from outer function");
143                         }
144                     }
145                     _ => {
146                         bug!("GenericParamsFromOuterFunction should only be used with Res::SelfTy, \
147                             DefKind::TyParam");
148                     }
149                 }
150
151                 // Try to retrieve the span of the function signature and generate a new message
152                 // with a local type or const parameter.
153                 let sugg_msg = &format!("try using a local generic parameter instead");
154                 if let Some((sugg_span, new_snippet)) = cm.generate_local_type_param_snippet(span) {
155                     // Suggest the modification to the user
156                     err.span_suggestion(
157                         sugg_span,
158                         sugg_msg,
159                         new_snippet,
160                         Applicability::MachineApplicable,
161                     );
162                 } else if let Some(sp) = cm.generate_fn_name_span(span) {
163                     err.span_label(sp,
164                         format!("try adding a local generic parameter in this method instead"));
165                 } else {
166                     err.help(&format!("try using a local generic parameter instead"));
167                 }
168
169                 err
170             }
171             ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {
172                 let mut err = struct_span_err!(self.session,
173                                                 span,
174                                                 E0403,
175                                                 "the name `{}` is already used for a generic \
176                                                 parameter in this list of generic parameters",
177                                                 name);
178                 err.span_label(span, "already used");
179                 err.span_label(first_use_span, format!("first use of `{}`", name));
180                 err
181             }
182             ResolutionError::MethodNotMemberOfTrait(method, trait_) => {
183                 let mut err = struct_span_err!(self.session,
184                                             span,
185                                             E0407,
186                                             "method `{}` is not a member of trait `{}`",
187                                             method,
188                                             trait_);
189                 err.span_label(span, format!("not a member of trait `{}`", trait_));
190                 err
191             }
192             ResolutionError::TypeNotMemberOfTrait(type_, trait_) => {
193                 let mut err = struct_span_err!(self.session,
194                                 span,
195                                 E0437,
196                                 "type `{}` is not a member of trait `{}`",
197                                 type_,
198                                 trait_);
199                 err.span_label(span, format!("not a member of trait `{}`", trait_));
200                 err
201             }
202             ResolutionError::ConstNotMemberOfTrait(const_, trait_) => {
203                 let mut err = struct_span_err!(self.session,
204                                 span,
205                                 E0438,
206                                 "const `{}` is not a member of trait `{}`",
207                                 const_,
208                                 trait_);
209                 err.span_label(span, format!("not a member of trait `{}`", trait_));
210                 err
211             }
212             ResolutionError::VariableNotBoundInPattern(binding_error) => {
213                 let BindingError { name, target, origin, could_be_path } = binding_error;
214
215                 let target_sp = target.iter().copied().collect::<Vec<_>>();
216                 let origin_sp = origin.iter().copied().collect::<Vec<_>>();
217
218                 let msp = MultiSpan::from_spans(target_sp.clone());
219                 let msg = format!("variable `{}` is not bound in all patterns", name);
220                 let mut err = self.session.struct_span_err_with_code(
221                     msp,
222                     &msg,
223                     DiagnosticId::Error("E0408".into()),
224                 );
225                 for sp in target_sp {
226                     err.span_label(sp, format!("pattern doesn't bind `{}`", name));
227                 }
228                 for sp in origin_sp {
229                     err.span_label(sp, "variable not in all patterns");
230                 }
231                 if *could_be_path {
232                     let help_msg = format!(
233                         "if you meant to match on a variant or a `const` item, consider \
234                          making the path in the pattern qualified: `?::{}`",
235                          name,
236                      );
237                     err.span_help(span, &help_msg);
238                 }
239                 err
240             }
241             ResolutionError::VariableBoundWithDifferentMode(variable_name,
242                                                             first_binding_span) => {
243                 let mut err = struct_span_err!(self.session,
244                                 span,
245                                 E0409,
246                                 "variable `{}` is bound in inconsistent \
247                                 ways within the same match arm",
248                                 variable_name);
249                 err.span_label(span, "bound in different ways");
250                 err.span_label(first_binding_span, "first binding");
251                 err
252             }
253             ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {
254                 let mut err = struct_span_err!(self.session,
255                                 span,
256                                 E0415,
257                                 "identifier `{}` is bound more than once in this parameter list",
258                                 identifier);
259                 err.span_label(span, "used as parameter more than once");
260                 err
261             }
262             ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {
263                 let mut err = struct_span_err!(self.session,
264                                 span,
265                                 E0416,
266                                 "identifier `{}` is bound more than once in the same pattern",
267                                 identifier);
268                 err.span_label(span, "used in a pattern more than once");
269                 err
270             }
271             ResolutionError::UndeclaredLabel(name, lev_candidate) => {
272                 let mut err = struct_span_err!(self.session,
273                                             span,
274                                             E0426,
275                                             "use of undeclared label `{}`",
276                                             name);
277                 if let Some(lev_candidate) = lev_candidate {
278                     err.span_suggestion(
279                         span,
280                         "a label with a similar name exists in this scope",
281                         lev_candidate.to_string(),
282                         Applicability::MaybeIncorrect,
283                     );
284                 } else {
285                     err.span_label(span, format!("undeclared label `{}`", name));
286                 }
287                 err
288             }
289             ResolutionError::SelfImportsOnlyAllowedWithin => {
290                 struct_span_err!(self.session,
291                                 span,
292                                 E0429,
293                                 "{}",
294                                 "`self` imports are only allowed within a { } list")
295             }
296             ResolutionError::SelfImportCanOnlyAppearOnceInTheList => {
297                 let mut err = struct_span_err!(self.session, span, E0430,
298                                             "`self` import can only appear once in an import list");
299                 err.span_label(span, "can only appear once in an import list");
300                 err
301             }
302             ResolutionError::SelfImportOnlyInImportListWithNonEmptyPrefix => {
303                 let mut err = struct_span_err!(self.session, span, E0431,
304                                             "`self` import can only appear in an import list with \
305                                                 a non-empty prefix");
306                 err.span_label(span, "can only appear in an import list with a non-empty prefix");
307                 err
308             }
309             ResolutionError::FailedToResolve { label, suggestion } => {
310                 let mut err = struct_span_err!(self.session, span, E0433,
311                                             "failed to resolve: {}", &label);
312                 err.span_label(span, label);
313
314                 if let Some((suggestions, msg, applicability)) = suggestion {
315                     err.multipart_suggestion(&msg, suggestions, applicability);
316                 }
317
318                 err
319             }
320             ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
321                 let mut err = struct_span_err!(self.session,
322                                             span,
323                                             E0434,
324                                             "{}",
325                                             "can't capture dynamic environment in a fn item");
326                 err.help("use the `|| { ... }` closure form instead");
327                 err
328             }
329             ResolutionError::AttemptToUseNonConstantValueInConstant => {
330                 let mut err = struct_span_err!(self.session, span, E0435,
331                                             "attempt to use a non-constant value in a constant");
332                 err.span_label(span, "non-constant value");
333                 err
334             }
335             ResolutionError::BindingShadowsSomethingUnacceptable(what_binding, name, binding) => {
336                 let res = binding.res();
337                 let shadows_what = res.descr();
338                 let mut err = struct_span_err!(self.session, span, E0530, "{}s cannot shadow {}s",
339                                             what_binding, shadows_what);
340                 err.span_label(span, format!("cannot be named the same as {} {}",
341                                             res.article(), shadows_what));
342                 let participle = if binding.is_import() { "imported" } else { "defined" };
343                 let msg = format!("the {} `{}` is {} here", shadows_what, name, participle);
344                 err.span_label(binding.span, msg);
345                 err
346             }
347             ResolutionError::ForwardDeclaredTyParam => {
348                 let mut err = struct_span_err!(self.session, span, E0128,
349                                             "type parameters with a default cannot use \
350                                                 forward declared identifiers");
351                 err.span_label(
352                     span, "defaulted type parameters cannot be forward declared".to_string());
353                 err
354             }
355             ResolutionError::ConstParamDependentOnTypeParam => {
356                 let mut err = struct_span_err!(
357                     self.session,
358                     span,
359                     E0671,
360                     "const parameters cannot depend on type parameters"
361                 );
362                 err.span_label(span, format!("const parameter depends on type parameter"));
363                 err
364             }
365         }
366     }
367
368     /// Lookup typo candidate in scope for a macro or import.
369     fn early_lookup_typo_candidate(
370         &mut self,
371         scope_set: ScopeSet,
372         parent_scope: &ParentScope<'a>,
373         ident: Ident,
374         filter_fn: &impl Fn(Res) -> bool,
375     ) -> Option<TypoSuggestion> {
376         let mut suggestions = Vec::new();
377         self.visit_scopes(scope_set, parent_scope, ident, |this, scope, use_prelude, _| {
378             match scope {
379                 Scope::DeriveHelpers => {
380                     let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
381                     if filter_fn(res) {
382                         for derive in parent_scope.derives {
383                             let parent_scope =
384                                 &ParentScope { derives: &[], ..*parent_scope };
385                             if let Ok((Some(ext), _)) = this.resolve_macro_path(
386                                 derive, Some(MacroKind::Derive), parent_scope, false, false
387                             ) {
388                                 suggestions.extend(ext.helper_attrs.iter().map(|name| {
389                                     TypoSuggestion::from_res(*name, res)
390                                 }));
391                             }
392                         }
393                     }
394                 }
395                 Scope::MacroRules(legacy_scope) => {
396                     if let LegacyScope::Binding(legacy_binding) = legacy_scope {
397                         let res = legacy_binding.binding.res();
398                         if filter_fn(res) {
399                             suggestions.push(
400                                 TypoSuggestion::from_res(legacy_binding.ident.name, res)
401                             )
402                         }
403                     }
404                 }
405                 Scope::CrateRoot => {
406                     let root_ident = Ident::new(kw::PathRoot, ident.span);
407                     let root_module = this.resolve_crate_root(root_ident);
408                     add_module_candidates(this, root_module, &mut suggestions, filter_fn);
409                 }
410                 Scope::Module(module) => {
411                     add_module_candidates(this, module, &mut suggestions, filter_fn);
412                 }
413                 Scope::MacroUsePrelude => {
414                     suggestions.extend(this.macro_use_prelude.iter().filter_map(|(name, binding)| {
415                         let res = binding.res();
416                         if filter_fn(res) {
417                             Some(TypoSuggestion::from_res(*name, res))
418                         } else {
419                             None
420                         }
421                     }));
422                 }
423                 Scope::BuiltinAttrs => {
424                     let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin);
425                     if filter_fn(res) {
426                         suggestions.extend(BUILTIN_ATTRIBUTES.iter().map(|(name, ..)| {
427                             TypoSuggestion::from_res(*name, res)
428                         }));
429                     }
430                 }
431                 Scope::LegacyPluginHelpers => {
432                     let res = Res::NonMacroAttr(NonMacroAttrKind::LegacyPluginHelper);
433                     if filter_fn(res) {
434                         let plugin_attributes = this.session.plugin_attributes.borrow();
435                         suggestions.extend(plugin_attributes.iter().map(|(name, _)| {
436                             TypoSuggestion::from_res(*name, res)
437                         }));
438                     }
439                 }
440                 Scope::ExternPrelude => {
441                     suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, _)| {
442                         let res = Res::Def(DefKind::Mod, DefId::local(CRATE_DEF_INDEX));
443                         if filter_fn(res) {
444                             Some(TypoSuggestion::from_res(ident.name, res))
445                         } else {
446                             None
447                         }
448                     }));
449                 }
450                 Scope::ToolPrelude => {
451                     let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
452                     suggestions.extend(KNOWN_TOOLS.iter().map(|name| {
453                         TypoSuggestion::from_res(*name, res)
454                     }));
455                 }
456                 Scope::StdLibPrelude => {
457                     if let Some(prelude) = this.prelude {
458                         let mut tmp_suggestions = Vec::new();
459                         add_module_candidates(this, prelude, &mut tmp_suggestions, filter_fn);
460                         suggestions.extend(tmp_suggestions.into_iter().filter(|s| {
461                             use_prelude || this.is_builtin_macro(s.res)
462                         }));
463                     }
464                 }
465                 Scope::BuiltinTypes => {
466                     let primitive_types = &this.primitive_type_table.primitive_types;
467                     suggestions.extend(
468                         primitive_types.iter().flat_map(|(name, prim_ty)| {
469                             let res = Res::PrimTy(*prim_ty);
470                             if filter_fn(res) {
471                                 Some(TypoSuggestion::from_res(*name, res))
472                             } else {
473                                 None
474                             }
475                         })
476                     )
477                 }
478             }
479
480             None::<()>
481         });
482
483         // Make sure error reporting is deterministic.
484         suggestions.sort_by_cached_key(|suggestion| suggestion.candidate.as_str());
485
486         match find_best_match_for_name(
487             suggestions.iter().map(|suggestion| &suggestion.candidate),
488             &ident.as_str(),
489             None,
490         ) {
491             Some(found) if found != ident.name => suggestions
492                 .into_iter()
493                 .find(|suggestion| suggestion.candidate == found),
494             _ => None,
495         }
496     }
497
498     fn lookup_import_candidates_from_module<FilterFn>(&mut self,
499                                           lookup_ident: Ident,
500                                           namespace: Namespace,
501                                           start_module: Module<'a>,
502                                           crate_name: Ident,
503                                           filter_fn: FilterFn)
504                                           -> Vec<ImportSuggestion>
505         where FilterFn: Fn(Res) -> bool
506     {
507         let mut candidates = Vec::new();
508         let mut seen_modules = FxHashSet::default();
509         let not_local_module = crate_name.name != kw::Crate;
510         let mut worklist = vec![(start_module, Vec::<ast::PathSegment>::new(), not_local_module)];
511
512         while let Some((in_module,
513                         path_segments,
514                         in_module_is_extern)) = worklist.pop() {
515             // We have to visit module children in deterministic order to avoid
516             // instabilities in reported imports (#43552).
517             in_module.for_each_child_stable(self, |this, ident, ns, name_binding| {
518                 // avoid imports entirely
519                 if name_binding.is_import() && !name_binding.is_extern_crate() { return; }
520                 // avoid non-importable candidates as well
521                 if !name_binding.is_importable() { return; }
522
523                 // collect results based on the filter function
524                 if ident.name == lookup_ident.name && ns == namespace {
525                     let res = name_binding.res();
526                     if filter_fn(res) {
527                         // create the path
528                         let mut segms = path_segments.clone();
529                         if lookup_ident.span.rust_2018() {
530                             // crate-local absolute paths start with `crate::` in edition 2018
531                             // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
532                             segms.insert(
533                                 0, ast::PathSegment::from_ident(crate_name)
534                             );
535                         }
536
537                         segms.push(ast::PathSegment::from_ident(ident));
538                         let path = Path {
539                             span: name_binding.span,
540                             segments: segms,
541                         };
542                         // the entity is accessible in the following cases:
543                         // 1. if it's defined in the same crate, it's always
544                         // accessible (since private entities can be made public)
545                         // 2. if it's defined in another crate, it's accessible
546                         // only if both the module is public and the entity is
547                         // declared as public (due to pruning, we don't explore
548                         // outside crate private modules => no need to check this)
549                         if !in_module_is_extern || name_binding.vis == ty::Visibility::Public {
550                             let did = match res {
551                                 Res::Def(DefKind::Ctor(..), did) => this.parent(did),
552                                 _ => res.opt_def_id(),
553                             };
554                             candidates.push(ImportSuggestion { did, path });
555                         }
556                     }
557                 }
558
559                 // collect submodules to explore
560                 if let Some(module) = name_binding.module() {
561                     // form the path
562                     let mut path_segments = path_segments.clone();
563                     path_segments.push(ast::PathSegment::from_ident(ident));
564
565                     let is_extern_crate_that_also_appears_in_prelude =
566                         name_binding.is_extern_crate() &&
567                         lookup_ident.span.rust_2018();
568
569                     let is_visible_to_user =
570                         !in_module_is_extern || name_binding.vis == ty::Visibility::Public;
571
572                     if !is_extern_crate_that_also_appears_in_prelude && is_visible_to_user {
573                         // add the module to the lookup
574                         let is_extern = in_module_is_extern || name_binding.is_extern_crate();
575                         if seen_modules.insert(module.def_id().unwrap()) {
576                             worklist.push((module, path_segments, is_extern));
577                         }
578                     }
579                 }
580             })
581         }
582
583         candidates
584     }
585
586     /// When name resolution fails, this method can be used to look up candidate
587     /// entities with the expected name. It allows filtering them using the
588     /// supplied predicate (which should be used to only accept the types of
589     /// definitions expected, e.g., traits). The lookup spans across all crates.
590     ///
591     /// N.B., the method does not look into imports, but this is not a problem,
592     /// since we report the definitions (thus, the de-aliased imports).
593     crate fn lookup_import_candidates<FilterFn>(
594         &mut self, lookup_ident: Ident, namespace: Namespace, filter_fn: FilterFn
595     ) -> Vec<ImportSuggestion>
596         where FilterFn: Fn(Res) -> bool
597     {
598         let mut suggestions = self.lookup_import_candidates_from_module(
599             lookup_ident, namespace, self.graph_root, Ident::with_dummy_span(kw::Crate), &filter_fn
600         );
601
602         if lookup_ident.span.rust_2018() {
603             let extern_prelude_names = self.extern_prelude.clone();
604             for (ident, _) in extern_prelude_names.into_iter() {
605                 if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name,
606                                                                                     ident.span) {
607                     let crate_root = self.get_module(DefId {
608                         krate: crate_id,
609                         index: CRATE_DEF_INDEX,
610                     });
611                     suggestions.extend(self.lookup_import_candidates_from_module(
612                         lookup_ident, namespace, crate_root, ident, &filter_fn));
613                 }
614             }
615         }
616
617         suggestions
618     }
619
620     crate fn unresolved_macro_suggestions(
621         &mut self,
622         err: &mut DiagnosticBuilder<'a>,
623         macro_kind: MacroKind,
624         parent_scope: &ParentScope<'a>,
625         ident: Ident,
626     ) {
627         let is_expected = &|res: Res| res.macro_kind() == Some(macro_kind);
628         let suggestion = self.early_lookup_typo_candidate(
629             ScopeSet::Macro(macro_kind), parent_scope, ident, is_expected
630         );
631         add_typo_suggestion(err, suggestion, ident.span);
632
633         if macro_kind == MacroKind::Derive &&
634            (ident.as_str() == "Send" || ident.as_str() == "Sync") {
635             let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident);
636             err.span_note(ident.span, &msg);
637         }
638         if self.macro_names.contains(&ident.modern()) {
639             err.help("have you added the `#[macro_use]` on the module/import?");
640         }
641     }
642 }
643
644 impl<'a, 'b> ImportResolver<'a, 'b> {
645     /// Adds suggestions for a path that cannot be resolved.
646     pub(crate) fn make_path_suggestion(
647         &mut self,
648         span: Span,
649         mut path: Vec<Segment>,
650         parent_scope: &ParentScope<'b>,
651     ) -> Option<(Vec<Segment>, Vec<String>)> {
652         debug!("make_path_suggestion: span={:?} path={:?}", span, path);
653
654         match (path.get(0), path.get(1)) {
655             // `{{root}}::ident::...` on both editions.
656             // On 2015 `{{root}}` is usually added implicitly.
657             (Some(fst), Some(snd)) if fst.ident.name == kw::PathRoot &&
658                                       !snd.ident.is_path_segment_keyword() => {}
659             // `ident::...` on 2018.
660             (Some(fst), _) if fst.ident.span.rust_2018() &&
661                               !fst.ident.is_path_segment_keyword() => {
662                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
663                 path.insert(0, Segment::from_ident(Ident::invalid()));
664             }
665             _ => return None,
666         }
667
668         self.make_missing_self_suggestion(span, path.clone(), parent_scope)
669             .or_else(|| self.make_missing_crate_suggestion(span, path.clone(), parent_scope))
670             .or_else(|| self.make_missing_super_suggestion(span, path.clone(), parent_scope))
671             .or_else(|| self.make_external_crate_suggestion(span, path, parent_scope))
672     }
673
674     /// Suggest a missing `self::` if that resolves to an correct module.
675     ///
676     /// ```
677     ///    |
678     /// LL | use foo::Bar;
679     ///    |     ^^^ did you mean `self::foo`?
680     /// ```
681     fn make_missing_self_suggestion(
682         &mut self,
683         span: Span,
684         mut path: Vec<Segment>,
685         parent_scope: &ParentScope<'b>,
686     ) -> Option<(Vec<Segment>, Vec<String>)> {
687         // Replace first ident with `self` and check if that is valid.
688         path[0].ident.name = kw::SelfLower;
689         let result = self.r.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
690         debug!("make_missing_self_suggestion: path={:?} result={:?}", path, result);
691         if let PathResult::Module(..) = result {
692             Some((path, Vec::new()))
693         } else {
694             None
695         }
696     }
697
698     /// Suggests a missing `crate::` if that resolves to an correct module.
699     ///
700     /// ```
701     ///    |
702     /// LL | use foo::Bar;
703     ///    |     ^^^ did you mean `crate::foo`?
704     /// ```
705     fn make_missing_crate_suggestion(
706         &mut self,
707         span: Span,
708         mut path: Vec<Segment>,
709         parent_scope: &ParentScope<'b>,
710     ) -> Option<(Vec<Segment>, Vec<String>)> {
711         // Replace first ident with `crate` and check if that is valid.
712         path[0].ident.name = kw::Crate;
713         let result = self.r.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
714         debug!("make_missing_crate_suggestion:  path={:?} result={:?}", path, result);
715         if let PathResult::Module(..) = result {
716             Some((
717                 path,
718                 vec![
719                     "`use` statements changed in Rust 2018; read more at \
720                      <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
721                      clarity.html>".to_string()
722                 ],
723             ))
724         } else {
725             None
726         }
727     }
728
729     /// Suggests a missing `super::` if that resolves to an correct module.
730     ///
731     /// ```
732     ///    |
733     /// LL | use foo::Bar;
734     ///    |     ^^^ did you mean `super::foo`?
735     /// ```
736     fn make_missing_super_suggestion(
737         &mut self,
738         span: Span,
739         mut path: Vec<Segment>,
740         parent_scope: &ParentScope<'b>,
741     ) -> Option<(Vec<Segment>, Vec<String>)> {
742         // Replace first ident with `crate` and check if that is valid.
743         path[0].ident.name = kw::Super;
744         let result = self.r.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
745         debug!("make_missing_super_suggestion:  path={:?} result={:?}", path, result);
746         if let PathResult::Module(..) = result {
747             Some((path, Vec::new()))
748         } else {
749             None
750         }
751     }
752
753     /// Suggests a missing external crate name if that resolves to an correct module.
754     ///
755     /// ```
756     ///    |
757     /// LL | use foobar::Baz;
758     ///    |     ^^^^^^ did you mean `baz::foobar`?
759     /// ```
760     ///
761     /// Used when importing a submodule of an external crate but missing that crate's
762     /// name as the first part of path.
763     fn make_external_crate_suggestion(
764         &mut self,
765         span: Span,
766         mut path: Vec<Segment>,
767         parent_scope: &ParentScope<'b>,
768     ) -> Option<(Vec<Segment>, Vec<String>)> {
769         if path[1].ident.span.rust_2015() {
770             return None;
771         }
772
773         // Sort extern crate names in reverse order to get
774         // 1) some consistent ordering for emitted dignostics, and
775         // 2) `std` suggestions before `core` suggestions.
776         let mut extern_crate_names =
777             self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::<Vec<_>>();
778         extern_crate_names.sort_by_key(|name| Reverse(name.as_str()));
779
780         for name in extern_crate_names.into_iter() {
781             // Replace first ident with a crate name and check if that is valid.
782             path[0].ident.name = name;
783             let result = self.r.resolve_path(&path, None, parent_scope, false, span, CrateLint::No);
784             debug!("make_external_crate_suggestion: name={:?} path={:?} result={:?}",
785                     name, path, result);
786             if let PathResult::Module(..) = result {
787                 return Some((path, Vec::new()));
788             }
789         }
790
791         None
792     }
793
794     /// Suggests importing a macro from the root of the crate rather than a module within
795     /// the crate.
796     ///
797     /// ```
798     /// help: a macro with this name exists at the root of the crate
799     ///    |
800     /// LL | use issue_59764::makro;
801     ///    |     ^^^^^^^^^^^^^^^^^^
802     ///    |
803     ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
804     ///            at the root of the crate instead of the module where it is defined
805     /// ```
806     pub(crate) fn check_for_module_export_macro(
807         &mut self,
808         directive: &'b ImportDirective<'b>,
809         module: ModuleOrUniformRoot<'b>,
810         ident: Ident,
811     ) -> Option<(Option<Suggestion>, Vec<String>)> {
812         let mut crate_module = if let ModuleOrUniformRoot::Module(module) = module {
813             module
814         } else {
815             return None;
816         };
817
818         while let Some(parent) = crate_module.parent {
819             crate_module = parent;
820         }
821
822         if ModuleOrUniformRoot::same_def(ModuleOrUniformRoot::Module(crate_module), module) {
823             // Don't make a suggestion if the import was already from the root of the
824             // crate.
825             return None;
826         }
827
828         let resolutions = self.r.resolutions(crate_module).borrow();
829         let resolution = resolutions.get(&(ident, MacroNS))?;
830         let binding = resolution.borrow().binding()?;
831         if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() {
832             let module_name = crate_module.kind.name().unwrap();
833             let import = match directive.subclass {
834                 ImportDirectiveSubclass::SingleImport { source, target, .. } if source != target =>
835                     format!("{} as {}", source, target),
836                 _ => format!("{}", ident),
837             };
838
839             let mut corrections: Vec<(Span, String)> = Vec::new();
840             if !directive.is_nested() {
841                 // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
842                 // intermediate segments.
843                 corrections.push((directive.span, format!("{}::{}", module_name, import)));
844             } else {
845                 // Find the binding span (and any trailing commas and spaces).
846                 //   ie. `use a::b::{c, d, e};`
847                 //                      ^^^
848                 let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
849                     self.r.session, directive.span, directive.use_span,
850                 );
851                 debug!("check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}",
852                        found_closing_brace, binding_span);
853
854                 let mut removal_span = binding_span;
855                 if found_closing_brace {
856                     // If the binding span ended with a closing brace, as in the below example:
857                     //   ie. `use a::b::{c, d};`
858                     //                      ^
859                     // Then expand the span of characters to remove to include the previous
860                     // binding's trailing comma.
861                     //   ie. `use a::b::{c, d};`
862                     //                    ^^^
863                     if let Some(previous_span) = extend_span_to_previous_binding(
864                         self.r.session, binding_span,
865                     ) {
866                         debug!("check_for_module_export_macro: previous_span={:?}", previous_span);
867                         removal_span = removal_span.with_lo(previous_span.lo());
868                     }
869                 }
870                 debug!("check_for_module_export_macro: removal_span={:?}", removal_span);
871
872                 // Remove the `removal_span`.
873                 corrections.push((removal_span, "".to_string()));
874
875                 // Find the span after the crate name and if it has nested imports immediatately
876                 // after the crate name already.
877                 //   ie. `use a::b::{c, d};`
878                 //               ^^^^^^^^^
879                 //   or  `use a::{b, c, d}};`
880                 //               ^^^^^^^^^^^
881                 let (has_nested, after_crate_name) = find_span_immediately_after_crate_name(
882                     self.r.session, module_name, directive.use_span,
883                 );
884                 debug!("check_for_module_export_macro: has_nested={:?} after_crate_name={:?}",
885                        has_nested, after_crate_name);
886
887                 let source_map = self.r.session.source_map();
888
889                 // Add the import to the start, with a `{` if required.
890                 let start_point = source_map.start_point(after_crate_name);
891                 if let Ok(start_snippet) = source_map.span_to_snippet(start_point) {
892                     corrections.push((
893                         start_point,
894                         if has_nested {
895                             // In this case, `start_snippet` must equal '{'.
896                             format!("{}{}, ", start_snippet, import)
897                         } else {
898                             // In this case, add a `{`, then the moved import, then whatever
899                             // was there before.
900                             format!("{{{}, {}", import, start_snippet)
901                         }
902                     ));
903                 }
904
905                 // Add a `};` to the end if nested, matching the `{` added at the start.
906                 if !has_nested {
907                     corrections.push((source_map.end_point(after_crate_name),
908                                      "};".to_string()));
909                 }
910             }
911
912             let suggestion = Some((
913                 corrections,
914                 String::from("a macro with this name exists at the root of the crate"),
915                 Applicability::MaybeIncorrect,
916             ));
917             let note = vec![
918                 "this could be because a macro annotated with `#[macro_export]` will be exported \
919                  at the root of the crate instead of the module where it is defined".to_string(),
920             ];
921             Some((suggestion, note))
922         } else {
923             None
924         }
925     }
926 }
927
928 /// Given a `binding_span` of a binding within a use statement:
929 ///
930 /// ```
931 /// use foo::{a, b, c};
932 ///              ^
933 /// ```
934 ///
935 /// then return the span until the next binding or the end of the statement:
936 ///
937 /// ```
938 /// use foo::{a, b, c};
939 ///              ^^^
940 /// ```
941 pub(crate) fn find_span_of_binding_until_next_binding(
942     sess: &Session,
943     binding_span: Span,
944     use_span: Span,
945 ) -> (bool, Span) {
946     let source_map = sess.source_map();
947
948     // Find the span of everything after the binding.
949     //   ie. `a, e};` or `a};`
950     let binding_until_end = binding_span.with_hi(use_span.hi());
951
952     // Find everything after the binding but not including the binding.
953     //   ie. `, e};` or `};`
954     let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());
955
956     // Keep characters in the span until we encounter something that isn't a comma or
957     // whitespace.
958     //   ie. `, ` or ``.
959     //
960     // Also note whether a closing brace character was encountered. If there
961     // was, then later go backwards to remove any trailing commas that are left.
962     let mut found_closing_brace = false;
963     let after_binding_until_next_binding = source_map.span_take_while(
964         after_binding_until_end,
965         |&ch| {
966             if ch == '}' { found_closing_brace = true; }
967             ch == ' ' || ch == ','
968         }
969     );
970
971     // Combine the two spans.
972     //   ie. `a, ` or `a`.
973     //
974     // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
975     let span = binding_span.with_hi(after_binding_until_next_binding.hi());
976
977     (found_closing_brace, span)
978 }
979
980 /// Given a `binding_span`, return the span through to the comma or opening brace of the previous
981 /// binding.
982 ///
983 /// ```
984 /// use foo::a::{a, b, c};
985 ///               ^^--- binding span
986 ///               |
987 ///               returned span
988 ///
989 /// use foo::{a, b, c};
990 ///           --- binding span
991 /// ```
992 pub(crate) fn extend_span_to_previous_binding(
993     sess: &Session,
994     binding_span: Span,
995 ) -> Option<Span> {
996     let source_map = sess.source_map();
997
998     // `prev_source` will contain all of the source that came before the span.
999     // Then split based on a command and take the first (ie. closest to our span)
1000     // snippet. In the example, this is a space.
1001     let prev_source = source_map.span_to_prev_source(binding_span).ok()?;
1002
1003     let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
1004     let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
1005     if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
1006         return None;
1007     }
1008
1009     let prev_comma = prev_comma.first().unwrap();
1010     let prev_starting_brace = prev_starting_brace.first().unwrap();
1011
1012     // If the amount of source code before the comma is greater than
1013     // the amount of source code before the starting brace then we've only
1014     // got one item in the nested item (eg. `issue_52891::{self}`).
1015     if prev_comma.len() > prev_starting_brace.len() {
1016         return None;
1017     }
1018
1019     Some(binding_span.with_lo(BytePos(
1020         // Take away the number of bytes for the characters we've found and an
1021         // extra for the comma.
1022         binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1
1023     )))
1024 }
1025
1026 /// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
1027 /// it is a nested use tree.
1028 ///
1029 /// ```
1030 /// use foo::a::{b, c};
1031 ///          ^^^^^^^^^^ // false
1032 ///
1033 /// use foo::{a, b, c};
1034 ///          ^^^^^^^^^^ // true
1035 ///
1036 /// use foo::{a, b::{c, d}};
1037 ///          ^^^^^^^^^^^^^^^ // true
1038 /// ```
1039 fn find_span_immediately_after_crate_name(
1040     sess: &Session,
1041     module_name: Symbol,
1042     use_span: Span,
1043 ) -> (bool, Span) {
1044     debug!("find_span_immediately_after_crate_name: module_name={:?} use_span={:?}",
1045            module_name, use_span);
1046     let source_map = sess.source_map();
1047
1048     // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
1049     let mut num_colons = 0;
1050     // Find second colon.. `use issue_59764:`
1051     let until_second_colon = source_map.span_take_while(use_span, |c| {
1052         if *c == ':' { num_colons += 1; }
1053         match c {
1054             ':' if num_colons == 2 => false,
1055             _ => true,
1056         }
1057     });
1058     // Find everything after the second colon.. `foo::{baz, makro};`
1059     let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));
1060
1061     let mut found_a_non_whitespace_character = false;
1062     // Find the first non-whitespace character in `from_second_colon`.. `f`
1063     let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
1064         if found_a_non_whitespace_character { return false; }
1065         if !c.is_whitespace() { found_a_non_whitespace_character = true; }
1066         true
1067     });
1068
1069     // Find the first `{` in from_second_colon.. `foo::{`
1070     let next_left_bracket = source_map.span_through_char(from_second_colon, '{');
1071
1072     (next_left_bracket == after_second_colon, from_second_colon)
1073 }
1074
1075 /// When an entity with a given name is not available in scope, we search for
1076 /// entities with that name in all crates. This method allows outputting the
1077 /// results of this search in a programmer-friendly way
1078 crate fn show_candidates(
1079     err: &mut DiagnosticBuilder<'_>,
1080     // This is `None` if all placement locations are inside expansions
1081     span: Option<Span>,
1082     candidates: &[ImportSuggestion],
1083     better: bool,
1084     found_use: bool,
1085 ) {
1086     // we want consistent results across executions, but candidates are produced
1087     // by iterating through a hash map, so make sure they are ordered:
1088     let mut path_strings: Vec<_> =
1089         candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect();
1090     path_strings.sort();
1091
1092     let better = if better { "better " } else { "" };
1093     let msg_diff = match path_strings.len() {
1094         1 => " is found in another module, you can import it",
1095         _ => "s are found in other modules, you can import them",
1096     };
1097     let msg = format!("possible {}candidate{} into scope", better, msg_diff);
1098
1099     if let Some(span) = span {
1100         for candidate in &mut path_strings {
1101             // produce an additional newline to separate the new use statement
1102             // from the directly following item.
1103             let additional_newline = if found_use {
1104                 ""
1105             } else {
1106                 "\n"
1107             };
1108             *candidate = format!("use {};\n{}", candidate, additional_newline);
1109         }
1110
1111         err.span_suggestions(
1112             span,
1113             &msg,
1114             path_strings.into_iter(),
1115             Applicability::Unspecified,
1116         );
1117     } else {
1118         let mut msg = msg;
1119         msg.push(':');
1120         for candidate in path_strings {
1121             msg.push('\n');
1122             msg.push_str(&candidate);
1123         }
1124     }
1125 }