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