]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_typeck/src/check/method/suggest.rs
Stop using walk_crate.
[rust.git] / compiler / rustc_typeck / src / check / method / suggest.rs
1 //! Give useful errors and suggestions to users when an item can't be
2 //! found or is otherwise invalid.
3
4 use crate::check::FnCtxt;
5 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
7 use rustc_hir as hir;
8 use rustc_hir::def::{DefKind, Namespace, Res};
9 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
10 use rustc_hir::intravisit;
11 use rustc_hir::lang_items::LangItem;
12 use rustc_hir::{ExprKind, Node, QPath};
13 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
14 use rustc_middle::ty::fast_reject::simplify_type;
15 use rustc_middle::ty::print::with_crate_prefix;
16 use rustc_middle::ty::{
17     self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
18 };
19 use rustc_span::lev_distance;
20 use rustc_span::symbol::{kw, sym, Ident};
21 use rustc_span::{source_map, FileName, Span};
22 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
23 use rustc_trait_selection::traits::Obligation;
24
25 use std::cmp::Ordering;
26 use std::iter;
27
28 use super::probe::Mode;
29 use super::{CandidateSource, MethodError, NoMatchData};
30
31 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32     fn is_fn_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
33         let tcx = self.tcx;
34         match ty.kind() {
35             // Not all of these (e.g., unsafe fns) implement `FnOnce`,
36             // so we look for these beforehand.
37             ty::Closure(..) | ty::FnDef(..) | ty::FnPtr(_) => true,
38             // If it's not a simple function, look for things which implement `FnOnce`.
39             _ => {
40                 let fn_once = match tcx.lang_items().require(LangItem::FnOnce) {
41                     Ok(fn_once) => fn_once,
42                     Err(..) => return false,
43                 };
44
45                 self.autoderef(span, ty).any(|(ty, _)| {
46                     self.probe(|_| {
47                         let fn_once_substs = tcx.mk_substs_trait(
48                             ty,
49                             &[self
50                                 .next_ty_var(TypeVariableOrigin {
51                                     kind: TypeVariableOriginKind::MiscVariable,
52                                     span,
53                                 })
54                                 .into()],
55                         );
56                         let trait_ref = ty::TraitRef::new(fn_once, fn_once_substs);
57                         let poly_trait_ref = trait_ref.to_poly_trait_ref();
58                         let obligation = Obligation::misc(
59                             span,
60                             self.body_id,
61                             self.param_env,
62                             poly_trait_ref.without_const().to_predicate(tcx),
63                         );
64                         self.predicate_may_hold(&obligation)
65                     })
66                 })
67             }
68         }
69     }
70
71     pub fn report_method_error(
72         &self,
73         mut span: Span,
74         rcvr_ty: Ty<'tcx>,
75         item_name: Ident,
76         source: SelfSource<'tcx>,
77         error: MethodError<'tcx>,
78         args: Option<&'tcx [hir::Expr<'tcx>]>,
79     ) -> Option<DiagnosticBuilder<'_>> {
80         // Avoid suggestions when we don't know what's going on.
81         if rcvr_ty.references_error() {
82             return None;
83         }
84
85         let report_candidates = |span: Span,
86                                  err: &mut DiagnosticBuilder<'_>,
87                                  mut sources: Vec<CandidateSource>,
88                                  sugg_span: Span| {
89             sources.sort();
90             sources.dedup();
91             // Dynamic limit to avoid hiding just one candidate, which is silly.
92             let limit = if sources.len() == 5 { 5 } else { 4 };
93
94             for (idx, source) in sources.iter().take(limit).enumerate() {
95                 match *source {
96                     CandidateSource::ImplSource(impl_did) => {
97                         // Provide the best span we can. Use the item, if local to crate, else
98                         // the impl, if local to crate (item may be defaulted), else nothing.
99                         let item = match self
100                             .associated_item(impl_did, item_name, Namespace::ValueNS)
101                             .or_else(|| {
102                                 let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?;
103                                 self.associated_item(
104                                     impl_trait_ref.def_id,
105                                     item_name,
106                                     Namespace::ValueNS,
107                                 )
108                             }) {
109                             Some(item) => item,
110                             None => continue,
111                         };
112                         let note_span = self
113                             .tcx
114                             .hir()
115                             .span_if_local(item.def_id)
116                             .or_else(|| self.tcx.hir().span_if_local(impl_did));
117
118                         let impl_ty = self.tcx.at(span).type_of(impl_did);
119
120                         let insertion = match self.tcx.impl_trait_ref(impl_did) {
121                             None => String::new(),
122                             Some(trait_ref) => format!(
123                                 " of the trait `{}`",
124                                 self.tcx.def_path_str(trait_ref.def_id)
125                             ),
126                         };
127
128                         let (note_str, idx) = if sources.len() > 1 {
129                             (
130                                 format!(
131                                     "candidate #{} is defined in an impl{} for the type `{}`",
132                                     idx + 1,
133                                     insertion,
134                                     impl_ty,
135                                 ),
136                                 Some(idx + 1),
137                             )
138                         } else {
139                             (
140                                 format!(
141                                     "the candidate is defined in an impl{} for the type `{}`",
142                                     insertion, impl_ty,
143                                 ),
144                                 None,
145                             )
146                         };
147                         if let Some(note_span) = note_span {
148                             // We have a span pointing to the method. Show note with snippet.
149                             err.span_note(
150                                 self.tcx.sess.source_map().guess_head_span(note_span),
151                                 &note_str,
152                             );
153                         } else {
154                             err.note(&note_str);
155                         }
156                         if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did) {
157                             let path = self.tcx.def_path_str(trait_ref.def_id);
158
159                             let ty = match item.kind {
160                                 ty::AssocKind::Const | ty::AssocKind::Type => rcvr_ty,
161                                 ty::AssocKind::Fn => self
162                                     .tcx
163                                     .fn_sig(item.def_id)
164                                     .inputs()
165                                     .skip_binder()
166                                     .get(0)
167                                     .filter(|ty| ty.is_region_ptr() && !rcvr_ty.is_region_ptr())
168                                     .copied()
169                                     .unwrap_or(rcvr_ty),
170                             };
171                             print_disambiguation_help(
172                                 item_name,
173                                 args,
174                                 err,
175                                 path,
176                                 ty,
177                                 item.kind,
178                                 item.def_id,
179                                 sugg_span,
180                                 idx,
181                                 self.tcx.sess.source_map(),
182                             );
183                         }
184                     }
185                     CandidateSource::TraitSource(trait_did) => {
186                         let item =
187                             match self.associated_item(trait_did, item_name, Namespace::ValueNS) {
188                                 Some(item) => item,
189                                 None => continue,
190                             };
191                         let item_span = self
192                             .tcx
193                             .sess
194                             .source_map()
195                             .guess_head_span(self.tcx.def_span(item.def_id));
196                         let idx = if sources.len() > 1 {
197                             let msg = &format!(
198                                 "candidate #{} is defined in the trait `{}`",
199                                 idx + 1,
200                                 self.tcx.def_path_str(trait_did)
201                             );
202                             err.span_note(item_span, msg);
203                             Some(idx + 1)
204                         } else {
205                             let msg = &format!(
206                                 "the candidate is defined in the trait `{}`",
207                                 self.tcx.def_path_str(trait_did)
208                             );
209                             err.span_note(item_span, msg);
210                             None
211                         };
212                         let path = self.tcx.def_path_str(trait_did);
213                         print_disambiguation_help(
214                             item_name,
215                             args,
216                             err,
217                             path,
218                             rcvr_ty,
219                             item.kind,
220                             item.def_id,
221                             sugg_span,
222                             idx,
223                             self.tcx.sess.source_map(),
224                         );
225                     }
226                 }
227             }
228             if sources.len() > limit {
229                 err.note(&format!("and {} others", sources.len() - limit));
230             }
231         };
232
233         let sugg_span = if let SelfSource::MethodCall(expr) = source {
234             // Given `foo.bar(baz)`, `expr` is `bar`, but we want to point to the whole thing.
235             self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id)).span
236         } else {
237             span
238         };
239
240         match error {
241             MethodError::NoMatch(NoMatchData {
242                 static_candidates: static_sources,
243                 unsatisfied_predicates,
244                 out_of_scope_traits,
245                 lev_candidate,
246                 mode,
247             }) => {
248                 let tcx = self.tcx;
249
250                 let actual = self.resolve_vars_if_possible(rcvr_ty);
251                 let ty_str = self.ty_to_string(actual);
252                 let is_method = mode == Mode::MethodCall;
253                 let item_kind = if is_method {
254                     "method"
255                 } else if actual.is_enum() {
256                     "variant or associated item"
257                 } else {
258                     match (item_name.as_str().chars().next(), actual.is_fresh_ty()) {
259                         (Some(name), false) if name.is_lowercase() => "function or associated item",
260                         (Some(_), false) => "associated item",
261                         (Some(_), true) | (None, false) => "variant or associated item",
262                         (None, true) => "variant",
263                     }
264                 };
265                 let mut err = if !actual.references_error() {
266                     // Suggest clamping down the type if the method that is being attempted to
267                     // be used exists at all, and the type is an ambiguous numeric type
268                     // ({integer}/{float}).
269                     let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| {
270                         self.associated_item(info.def_id, item_name, Namespace::ValueNS)
271                     });
272                     // There are methods that are defined on the primitive types and won't be
273                     // found when exploring `all_traits`, but we also need them to be acurate on
274                     // our suggestions (#47759).
275                     let fund_assoc = |opt_def_id: Option<DefId>| {
276                         opt_def_id
277                             .and_then(|id| self.associated_item(id, item_name, Namespace::ValueNS))
278                             .is_some()
279                     };
280                     let lang_items = tcx.lang_items();
281                     let found_candidate = candidates.next().is_some()
282                         || fund_assoc(lang_items.i8_impl())
283                         || fund_assoc(lang_items.i16_impl())
284                         || fund_assoc(lang_items.i32_impl())
285                         || fund_assoc(lang_items.i64_impl())
286                         || fund_assoc(lang_items.i128_impl())
287                         || fund_assoc(lang_items.u8_impl())
288                         || fund_assoc(lang_items.u16_impl())
289                         || fund_assoc(lang_items.u32_impl())
290                         || fund_assoc(lang_items.u64_impl())
291                         || fund_assoc(lang_items.u128_impl())
292                         || fund_assoc(lang_items.f32_impl())
293                         || fund_assoc(lang_items.f32_runtime_impl())
294                         || fund_assoc(lang_items.f64_impl())
295                         || fund_assoc(lang_items.f64_runtime_impl());
296                     if let (true, false, SelfSource::MethodCall(expr), true) = (
297                         actual.is_numeric(),
298                         actual.has_concrete_skeleton(),
299                         source,
300                         found_candidate,
301                     ) {
302                         let mut err = struct_span_err!(
303                             tcx.sess,
304                             span,
305                             E0689,
306                             "can't call {} `{}` on ambiguous numeric type `{}`",
307                             item_kind,
308                             item_name,
309                             ty_str
310                         );
311                         let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
312                         match expr.kind {
313                             ExprKind::Lit(ref lit) => {
314                                 // numeric literal
315                                 let snippet = tcx
316                                     .sess
317                                     .source_map()
318                                     .span_to_snippet(lit.span)
319                                     .unwrap_or_else(|_| "<numeric literal>".to_owned());
320
321                                 err.span_suggestion(
322                                     lit.span,
323                                     &format!(
324                                         "you must specify a concrete type for this numeric value, \
325                                          like `{}`",
326                                         concrete_type
327                                     ),
328                                     format!("{}_{}", snippet, concrete_type),
329                                     Applicability::MaybeIncorrect,
330                                 );
331                             }
332                             ExprKind::Path(ref qpath) => {
333                                 // local binding
334                                 if let QPath::Resolved(_, path) = qpath {
335                                     if let hir::def::Res::Local(hir_id) = path.res {
336                                         let span = tcx.hir().span(hir_id);
337                                         let snippet = tcx.sess.source_map().span_to_snippet(span);
338                                         let filename = tcx.sess.source_map().span_to_filename(span);
339
340                                         let parent_node = self
341                                             .tcx
342                                             .hir()
343                                             .get(self.tcx.hir().get_parent_node(hir_id));
344                                         let msg = format!(
345                                             "you must specify a type for this binding, like `{}`",
346                                             concrete_type,
347                                         );
348
349                                         match (filename, parent_node, snippet) {
350                                             (
351                                                 FileName::Real(_),
352                                                 Node::Local(hir::Local {
353                                                     source: hir::LocalSource::Normal,
354                                                     ty,
355                                                     ..
356                                                 }),
357                                                 Ok(ref snippet),
358                                             ) => {
359                                                 err.span_suggestion(
360                                                     // account for `let x: _ = 42;`
361                                                     //                  ^^^^
362                                                     span.to(ty
363                                                         .as_ref()
364                                                         .map(|ty| ty.span)
365                                                         .unwrap_or(span)),
366                                                     &msg,
367                                                     format!("{}: {}", snippet, concrete_type),
368                                                     Applicability::MaybeIncorrect,
369                                                 );
370                                             }
371                                             _ => {
372                                                 err.span_label(span, msg);
373                                             }
374                                         }
375                                     }
376                                 }
377                             }
378                             _ => {}
379                         }
380                         err.emit();
381                         return None;
382                     } else {
383                         span = item_name.span;
384
385                         // Don't show generic arguments when the method can't be found in any implementation (#81576).
386                         let mut ty_str_reported = ty_str.clone();
387                         if let ty::Adt(_, ref generics) = actual.kind() {
388                             if generics.len() > 0 {
389                                 let mut autoderef = self.autoderef(span, actual);
390                                 let candidate_found = autoderef.any(|(ty, _)| {
391                                     if let ty::Adt(ref adt_deref, _) = ty.kind() {
392                                         self.tcx
393                                             .inherent_impls(adt_deref.did)
394                                             .iter()
395                                             .filter_map(|def_id| {
396                                                 self.associated_item(
397                                                     *def_id,
398                                                     item_name,
399                                                     Namespace::ValueNS,
400                                                 )
401                                             })
402                                             .count()
403                                             >= 1
404                                     } else {
405                                         false
406                                     }
407                                 });
408                                 let has_deref = autoderef.step_count() > 0;
409                                 if !candidate_found
410                                     && !has_deref
411                                     && unsatisfied_predicates.is_empty()
412                                 {
413                                     if let Some((path_string, _)) = ty_str.split_once('<') {
414                                         ty_str_reported = path_string.to_string();
415                                     }
416                                 }
417                             }
418                         }
419
420                         let mut err = struct_span_err!(
421                             tcx.sess,
422                             span,
423                             E0599,
424                             "no {} named `{}` found for {} `{}` in the current scope",
425                             item_kind,
426                             item_name,
427                             actual.prefix_string(self.tcx),
428                             ty_str_reported,
429                         );
430                         if let Mode::MethodCall = mode {
431                             if let SelfSource::MethodCall(call) = source {
432                                 self.suggest_await_before_method(
433                                     &mut err, item_name, actual, call, span,
434                                 );
435                             }
436                         }
437                         if let Some(span) =
438                             tcx.sess.confused_type_with_std_module.borrow().get(&span)
439                         {
440                             if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(*span) {
441                                 err.span_suggestion(
442                                     *span,
443                                     "you are looking for the module in `std`, \
444                                      not the primitive type",
445                                     format!("std::{}", snippet),
446                                     Applicability::MachineApplicable,
447                                 );
448                             }
449                         }
450                         if let ty::RawPtr(_) = &actual.kind() {
451                             err.note(
452                                 "try using `<*const T>::as_ref()` to get a reference to the \
453                                       type behind the pointer: https://doc.rust-lang.org/std/\
454                                       primitive.pointer.html#method.as_ref",
455                             );
456                             err.note(
457                                 "using `<*const T>::as_ref()` on a pointer \
458                                       which is unaligned or points to invalid \
459                                       or uninitialized memory is undefined behavior",
460                             );
461                         }
462                         err
463                     }
464                 } else {
465                     tcx.sess.diagnostic().struct_dummy()
466                 };
467
468                 if let Some(def) = actual.ty_adt_def() {
469                     if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
470                         let def_sp = tcx.sess.source_map().guess_head_span(full_sp);
471                         err.span_label(
472                             def_sp,
473                             format!(
474                                 "{} `{}` not found {}",
475                                 item_kind,
476                                 item_name,
477                                 if def.is_enum() && !is_method { "here" } else { "for this" }
478                             ),
479                         );
480                     }
481                 }
482
483                 let mut label_span_not_found = || {
484                     if unsatisfied_predicates.is_empty() {
485                         err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
486                         if let ty::Adt(ref adt, _) = rcvr_ty.kind() {
487                             let mut inherent_impls_candidate = self
488                                 .tcx
489                                 .inherent_impls(adt.did)
490                                 .iter()
491                                 .copied()
492                                 .filter(|def_id| {
493                                     if let Some(assoc) =
494                                         self.associated_item(*def_id, item_name, Namespace::ValueNS)
495                                     {
496                                         // Check for both mode is the same so we avoid suggesting
497                                         // incorrect associated item.
498                                         match (mode, assoc.fn_has_self_parameter, source) {
499                                             (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
500                                                 // We check that the suggest type is actually
501                                                 // different from the received one
502                                                 // So we avoid suggestion method with Box<Self>
503                                                 // for instance
504                                                 self.tcx.at(span).type_of(*def_id) != actual
505                                                     && self.tcx.at(span).type_of(*def_id) != rcvr_ty
506                                             }
507                                             (Mode::Path, false, _) => true,
508                                             _ => false,
509                                         }
510                                     } else {
511                                         false
512                                     }
513                                 })
514                                 .collect::<Vec<_>>();
515                             if inherent_impls_candidate.len() > 0 {
516                                 inherent_impls_candidate.sort();
517                                 inherent_impls_candidate.dedup();
518
519                                 // number of type to shows at most.
520                                 let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
521                                 let type_candidates = inherent_impls_candidate
522                                     .iter()
523                                     .take(limit)
524                                     .map(|impl_item| {
525                                         format!("- `{}`", self.tcx.at(span).type_of(*impl_item))
526                                     })
527                                     .collect::<Vec<_>>()
528                                     .join("\n");
529                                 let additional_types = if inherent_impls_candidate.len() > limit {
530                                     format!(
531                                         "\nand {} more types",
532                                         inherent_impls_candidate.len() - limit
533                                     )
534                                 } else {
535                                     "".to_string()
536                                 };
537                                 err.note(&format!(
538                                     "the {item_kind} was found for\n{}{}",
539                                     type_candidates, additional_types
540                                 ));
541                             }
542                         }
543                     } else {
544                         err.span_label(span, format!("{item_kind} cannot be called on `{ty_str}` due to unsatisfied trait bounds"));
545                     }
546                 };
547
548                 // If the method name is the name of a field with a function or closure type,
549                 // give a helping note that it has to be called as `(x.f)(...)`.
550                 if let SelfSource::MethodCall(expr) = source {
551                     let field_receiver =
552                         self.autoderef(span, rcvr_ty).find_map(|(ty, _)| match ty.kind() {
553                             ty::Adt(def, substs) if !def.is_enum() => {
554                                 let variant = &def.non_enum_variant();
555                                 self.tcx.find_field_index(item_name, variant).map(|index| {
556                                     let field = &variant.fields[index];
557                                     let field_ty = field.ty(tcx, substs);
558                                     (field, field_ty)
559                                 })
560                             }
561                             _ => None,
562                         });
563
564                     if let Some((field, field_ty)) = field_receiver {
565                         let scope = self.tcx.parent_module(self.body_id).to_def_id();
566                         let is_accessible = field.vis.is_accessible_from(scope, self.tcx);
567
568                         if is_accessible {
569                             if self.is_fn_ty(&field_ty, span) {
570                                 let expr_span = expr.span.to(item_name.span);
571                                 err.multipart_suggestion(
572                                     &format!(
573                                         "to call the function stored in `{}`, \
574                                          surround the field access with parentheses",
575                                         item_name,
576                                     ),
577                                     vec![
578                                         (expr_span.shrink_to_lo(), '('.to_string()),
579                                         (expr_span.shrink_to_hi(), ')'.to_string()),
580                                     ],
581                                     Applicability::MachineApplicable,
582                                 );
583                             } else {
584                                 let call_expr = self
585                                     .tcx
586                                     .hir()
587                                     .expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
588
589                                 if let Some(span) = call_expr.span.trim_start(item_name.span) {
590                                     err.span_suggestion(
591                                         span,
592                                         "remove the arguments",
593                                         String::new(),
594                                         Applicability::MaybeIncorrect,
595                                     );
596                                 }
597                             }
598                         }
599
600                         let field_kind = if is_accessible { "field" } else { "private field" };
601                         err.span_label(item_name.span, format!("{}, not a method", field_kind));
602                     } else if lev_candidate.is_none() && static_sources.is_empty() {
603                         label_span_not_found();
604                     }
605                 } else {
606                     label_span_not_found();
607                 }
608
609                 if self.is_fn_ty(&rcvr_ty, span) {
610                     fn report_function<T: std::fmt::Display>(
611                         err: &mut DiagnosticBuilder<'_>,
612                         name: T,
613                     ) {
614                         err.note(
615                             &format!("`{}` is a function, perhaps you wish to call it", name,),
616                         );
617                     }
618
619                     if let SelfSource::MethodCall(expr) = source {
620                         if let Ok(expr_string) = tcx.sess.source_map().span_to_snippet(expr.span) {
621                             report_function(&mut err, expr_string);
622                         } else if let ExprKind::Path(QPath::Resolved(_, ref path)) = expr.kind {
623                             if let Some(segment) = path.segments.last() {
624                                 report_function(&mut err, segment.ident);
625                             }
626                         }
627                     }
628                 }
629
630                 if !static_sources.is_empty() {
631                     err.note(
632                         "found the following associated functions; to be used as methods, \
633                          functions must have a `self` parameter",
634                     );
635                     err.span_label(span, "this is an associated function, not a method");
636                 }
637                 if static_sources.len() == 1 {
638                     let ty_str = if let Some(CandidateSource::ImplSource(impl_did)) =
639                         static_sources.get(0)
640                     {
641                         // When the "method" is resolved through dereferencing, we really want the
642                         // original type that has the associated function for accurate suggestions.
643                         // (#61411)
644                         let ty = tcx.at(span).type_of(*impl_did);
645                         match (&ty.peel_refs().kind(), &actual.peel_refs().kind()) {
646                             (ty::Adt(def, _), ty::Adt(def_actual, _)) if def == def_actual => {
647                                 // Use `actual` as it will have more `substs` filled in.
648                                 self.ty_to_value_string(actual.peel_refs())
649                             }
650                             _ => self.ty_to_value_string(ty.peel_refs()),
651                         }
652                     } else {
653                         self.ty_to_value_string(actual.peel_refs())
654                     };
655                     if let SelfSource::MethodCall(expr) = source {
656                         err.span_suggestion(
657                             expr.span.to(span),
658                             "use associated function syntax instead",
659                             format!("{}::{}", ty_str, item_name),
660                             Applicability::MachineApplicable,
661                         );
662                     } else {
663                         err.help(&format!("try with `{}::{}`", ty_str, item_name,));
664                     }
665
666                     report_candidates(span, &mut err, static_sources, sugg_span);
667                 } else if static_sources.len() > 1 {
668                     report_candidates(span, &mut err, static_sources, sugg_span);
669                 }
670
671                 let mut restrict_type_params = false;
672                 let mut unsatisfied_bounds = false;
673                 if !unsatisfied_predicates.is_empty() {
674                     let def_span = |def_id| {
675                         self.tcx.sess.source_map().guess_head_span(self.tcx.def_span(def_id))
676                     };
677                     let mut type_params = FxHashMap::default();
678                     let mut bound_spans = vec![];
679
680                     let mut collect_type_param_suggestions =
681                         |self_ty: Ty<'tcx>, parent_pred: &ty::Predicate<'tcx>, obligation: &str| {
682                             // We don't care about regions here, so it's fine to skip the binder here.
683                             if let (ty::Param(_), ty::PredicateKind::Trait(p)) =
684                                 (self_ty.kind(), parent_pred.kind().skip_binder())
685                             {
686                                 if let ty::Adt(def, _) = p.trait_ref.self_ty().kind() {
687                                     let node = def.did.as_local().map(|def_id| {
688                                         self.tcx
689                                             .hir()
690                                             .get(self.tcx.hir().local_def_id_to_hir_id(def_id))
691                                     });
692                                     if let Some(hir::Node::Item(hir::Item { kind, .. })) = node {
693                                         if let Some(g) = kind.generics() {
694                                             let key = match g.where_clause.predicates {
695                                                 [.., pred] => (pred.span().shrink_to_hi(), false),
696                                                 [] => (
697                                                     g.where_clause
698                                                         .span_for_predicates_or_empty_place(),
699                                                     true,
700                                                 ),
701                                             };
702                                             type_params
703                                                 .entry(key)
704                                                 .or_insert_with(FxHashSet::default)
705                                                 .insert(obligation.to_owned());
706                                         }
707                                     }
708                                 }
709                             }
710                         };
711                     let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
712                         let msg = format!(
713                             "doesn't satisfy `{}`",
714                             if obligation.len() > 50 { quiet } else { obligation }
715                         );
716                         match &self_ty.kind() {
717                             // Point at the type that couldn't satisfy the bound.
718                             ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)),
719                             // Point at the trait object that couldn't satisfy the bound.
720                             ty::Dynamic(preds, _) => {
721                                 for pred in preds.iter() {
722                                     match pred.skip_binder() {
723                                         ty::ExistentialPredicate::Trait(tr) => {
724                                             bound_spans.push((def_span(tr.def_id), msg.clone()))
725                                         }
726                                         ty::ExistentialPredicate::Projection(_)
727                                         | ty::ExistentialPredicate::AutoTrait(_) => {}
728                                     }
729                                 }
730                             }
731                             // Point at the closure that couldn't satisfy the bound.
732                             ty::Closure(def_id, _) => bound_spans
733                                 .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))),
734                             _ => {}
735                         }
736                     };
737                     let mut format_pred = |pred: ty::Predicate<'tcx>| {
738                         let bound_predicate = pred.kind();
739                         match bound_predicate.skip_binder() {
740                             ty::PredicateKind::Projection(pred) => {
741                                 let pred = bound_predicate.rebind(pred);
742                                 // `<Foo as Iterator>::Item = String`.
743                                 let projection_ty = pred.skip_binder().projection_ty;
744
745                                 let substs_with_infer_self = tcx.mk_substs(
746                                     iter::once(tcx.mk_ty_var(ty::TyVid { index: 0 }).into())
747                                         .chain(projection_ty.substs.iter().skip(1)),
748                                 );
749
750                                 let quiet_projection_ty = ty::ProjectionTy {
751                                     substs: substs_with_infer_self,
752                                     item_def_id: projection_ty.item_def_id,
753                                 };
754
755                                 let ty = pred.skip_binder().ty;
756
757                                 let obligation = format!("{} = {}", projection_ty, ty);
758                                 let quiet = format!("{} = {}", quiet_projection_ty, ty);
759
760                                 bound_span_label(projection_ty.self_ty(), &obligation, &quiet);
761                                 Some((obligation, projection_ty.self_ty()))
762                             }
763                             ty::PredicateKind::Trait(poly_trait_ref) => {
764                                 let p = poly_trait_ref.trait_ref;
765                                 let self_ty = p.self_ty();
766                                 let path = p.print_only_trait_path();
767                                 let obligation = format!("{}: {}", self_ty, path);
768                                 let quiet = format!("_: {}", path);
769                                 bound_span_label(self_ty, &obligation, &quiet);
770                                 Some((obligation, self_ty))
771                             }
772                             _ => None,
773                         }
774                     };
775                     let mut bound_list = unsatisfied_predicates
776                         .iter()
777                         .filter_map(|(pred, parent_pred)| {
778                             format_pred(*pred).map(|(p, self_ty)| match parent_pred {
779                                 None => format!("`{}`", &p),
780                                 Some(parent_pred) => match format_pred(*parent_pred) {
781                                     None => format!("`{}`", &p),
782                                     Some((parent_p, _)) => {
783                                         collect_type_param_suggestions(self_ty, parent_pred, &p);
784                                         format!("`{}`\nwhich is required by `{}`", p, parent_p)
785                                     }
786                                 },
787                             })
788                         })
789                         .enumerate()
790                         .collect::<Vec<(usize, String)>>();
791                     for ((span, empty_where), obligations) in type_params.into_iter() {
792                         restrict_type_params = true;
793                         // #74886: Sort here so that the output is always the same.
794                         let mut obligations = obligations.into_iter().collect::<Vec<_>>();
795                         obligations.sort();
796                         err.span_suggestion_verbose(
797                             span,
798                             &format!(
799                                 "consider restricting the type parameter{s} to satisfy the \
800                                  trait bound{s}",
801                                 s = pluralize!(obligations.len())
802                             ),
803                             format!(
804                                 "{} {}",
805                                 if empty_where { " where" } else { "," },
806                                 obligations.join(", ")
807                             ),
808                             Applicability::MaybeIncorrect,
809                         );
810                     }
811
812                     bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically.
813                     bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
814                     bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
815                     bound_spans.sort();
816                     bound_spans.dedup();
817                     for (span, msg) in bound_spans.into_iter() {
818                         err.span_label(span, &msg);
819                     }
820                     if !bound_list.is_empty() {
821                         let bound_list = bound_list
822                             .into_iter()
823                             .map(|(_, path)| path)
824                             .collect::<Vec<_>>()
825                             .join("\n");
826                         let actual_prefix = actual.prefix_string(self.tcx);
827                         err.set_primary_message(&format!(
828                             "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
829                         ));
830                         err.note(&format!(
831                             "the following trait bounds were not satisfied:\n{bound_list}"
832                         ));
833                         unsatisfied_bounds = true;
834                     }
835                 }
836
837                 if actual.is_numeric() && actual.is_fresh() || restrict_type_params {
838                 } else {
839                     self.suggest_traits_to_import(
840                         &mut err,
841                         span,
842                         rcvr_ty,
843                         item_name,
844                         source,
845                         out_of_scope_traits,
846                         &unsatisfied_predicates,
847                         unsatisfied_bounds,
848                     );
849                 }
850
851                 // Don't emit a suggestion if we found an actual method
852                 // that had unsatisfied trait bounds
853                 if unsatisfied_predicates.is_empty() && actual.is_enum() {
854                     let adt_def = actual.ty_adt_def().expect("enum is not an ADT");
855                     if let Some(suggestion) = lev_distance::find_best_match_for_name(
856                         &adt_def.variants.iter().map(|s| s.ident.name).collect::<Vec<_>>(),
857                         item_name.name,
858                         None,
859                     ) {
860                         err.span_suggestion(
861                             span,
862                             "there is a variant with a similar name",
863                             suggestion.to_string(),
864                             Applicability::MaybeIncorrect,
865                         );
866                     }
867                 }
868
869                 let mut fallback_span = true;
870                 let msg = "remove this method call";
871                 if item_name.name == sym::as_str && actual.peel_refs().is_str() {
872                     if let SelfSource::MethodCall(expr) = source {
873                         let call_expr =
874                             self.tcx.hir().expect_expr(self.tcx.hir().get_parent_node(expr.hir_id));
875                         if let Some(span) = call_expr.span.trim_start(expr.span) {
876                             err.span_suggestion(
877                                 span,
878                                 msg,
879                                 String::new(),
880                                 Applicability::MachineApplicable,
881                             );
882                             fallback_span = false;
883                         }
884                     }
885                     if fallback_span {
886                         err.span_label(span, msg);
887                     }
888                 } else if let Some(lev_candidate) = lev_candidate {
889                     // Don't emit a suggestion if we found an actual method
890                     // that had unsatisfied trait bounds
891                     if unsatisfied_predicates.is_empty() {
892                         let def_kind = lev_candidate.kind.as_def_kind();
893                         err.span_suggestion(
894                             span,
895                             &format!(
896                                 "there is {} {} with a similar name",
897                                 def_kind.article(),
898                                 def_kind.descr(lev_candidate.def_id),
899                             ),
900                             lev_candidate.ident.to_string(),
901                             Applicability::MaybeIncorrect,
902                         );
903                     }
904                 }
905
906                 return Some(err);
907             }
908
909             MethodError::Ambiguity(sources) => {
910                 let mut err = struct_span_err!(
911                     self.sess(),
912                     item_name.span,
913                     E0034,
914                     "multiple applicable items in scope"
915                 );
916                 err.span_label(item_name.span, format!("multiple `{}` found", item_name));
917
918                 report_candidates(span, &mut err, sources, sugg_span);
919                 err.emit();
920             }
921
922             MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
923                 let kind = kind.descr(def_id);
924                 let mut err = struct_span_err!(
925                     self.tcx.sess,
926                     item_name.span,
927                     E0624,
928                     "{} `{}` is private",
929                     kind,
930                     item_name
931                 );
932                 err.span_label(item_name.span, &format!("private {}", kind));
933                 let sp = self
934                     .tcx
935                     .hir()
936                     .span_if_local(def_id)
937                     .unwrap_or_else(|| self.tcx.def_span(def_id));
938                 err.span_label(sp, &format!("private {} defined here", kind));
939                 self.suggest_valid_traits(&mut err, out_of_scope_traits);
940                 err.emit();
941             }
942
943             MethodError::IllegalSizedBound(candidates, needs_mut, bound_span) => {
944                 let msg = format!("the `{}` method cannot be invoked on a trait object", item_name);
945                 let mut err = self.sess().struct_span_err(span, &msg);
946                 err.span_label(bound_span, "this has a `Sized` requirement");
947                 if !candidates.is_empty() {
948                     let help = format!(
949                         "{an}other candidate{s} {were} found in the following trait{s}, perhaps \
950                          add a `use` for {one_of_them}:",
951                         an = if candidates.len() == 1 { "an" } else { "" },
952                         s = pluralize!(candidates.len()),
953                         were = if candidates.len() == 1 { "was" } else { "were" },
954                         one_of_them = if candidates.len() == 1 { "it" } else { "one_of_them" },
955                     );
956                     self.suggest_use_candidates(&mut err, help, candidates);
957                 }
958                 if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
959                     if needs_mut {
960                         let trait_type = self.tcx.mk_ref(
961                             region,
962                             ty::TypeAndMut { ty: t_type, mutbl: mutability.invert() },
963                         );
964                         err.note(&format!("you need `{}` instead of `{}`", trait_type, rcvr_ty));
965                     }
966                 }
967                 err.emit();
968             }
969
970             MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
971         }
972         None
973     }
974
975     /// Print out the type for use in value namespace.
976     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
977         match ty.kind() {
978             ty::Adt(def, substs) => format!("{}", ty::Instance::new(def.did, substs)),
979             _ => self.ty_to_string(ty),
980         }
981     }
982
983     fn suggest_await_before_method(
984         &self,
985         err: &mut DiagnosticBuilder<'_>,
986         item_name: Ident,
987         ty: Ty<'tcx>,
988         call: &hir::Expr<'_>,
989         span: Span,
990     ) {
991         let output_ty = match self.infcx.get_impl_future_output_ty(ty) {
992             Some(output_ty) => self.resolve_vars_if_possible(output_ty),
993             _ => return,
994         };
995         let method_exists = self.method_exists(item_name, output_ty, call.hir_id, true);
996         debug!("suggest_await_before_method: is_method_exist={}", method_exists);
997         if method_exists {
998             err.span_suggestion_verbose(
999                 span.shrink_to_lo(),
1000                 "consider `await`ing on the `Future` and calling the method on its `Output`",
1001                 "await.".to_string(),
1002                 Applicability::MaybeIncorrect,
1003             );
1004         }
1005     }
1006
1007     fn suggest_use_candidates(
1008         &self,
1009         err: &mut DiagnosticBuilder<'_>,
1010         mut msg: String,
1011         candidates: Vec<DefId>,
1012     ) {
1013         let module_did = self.tcx.parent_module(self.body_id);
1014         let module_id = self.tcx.hir().local_def_id_to_hir_id(module_did);
1015         let (span, found_use) = UsePlacementFinder::check(self.tcx, module_id);
1016         if let Some(span) = span {
1017             let path_strings = candidates.iter().map(|did| {
1018                 // Produce an additional newline to separate the new use statement
1019                 // from the directly following item.
1020                 let additional_newline = if found_use { "" } else { "\n" };
1021                 format!(
1022                     "use {};\n{}",
1023                     with_crate_prefix(|| self.tcx.def_path_str(*did)),
1024                     additional_newline
1025                 )
1026             });
1027
1028             err.span_suggestions(span, &msg, path_strings, Applicability::MaybeIncorrect);
1029         } else {
1030             let limit = if candidates.len() == 5 { 5 } else { 4 };
1031             for (i, trait_did) in candidates.iter().take(limit).enumerate() {
1032                 if candidates.len() > 1 {
1033                     msg.push_str(&format!(
1034                         "\ncandidate #{}: `use {};`",
1035                         i + 1,
1036                         with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1037                     ));
1038                 } else {
1039                     msg.push_str(&format!(
1040                         "\n`use {};`",
1041                         with_crate_prefix(|| self.tcx.def_path_str(*trait_did))
1042                     ));
1043                 }
1044             }
1045             if candidates.len() > limit {
1046                 msg.push_str(&format!("\nand {} others", candidates.len() - limit));
1047             }
1048             err.note(&msg[..]);
1049         }
1050     }
1051
1052     fn suggest_valid_traits(
1053         &self,
1054         err: &mut DiagnosticBuilder<'_>,
1055         valid_out_of_scope_traits: Vec<DefId>,
1056     ) -> bool {
1057         if !valid_out_of_scope_traits.is_empty() {
1058             let mut candidates = valid_out_of_scope_traits;
1059             candidates.sort();
1060             candidates.dedup();
1061             err.help("items from traits can only be used if the trait is in scope");
1062             let msg = format!(
1063                 "the following {traits_are} implemented but not in scope; \
1064                  perhaps add a `use` for {one_of_them}:",
1065                 traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
1066                 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
1067             );
1068
1069             self.suggest_use_candidates(err, msg, candidates);
1070             true
1071         } else {
1072             false
1073         }
1074     }
1075
1076     fn suggest_traits_to_import(
1077         &self,
1078         err: &mut DiagnosticBuilder<'_>,
1079         span: Span,
1080         rcvr_ty: Ty<'tcx>,
1081         item_name: Ident,
1082         source: SelfSource<'tcx>,
1083         valid_out_of_scope_traits: Vec<DefId>,
1084         unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)],
1085         unsatisfied_bounds: bool,
1086     ) {
1087         let mut alt_rcvr_sugg = false;
1088         if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
1089             debug!(?span, ?item_name, ?rcvr_ty, ?rcvr);
1090             let skippable = [
1091                 self.tcx.lang_items().clone_trait(),
1092                 self.tcx.lang_items().deref_trait(),
1093                 self.tcx.lang_items().deref_mut_trait(),
1094                 self.tcx.lang_items().drop_trait(),
1095             ];
1096             // Try alternative arbitrary self types that could fulfill this call.
1097             // FIXME: probe for all types that *could* be arbitrary self-types, not
1098             // just this list.
1099             for (rcvr_ty, post) in &[
1100                 (rcvr_ty, ""),
1101                 (self.tcx.mk_mut_ref(&ty::ReErased, rcvr_ty), "&mut "),
1102                 (self.tcx.mk_imm_ref(&ty::ReErased, rcvr_ty), "&"),
1103             ] {
1104                 if let Ok(pick) = self.lookup_probe(
1105                     span,
1106                     item_name,
1107                     rcvr_ty,
1108                     rcvr,
1109                     crate::check::method::probe::ProbeScope::AllTraits,
1110                 ) {
1111                     // If the method is defined for the receiver we have, it likely wasn't `use`d.
1112                     // We point at the method, but we just skip the rest of the check for arbitrary
1113                     // self types and rely on the suggestion to `use` the trait from
1114                     // `suggest_valid_traits`.
1115                     let did = Some(pick.item.container.id());
1116                     let skip = skippable.contains(&did);
1117                     if pick.autoderefs == 0 && !skip {
1118                         err.span_label(
1119                             pick.item.ident.span,
1120                             &format!("the method is available for `{}` here", rcvr_ty),
1121                         );
1122                     }
1123                     break;
1124                 }
1125                 for (rcvr_ty, pre) in &[
1126                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::OwnedBox), "Box::new"),
1127                     (self.tcx.mk_lang_item(rcvr_ty, LangItem::Pin), "Pin::new"),
1128                     (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Arc), "Arc::new"),
1129                     (self.tcx.mk_diagnostic_item(rcvr_ty, sym::Rc), "Rc::new"),
1130                 ] {
1131                     if let Some(new_rcvr_t) = *rcvr_ty {
1132                         if let Ok(pick) = self.lookup_probe(
1133                             span,
1134                             item_name,
1135                             new_rcvr_t,
1136                             rcvr,
1137                             crate::check::method::probe::ProbeScope::AllTraits,
1138                         ) {
1139                             debug!("try_alt_rcvr: pick candidate {:?}", pick);
1140                             let did = Some(pick.item.container.id());
1141                             // We don't want to suggest a container type when the missing
1142                             // method is `.clone()` or `.deref()` otherwise we'd suggest
1143                             // `Arc::new(foo).clone()`, which is far from what the user wants.
1144                             let skip = skippable.contains(&did);
1145                             // Make sure the method is defined for the *actual* receiver: we don't
1146                             // want to treat `Box<Self>` as a receiver if it only works because of
1147                             // an autoderef to `&self`
1148                             if pick.autoderefs == 0 && !skip {
1149                                 err.span_label(
1150                                     pick.item.ident.span,
1151                                     &format!("the method is available for `{}` here", new_rcvr_t),
1152                                 );
1153                                 err.multipart_suggestion(
1154                                     "consider wrapping the receiver expression with the \
1155                                         appropriate type",
1156                                     vec![
1157                                         (rcvr.span.shrink_to_lo(), format!("{}({}", pre, post)),
1158                                         (rcvr.span.shrink_to_hi(), ")".to_string()),
1159                                     ],
1160                                     Applicability::MaybeIncorrect,
1161                                 );
1162                                 // We don't care about the other suggestions.
1163                                 alt_rcvr_sugg = true;
1164                             }
1165                         }
1166                     }
1167                 }
1168             }
1169         }
1170         if self.suggest_valid_traits(err, valid_out_of_scope_traits) {
1171             return;
1172         }
1173
1174         let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
1175
1176         let mut arbitrary_rcvr = vec![];
1177         // There are no traits implemented, so lets suggest some traits to
1178         // implement, by finding ones that have the item name, and are
1179         // legal to implement.
1180         let mut candidates = all_traits(self.tcx)
1181             .into_iter()
1182             // Don't issue suggestions for unstable traits since they're
1183             // unlikely to be implementable anyway
1184             .filter(|info| match self.tcx.lookup_stability(info.def_id) {
1185                 Some(attr) => attr.level.is_stable(),
1186                 None => true,
1187             })
1188             .filter(|info| {
1189                 // We approximate the coherence rules to only suggest
1190                 // traits that are legal to implement by requiring that
1191                 // either the type or trait is local. Multi-dispatch means
1192                 // this isn't perfect (that is, there are cases when
1193                 // implementing a trait would be legal but is rejected
1194                 // here).
1195                 unsatisfied_predicates.iter().all(|(p, _)| {
1196                     match p.kind().skip_binder() {
1197                         // Hide traits if they are present in predicates as they can be fixed without
1198                         // having to implement them.
1199                         ty::PredicateKind::Trait(t) => t.def_id() == info.def_id,
1200                         ty::PredicateKind::Projection(p) => {
1201                             p.projection_ty.item_def_id == info.def_id
1202                         }
1203                         _ => false,
1204                     }
1205                 }) && (type_is_local || info.def_id.is_local())
1206                     && self
1207                         .associated_item(info.def_id, item_name, Namespace::ValueNS)
1208                         .filter(|item| {
1209                             if let ty::AssocKind::Fn = item.kind {
1210                                 let id = item
1211                                     .def_id
1212                                     .as_local()
1213                                     .map(|def_id| self.tcx.hir().local_def_id_to_hir_id(def_id));
1214                                 if let Some(hir::Node::TraitItem(hir::TraitItem {
1215                                     kind: hir::TraitItemKind::Fn(fn_sig, method),
1216                                     ..
1217                                 })) = id.map(|id| self.tcx.hir().get(id))
1218                                 {
1219                                     let self_first_arg = match method {
1220                                         hir::TraitFn::Required([ident, ..]) => {
1221                                             ident.name == kw::SelfLower
1222                                         }
1223                                         hir::TraitFn::Provided(body_id) => {
1224                                             self.tcx.hir().body(*body_id).params.first().map_or(
1225                                                 false,
1226                                                 |param| {
1227                                                     matches!(
1228                                                         param.pat.kind,
1229                                                         hir::PatKind::Binding(_, _, ident, _)
1230                                                             if ident.name == kw::SelfLower
1231                                                     )
1232                                                 },
1233                                             )
1234                                         }
1235                                         _ => false,
1236                                     };
1237
1238                                     if !fn_sig.decl.implicit_self.has_implicit_self()
1239                                         && self_first_arg
1240                                     {
1241                                         if let Some(ty) = fn_sig.decl.inputs.get(0) {
1242                                             arbitrary_rcvr.push(ty.span);
1243                                         }
1244                                         return false;
1245                                     }
1246                                 }
1247                             }
1248                             // We only want to suggest public or local traits (#45781).
1249                             item.vis == ty::Visibility::Public || info.def_id.is_local()
1250                         })
1251                         .is_some()
1252             })
1253             .collect::<Vec<_>>();
1254         for span in &arbitrary_rcvr {
1255             err.span_label(
1256                 *span,
1257                 "the method might not be found because of this arbitrary self type",
1258             );
1259         }
1260         if alt_rcvr_sugg {
1261             return;
1262         }
1263
1264         if !candidates.is_empty() {
1265             // Sort from most relevant to least relevant.
1266             candidates.sort_by(|a, b| a.cmp(b).reverse());
1267             candidates.dedup();
1268
1269             let param_type = match rcvr_ty.kind() {
1270                 ty::Param(param) => Some(param),
1271                 ty::Ref(_, ty, _) => match ty.kind() {
1272                     ty::Param(param) => Some(param),
1273                     _ => None,
1274                 },
1275                 _ => None,
1276             };
1277             err.help(if param_type.is_some() {
1278                 "items from traits can only be used if the type parameter is bounded by the trait"
1279             } else {
1280                 "items from traits can only be used if the trait is implemented and in scope"
1281             });
1282             let candidates_len = candidates.len();
1283             let message = |action| {
1284                 format!(
1285                     "the following {traits_define} an item `{name}`, perhaps you need to {action} \
1286                      {one_of_them}:",
1287                     traits_define =
1288                         if candidates_len == 1 { "trait defines" } else { "traits define" },
1289                     action = action,
1290                     one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
1291                     name = item_name,
1292                 )
1293             };
1294             // Obtain the span for `param` and use it for a structured suggestion.
1295             if let (Some(ref param), Some(ref table)) =
1296                 (param_type, self.in_progress_typeck_results)
1297             {
1298                 let table_owner = table.borrow().hir_owner;
1299                 let generics = self.tcx.generics_of(table_owner.to_def_id());
1300                 let type_param = generics.type_param(param, self.tcx);
1301                 let hir = &self.tcx.hir();
1302                 if let Some(def_id) = type_param.def_id.as_local() {
1303                     let id = hir.local_def_id_to_hir_id(def_id);
1304                     // Get the `hir::Param` to verify whether it already has any bounds.
1305                     // We do this to avoid suggesting code that ends up as `T: FooBar`,
1306                     // instead we suggest `T: Foo + Bar` in that case.
1307                     match hir.get(id) {
1308                         Node::GenericParam(ref param) => {
1309                             let mut impl_trait = false;
1310                             let has_bounds =
1311                                 if let hir::GenericParamKind::Type { synthetic: Some(_), .. } =
1312                                     &param.kind
1313                                 {
1314                                     // We've found `fn foo(x: impl Trait)` instead of
1315                                     // `fn foo<T>(x: T)`. We want to suggest the correct
1316                                     // `fn foo(x: impl Trait + TraitBound)` instead of
1317                                     // `fn foo<T: TraitBound>(x: T)`. (#63706)
1318                                     impl_trait = true;
1319                                     param.bounds.get(1)
1320                                 } else {
1321                                     param.bounds.get(0)
1322                                 };
1323                             let sp = hir.span(id);
1324                             let sp = if let Some(first_bound) = has_bounds {
1325                                 // `sp` only covers `T`, change it so that it covers
1326                                 // `T:` when appropriate
1327                                 sp.until(first_bound.span())
1328                             } else {
1329                                 sp
1330                             };
1331                             let trait_def_ids: FxHashSet<DefId> = param
1332                                 .bounds
1333                                 .iter()
1334                                 .filter_map(|bound| bound.trait_ref()?.trait_def_id())
1335                                 .collect();
1336                             if !candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
1337                                 err.span_suggestions(
1338                                     sp,
1339                                     &message(format!(
1340                                         "restrict type parameter `{}` with",
1341                                         param.name.ident(),
1342                                     )),
1343                                     candidates.iter().map(|t| {
1344                                         format!(
1345                                             "{}{} {}{}",
1346                                             param.name.ident(),
1347                                             if impl_trait { " +" } else { ":" },
1348                                             self.tcx.def_path_str(t.def_id),
1349                                             if has_bounds.is_some() { " + " } else { "" },
1350                                         )
1351                                     }),
1352                                     Applicability::MaybeIncorrect,
1353                                 );
1354                             }
1355                             return;
1356                         }
1357                         Node::Item(hir::Item {
1358                             kind: hir::ItemKind::Trait(.., bounds, _),
1359                             ident,
1360                             ..
1361                         }) => {
1362                             let (sp, sep, article) = if bounds.is_empty() {
1363                                 (ident.span.shrink_to_hi(), ":", "a")
1364                             } else {
1365                                 (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
1366                             };
1367                             err.span_suggestions(
1368                                 sp,
1369                                 &message(format!("add {} supertrait for", article)),
1370                                 candidates.iter().map(|t| {
1371                                     format!("{} {}", sep, self.tcx.def_path_str(t.def_id),)
1372                                 }),
1373                                 Applicability::MaybeIncorrect,
1374                             );
1375                             return;
1376                         }
1377                         _ => {}
1378                     }
1379                 }
1380             }
1381
1382             let (potential_candidates, explicitly_negative) = if param_type.is_some() {
1383                 // FIXME: Even though negative bounds are not implemented, we could maybe handle
1384                 // cases where a positive bound implies a negative impl.
1385                 (candidates, Vec::new())
1386             } else if let Some(simp_rcvr_ty) = simplify_type(self.tcx, rcvr_ty, true) {
1387                 let mut potential_candidates = Vec::new();
1388                 let mut explicitly_negative = Vec::new();
1389                 for candidate in candidates {
1390                     // Check if there's a negative impl of `candidate` for `rcvr_ty`
1391                     if self
1392                         .tcx
1393                         .all_impls(candidate.def_id)
1394                         .filter(|imp_did| {
1395                             self.tcx.impl_polarity(*imp_did) == ty::ImplPolarity::Negative
1396                         })
1397                         .any(|imp_did| {
1398                             let imp = self.tcx.impl_trait_ref(imp_did).unwrap();
1399                             let imp_simp = simplify_type(self.tcx, imp.self_ty(), true);
1400                             imp_simp.map_or(false, |s| s == simp_rcvr_ty)
1401                         })
1402                     {
1403                         explicitly_negative.push(candidate);
1404                     } else {
1405                         potential_candidates.push(candidate);
1406                     }
1407                 }
1408                 (potential_candidates, explicitly_negative)
1409             } else {
1410                 // We don't know enough about `recv_ty` to make proper suggestions.
1411                 (candidates, Vec::new())
1412             };
1413
1414             let action = if let Some(param) = param_type {
1415                 format!("restrict type parameter `{}` with", param)
1416             } else {
1417                 // FIXME: it might only need to be imported into scope, not implemented.
1418                 "implement".to_string()
1419             };
1420             match &potential_candidates[..] {
1421                 [] => {}
1422                 [trait_info] if trait_info.def_id.is_local() => {
1423                     let span = self.tcx.hir().span_if_local(trait_info.def_id).unwrap();
1424                     err.span_note(
1425                         self.tcx.sess.source_map().guess_head_span(span),
1426                         &format!(
1427                             "`{}` defines an item `{}`, perhaps you need to {} it",
1428                             self.tcx.def_path_str(trait_info.def_id),
1429                             item_name,
1430                             action
1431                         ),
1432                     );
1433                 }
1434                 trait_infos => {
1435                     let mut msg = message(action);
1436                     for (i, trait_info) in trait_infos.iter().enumerate() {
1437                         msg.push_str(&format!(
1438                             "\ncandidate #{}: `{}`",
1439                             i + 1,
1440                             self.tcx.def_path_str(trait_info.def_id),
1441                         ));
1442                     }
1443                     err.note(&msg);
1444                 }
1445             }
1446             match &explicitly_negative[..] {
1447                 [] => {}
1448                 [trait_info] => {
1449                     let msg = format!(
1450                         "the trait `{}` defines an item `{}`, but is explicitely unimplemented",
1451                         self.tcx.def_path_str(trait_info.def_id),
1452                         item_name
1453                     );
1454                     err.note(&msg);
1455                 }
1456                 trait_infos => {
1457                     let mut msg = format!(
1458                         "the following traits define an item `{}`, but are explicitely unimplemented:",
1459                         item_name
1460                     );
1461                     for trait_info in trait_infos {
1462                         msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
1463                     }
1464                     err.note(&msg);
1465                 }
1466             }
1467         }
1468     }
1469
1470     /// Checks whether there is a local type somewhere in the chain of
1471     /// autoderefs of `rcvr_ty`.
1472     fn type_derefs_to_local(
1473         &self,
1474         span: Span,
1475         rcvr_ty: Ty<'tcx>,
1476         source: SelfSource<'tcx>,
1477     ) -> bool {
1478         fn is_local(ty: Ty<'_>) -> bool {
1479             match ty.kind() {
1480                 ty::Adt(def, _) => def.did.is_local(),
1481                 ty::Foreign(did) => did.is_local(),
1482                 ty::Dynamic(ref tr, ..) => tr.principal().map_or(false, |d| d.def_id().is_local()),
1483                 ty::Param(_) => true,
1484
1485                 // Everything else (primitive types, etc.) is effectively
1486                 // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
1487                 // the noise from these sort of types is usually just really
1488                 // annoying, rather than any sort of help).
1489                 _ => false,
1490             }
1491         }
1492
1493         // This occurs for UFCS desugaring of `T::method`, where there is no
1494         // receiver expression for the method call, and thus no autoderef.
1495         if let SelfSource::QPath(_) = source {
1496             return is_local(self.resolve_vars_with_obligations(rcvr_ty));
1497         }
1498
1499         self.autoderef(span, rcvr_ty).any(|(ty, _)| is_local(ty))
1500     }
1501 }
1502
1503 #[derive(Copy, Clone, Debug)]
1504 pub enum SelfSource<'a> {
1505     QPath(&'a hir::Ty<'a>),
1506     MethodCall(&'a hir::Expr<'a> /* rcvr */),
1507 }
1508
1509 #[derive(Copy, Clone)]
1510 pub struct TraitInfo {
1511     pub def_id: DefId,
1512 }
1513
1514 impl PartialEq for TraitInfo {
1515     fn eq(&self, other: &TraitInfo) -> bool {
1516         self.cmp(other) == Ordering::Equal
1517     }
1518 }
1519 impl Eq for TraitInfo {}
1520 impl PartialOrd for TraitInfo {
1521     fn partial_cmp(&self, other: &TraitInfo) -> Option<Ordering> {
1522         Some(self.cmp(other))
1523     }
1524 }
1525 impl Ord for TraitInfo {
1526     fn cmp(&self, other: &TraitInfo) -> Ordering {
1527         // Local crates are more important than remote ones (local:
1528         // `cnum == 0`), and otherwise we throw in the defid for totality.
1529
1530         let lhs = (other.def_id.krate, other.def_id);
1531         let rhs = (self.def_id.krate, self.def_id);
1532         lhs.cmp(&rhs)
1533     }
1534 }
1535
1536 /// Retrieves all traits in this crate and any dependent crates.
1537 pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
1538     tcx.all_traits(()).iter().map(|&def_id| TraitInfo { def_id }).collect()
1539 }
1540
1541 /// Computes all traits in this crate and any dependent crates.
1542 fn compute_all_traits(tcx: TyCtxt<'_>, (): ()) -> &[DefId] {
1543     use hir::itemlikevisit;
1544
1545     let mut traits = vec![];
1546
1547     // Crate-local:
1548
1549     struct Visitor<'a> {
1550         traits: &'a mut Vec<DefId>,
1551     }
1552
1553     impl<'v, 'a> itemlikevisit::ItemLikeVisitor<'v> for Visitor<'a> {
1554         fn visit_item(&mut self, i: &'v hir::Item<'v>) {
1555             match i.kind {
1556                 hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) => {
1557                     self.traits.push(i.def_id.to_def_id());
1558                 }
1559                 _ => (),
1560             }
1561         }
1562
1563         fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
1564
1565         fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
1566
1567         fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
1568     }
1569
1570     tcx.hir().krate().visit_all_item_likes(&mut Visitor { traits: &mut traits });
1571
1572     // Cross-crate:
1573
1574     let mut external_mods = FxHashSet::default();
1575     fn handle_external_res(
1576         tcx: TyCtxt<'_>,
1577         traits: &mut Vec<DefId>,
1578         external_mods: &mut FxHashSet<DefId>,
1579         res: Res,
1580     ) {
1581         match res {
1582             Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) => {
1583                 traits.push(def_id);
1584             }
1585             Res::Def(DefKind::Mod, def_id) => {
1586                 if !external_mods.insert(def_id) {
1587                     return;
1588                 }
1589                 for child in tcx.item_children(def_id).iter() {
1590                     handle_external_res(tcx, traits, external_mods, child.res)
1591                 }
1592             }
1593             _ => {}
1594         }
1595     }
1596     for &cnum in tcx.crates(()).iter() {
1597         let def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
1598         handle_external_res(tcx, &mut traits, &mut external_mods, Res::Def(DefKind::Mod, def_id));
1599     }
1600
1601     tcx.arena.alloc_from_iter(traits)
1602 }
1603
1604 pub fn provide(providers: &mut ty::query::Providers) {
1605     providers.all_traits = compute_all_traits;
1606 }
1607
1608 struct UsePlacementFinder<'tcx> {
1609     target_module: hir::HirId,
1610     span: Option<Span>,
1611     found_use: bool,
1612     tcx: TyCtxt<'tcx>,
1613 }
1614
1615 impl UsePlacementFinder<'tcx> {
1616     fn check(tcx: TyCtxt<'tcx>, target_module: hir::HirId) -> (Option<Span>, bool) {
1617         let mut finder = UsePlacementFinder { target_module, span: None, found_use: false, tcx };
1618         tcx.hir().walk_crate(&mut finder);
1619         (finder.span, finder.found_use)
1620     }
1621 }
1622
1623 impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> {
1624     fn visit_mod(&mut self, module: &'tcx hir::Mod<'tcx>, _: Span, hir_id: hir::HirId) {
1625         if self.span.is_some() {
1626             return;
1627         }
1628         if hir_id != self.target_module {
1629             intravisit::walk_mod(self, module, hir_id);
1630             return;
1631         }
1632         // Find a `use` statement.
1633         for &item_id in module.item_ids {
1634             let item = self.tcx.hir().item(item_id);
1635             match item.kind {
1636                 hir::ItemKind::Use(..) => {
1637                     // Don't suggest placing a `use` before the prelude
1638                     // import or other generated ones.
1639                     if !item.span.from_expansion() {
1640                         self.span = Some(item.span.shrink_to_lo());
1641                         self.found_use = true;
1642                         return;
1643                     }
1644                 }
1645                 // Don't place `use` before `extern crate`...
1646                 hir::ItemKind::ExternCrate(_) => {}
1647                 // ...but do place them before the first other item.
1648                 _ => {
1649                     if self.span.map_or(true, |span| item.span < span) {
1650                         if !item.span.from_expansion() {
1651                             self.span = Some(item.span.shrink_to_lo());
1652                             // Don't insert between attributes and an item.
1653                             let attrs = self.tcx.hir().attrs(item.hir_id());
1654                             // Find the first attribute on the item.
1655                             // FIXME: This is broken for active attributes.
1656                             for attr in attrs {
1657                                 if !attr.span.is_dummy()
1658                                     && self.span.map_or(true, |span| attr.span < span)
1659                                 {
1660                                     self.span = Some(attr.span.shrink_to_lo());
1661                                 }
1662                             }
1663                         }
1664                     }
1665                 }
1666             }
1667         }
1668     }
1669
1670     type Map = intravisit::ErasedMap<'tcx>;
1671
1672     fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
1673         intravisit::NestedVisitorMap::None
1674     }
1675 }
1676
1677 fn print_disambiguation_help(
1678     item_name: Ident,
1679     args: Option<&'tcx [hir::Expr<'tcx>]>,
1680     err: &mut DiagnosticBuilder<'_>,
1681     trait_name: String,
1682     rcvr_ty: Ty<'_>,
1683     kind: ty::AssocKind,
1684     def_id: DefId,
1685     span: Span,
1686     candidate: Option<usize>,
1687     source_map: &source_map::SourceMap,
1688 ) {
1689     let mut applicability = Applicability::MachineApplicable;
1690     let (span, sugg) = if let (ty::AssocKind::Fn, Some(args)) = (kind, args) {
1691         let args = format!(
1692             "({}{})",
1693             if rcvr_ty.is_region_ptr() {
1694                 if rcvr_ty.is_mutable_ptr() { "&mut " } else { "&" }
1695             } else {
1696                 ""
1697             },
1698             args.iter()
1699                 .map(|arg| source_map.span_to_snippet(arg.span).unwrap_or_else(|_| {
1700                     applicability = Applicability::HasPlaceholders;
1701                     "_".to_owned()
1702                 }))
1703                 .collect::<Vec<_>>()
1704                 .join(", "),
1705         );
1706         (span, format!("{}::{}{}", trait_name, item_name, args))
1707     } else {
1708         (span.with_hi(item_name.span.lo()), format!("{}::", trait_name))
1709     };
1710     err.span_suggestion_verbose(
1711         span,
1712         &format!(
1713             "disambiguate the {} for {}",
1714             kind.as_def_kind().descr(def_id),
1715             if let Some(candidate) = candidate {
1716                 format!("candidate #{}", candidate)
1717             } else {
1718                 "the candidate".to_string()
1719             },
1720         ),
1721         sugg,
1722         applicability,
1723     );
1724 }