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