]> git.lizzy.rs Git - rust.git/blob - src/librustc/traits/error_reporting/suggestions.rs
b2aec78c175adbd05d4cac88545ae523f230aa1d
[rust.git] / src / librustc / traits / error_reporting / suggestions.rs
1 use super::{
2     ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
3     PredicateObligation,
4 };
5
6 use crate::infer::InferCtxt;
7 use crate::traits::object_safety::object_safety_violations;
8 use crate::ty::TypeckTables;
9 use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
10
11 use rustc_errors::{
12     error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
13 };
14 use rustc_hir as hir;
15 use rustc_hir::def_id::DefId;
16 use rustc_hir::intravisit::Visitor;
17 use rustc_hir::Node;
18 use rustc_span::source_map::SourceMap;
19 use rustc_span::symbol::{kw, sym};
20 use rustc_span::{MultiSpan, Span, DUMMY_SP};
21 use std::fmt;
22
23 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
24     crate fn suggest_restricting_param_bound(
25         &self,
26         mut err: &mut DiagnosticBuilder<'_>,
27         trait_ref: &ty::PolyTraitRef<'_>,
28         body_id: hir::HirId,
29     ) {
30         let self_ty = trait_ref.self_ty();
31         let (param_ty, projection) = match &self_ty.kind {
32             ty::Param(_) => (true, None),
33             ty::Projection(projection) => (false, Some(projection)),
34             _ => return,
35         };
36
37         let suggest_restriction =
38             |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
39                 let span = generics.where_clause.span_for_predicates_or_empty_place();
40                 if !span.from_expansion() && span.desugaring_kind().is_none() {
41                     err.span_suggestion(
42                         generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
43                         &format!("consider further restricting {}", msg),
44                         format!(
45                             "{} {} ",
46                             if !generics.where_clause.predicates.is_empty() {
47                                 ","
48                             } else {
49                                 " where"
50                             },
51                             trait_ref.without_const().to_predicate(),
52                         ),
53                         Applicability::MachineApplicable,
54                     );
55                 }
56             };
57
58         // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
59         //        don't suggest `T: Sized + ?Sized`.
60         let mut hir_id = body_id;
61         while let Some(node) = self.tcx.hir().find(hir_id) {
62             match node {
63                 hir::Node::TraitItem(hir::TraitItem {
64                     generics,
65                     kind: hir::TraitItemKind::Method(..),
66                     ..
67                 }) if param_ty && self_ty == self.tcx.types.self_param => {
68                     // Restricting `Self` for a single method.
69                     suggest_restriction(&generics, "`Self`", err);
70                     return;
71                 }
72
73                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
74                 | hir::Node::TraitItem(hir::TraitItem {
75                     generics,
76                     kind: hir::TraitItemKind::Method(..),
77                     ..
78                 })
79                 | hir::Node::ImplItem(hir::ImplItem {
80                     generics,
81                     kind: hir::ImplItemKind::Method(..),
82                     ..
83                 })
84                 | hir::Node::Item(hir::Item {
85                     kind: hir::ItemKind::Trait(_, _, generics, _, _),
86                     ..
87                 })
88                 | hir::Node::Item(hir::Item {
89                     kind: hir::ItemKind::Impl { generics, .. }, ..
90                 }) if projection.is_some() => {
91                     // Missing associated type bound.
92                     suggest_restriction(&generics, "the associated type", err);
93                     return;
94                 }
95
96                 hir::Node::Item(hir::Item {
97                     kind: hir::ItemKind::Struct(_, generics),
98                     span,
99                     ..
100                 })
101                 | hir::Node::Item(hir::Item {
102                     kind: hir::ItemKind::Enum(_, generics), span, ..
103                 })
104                 | hir::Node::Item(hir::Item {
105                     kind: hir::ItemKind::Union(_, generics),
106                     span,
107                     ..
108                 })
109                 | hir::Node::Item(hir::Item {
110                     kind: hir::ItemKind::Trait(_, _, generics, ..),
111                     span,
112                     ..
113                 })
114                 | hir::Node::Item(hir::Item {
115                     kind: hir::ItemKind::Impl { generics, .. },
116                     span,
117                     ..
118                 })
119                 | hir::Node::Item(hir::Item {
120                     kind: hir::ItemKind::Fn(_, generics, _),
121                     span,
122                     ..
123                 })
124                 | hir::Node::Item(hir::Item {
125                     kind: hir::ItemKind::TyAlias(_, generics),
126                     span,
127                     ..
128                 })
129                 | hir::Node::Item(hir::Item {
130                     kind: hir::ItemKind::TraitAlias(generics, _),
131                     span,
132                     ..
133                 })
134                 | hir::Node::Item(hir::Item {
135                     kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
136                     span,
137                     ..
138                 })
139                 | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
140                 | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
141                     if param_ty =>
142                 {
143                     // Missing generic type parameter bound.
144                     let param_name = self_ty.to_string();
145                     let constraint = trait_ref.print_only_trait_path().to_string();
146                     if suggest_constraining_type_param(
147                         generics,
148                         &mut err,
149                         &param_name,
150                         &constraint,
151                         self.tcx.sess.source_map(),
152                         *span,
153                     ) {
154                         return;
155                     }
156                 }
157
158                 hir::Node::Crate => return,
159
160                 _ => {}
161             }
162
163             hir_id = self.tcx.hir().get_parent_item(hir_id);
164         }
165     }
166
167     /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
168     /// suggestion to borrow the initializer in order to use have a slice instead.
169     crate fn suggest_borrow_on_unsized_slice(
170         &self,
171         code: &ObligationCauseCode<'tcx>,
172         err: &mut DiagnosticBuilder<'tcx>,
173     ) {
174         if let &ObligationCauseCode::VariableType(hir_id) = code {
175             let parent_node = self.tcx.hir().get_parent_node(hir_id);
176             if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
177                 if let Some(ref expr) = local.init {
178                     if let hir::ExprKind::Index(_, _) = expr.kind {
179                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
180                             err.span_suggestion(
181                                 expr.span,
182                                 "consider borrowing here",
183                                 format!("&{}", snippet),
184                                 Applicability::MachineApplicable,
185                             );
186                         }
187                     }
188                 }
189             }
190         }
191     }
192
193     /// Given a closure's `DefId`, return the given name of the closure.
194     ///
195     /// This doesn't account for reassignments, but it's only used for suggestions.
196     crate fn get_closure_name(
197         &self,
198         def_id: DefId,
199         err: &mut DiagnosticBuilder<'_>,
200         msg: &str,
201     ) -> Option<String> {
202         let get_name =
203             |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
204                 // Get the local name of this closure. This can be inaccurate because
205                 // of the possibility of reassignment, but this should be good enough.
206                 match &kind {
207                     hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
208                         Some(format!("{}", name))
209                     }
210                     _ => {
211                         err.note(&msg);
212                         None
213                     }
214                 }
215             };
216
217         let hir = self.tcx.hir();
218         let hir_id = hir.as_local_hir_id(def_id)?;
219         let parent_node = hir.get_parent_node(hir_id);
220         match hir.find(parent_node) {
221             Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
222                 get_name(err, &local.pat.kind)
223             }
224             // Different to previous arm because one is `&hir::Local` and the other
225             // is `P<hir::Local>`.
226             Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
227             _ => return None,
228         }
229     }
230
231     /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
232     /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
233     /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
234     crate fn suggest_fn_call(
235         &self,
236         obligation: &PredicateObligation<'tcx>,
237         err: &mut DiagnosticBuilder<'_>,
238         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
239         points_at_arg: bool,
240     ) {
241         let self_ty = trait_ref.self_ty();
242         let (def_id, output_ty, callable) = match self_ty.kind {
243             ty::Closure(def_id, substs) => {
244                 (def_id, self.closure_sig(def_id, substs).output(), "closure")
245             }
246             ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
247             _ => return,
248         };
249         let msg = format!("use parentheses to call the {}", callable);
250
251         let obligation = self.mk_obligation_for_def_id(
252             trait_ref.def_id(),
253             output_ty.skip_binder(),
254             obligation.cause.clone(),
255             obligation.param_env,
256         );
257
258         match self.evaluate_obligation(&obligation) {
259             Ok(EvaluationResult::EvaluatedToOk)
260             | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
261             | Ok(EvaluationResult::EvaluatedToAmbig) => {}
262             _ => return,
263         }
264         let hir = self.tcx.hir();
265         // Get the name of the callable and the arguments to be used in the suggestion.
266         let snippet = match hir.get_if_local(def_id) {
267             Some(hir::Node::Expr(hir::Expr {
268                 kind: hir::ExprKind::Closure(_, decl, _, span, ..),
269                 ..
270             })) => {
271                 err.span_label(*span, "consider calling this closure");
272                 let name = match self.get_closure_name(def_id, err, &msg) {
273                     Some(name) => name,
274                     None => return,
275                 };
276                 let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
277                 format!("{}({})", name, args)
278             }
279             Some(hir::Node::Item(hir::Item {
280                 ident,
281                 kind: hir::ItemKind::Fn(.., body_id),
282                 ..
283             })) => {
284                 err.span_label(ident.span, "consider calling this function");
285                 let body = hir.body(*body_id);
286                 let args = body
287                     .params
288                     .iter()
289                     .map(|arg| match &arg.pat.kind {
290                         hir::PatKind::Binding(_, _, ident, None)
291                         // FIXME: provide a better suggestion when encountering `SelfLower`, it
292                         // should suggest a method call.
293                         if ident.name != kw::SelfLower => ident.to_string(),
294                         _ => "_".to_string(),
295                     })
296                     .collect::<Vec<_>>()
297                     .join(", ");
298                 format!("{}({})", ident, args)
299             }
300             _ => return,
301         };
302         if points_at_arg {
303             // When the obligation error has been ensured to have been caused by
304             // an argument, the `obligation.cause.span` points at the expression
305             // of the argument, so we can provide a suggestion. This is signaled
306             // by `points_at_arg`. Otherwise, we give a more general note.
307             err.span_suggestion(
308                 obligation.cause.span,
309                 &msg,
310                 snippet,
311                 Applicability::HasPlaceholders,
312             );
313         } else {
314             err.help(&format!("{}: `{}`", msg, snippet));
315         }
316     }
317
318     crate fn suggest_add_reference_to_arg(
319         &self,
320         obligation: &PredicateObligation<'tcx>,
321         err: &mut DiagnosticBuilder<'tcx>,
322         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
323         points_at_arg: bool,
324         has_custom_message: bool,
325     ) -> bool {
326         if !points_at_arg {
327             return false;
328         }
329
330         let span = obligation.cause.span;
331         let param_env = obligation.param_env;
332         let trait_ref = trait_ref.skip_binder();
333
334         if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
335             // Try to apply the original trait binding obligation by borrowing.
336             let self_ty = trait_ref.self_ty();
337             let found = self_ty.to_string();
338             let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
339             let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
340             let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
341             let new_obligation = Obligation::new(
342                 ObligationCause::dummy(),
343                 param_env,
344                 new_trait_ref.without_const().to_predicate(),
345             );
346             if self.predicate_must_hold_modulo_regions(&new_obligation) {
347                 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
348                     // We have a very specific type of error, where just borrowing this argument
349                     // might solve the problem. In cases like this, the important part is the
350                     // original type obligation, not the last one that failed, which is arbitrary.
351                     // Because of this, we modify the error to refer to the original obligation and
352                     // return early in the caller.
353                     let msg = format!(
354                         "the trait bound `{}: {}` is not satisfied",
355                         found,
356                         obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
357                     );
358                     if has_custom_message {
359                         err.note(&msg);
360                     } else {
361                         err.message = vec![(msg, Style::NoStyle)];
362                     }
363                     if snippet.starts_with('&') {
364                         // This is already a literal borrow and the obligation is failing
365                         // somewhere else in the obligation chain. Do not suggest non-sense.
366                         return false;
367                     }
368                     err.span_label(
369                         span,
370                         &format!(
371                             "expected an implementor of trait `{}`",
372                             obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
373                         ),
374                     );
375                     err.span_suggestion(
376                         span,
377                         "consider borrowing here",
378                         format!("&{}", snippet),
379                         Applicability::MaybeIncorrect,
380                     );
381                     return true;
382                 }
383             }
384         }
385         false
386     }
387
388     /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
389     /// suggest removing these references until we reach a type that implements the trait.
390     crate fn suggest_remove_reference(
391         &self,
392         obligation: &PredicateObligation<'tcx>,
393         err: &mut DiagnosticBuilder<'tcx>,
394         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
395     ) {
396         let trait_ref = trait_ref.skip_binder();
397         let span = obligation.cause.span;
398
399         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
400             let refs_number =
401                 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
402             if let Some('\'') =
403                 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
404             {
405                 // Do not suggest removal of borrow from type arguments.
406                 return;
407             }
408
409             let mut trait_type = trait_ref.self_ty();
410
411             for refs_remaining in 0..refs_number {
412                 if let ty::Ref(_, t_type, _) = trait_type.kind {
413                     trait_type = t_type;
414
415                     let new_obligation = self.mk_obligation_for_def_id(
416                         trait_ref.def_id,
417                         trait_type,
418                         ObligationCause::dummy(),
419                         obligation.param_env,
420                     );
421
422                     if self.predicate_may_hold(&new_obligation) {
423                         let sp = self
424                             .tcx
425                             .sess
426                             .source_map()
427                             .span_take_while(span, |c| c.is_whitespace() || *c == '&');
428
429                         let remove_refs = refs_remaining + 1;
430                         let format_str =
431                             format!("consider removing {} leading `&`-references", remove_refs);
432
433                         err.span_suggestion_short(
434                             sp,
435                             &format_str,
436                             String::new(),
437                             Applicability::MachineApplicable,
438                         );
439                         break;
440                     }
441                 } else {
442                     break;
443                 }
444             }
445         }
446     }
447
448     /// Check if the trait bound is implemented for a different mutability and note it in the
449     /// final error.
450     crate fn suggest_change_mut(
451         &self,
452         obligation: &PredicateObligation<'tcx>,
453         err: &mut DiagnosticBuilder<'tcx>,
454         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
455         points_at_arg: bool,
456     ) {
457         let span = obligation.cause.span;
458         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
459             let refs_number =
460                 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
461             if let Some('\'') =
462                 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
463             {
464                 // Do not suggest removal of borrow from type arguments.
465                 return;
466             }
467             let trait_ref = self.resolve_vars_if_possible(trait_ref);
468             if trait_ref.has_infer_types() {
469                 // Do not ICE while trying to find if a reborrow would succeed on a trait with
470                 // unresolved bindings.
471                 return;
472             }
473
474             if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
475                 let trait_type = match mutability {
476                     hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
477                     hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
478                 };
479
480                 let new_obligation = self.mk_obligation_for_def_id(
481                     trait_ref.skip_binder().def_id,
482                     trait_type,
483                     ObligationCause::dummy(),
484                     obligation.param_env,
485                 );
486
487                 if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
488                 {
489                     let sp = self
490                         .tcx
491                         .sess
492                         .source_map()
493                         .span_take_while(span, |c| c.is_whitespace() || *c == '&');
494                     if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
495                         err.span_suggestion(
496                             sp,
497                             "consider changing this borrow's mutability",
498                             "&mut ".to_string(),
499                             Applicability::MachineApplicable,
500                         );
501                     } else {
502                         err.note(&format!(
503                             "`{}` is implemented for `{:?}`, but not for `{:?}`",
504                             trait_ref.print_only_trait_path(),
505                             trait_type,
506                             trait_ref.skip_binder().self_ty(),
507                         ));
508                     }
509                 }
510             }
511         }
512     }
513
514     crate fn suggest_semicolon_removal(
515         &self,
516         obligation: &PredicateObligation<'tcx>,
517         err: &mut DiagnosticBuilder<'tcx>,
518         span: Span,
519         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
520     ) {
521         let hir = self.tcx.hir();
522         let parent_node = hir.get_parent_node(obligation.cause.body_id);
523         let node = hir.find(parent_node);
524         if let Some(hir::Node::Item(hir::Item {
525             kind: hir::ItemKind::Fn(sig, _, body_id), ..
526         })) = node
527         {
528             let body = hir.body(*body_id);
529             if let hir::ExprKind::Block(blk, _) = &body.value.kind {
530                 if sig.decl.output.span().overlaps(span)
531                     && blk.expr.is_none()
532                     && "()" == &trait_ref.self_ty().to_string()
533                 {
534                     // FIXME(estebank): When encountering a method with a trait
535                     // bound not satisfied in the return type with a body that has
536                     // no return, suggest removal of semicolon on last statement.
537                     // Once that is added, close #54771.
538                     if let Some(ref stmt) = blk.stmts.last() {
539                         let sp = self.tcx.sess.source_map().end_point(stmt.span);
540                         err.span_label(sp, "consider removing this semicolon");
541                     }
542                 }
543             }
544         }
545     }
546
547     /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
548     /// applicable and signal that the error has been expanded appropriately and needs to be
549     /// emitted.
550     crate fn suggest_impl_trait(
551         &self,
552         err: &mut DiagnosticBuilder<'tcx>,
553         span: Span,
554         obligation: &PredicateObligation<'tcx>,
555         trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
556     ) -> bool {
557         match obligation.cause.code.peel_derives() {
558             // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
559             ObligationCauseCode::SizedReturnType => {}
560             _ => return false,
561         }
562
563         let hir = self.tcx.hir();
564         let parent_node = hir.get_parent_node(obligation.cause.body_id);
565         let node = hir.find(parent_node);
566         let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
567             kind: hir::ItemKind::Fn(sig, _, body_id),
568             ..
569         })) = node
570         {
571             (sig, body_id)
572         } else {
573             return false;
574         };
575         let body = hir.body(*body_id);
576         let trait_ref = self.resolve_vars_if_possible(trait_ref);
577         let ty = trait_ref.skip_binder().self_ty();
578         let is_object_safe = match ty.kind {
579             ty::Dynamic(predicates, _) => {
580                 // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
581                 predicates
582                     .principal_def_id()
583                     .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
584             }
585             // We only want to suggest `impl Trait` to `dyn Trait`s.
586             // For example, `fn foo() -> str` needs to be filtered out.
587             _ => return false,
588         };
589
590         let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
591             ret_ty
592         } else {
593             return false;
594         };
595
596         // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
597         // cases like `fn foo() -> (dyn Trait, i32) {}`.
598         // Recursively look for `TraitObject` types and if there's only one, use that span to
599         // suggest `impl Trait`.
600
601         // Visit to make sure there's a single `return` type to suggest `impl Trait`,
602         // otherwise suggest using `Box<dyn Trait>` or an enum.
603         let mut visitor = ReturnsVisitor::default();
604         visitor.visit_body(&body);
605
606         let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
607
608         let mut ret_types = visitor
609             .returns
610             .iter()
611             .filter_map(|expr| tables.node_type_opt(expr.hir_id))
612             .map(|ty| self.resolve_vars_if_possible(&ty));
613         let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
614             (None, true),
615             |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
616                 let ty = self.resolve_vars_if_possible(&ty);
617                 same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
618                 (Some(ty), same)
619             },
620         );
621         let all_returns_conform_to_trait =
622             if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
623                 match ty_ret_ty.kind {
624                     ty::Dynamic(predicates, _) => {
625                         let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
626                         let param_env = ty::ParamEnv::empty();
627                         ret_types.all(|returned_ty| {
628                             predicates.iter().all(|predicate| {
629                                 let pred = predicate.with_self_ty(self.tcx, returned_ty);
630                                 let obl = Obligation::new(cause.clone(), param_env, pred);
631                                 self.predicate_may_hold(&obl)
632                             })
633                         })
634                     }
635                     _ => false,
636                 }
637             } else {
638                 true
639             };
640
641         let (snippet, last_ty) =
642             if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
643                 // Verify that we're dealing with a return `dyn Trait`
644                 ret_ty.span.overlaps(span),
645                 &ret_ty.kind,
646                 self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
647                 // If any of the return types does not conform to the trait, then we can't
648                 // suggest `impl Trait` nor trait objects, it is a type mismatch error.
649                 all_returns_conform_to_trait,
650                 last_ty,
651             ) {
652                 (snippet, last_ty)
653             } else {
654                 return false;
655             };
656         err.code(error_code!(E0746));
657         err.set_primary_message("return type cannot have an unboxed trait object");
658         err.children.clear();
659         let impl_trait_msg = "for information on `impl Trait`, see \
660             <https://doc.rust-lang.org/book/ch10-02-traits.html\
661             #returning-types-that-implement-traits>";
662         let trait_obj_msg = "for information on trait objects, see \
663             <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
664             #using-trait-objects-that-allow-for-values-of-different-types>";
665         let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
666         let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
667         if all_returns_have_same_type {
668             // Suggest `-> impl Trait`.
669             err.span_suggestion(
670                 ret_ty.span,
671                 &format!(
672                     "return `impl {1}` instead, as all return paths are of type `{}`, \
673                         which implements `{1}`",
674                     last_ty, trait_obj,
675                 ),
676                 format!("impl {}", trait_obj),
677                 Applicability::MachineApplicable,
678             );
679             err.note(impl_trait_msg);
680         } else {
681             if is_object_safe {
682                 // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
683                 // Get all the return values and collect their span and suggestion.
684                 let mut suggestions = visitor
685                     .returns
686                     .iter()
687                     .map(|expr| {
688                         (
689                             expr.span,
690                             format!(
691                                 "Box::new({})",
692                                 self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
693                             ),
694                         )
695                     })
696                     .collect::<Vec<_>>();
697                 // Add the suggestion for the return type.
698                 suggestions.push((
699                     ret_ty.span,
700                     format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
701                 ));
702                 err.multipart_suggestion(
703                     "return a boxed trait object instead",
704                     suggestions,
705                     Applicability::MaybeIncorrect,
706                 );
707             } else {
708                 // This is currently not possible to trigger because E0038 takes precedence, but
709                 // leave it in for completeness in case anything changes in an earlier stage.
710                 err.note(&format!(
711                     "if trait `{}` was object safe, you could return a trait object",
712                     trait_obj,
713                 ));
714             }
715             err.note(trait_obj_msg);
716             err.note(&format!(
717                 "if all the returned values were of the same type you could use \
718                     `impl {}` as the return type",
719                 trait_obj,
720             ));
721             err.note(impl_trait_msg);
722             err.note("you can create a new `enum` with a variant for each returned type");
723         }
724         true
725     }
726
727     crate fn point_at_returns_when_relevant(
728         &self,
729         err: &mut DiagnosticBuilder<'tcx>,
730         obligation: &PredicateObligation<'tcx>,
731     ) {
732         match obligation.cause.code.peel_derives() {
733             ObligationCauseCode::SizedReturnType => {}
734             _ => return,
735         }
736
737         let hir = self.tcx.hir();
738         let parent_node = hir.get_parent_node(obligation.cause.body_id);
739         let node = hir.find(parent_node);
740         if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
741             node
742         {
743             let body = hir.body(*body_id);
744             // Point at all the `return`s in the function as they have failed trait bounds.
745             let mut visitor = ReturnsVisitor::default();
746             visitor.visit_body(&body);
747             let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
748             for expr in &visitor.returns {
749                 if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
750                     let ty = self.resolve_vars_if_possible(&returned_ty);
751                     err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
752                 }
753             }
754         }
755     }
756
757     /// Given some node representing a fn-like thing in the HIR map,
758     /// returns a span and `ArgKind` information that describes the
759     /// arguments it expects. This can be supplied to
760     /// `report_arg_count_mismatch`.
761     pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
762         match node {
763             Node::Expr(&hir::Expr {
764                 kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
765                 ..
766             }) => (
767                 self.tcx.sess.source_map().def_span(span),
768                 self.tcx
769                     .hir()
770                     .body(id)
771                     .params
772                     .iter()
773                     .map(|arg| {
774                         if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
775                             *arg.pat
776                         {
777                             ArgKind::Tuple(
778                                 Some(span),
779                                 args.iter()
780                                     .map(|pat| {
781                                         let snippet = self
782                                             .tcx
783                                             .sess
784                                             .source_map()
785                                             .span_to_snippet(pat.span)
786                                             .unwrap();
787                                         (snippet, "_".to_owned())
788                                     })
789                                     .collect::<Vec<_>>(),
790                             )
791                         } else {
792                             let name =
793                                 self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
794                             ArgKind::Arg(name, "_".to_owned())
795                         }
796                     })
797                     .collect::<Vec<ArgKind>>(),
798             ),
799             Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
800             | Node::ImplItem(&hir::ImplItem {
801                 span,
802                 kind: hir::ImplItemKind::Method(ref sig, _),
803                 ..
804             })
805             | Node::TraitItem(&hir::TraitItem {
806                 span,
807                 kind: hir::TraitItemKind::Method(ref sig, _),
808                 ..
809             }) => (
810                 self.tcx.sess.source_map().def_span(span),
811                 sig.decl
812                     .inputs
813                     .iter()
814                     .map(|arg| match arg.clone().kind {
815                         hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
816                             Some(arg.span),
817                             vec![("_".to_owned(), "_".to_owned()); tys.len()],
818                         ),
819                         _ => ArgKind::empty(),
820                     })
821                     .collect::<Vec<ArgKind>>(),
822             ),
823             Node::Ctor(ref variant_data) => {
824                 let span = variant_data
825                     .ctor_hir_id()
826                     .map(|hir_id| self.tcx.hir().span(hir_id))
827                     .unwrap_or(DUMMY_SP);
828                 let span = self.tcx.sess.source_map().def_span(span);
829
830                 (span, vec![ArgKind::empty(); variant_data.fields().len()])
831             }
832             _ => panic!("non-FnLike node found: {:?}", node),
833         }
834     }
835
836     /// Reports an error when the number of arguments needed by a
837     /// trait match doesn't match the number that the expression
838     /// provides.
839     pub fn report_arg_count_mismatch(
840         &self,
841         span: Span,
842         found_span: Option<Span>,
843         expected_args: Vec<ArgKind>,
844         found_args: Vec<ArgKind>,
845         is_closure: bool,
846     ) -> DiagnosticBuilder<'tcx> {
847         let kind = if is_closure { "closure" } else { "function" };
848
849         let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
850             let arg_length = arguments.len();
851             let distinct = match &other[..] {
852                 &[ArgKind::Tuple(..)] => true,
853                 _ => false,
854             };
855             match (arg_length, arguments.get(0)) {
856                 (1, Some(&ArgKind::Tuple(_, ref fields))) => {
857                     format!("a single {}-tuple as argument", fields.len())
858                 }
859                 _ => format!(
860                     "{} {}argument{}",
861                     arg_length,
862                     if distinct && arg_length > 1 { "distinct " } else { "" },
863                     pluralize!(arg_length)
864                 ),
865             }
866         };
867
868         let expected_str = args_str(&expected_args, &found_args);
869         let found_str = args_str(&found_args, &expected_args);
870
871         let mut err = struct_span_err!(
872             self.tcx.sess,
873             span,
874             E0593,
875             "{} is expected to take {}, but it takes {}",
876             kind,
877             expected_str,
878             found_str,
879         );
880
881         err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
882
883         if let Some(found_span) = found_span {
884             err.span_label(found_span, format!("takes {}", found_str));
885
886             // move |_| { ... }
887             // ^^^^^^^^-- def_span
888             //
889             // move |_| { ... }
890             // ^^^^^-- prefix
891             let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
892             // move |_| { ... }
893             //      ^^^-- pipe_span
894             let pipe_span =
895                 if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
896
897             // Suggest to take and ignore the arguments with expected_args_length `_`s if
898             // found arguments is empty (assume the user just wants to ignore args in this case).
899             // For example, if `expected_args_length` is 2, suggest `|_, _|`.
900             if found_args.is_empty() && is_closure {
901                 let underscores = vec!["_"; expected_args.len()].join(", ");
902                 err.span_suggestion(
903                     pipe_span,
904                     &format!(
905                         "consider changing the closure to take and ignore the expected argument{}",
906                         if expected_args.len() < 2 { "" } else { "s" }
907                     ),
908                     format!("|{}|", underscores),
909                     Applicability::MachineApplicable,
910                 );
911             }
912
913             if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
914                 if fields.len() == expected_args.len() {
915                     let sugg = fields
916                         .iter()
917                         .map(|(name, _)| name.to_owned())
918                         .collect::<Vec<String>>()
919                         .join(", ");
920                     err.span_suggestion(
921                         found_span,
922                         "change the closure to take multiple arguments instead of a single tuple",
923                         format!("|{}|", sugg),
924                         Applicability::MachineApplicable,
925                     );
926                 }
927             }
928             if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
929                 if fields.len() == found_args.len() && is_closure {
930                     let sugg = format!(
931                         "|({}){}|",
932                         found_args
933                             .iter()
934                             .map(|arg| match arg {
935                                 ArgKind::Arg(name, _) => name.to_owned(),
936                                 _ => "_".to_owned(),
937                             })
938                             .collect::<Vec<String>>()
939                             .join(", "),
940                         // add type annotations if available
941                         if found_args.iter().any(|arg| match arg {
942                             ArgKind::Arg(_, ty) => ty != "_",
943                             _ => false,
944                         }) {
945                             format!(
946                                 ": ({})",
947                                 fields
948                                     .iter()
949                                     .map(|(_, ty)| ty.to_owned())
950                                     .collect::<Vec<String>>()
951                                     .join(", ")
952                             )
953                         } else {
954                             String::new()
955                         },
956                     );
957                     err.span_suggestion(
958                         found_span,
959                         "change the closure to accept a tuple instead of individual arguments",
960                         sugg,
961                         Applicability::MachineApplicable,
962                     );
963                 }
964             }
965         }
966
967         err
968     }
969
970     crate fn report_closure_arg_mismatch(
971         &self,
972         span: Span,
973         found_span: Option<Span>,
974         expected_ref: ty::PolyTraitRef<'tcx>,
975         found: ty::PolyTraitRef<'tcx>,
976     ) -> DiagnosticBuilder<'tcx> {
977         crate fn build_fn_sig_string<'tcx>(
978             tcx: TyCtxt<'tcx>,
979             trait_ref: &ty::TraitRef<'tcx>,
980         ) -> String {
981             let inputs = trait_ref.substs.type_at(1);
982             let sig = if let ty::Tuple(inputs) = inputs.kind {
983                 tcx.mk_fn_sig(
984                     inputs.iter().map(|k| k.expect_ty()),
985                     tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
986                     false,
987                     hir::Unsafety::Normal,
988                     ::rustc_target::spec::abi::Abi::Rust,
989                 )
990             } else {
991                 tcx.mk_fn_sig(
992                     ::std::iter::once(inputs),
993                     tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
994                     false,
995                     hir::Unsafety::Normal,
996                     ::rustc_target::spec::abi::Abi::Rust,
997                 )
998             };
999             ty::Binder::bind(sig).to_string()
1000         }
1001
1002         let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
1003         let mut err = struct_span_err!(
1004             self.tcx.sess,
1005             span,
1006             E0631,
1007             "type mismatch in {} arguments",
1008             if argument_is_closure { "closure" } else { "function" }
1009         );
1010
1011         let found_str = format!(
1012             "expected signature of `{}`",
1013             build_fn_sig_string(self.tcx, found.skip_binder())
1014         );
1015         err.span_label(span, found_str);
1016
1017         let found_span = found_span.unwrap_or(span);
1018         let expected_str = format!(
1019             "found signature of `{}`",
1020             build_fn_sig_string(self.tcx, expected_ref.skip_binder())
1021         );
1022         err.span_label(found_span, expected_str);
1023
1024         err
1025     }
1026 }
1027
1028 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1029     crate fn suggest_fully_qualified_path(
1030         &self,
1031         err: &mut DiagnosticBuilder<'_>,
1032         def_id: DefId,
1033         span: Span,
1034         trait_ref: DefId,
1035     ) {
1036         if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
1037             if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
1038                 err.note(&format!(
1039                     "{}s cannot be accessed directly on a `trait`, they can only be \
1040                         accessed through a specific `impl`",
1041                     assoc_item.kind.suggestion_descr(),
1042                 ));
1043                 err.span_suggestion(
1044                     span,
1045                     "use the fully qualified path to an implementation",
1046                     format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
1047                     Applicability::HasPlaceholders,
1048                 );
1049             }
1050         }
1051     }
1052
1053     /// Adds an async-await specific note to the diagnostic when the future does not implement
1054     /// an auto trait because of a captured type.
1055     ///
1056     /// ```ignore (diagnostic)
1057     /// note: future does not implement `Qux` as this value is used across an await
1058     ///   --> $DIR/issue-64130-3-other.rs:17:5
1059     ///    |
1060     /// LL |     let x = Foo;
1061     ///    |         - has type `Foo`
1062     /// LL |     baz().await;
1063     ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1064     /// LL | }
1065     ///    | - `x` is later dropped here
1066     /// ```
1067     ///
1068     /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
1069     /// is "replaced" with a different message and a more specific error.
1070     ///
1071     /// ```ignore (diagnostic)
1072     /// error: future cannot be sent between threads safely
1073     ///   --> $DIR/issue-64130-2-send.rs:21:5
1074     ///    |
1075     /// LL | fn is_send<T: Send>(t: T) { }
1076     ///    |    -------    ---- required by this bound in `is_send`
1077     /// ...
1078     /// LL |     is_send(bar());
1079     ///    |     ^^^^^^^ future returned by `bar` is not send
1080     ///    |
1081     ///    = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
1082     ///            implemented for `Foo`
1083     /// note: future is not send as this value is used across an await
1084     ///   --> $DIR/issue-64130-2-send.rs:15:5
1085     ///    |
1086     /// LL |     let x = Foo;
1087     ///    |         - has type `Foo`
1088     /// LL |     baz().await;
1089     ///    |     ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1090     /// LL | }
1091     ///    | - `x` is later dropped here
1092     /// ```
1093     ///
1094     /// Returns `true` if an async-await specific note was added to the diagnostic.
1095     crate fn maybe_note_obligation_cause_for_async_await(
1096         &self,
1097         err: &mut DiagnosticBuilder<'_>,
1098         obligation: &PredicateObligation<'tcx>,
1099     ) -> bool {
1100         debug!(
1101             "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
1102                 obligation.cause.span={:?}",
1103             obligation.predicate, obligation.cause.span
1104         );
1105         let source_map = self.tcx.sess.source_map();
1106
1107         // Attempt to detect an async-await error by looking at the obligation causes, looking
1108         // for a generator to be present.
1109         //
1110         // When a future does not implement a trait because of a captured type in one of the
1111         // generators somewhere in the call stack, then the result is a chain of obligations.
1112         //
1113         // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
1114         // future is passed as an argument to a function C which requires a `Send` type, then the
1115         // chain looks something like this:
1116         //
1117         // - `BuiltinDerivedObligation` with a generator witness (B)
1118         // - `BuiltinDerivedObligation` with a generator (B)
1119         // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
1120         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1121         // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1122         // - `BuiltinDerivedObligation` with a generator witness (A)
1123         // - `BuiltinDerivedObligation` with a generator (A)
1124         // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
1125         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1126         // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1127         // - `BindingObligation` with `impl_send (Send requirement)
1128         //
1129         // The first obligation in the chain is the most useful and has the generator that captured
1130         // the type. The last generator has information about where the bound was introduced. At
1131         // least one generator should be present for this diagnostic to be modified.
1132         let (mut trait_ref, mut target_ty) = match obligation.predicate {
1133             ty::Predicate::Trait(p, _) => {
1134                 (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
1135             }
1136             _ => (None, None),
1137         };
1138         let mut generator = None;
1139         let mut last_generator = None;
1140         let mut next_code = Some(&obligation.cause.code);
1141         while let Some(code) = next_code {
1142             debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
1143             match code {
1144                 ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
1145                 | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
1146                     let ty = derived_obligation.parent_trait_ref.self_ty();
1147                     debug!(
1148                         "maybe_note_obligation_cause_for_async_await: \
1149                             parent_trait_ref={:?} self_ty.kind={:?}",
1150                         derived_obligation.parent_trait_ref, ty.kind
1151                     );
1152
1153                     match ty.kind {
1154                         ty::Generator(did, ..) => {
1155                             generator = generator.or(Some(did));
1156                             last_generator = Some(did);
1157                         }
1158                         ty::GeneratorWitness(..) => {}
1159                         _ if generator.is_none() => {
1160                             trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
1161                             target_ty = Some(ty);
1162                         }
1163                         _ => {}
1164                     }
1165
1166                     next_code = Some(derived_obligation.parent_code.as_ref());
1167                 }
1168                 _ => break,
1169             }
1170         }
1171
1172         // Only continue if a generator was found.
1173         debug!(
1174             "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
1175                 target_ty={:?}",
1176             generator, trait_ref, target_ty
1177         );
1178         let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
1179             (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
1180                 (generator_did, trait_ref, target_ty)
1181             }
1182             _ => return false,
1183         };
1184
1185         let span = self.tcx.def_span(generator_did);
1186
1187         // Do not ICE on closure typeck (#66868).
1188         if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
1189             return false;
1190         }
1191
1192         // Get the tables from the infcx if the generator is the function we are
1193         // currently type-checking; otherwise, get them by performing a query.
1194         // This is needed to avoid cycles.
1195         let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
1196         let generator_did_root = self.tcx.closure_base_def_id(generator_did);
1197         debug!(
1198             "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
1199              generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
1200             generator_did,
1201             generator_did_root,
1202             in_progress_tables.as_ref().map(|t| t.local_id_root),
1203             span
1204         );
1205         let query_tables;
1206         let tables: &TypeckTables<'tcx> = match &in_progress_tables {
1207             Some(t) if t.local_id_root == Some(generator_did_root) => t,
1208             _ => {
1209                 query_tables = self.tcx.typeck_tables_of(generator_did);
1210                 &query_tables
1211             }
1212         };
1213
1214         // Look for a type inside the generator interior that matches the target type to get
1215         // a span.
1216         let target_ty_erased = self.tcx.erase_regions(&target_ty);
1217         let target_span = tables
1218             .generator_interior_types
1219             .iter()
1220             .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
1221                 // Careful: the regions for types that appear in the
1222                 // generator interior are not generally known, so we
1223                 // want to erase them when comparing (and anyway,
1224                 // `Send` and other bounds are generally unaffected by
1225                 // the choice of region).  When erasing regions, we
1226                 // also have to erase late-bound regions. This is
1227                 // because the types that appear in the generator
1228                 // interior generally contain "bound regions" to
1229                 // represent regions that are part of the suspended
1230                 // generator frame. Bound regions are preserved by
1231                 // `erase_regions` and so we must also call
1232                 // `erase_late_bound_regions`.
1233                 let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
1234                 let ty_erased = self.tcx.erase_regions(&ty_erased);
1235                 let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
1236                 debug!(
1237                     "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
1238                         target_ty_erased={:?} eq={:?}",
1239                     ty_erased, target_ty_erased, eq
1240                 );
1241                 eq
1242             })
1243             .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
1244                 (span, source_map.span_to_snippet(*span), scope_span, expr)
1245             });
1246
1247         debug!(
1248             "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
1249                 generator_interior_types={:?} target_span={:?}",
1250             target_ty, tables.generator_interior_types, target_span
1251         );
1252         if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
1253             self.note_obligation_cause_for_async_await(
1254                 err,
1255                 *target_span,
1256                 scope_span,
1257                 *expr,
1258                 snippet,
1259                 generator_did,
1260                 last_generator,
1261                 trait_ref,
1262                 target_ty,
1263                 tables,
1264                 obligation,
1265                 next_code,
1266             );
1267             true
1268         } else {
1269             false
1270         }
1271     }
1272
1273     /// Unconditionally adds the diagnostic note described in
1274     /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
1275     crate fn note_obligation_cause_for_async_await(
1276         &self,
1277         err: &mut DiagnosticBuilder<'_>,
1278         target_span: Span,
1279         scope_span: &Option<Span>,
1280         expr: Option<hir::HirId>,
1281         snippet: String,
1282         first_generator: DefId,
1283         last_generator: Option<DefId>,
1284         trait_ref: ty::TraitRef<'_>,
1285         target_ty: Ty<'tcx>,
1286         tables: &ty::TypeckTables<'_>,
1287         obligation: &PredicateObligation<'tcx>,
1288         next_code: Option<&ObligationCauseCode<'tcx>>,
1289     ) {
1290         let source_map = self.tcx.sess.source_map();
1291
1292         let is_async_fn = self
1293             .tcx
1294             .parent(first_generator)
1295             .map(|parent_did| self.tcx.asyncness(parent_did))
1296             .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
1297             .unwrap_or(false);
1298         let is_async_move = self
1299             .tcx
1300             .hir()
1301             .as_local_hir_id(first_generator)
1302             .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
1303             .map(|body_id| self.tcx.hir().body(body_id))
1304             .and_then(|body| body.generator_kind())
1305             .map(|generator_kind| match generator_kind {
1306                 hir::GeneratorKind::Async(..) => true,
1307                 _ => false,
1308             })
1309             .unwrap_or(false);
1310         let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
1311
1312         // Special case the primary error message when send or sync is the trait that was
1313         // not implemented.
1314         let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
1315         let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
1316         let hir = self.tcx.hir();
1317         let trait_explanation = if is_send || is_sync {
1318             let (trait_name, trait_verb) =
1319                 if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
1320
1321             err.clear_code();
1322             err.set_primary_message(format!(
1323                 "future cannot be {} between threads safely",
1324                 trait_verb
1325             ));
1326
1327             let original_span = err.span.primary_span().unwrap();
1328             let mut span = MultiSpan::from_span(original_span);
1329
1330             let message = if let Some(name) = last_generator
1331                 .and_then(|generator_did| self.tcx.parent(generator_did))
1332                 .and_then(|parent_did| hir.as_local_hir_id(parent_did))
1333                 .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
1334             {
1335                 format!("future returned by `{}` is not {}", name, trait_name)
1336             } else {
1337                 format!("future is not {}", trait_name)
1338             };
1339
1340             span.push_span_label(original_span, message);
1341             err.set_span(span);
1342
1343             format!("is not {}", trait_name)
1344         } else {
1345             format!("does not implement `{}`", trait_ref.print_only_trait_path())
1346         };
1347
1348         // Look at the last interior type to get a span for the `.await`.
1349         let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
1350         let mut span = MultiSpan::from_span(await_span);
1351         span.push_span_label(
1352             await_span,
1353             format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
1354         );
1355
1356         span.push_span_label(target_span, format!("has type `{}`", target_ty));
1357
1358         // If available, use the scope span to annotate the drop location.
1359         if let Some(scope_span) = scope_span {
1360             span.push_span_label(
1361                 source_map.end_point(*scope_span),
1362                 format!("`{}` is later dropped here", snippet),
1363             );
1364         }
1365
1366         err.span_note(
1367             span,
1368             &format!(
1369                 "future {} as this value is used across an {}",
1370                 trait_explanation, await_or_yield,
1371             ),
1372         );
1373
1374         if let Some(expr_id) = expr {
1375             let expr = hir.expect_expr(expr_id);
1376             let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
1377             let parent = hir.get_parent_node(expr_id);
1378             if let Some(hir::Node::Expr(e)) = hir.find(parent) {
1379                 let method_span = hir.span(parent);
1380                 if tables.is_method_call(e) && is_ref {
1381                     err.span_help(
1382                         method_span,
1383                         "consider moving this method call into a `let` \
1384                         binding to create a shorter lived borrow",
1385                     );
1386                 }
1387             }
1388         }
1389
1390         // Add a note for the item obligation that remains - normally a note pointing to the
1391         // bound that introduced the obligation (e.g. `T: Send`).
1392         debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
1393         self.note_obligation_cause_code(
1394             err,
1395             &obligation.predicate,
1396             next_code.unwrap(),
1397             &mut Vec::new(),
1398         );
1399     }
1400
1401     crate fn note_obligation_cause_code<T>(
1402         &self,
1403         err: &mut DiagnosticBuilder<'_>,
1404         predicate: &T,
1405         cause_code: &ObligationCauseCode<'tcx>,
1406         obligated_types: &mut Vec<&ty::TyS<'tcx>>,
1407     ) where
1408         T: fmt::Display,
1409     {
1410         let tcx = self.tcx;
1411         match *cause_code {
1412             ObligationCauseCode::ExprAssignable
1413             | ObligationCauseCode::MatchExpressionArm { .. }
1414             | ObligationCauseCode::Pattern { .. }
1415             | ObligationCauseCode::IfExpression { .. }
1416             | ObligationCauseCode::IfExpressionWithNoElse
1417             | ObligationCauseCode::MainFunctionType
1418             | ObligationCauseCode::StartFunctionType
1419             | ObligationCauseCode::IntrinsicType
1420             | ObligationCauseCode::MethodReceiver
1421             | ObligationCauseCode::ReturnNoExpression
1422             | ObligationCauseCode::MiscObligation => {}
1423             ObligationCauseCode::SliceOrArrayElem => {
1424                 err.note("slice and array elements must have `Sized` type");
1425             }
1426             ObligationCauseCode::TupleElem => {
1427                 err.note("only the last element of a tuple may have a dynamically sized type");
1428             }
1429             ObligationCauseCode::ProjectionWf(data) => {
1430                 err.note(&format!("required so that the projection `{}` is well-formed", data,));
1431             }
1432             ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
1433                 err.note(&format!(
1434                     "required so that reference `{}` does not outlive its referent",
1435                     ref_ty,
1436                 ));
1437             }
1438             ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
1439                 err.note(&format!(
1440                     "required so that the lifetime bound of `{}` for `{}` is satisfied",
1441                     region, object_ty,
1442                 ));
1443             }
1444             ObligationCauseCode::ItemObligation(item_def_id) => {
1445                 let item_name = tcx.def_path_str(item_def_id);
1446                 let msg = format!("required by `{}`", item_name);
1447
1448                 if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
1449                     let sp = tcx.sess.source_map().def_span(sp);
1450                     err.span_label(sp, &msg);
1451                 } else {
1452                     err.note(&msg);
1453                 }
1454             }
1455             ObligationCauseCode::BindingObligation(item_def_id, span) => {
1456                 let item_name = tcx.def_path_str(item_def_id);
1457                 let msg = format!("required by this bound in `{}`", item_name);
1458                 if let Some(ident) = tcx.opt_item_name(item_def_id) {
1459                     err.span_label(ident.span, "");
1460                 }
1461                 if span != DUMMY_SP {
1462                     err.span_label(span, &msg);
1463                 } else {
1464                     err.note(&msg);
1465                 }
1466             }
1467             ObligationCauseCode::ObjectCastObligation(object_ty) => {
1468                 err.note(&format!(
1469                     "required for the cast to the object type `{}`",
1470                     self.ty_to_string(object_ty)
1471                 ));
1472             }
1473             ObligationCauseCode::Coercion { source: _, target } => {
1474                 err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
1475             }
1476             ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
1477                 err.note(
1478                     "the `Copy` trait is required because the repeated element will be copied",
1479                 );
1480                 if suggest_const_in_array_repeat_expressions {
1481                     err.note(
1482                         "this array initializer can be evaluated at compile-time, for more \
1483                          information, see issue \
1484                          https://github.com/rust-lang/rust/issues/49147",
1485                     );
1486                     if tcx.sess.opts.unstable_features.is_nightly_build() {
1487                         err.help(
1488                             "add `#![feature(const_in_array_repeat_expressions)]` to the \
1489                              crate attributes to enable",
1490                         );
1491                     }
1492                 }
1493             }
1494             ObligationCauseCode::VariableType(_) => {
1495                 err.note("all local variables must have a statically known size");
1496                 if !self.tcx.features().unsized_locals {
1497                     err.help("unsized locals are gated as an unstable feature");
1498                 }
1499             }
1500             ObligationCauseCode::SizedArgumentType => {
1501                 err.note("all function arguments must have a statically known size");
1502                 if !self.tcx.features().unsized_locals {
1503                     err.help("unsized locals are gated as an unstable feature");
1504                 }
1505             }
1506             ObligationCauseCode::SizedReturnType => {
1507                 err.note("the return type of a function must have a statically known size");
1508             }
1509             ObligationCauseCode::SizedYieldType => {
1510                 err.note("the yield type of a generator must have a statically known size");
1511             }
1512             ObligationCauseCode::AssignmentLhsSized => {
1513                 err.note("the left-hand-side of an assignment must have a statically known size");
1514             }
1515             ObligationCauseCode::TupleInitializerSized => {
1516                 err.note("tuples must have a statically known size to be initialized");
1517             }
1518             ObligationCauseCode::StructInitializerSized => {
1519                 err.note("structs must have a statically known size to be initialized");
1520             }
1521             ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
1522                 AdtKind::Struct => {
1523                     if last {
1524                         err.note(
1525                             "the last field of a packed struct may only have a \
1526                              dynamically sized type if it does not need drop to be run",
1527                         );
1528                     } else {
1529                         err.note(
1530                             "only the last field of a struct may have a dynamically sized type",
1531                         );
1532                     }
1533                 }
1534                 AdtKind::Union => {
1535                     err.note("no field of a union may have a dynamically sized type");
1536                 }
1537                 AdtKind::Enum => {
1538                     err.note("no field of an enum variant may have a dynamically sized type");
1539                 }
1540             },
1541             ObligationCauseCode::ConstSized => {
1542                 err.note("constant expressions must have a statically known size");
1543             }
1544             ObligationCauseCode::ConstPatternStructural => {
1545                 err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
1546             }
1547             ObligationCauseCode::SharedStatic => {
1548                 err.note("shared static variables must have a type that implements `Sync`");
1549             }
1550             ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
1551                 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1552                 let ty = parent_trait_ref.skip_binder().self_ty();
1553                 err.note(&format!("required because it appears within the type `{}`", ty));
1554                 obligated_types.push(ty);
1555
1556                 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1557                 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
1558                     self.note_obligation_cause_code(
1559                         err,
1560                         &parent_predicate,
1561                         &data.parent_code,
1562                         obligated_types,
1563                     );
1564                 }
1565             }
1566             ObligationCauseCode::ImplDerivedObligation(ref data) => {
1567                 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1568                 err.note(&format!(
1569                     "required because of the requirements on the impl of `{}` for `{}`",
1570                     parent_trait_ref.print_only_trait_path(),
1571                     parent_trait_ref.skip_binder().self_ty()
1572                 ));
1573                 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1574                 self.note_obligation_cause_code(
1575                     err,
1576                     &parent_predicate,
1577                     &data.parent_code,
1578                     obligated_types,
1579                 );
1580             }
1581             ObligationCauseCode::CompareImplMethodObligation { .. } => {
1582                 err.note(&format!(
1583                     "the requirement `{}` appears on the impl method \
1584                      but not on the corresponding trait method",
1585                     predicate
1586                 ));
1587             }
1588             ObligationCauseCode::CompareImplTypeObligation { .. } => {
1589                 err.note(&format!(
1590                     "the requirement `{}` appears on the associated impl type \
1591                      but not on the corresponding associated trait type",
1592                     predicate
1593                 ));
1594             }
1595             ObligationCauseCode::ReturnType
1596             | ObligationCauseCode::ReturnValue(_)
1597             | ObligationCauseCode::BlockTailExpression(_) => (),
1598             ObligationCauseCode::TrivialBound => {
1599                 err.help("see issue #48214");
1600                 if tcx.sess.opts.unstable_features.is_nightly_build() {
1601                     err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
1602                 }
1603             }
1604             ObligationCauseCode::AssocTypeBound(ref data) => {
1605                 err.span_label(data.original, "associated type defined here");
1606                 if let Some(sp) = data.impl_span {
1607                     err.span_label(sp, "in this `impl` item");
1608                 }
1609                 for sp in &data.bounds {
1610                     err.span_label(*sp, "restricted in this bound");
1611                 }
1612             }
1613         }
1614     }
1615
1616     crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
1617         let current_limit = self.tcx.sess.recursion_limit.get();
1618         let suggested_limit = current_limit * 2;
1619         err.help(&format!(
1620             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
1621             suggested_limit
1622         ));
1623     }
1624 }
1625
1626 /// Suggest restricting a type param with a new bound.
1627 pub fn suggest_constraining_type_param(
1628     generics: &hir::Generics<'_>,
1629     err: &mut DiagnosticBuilder<'_>,
1630     param_name: &str,
1631     constraint: &str,
1632     source_map: &SourceMap,
1633     span: Span,
1634 ) -> bool {
1635     let restrict_msg = "consider further restricting this bound";
1636     if let Some(param) =
1637         generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
1638     {
1639         if param_name.starts_with("impl ") {
1640             // `impl Trait` in argument:
1641             // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
1642             err.span_suggestion(
1643                 param.span,
1644                 restrict_msg,
1645                 // `impl CurrentTrait + MissingTrait`
1646                 format!("{} + {}", param_name, constraint),
1647                 Applicability::MachineApplicable,
1648             );
1649         } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
1650             // If there are no bounds whatsoever, suggest adding a constraint
1651             // to the type parameter:
1652             // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
1653             err.span_suggestion(
1654                 param.span,
1655                 "consider restricting this bound",
1656                 format!("{}: {}", param_name, constraint),
1657                 Applicability::MachineApplicable,
1658             );
1659         } else if !generics.where_clause.predicates.is_empty() {
1660             // There is a `where` clause, so suggest expanding it:
1661             // `fn foo<T>(t: T) where T: Debug {}` →
1662             // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
1663             err.span_suggestion(
1664                 generics.where_clause.span().unwrap().shrink_to_hi(),
1665                 &format!("consider further restricting type parameter `{}`", param_name),
1666                 format!(", {}: {}", param_name, constraint),
1667                 Applicability::MachineApplicable,
1668             );
1669         } else {
1670             // If there is no `where` clause lean towards constraining to the
1671             // type parameter:
1672             // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
1673             // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
1674             let sp = param.span.with_hi(span.hi());
1675             let span = source_map.span_through_char(sp, ':');
1676             if sp != param.span && sp != span {
1677                 // Only suggest if we have high certainty that the span
1678                 // covers the colon in `foo<T: Trait>`.
1679                 err.span_suggestion(
1680                     span,
1681                     restrict_msg,
1682                     format!("{}: {} + ", param_name, constraint),
1683                     Applicability::MachineApplicable,
1684                 );
1685             } else {
1686                 err.span_label(
1687                     param.span,
1688                     &format!("consider adding a `where {}: {}` bound", param_name, constraint),
1689                 );
1690             }
1691         }
1692         return true;
1693     }
1694     false
1695 }
1696
1697 /// Collect all the returned expressions within the input expression.
1698 /// Used to point at the return spans when we want to suggest some change to them.
1699 #[derive(Default)]
1700 struct ReturnsVisitor<'v> {
1701     returns: Vec<&'v hir::Expr<'v>>,
1702     in_block_tail: bool,
1703 }
1704
1705 impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
1706     type Map = rustc::hir::map::Map<'v>;
1707
1708     fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
1709         hir::intravisit::NestedVisitorMap::None
1710     }
1711
1712     fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
1713         // Visit every expression to detect `return` paths, either through the function's tail
1714         // expression or `return` statements. We walk all nodes to find `return` statements, but
1715         // we only care about tail expressions when `in_block_tail` is `true`, which means that
1716         // they're in the return path of the function body.
1717         match ex.kind {
1718             hir::ExprKind::Ret(Some(ex)) => {
1719                 self.returns.push(ex);
1720             }
1721             hir::ExprKind::Block(block, _) if self.in_block_tail => {
1722                 self.in_block_tail = false;
1723                 for stmt in block.stmts {
1724                     hir::intravisit::walk_stmt(self, stmt);
1725                 }
1726                 self.in_block_tail = true;
1727                 if let Some(expr) = block.expr {
1728                     self.visit_expr(expr);
1729                 }
1730             }
1731             hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
1732                 for arm in arms {
1733                     self.visit_expr(arm.body);
1734                 }
1735             }
1736             // We need to walk to find `return`s in the entire body.
1737             _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
1738             _ => self.returns.push(ex),
1739         }
1740     }
1741
1742     fn visit_body(&mut self, body: &'v hir::Body<'v>) {
1743         assert!(!self.in_block_tail);
1744         if body.generator_kind().is_none() {
1745             if let hir::ExprKind::Block(block, None) = body.value.kind {
1746                 if block.expr.is_some() {
1747                     self.in_block_tail = true;
1748                 }
1749             }
1750         }
1751         hir::intravisit::walk_body(self, body);
1752     }
1753 }