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