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