2 ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
6 use crate::infer::InferCtxt;
7 use crate::traits::object_safety::object_safety_violations;
8 use crate::ty::TypeckTables;
9 use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
12 error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
15 use rustc_hir::def_id::DefId;
16 use rustc_hir::intravisit::Visitor;
18 use rustc_span::source_map::SourceMap;
19 use rustc_span::symbol::{kw, sym};
20 use rustc_span::{MultiSpan, Span, DUMMY_SP};
23 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
24 crate fn suggest_restricting_param_bound(
26 mut err: &mut DiagnosticBuilder<'_>,
27 trait_ref: &ty::PolyTraitRef<'_>,
30 let self_ty = trait_ref.self_ty();
31 let (param_ty, projection) = match &self_ty.kind {
32 ty::Param(_) => (true, None),
33 ty::Projection(projection) => (false, Some(projection)),
37 let suggest_restriction =
38 |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
39 let span = generics.where_clause.span_for_predicates_or_empty_place();
40 if !span.from_expansion() && span.desugaring_kind().is_none() {
42 generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
43 &format!("consider further restricting {}", msg),
46 if !generics.where_clause.predicates.is_empty() {
51 trait_ref.without_const().to_predicate(),
53 Applicability::MachineApplicable,
58 // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
59 // don't suggest `T: Sized + ?Sized`.
60 let mut hir_id = body_id;
61 while let Some(node) = self.tcx.hir().find(hir_id) {
63 hir::Node::TraitItem(hir::TraitItem {
65 kind: hir::TraitItemKind::Method(..),
67 }) if param_ty && self_ty == self.tcx.types.self_param => {
68 // Restricting `Self` for a single method.
69 suggest_restriction(&generics, "`Self`", err);
73 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
74 | hir::Node::TraitItem(hir::TraitItem {
76 kind: hir::TraitItemKind::Method(..),
79 | hir::Node::ImplItem(hir::ImplItem {
81 kind: hir::ImplItemKind::Method(..),
84 | hir::Node::Item(hir::Item {
85 kind: hir::ItemKind::Trait(_, _, generics, _, _),
88 | hir::Node::Item(hir::Item {
89 kind: hir::ItemKind::Impl { generics, .. }, ..
90 }) if projection.is_some() => {
91 // Missing associated type bound.
92 suggest_restriction(&generics, "the associated type", err);
96 hir::Node::Item(hir::Item {
97 kind: hir::ItemKind::Struct(_, generics),
101 | hir::Node::Item(hir::Item {
102 kind: hir::ItemKind::Enum(_, generics), span, ..
104 | hir::Node::Item(hir::Item {
105 kind: hir::ItemKind::Union(_, generics),
109 | hir::Node::Item(hir::Item {
110 kind: hir::ItemKind::Trait(_, _, generics, ..),
114 | hir::Node::Item(hir::Item {
115 kind: hir::ItemKind::Impl { generics, .. },
119 | hir::Node::Item(hir::Item {
120 kind: hir::ItemKind::Fn(_, generics, _),
124 | hir::Node::Item(hir::Item {
125 kind: hir::ItemKind::TyAlias(_, generics),
129 | hir::Node::Item(hir::Item {
130 kind: hir::ItemKind::TraitAlias(generics, _),
134 | hir::Node::Item(hir::Item {
135 kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
139 | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
140 | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
143 // Missing generic type parameter bound.
144 let param_name = self_ty.to_string();
145 let constraint = trait_ref.print_only_trait_path().to_string();
146 if suggest_constraining_type_param(
151 self.tcx.sess.source_map(),
158 hir::Node::Crate => return,
163 hir_id = self.tcx.hir().get_parent_item(hir_id);
167 /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
168 /// suggestion to borrow the initializer in order to use have a slice instead.
169 crate fn suggest_borrow_on_unsized_slice(
171 code: &ObligationCauseCode<'tcx>,
172 err: &mut DiagnosticBuilder<'tcx>,
174 if let &ObligationCauseCode::VariableType(hir_id) = code {
175 let parent_node = self.tcx.hir().get_parent_node(hir_id);
176 if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
177 if let Some(ref expr) = local.init {
178 if let hir::ExprKind::Index(_, _) = expr.kind {
179 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
182 "consider borrowing here",
183 format!("&{}", snippet),
184 Applicability::MachineApplicable,
193 /// Given a closure's `DefId`, return the given name of the closure.
195 /// This doesn't account for reassignments, but it's only used for suggestions.
196 crate fn get_closure_name(
199 err: &mut DiagnosticBuilder<'_>,
201 ) -> Option<String> {
203 |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
204 // Get the local name of this closure. This can be inaccurate because
205 // of the possibility of reassignment, but this should be good enough.
207 hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
208 Some(format!("{}", name))
217 let hir = self.tcx.hir();
218 let hir_id = hir.as_local_hir_id(def_id)?;
219 let parent_node = hir.get_parent_node(hir_id);
220 match hir.find(parent_node) {
221 Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
222 get_name(err, &local.pat.kind)
224 // Different to previous arm because one is `&hir::Local` and the other
225 // is `P<hir::Local>`.
226 Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
231 /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
232 /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
233 /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
234 crate fn suggest_fn_call(
236 obligation: &PredicateObligation<'tcx>,
237 err: &mut DiagnosticBuilder<'_>,
238 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
241 let self_ty = trait_ref.self_ty();
242 let (def_id, output_ty, callable) = match self_ty.kind {
243 ty::Closure(def_id, substs) => {
244 (def_id, self.closure_sig(def_id, substs).output(), "closure")
246 ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
249 let msg = format!("use parentheses to call the {}", callable);
251 let obligation = self.mk_obligation_for_def_id(
253 output_ty.skip_binder(),
254 obligation.cause.clone(),
255 obligation.param_env,
258 match self.evaluate_obligation(&obligation) {
259 Ok(EvaluationResult::EvaluatedToOk)
260 | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
261 | Ok(EvaluationResult::EvaluatedToAmbig) => {}
264 let hir = self.tcx.hir();
265 // Get the name of the callable and the arguments to be used in the suggestion.
266 let snippet = match hir.get_if_local(def_id) {
267 Some(hir::Node::Expr(hir::Expr {
268 kind: hir::ExprKind::Closure(_, decl, _, span, ..),
271 err.span_label(*span, "consider calling this closure");
272 let name = match self.get_closure_name(def_id, err, &msg) {
276 let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
277 format!("{}({})", name, args)
279 Some(hir::Node::Item(hir::Item {
281 kind: hir::ItemKind::Fn(.., body_id),
284 err.span_label(ident.span, "consider calling this function");
285 let body = hir.body(*body_id);
289 .map(|arg| match &arg.pat.kind {
290 hir::PatKind::Binding(_, _, ident, None)
291 // FIXME: provide a better suggestion when encountering `SelfLower`, it
292 // should suggest a method call.
293 if ident.name != kw::SelfLower => ident.to_string(),
294 _ => "_".to_string(),
298 format!("{}({})", ident, args)
303 // When the obligation error has been ensured to have been caused by
304 // an argument, the `obligation.cause.span` points at the expression
305 // of the argument, so we can provide a suggestion. This is signaled
306 // by `points_at_arg`. Otherwise, we give a more general note.
308 obligation.cause.span,
311 Applicability::HasPlaceholders,
314 err.help(&format!("{}: `{}`", msg, snippet));
318 crate fn suggest_add_reference_to_arg(
320 obligation: &PredicateObligation<'tcx>,
321 err: &mut DiagnosticBuilder<'tcx>,
322 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
324 has_custom_message: bool,
330 let span = obligation.cause.span;
331 let param_env = obligation.param_env;
332 let trait_ref = trait_ref.skip_binder();
334 if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
335 // Try to apply the original trait binding obligation by borrowing.
336 let self_ty = trait_ref.self_ty();
337 let found = self_ty.to_string();
338 let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
339 let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
340 let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
341 let new_obligation = Obligation::new(
342 ObligationCause::dummy(),
344 new_trait_ref.without_const().to_predicate(),
346 if self.predicate_must_hold_modulo_regions(&new_obligation) {
347 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
348 // We have a very specific type of error, where just borrowing this argument
349 // might solve the problem. In cases like this, the important part is the
350 // original type obligation, not the last one that failed, which is arbitrary.
351 // Because of this, we modify the error to refer to the original obligation and
352 // return early in the caller.
354 "the trait bound `{}: {}` is not satisfied",
356 obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
358 if has_custom_message {
361 err.message = vec![(msg, Style::NoStyle)];
363 if snippet.starts_with('&') {
364 // This is already a literal borrow and the obligation is failing
365 // somewhere else in the obligation chain. Do not suggest non-sense.
371 "expected an implementor of trait `{}`",
372 obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
377 "consider borrowing here",
378 format!("&{}", snippet),
379 Applicability::MaybeIncorrect,
388 /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
389 /// suggest removing these references until we reach a type that implements the trait.
390 crate fn suggest_remove_reference(
392 obligation: &PredicateObligation<'tcx>,
393 err: &mut DiagnosticBuilder<'tcx>,
394 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
396 let trait_ref = trait_ref.skip_binder();
397 let span = obligation.cause.span;
399 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
401 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
403 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
405 // Do not suggest removal of borrow from type arguments.
409 let mut trait_type = trait_ref.self_ty();
411 for refs_remaining in 0..refs_number {
412 if let ty::Ref(_, t_type, _) = trait_type.kind {
415 let new_obligation = self.mk_obligation_for_def_id(
418 ObligationCause::dummy(),
419 obligation.param_env,
422 if self.predicate_may_hold(&new_obligation) {
427 .span_take_while(span, |c| c.is_whitespace() || *c == '&');
429 let remove_refs = refs_remaining + 1;
431 format!("consider removing {} leading `&`-references", remove_refs);
433 err.span_suggestion_short(
437 Applicability::MachineApplicable,
448 /// Check if the trait bound is implemented for a different mutability and note it in the
450 crate fn suggest_change_mut(
452 obligation: &PredicateObligation<'tcx>,
453 err: &mut DiagnosticBuilder<'tcx>,
454 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
457 let span = obligation.cause.span;
458 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
460 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
462 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
464 // Do not suggest removal of borrow from type arguments.
467 let trait_ref = self.resolve_vars_if_possible(trait_ref);
468 if trait_ref.has_infer_types() {
469 // Do not ICE while trying to find if a reborrow would succeed on a trait with
470 // unresolved bindings.
474 if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
475 let trait_type = match mutability {
476 hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
477 hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
480 let new_obligation = self.mk_obligation_for_def_id(
481 trait_ref.skip_binder().def_id,
483 ObligationCause::dummy(),
484 obligation.param_env,
487 if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
493 .span_take_while(span, |c| c.is_whitespace() || *c == '&');
494 if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
497 "consider changing this borrow's mutability",
499 Applicability::MachineApplicable,
503 "`{}` is implemented for `{:?}`, but not for `{:?}`",
504 trait_ref.print_only_trait_path(),
506 trait_ref.skip_binder().self_ty(),
514 crate fn suggest_semicolon_removal(
516 obligation: &PredicateObligation<'tcx>,
517 err: &mut DiagnosticBuilder<'tcx>,
519 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
521 let hir = self.tcx.hir();
522 let parent_node = hir.get_parent_node(obligation.cause.body_id);
523 let node = hir.find(parent_node);
524 if let Some(hir::Node::Item(hir::Item {
525 kind: hir::ItemKind::Fn(sig, _, body_id), ..
528 let body = hir.body(*body_id);
529 if let hir::ExprKind::Block(blk, _) = &body.value.kind {
530 if sig.decl.output.span().overlaps(span)
531 && blk.expr.is_none()
532 && "()" == &trait_ref.self_ty().to_string()
534 // FIXME(estebank): When encountering a method with a trait
535 // bound not satisfied in the return type with a body that has
536 // no return, suggest removal of semicolon on last statement.
537 // Once that is added, close #54771.
538 if let Some(ref stmt) = blk.stmts.last() {
539 let sp = self.tcx.sess.source_map().end_point(stmt.span);
540 err.span_label(sp, "consider removing this semicolon");
547 /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
548 /// applicable and signal that the error has been expanded appropriately and needs to be
550 crate fn suggest_impl_trait(
552 err: &mut DiagnosticBuilder<'tcx>,
554 obligation: &PredicateObligation<'tcx>,
555 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
557 match obligation.cause.code.peel_derives() {
558 // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
559 ObligationCauseCode::SizedReturnType => {}
563 let hir = self.tcx.hir();
564 let parent_node = hir.get_parent_node(obligation.cause.body_id);
565 let node = hir.find(parent_node);
566 let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
567 kind: hir::ItemKind::Fn(sig, _, body_id),
575 let body = hir.body(*body_id);
576 let trait_ref = self.resolve_vars_if_possible(trait_ref);
577 let ty = trait_ref.skip_binder().self_ty();
578 let is_object_safe = match ty.kind {
579 ty::Dynamic(predicates, _) => {
580 // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
583 .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
585 // We only want to suggest `impl Trait` to `dyn Trait`s.
586 // For example, `fn foo() -> str` needs to be filtered out.
590 let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
596 // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
597 // cases like `fn foo() -> (dyn Trait, i32) {}`.
598 // Recursively look for `TraitObject` types and if there's only one, use that span to
599 // suggest `impl Trait`.
601 // Visit to make sure there's a single `return` type to suggest `impl Trait`,
602 // otherwise suggest using `Box<dyn Trait>` or an enum.
603 let mut visitor = ReturnsVisitor::default();
604 visitor.visit_body(&body);
606 let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
608 let mut ret_types = visitor
611 .filter_map(|expr| tables.node_type_opt(expr.hir_id))
612 .map(|ty| self.resolve_vars_if_possible(&ty));
613 let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
615 |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
616 let ty = self.resolve_vars_if_possible(&ty);
617 same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
621 let all_returns_conform_to_trait =
622 if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
623 match ty_ret_ty.kind {
624 ty::Dynamic(predicates, _) => {
625 let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
626 let param_env = ty::ParamEnv::empty();
627 ret_types.all(|returned_ty| {
628 predicates.iter().all(|predicate| {
629 let pred = predicate.with_self_ty(self.tcx, returned_ty);
630 let obl = Obligation::new(cause.clone(), param_env, pred);
631 self.predicate_may_hold(&obl)
641 let (snippet, last_ty) =
642 if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
643 // Verify that we're dealing with a return `dyn Trait`
644 ret_ty.span.overlaps(span),
646 self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
647 // If any of the return types does not conform to the trait, then we can't
648 // suggest `impl Trait` nor trait objects, it is a type mismatch error.
649 all_returns_conform_to_trait,
656 err.code(error_code!(E0746));
657 err.set_primary_message("return type cannot have an unboxed trait object");
658 err.children.clear();
659 let impl_trait_msg = "for information on `impl Trait`, see \
660 <https://doc.rust-lang.org/book/ch10-02-traits.html\
661 #returning-types-that-implement-traits>";
662 let trait_obj_msg = "for information on trait objects, see \
663 <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
664 #using-trait-objects-that-allow-for-values-of-different-types>";
665 let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
666 let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
667 if all_returns_have_same_type {
668 // Suggest `-> impl Trait`.
672 "return `impl {1}` instead, as all return paths are of type `{}`, \
673 which implements `{1}`",
676 format!("impl {}", trait_obj),
677 Applicability::MachineApplicable,
679 err.note(impl_trait_msg);
682 // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
683 // Get all the return values and collect their span and suggestion.
684 let mut suggestions = visitor
692 self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
696 .collect::<Vec<_>>();
697 // Add the suggestion for the return type.
700 format!("Box<{}{}>", if has_dyn { "" } else { "dyn " }, snippet),
702 err.multipart_suggestion(
703 "return a boxed trait object instead",
705 Applicability::MaybeIncorrect,
708 // This is currently not possible to trigger because E0038 takes precedence, but
709 // leave it in for completeness in case anything changes in an earlier stage.
711 "if trait `{}` was object safe, you could return a trait object",
715 err.note(trait_obj_msg);
717 "if all the returned values were of the same type you could use \
718 `impl {}` as the return type",
721 err.note(impl_trait_msg);
722 err.note("you can create a new `enum` with a variant for each returned type");
727 crate fn point_at_returns_when_relevant(
729 err: &mut DiagnosticBuilder<'tcx>,
730 obligation: &PredicateObligation<'tcx>,
732 match obligation.cause.code.peel_derives() {
733 ObligationCauseCode::SizedReturnType => {}
737 let hir = self.tcx.hir();
738 let parent_node = hir.get_parent_node(obligation.cause.body_id);
739 let node = hir.find(parent_node);
740 if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
743 let body = hir.body(*body_id);
744 // Point at all the `return`s in the function as they have failed trait bounds.
745 let mut visitor = ReturnsVisitor::default();
746 visitor.visit_body(&body);
747 let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
748 for expr in &visitor.returns {
749 if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
750 let ty = self.resolve_vars_if_possible(&returned_ty);
751 err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
757 /// Given some node representing a fn-like thing in the HIR map,
758 /// returns a span and `ArgKind` information that describes the
759 /// arguments it expects. This can be supplied to
760 /// `report_arg_count_mismatch`.
761 pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
763 Node::Expr(&hir::Expr {
764 kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
767 self.tcx.sess.source_map().def_span(span),
774 if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
785 .span_to_snippet(pat.span)
787 (snippet, "_".to_owned())
789 .collect::<Vec<_>>(),
793 self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
794 ArgKind::Arg(name, "_".to_owned())
797 .collect::<Vec<ArgKind>>(),
799 Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
800 | Node::ImplItem(&hir::ImplItem {
802 kind: hir::ImplItemKind::Method(ref sig, _),
805 | Node::TraitItem(&hir::TraitItem {
807 kind: hir::TraitItemKind::Method(ref sig, _),
810 self.tcx.sess.source_map().def_span(span),
814 .map(|arg| match arg.clone().kind {
815 hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
817 vec![("_".to_owned(), "_".to_owned()); tys.len()],
819 _ => ArgKind::empty(),
821 .collect::<Vec<ArgKind>>(),
823 Node::Ctor(ref variant_data) => {
824 let span = variant_data
826 .map(|hir_id| self.tcx.hir().span(hir_id))
827 .unwrap_or(DUMMY_SP);
828 let span = self.tcx.sess.source_map().def_span(span);
830 (span, vec![ArgKind::empty(); variant_data.fields().len()])
832 _ => panic!("non-FnLike node found: {:?}", node),
836 /// Reports an error when the number of arguments needed by a
837 /// trait match doesn't match the number that the expression
839 pub fn report_arg_count_mismatch(
842 found_span: Option<Span>,
843 expected_args: Vec<ArgKind>,
844 found_args: Vec<ArgKind>,
846 ) -> DiagnosticBuilder<'tcx> {
847 let kind = if is_closure { "closure" } else { "function" };
849 let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
850 let arg_length = arguments.len();
851 let distinct = match &other[..] {
852 &[ArgKind::Tuple(..)] => true,
855 match (arg_length, arguments.get(0)) {
856 (1, Some(&ArgKind::Tuple(_, ref fields))) => {
857 format!("a single {}-tuple as argument", fields.len())
862 if distinct && arg_length > 1 { "distinct " } else { "" },
863 pluralize!(arg_length)
868 let expected_str = args_str(&expected_args, &found_args);
869 let found_str = args_str(&found_args, &expected_args);
871 let mut err = struct_span_err!(
875 "{} is expected to take {}, but it takes {}",
881 err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
883 if let Some(found_span) = found_span {
884 err.span_label(found_span, format!("takes {}", found_str));
887 // ^^^^^^^^-- def_span
891 let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
895 if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
897 // Suggest to take and ignore the arguments with expected_args_length `_`s if
898 // found arguments is empty (assume the user just wants to ignore args in this case).
899 // For example, if `expected_args_length` is 2, suggest `|_, _|`.
900 if found_args.is_empty() && is_closure {
901 let underscores = vec!["_"; expected_args.len()].join(", ");
905 "consider changing the closure to take and ignore the expected argument{}",
906 if expected_args.len() < 2 { "" } else { "s" }
908 format!("|{}|", underscores),
909 Applicability::MachineApplicable,
913 if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
914 if fields.len() == expected_args.len() {
917 .map(|(name, _)| name.to_owned())
918 .collect::<Vec<String>>()
922 "change the closure to take multiple arguments instead of a single tuple",
923 format!("|{}|", sugg),
924 Applicability::MachineApplicable,
928 if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
929 if fields.len() == found_args.len() && is_closure {
934 .map(|arg| match arg {
935 ArgKind::Arg(name, _) => name.to_owned(),
938 .collect::<Vec<String>>()
940 // add type annotations if available
941 if found_args.iter().any(|arg| match arg {
942 ArgKind::Arg(_, ty) => ty != "_",
949 .map(|(_, ty)| ty.to_owned())
950 .collect::<Vec<String>>()
959 "change the closure to accept a tuple instead of individual arguments",
961 Applicability::MachineApplicable,
970 crate fn report_closure_arg_mismatch(
973 found_span: Option<Span>,
974 expected_ref: ty::PolyTraitRef<'tcx>,
975 found: ty::PolyTraitRef<'tcx>,
976 ) -> DiagnosticBuilder<'tcx> {
977 crate fn build_fn_sig_string<'tcx>(
979 trait_ref: &ty::TraitRef<'tcx>,
981 let inputs = trait_ref.substs.type_at(1);
982 let sig = if let ty::Tuple(inputs) = inputs.kind {
984 inputs.iter().map(|k| k.expect_ty()),
985 tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
987 hir::Unsafety::Normal,
988 ::rustc_target::spec::abi::Abi::Rust,
992 ::std::iter::once(inputs),
993 tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
995 hir::Unsafety::Normal,
996 ::rustc_target::spec::abi::Abi::Rust,
999 ty::Binder::bind(sig).to_string()
1002 let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
1003 let mut err = struct_span_err!(
1007 "type mismatch in {} arguments",
1008 if argument_is_closure { "closure" } else { "function" }
1011 let found_str = format!(
1012 "expected signature of `{}`",
1013 build_fn_sig_string(self.tcx, found.skip_binder())
1015 err.span_label(span, found_str);
1017 let found_span = found_span.unwrap_or(span);
1018 let expected_str = format!(
1019 "found signature of `{}`",
1020 build_fn_sig_string(self.tcx, expected_ref.skip_binder())
1022 err.span_label(found_span, expected_str);
1028 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1029 crate fn suggest_fully_qualified_path(
1031 err: &mut DiagnosticBuilder<'_>,
1036 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
1037 if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
1039 "{}s cannot be accessed directly on a `trait`, they can only be \
1040 accessed through a specific `impl`",
1041 assoc_item.kind.suggestion_descr(),
1043 err.span_suggestion(
1045 "use the fully qualified path to an implementation",
1046 format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
1047 Applicability::HasPlaceholders,
1053 /// Adds an async-await specific note to the diagnostic when the future does not implement
1054 /// an auto trait because of a captured type.
1056 /// ```ignore (diagnostic)
1057 /// note: future does not implement `Qux` as this value is used across an await
1058 /// --> $DIR/issue-64130-3-other.rs:17:5
1060 /// LL | let x = Foo;
1061 /// | - has type `Foo`
1062 /// LL | baz().await;
1063 /// | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1065 /// | - `x` is later dropped here
1068 /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
1069 /// is "replaced" with a different message and a more specific error.
1071 /// ```ignore (diagnostic)
1072 /// error: future cannot be sent between threads safely
1073 /// --> $DIR/issue-64130-2-send.rs:21:5
1075 /// LL | fn is_send<T: Send>(t: T) { }
1076 /// | ------- ---- required by this bound in `is_send`
1078 /// LL | is_send(bar());
1079 /// | ^^^^^^^ future returned by `bar` is not send
1081 /// = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
1082 /// implemented for `Foo`
1083 /// note: future is not send as this value is used across an await
1084 /// --> $DIR/issue-64130-2-send.rs:15:5
1086 /// LL | let x = Foo;
1087 /// | - has type `Foo`
1088 /// LL | baz().await;
1089 /// | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1091 /// | - `x` is later dropped here
1094 /// Returns `true` if an async-await specific note was added to the diagnostic.
1095 crate fn maybe_note_obligation_cause_for_async_await(
1097 err: &mut DiagnosticBuilder<'_>,
1098 obligation: &PredicateObligation<'tcx>,
1101 "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
1102 obligation.cause.span={:?}",
1103 obligation.predicate, obligation.cause.span
1105 let source_map = self.tcx.sess.source_map();
1107 // Attempt to detect an async-await error by looking at the obligation causes, looking
1108 // for a generator to be present.
1110 // When a future does not implement a trait because of a captured type in one of the
1111 // generators somewhere in the call stack, then the result is a chain of obligations.
1113 // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
1114 // future is passed as an argument to a function C which requires a `Send` type, then the
1115 // chain looks something like this:
1117 // - `BuiltinDerivedObligation` with a generator witness (B)
1118 // - `BuiltinDerivedObligation` with a generator (B)
1119 // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
1120 // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1121 // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1122 // - `BuiltinDerivedObligation` with a generator witness (A)
1123 // - `BuiltinDerivedObligation` with a generator (A)
1124 // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
1125 // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1126 // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1127 // - `BindingObligation` with `impl_send (Send requirement)
1129 // The first obligation in the chain is the most useful and has the generator that captured
1130 // the type. The last generator has information about where the bound was introduced. At
1131 // least one generator should be present for this diagnostic to be modified.
1132 let (mut trait_ref, mut target_ty) = match obligation.predicate {
1133 ty::Predicate::Trait(p, _) => {
1134 (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
1138 let mut generator = None;
1139 let mut last_generator = None;
1140 let mut next_code = Some(&obligation.cause.code);
1141 while let Some(code) = next_code {
1142 debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
1144 ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
1145 | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
1146 let ty = derived_obligation.parent_trait_ref.self_ty();
1148 "maybe_note_obligation_cause_for_async_await: \
1149 parent_trait_ref={:?} self_ty.kind={:?}",
1150 derived_obligation.parent_trait_ref, ty.kind
1154 ty::Generator(did, ..) => {
1155 generator = generator.or(Some(did));
1156 last_generator = Some(did);
1158 ty::GeneratorWitness(..) => {}
1159 _ if generator.is_none() => {
1160 trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
1161 target_ty = Some(ty);
1166 next_code = Some(derived_obligation.parent_code.as_ref());
1172 // Only continue if a generator was found.
1174 "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
1176 generator, trait_ref, target_ty
1178 let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
1179 (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
1180 (generator_did, trait_ref, target_ty)
1185 let span = self.tcx.def_span(generator_did);
1187 // Do not ICE on closure typeck (#66868).
1188 if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
1192 // Get the tables from the infcx if the generator is the function we are
1193 // currently type-checking; otherwise, get them by performing a query.
1194 // This is needed to avoid cycles.
1195 let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
1196 let generator_did_root = self.tcx.closure_base_def_id(generator_did);
1198 "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
1199 generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
1202 in_progress_tables.as_ref().map(|t| t.local_id_root),
1206 let tables: &TypeckTables<'tcx> = match &in_progress_tables {
1207 Some(t) if t.local_id_root == Some(generator_did_root) => t,
1209 query_tables = self.tcx.typeck_tables_of(generator_did);
1214 // Look for a type inside the generator interior that matches the target type to get
1216 let target_ty_erased = self.tcx.erase_regions(&target_ty);
1217 let target_span = tables
1218 .generator_interior_types
1220 .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
1221 // Careful: the regions for types that appear in the
1222 // generator interior are not generally known, so we
1223 // want to erase them when comparing (and anyway,
1224 // `Send` and other bounds are generally unaffected by
1225 // the choice of region). When erasing regions, we
1226 // also have to erase late-bound regions. This is
1227 // because the types that appear in the generator
1228 // interior generally contain "bound regions" to
1229 // represent regions that are part of the suspended
1230 // generator frame. Bound regions are preserved by
1231 // `erase_regions` and so we must also call
1232 // `erase_late_bound_regions`.
1233 let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
1234 let ty_erased = self.tcx.erase_regions(&ty_erased);
1235 let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
1237 "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
1238 target_ty_erased={:?} eq={:?}",
1239 ty_erased, target_ty_erased, eq
1243 .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
1244 (span, source_map.span_to_snippet(*span), scope_span, expr)
1248 "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
1249 generator_interior_types={:?} target_span={:?}",
1250 target_ty, tables.generator_interior_types, target_span
1252 if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
1253 self.note_obligation_cause_for_async_await(
1273 /// Unconditionally adds the diagnostic note described in
1274 /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
1275 crate fn note_obligation_cause_for_async_await(
1277 err: &mut DiagnosticBuilder<'_>,
1279 scope_span: &Option<Span>,
1280 expr: Option<hir::HirId>,
1282 first_generator: DefId,
1283 last_generator: Option<DefId>,
1284 trait_ref: ty::TraitRef<'_>,
1285 target_ty: Ty<'tcx>,
1286 tables: &ty::TypeckTables<'_>,
1287 obligation: &PredicateObligation<'tcx>,
1288 next_code: Option<&ObligationCauseCode<'tcx>>,
1290 let source_map = self.tcx.sess.source_map();
1292 let is_async_fn = self
1294 .parent(first_generator)
1295 .map(|parent_did| self.tcx.asyncness(parent_did))
1296 .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
1298 let is_async_move = self
1301 .as_local_hir_id(first_generator)
1302 .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
1303 .map(|body_id| self.tcx.hir().body(body_id))
1304 .and_then(|body| body.generator_kind())
1305 .map(|generator_kind| match generator_kind {
1306 hir::GeneratorKind::Async(..) => true,
1310 let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
1312 // Special case the primary error message when send or sync is the trait that was
1314 let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
1315 let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
1316 let hir = self.tcx.hir();
1317 let trait_explanation = if is_send || is_sync {
1318 let (trait_name, trait_verb) =
1319 if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
1322 err.set_primary_message(format!(
1323 "future cannot be {} between threads safely",
1327 let original_span = err.span.primary_span().unwrap();
1328 let mut span = MultiSpan::from_span(original_span);
1330 let message = if let Some(name) = last_generator
1331 .and_then(|generator_did| self.tcx.parent(generator_did))
1332 .and_then(|parent_did| hir.as_local_hir_id(parent_did))
1333 .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
1335 format!("future returned by `{}` is not {}", name, trait_name)
1337 format!("future is not {}", trait_name)
1340 span.push_span_label(original_span, message);
1343 format!("is not {}", trait_name)
1345 format!("does not implement `{}`", trait_ref.print_only_trait_path())
1348 // Look at the last interior type to get a span for the `.await`.
1349 let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
1350 let mut span = MultiSpan::from_span(await_span);
1351 span.push_span_label(
1353 format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
1356 span.push_span_label(target_span, format!("has type `{}`", target_ty));
1358 // If available, use the scope span to annotate the drop location.
1359 if let Some(scope_span) = scope_span {
1360 span.push_span_label(
1361 source_map.end_point(*scope_span),
1362 format!("`{}` is later dropped here", snippet),
1369 "future {} as this value is used across an {}",
1370 trait_explanation, await_or_yield,
1374 if let Some(expr_id) = expr {
1375 let expr = hir.expect_expr(expr_id);
1376 let is_ref = tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
1377 let parent = hir.get_parent_node(expr_id);
1378 if let Some(hir::Node::Expr(e)) = hir.find(parent) {
1379 let method_span = hir.span(parent);
1380 if tables.is_method_call(e) && is_ref {
1383 "consider moving this method call into a `let` \
1384 binding to create a shorter lived borrow",
1390 // Add a note for the item obligation that remains - normally a note pointing to the
1391 // bound that introduced the obligation (e.g. `T: Send`).
1392 debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
1393 self.note_obligation_cause_code(
1395 &obligation.predicate,
1401 crate fn note_obligation_cause_code<T>(
1403 err: &mut DiagnosticBuilder<'_>,
1405 cause_code: &ObligationCauseCode<'tcx>,
1406 obligated_types: &mut Vec<&ty::TyS<'tcx>>,
1412 ObligationCauseCode::ExprAssignable
1413 | ObligationCauseCode::MatchExpressionArm { .. }
1414 | ObligationCauseCode::Pattern { .. }
1415 | ObligationCauseCode::IfExpression { .. }
1416 | ObligationCauseCode::IfExpressionWithNoElse
1417 | ObligationCauseCode::MainFunctionType
1418 | ObligationCauseCode::StartFunctionType
1419 | ObligationCauseCode::IntrinsicType
1420 | ObligationCauseCode::MethodReceiver
1421 | ObligationCauseCode::ReturnNoExpression
1422 | ObligationCauseCode::MiscObligation => {}
1423 ObligationCauseCode::SliceOrArrayElem => {
1424 err.note("slice and array elements must have `Sized` type");
1426 ObligationCauseCode::TupleElem => {
1427 err.note("only the last element of a tuple may have a dynamically sized type");
1429 ObligationCauseCode::ProjectionWf(data) => {
1430 err.note(&format!("required so that the projection `{}` is well-formed", data,));
1432 ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
1434 "required so that reference `{}` does not outlive its referent",
1438 ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
1440 "required so that the lifetime bound of `{}` for `{}` is satisfied",
1444 ObligationCauseCode::ItemObligation(item_def_id) => {
1445 let item_name = tcx.def_path_str(item_def_id);
1446 let msg = format!("required by `{}`", item_name);
1448 if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
1449 let sp = tcx.sess.source_map().def_span(sp);
1450 err.span_label(sp, &msg);
1455 ObligationCauseCode::BindingObligation(item_def_id, span) => {
1456 let item_name = tcx.def_path_str(item_def_id);
1457 let msg = format!("required by this bound in `{}`", item_name);
1458 if let Some(ident) = tcx.opt_item_name(item_def_id) {
1459 err.span_label(ident.span, "");
1461 if span != DUMMY_SP {
1462 err.span_label(span, &msg);
1467 ObligationCauseCode::ObjectCastObligation(object_ty) => {
1469 "required for the cast to the object type `{}`",
1470 self.ty_to_string(object_ty)
1473 ObligationCauseCode::Coercion { source: _, target } => {
1474 err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
1476 ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
1478 "the `Copy` trait is required because the repeated element will be copied",
1480 if suggest_const_in_array_repeat_expressions {
1482 "this array initializer can be evaluated at compile-time, for more \
1483 information, see issue \
1484 https://github.com/rust-lang/rust/issues/49147",
1486 if tcx.sess.opts.unstable_features.is_nightly_build() {
1488 "add `#![feature(const_in_array_repeat_expressions)]` to the \
1489 crate attributes to enable",
1494 ObligationCauseCode::VariableType(_) => {
1495 err.note("all local variables must have a statically known size");
1496 if !self.tcx.features().unsized_locals {
1497 err.help("unsized locals are gated as an unstable feature");
1500 ObligationCauseCode::SizedArgumentType => {
1501 err.note("all function arguments must have a statically known size");
1502 if !self.tcx.features().unsized_locals {
1503 err.help("unsized locals are gated as an unstable feature");
1506 ObligationCauseCode::SizedReturnType => {
1507 err.note("the return type of a function must have a statically known size");
1509 ObligationCauseCode::SizedYieldType => {
1510 err.note("the yield type of a generator must have a statically known size");
1512 ObligationCauseCode::AssignmentLhsSized => {
1513 err.note("the left-hand-side of an assignment must have a statically known size");
1515 ObligationCauseCode::TupleInitializerSized => {
1516 err.note("tuples must have a statically known size to be initialized");
1518 ObligationCauseCode::StructInitializerSized => {
1519 err.note("structs must have a statically known size to be initialized");
1521 ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
1522 AdtKind::Struct => {
1525 "the last field of a packed struct may only have a \
1526 dynamically sized type if it does not need drop to be run",
1530 "only the last field of a struct may have a dynamically sized type",
1535 err.note("no field of a union may have a dynamically sized type");
1538 err.note("no field of an enum variant may have a dynamically sized type");
1541 ObligationCauseCode::ConstSized => {
1542 err.note("constant expressions must have a statically known size");
1544 ObligationCauseCode::ConstPatternStructural => {
1545 err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
1547 ObligationCauseCode::SharedStatic => {
1548 err.note("shared static variables must have a type that implements `Sync`");
1550 ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
1551 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1552 let ty = parent_trait_ref.skip_binder().self_ty();
1553 err.note(&format!("required because it appears within the type `{}`", ty));
1554 obligated_types.push(ty);
1556 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1557 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
1558 self.note_obligation_cause_code(
1566 ObligationCauseCode::ImplDerivedObligation(ref data) => {
1567 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1569 "required because of the requirements on the impl of `{}` for `{}`",
1570 parent_trait_ref.print_only_trait_path(),
1571 parent_trait_ref.skip_binder().self_ty()
1573 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1574 self.note_obligation_cause_code(
1581 ObligationCauseCode::CompareImplMethodObligation { .. } => {
1583 "the requirement `{}` appears on the impl method \
1584 but not on the corresponding trait method",
1588 ObligationCauseCode::CompareImplTypeObligation { .. } => {
1590 "the requirement `{}` appears on the associated impl type \
1591 but not on the corresponding associated trait type",
1595 ObligationCauseCode::ReturnType
1596 | ObligationCauseCode::ReturnValue(_)
1597 | ObligationCauseCode::BlockTailExpression(_) => (),
1598 ObligationCauseCode::TrivialBound => {
1599 err.help("see issue #48214");
1600 if tcx.sess.opts.unstable_features.is_nightly_build() {
1601 err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
1604 ObligationCauseCode::AssocTypeBound(ref data) => {
1605 err.span_label(data.original, "associated type defined here");
1606 if let Some(sp) = data.impl_span {
1607 err.span_label(sp, "in this `impl` item");
1609 for sp in &data.bounds {
1610 err.span_label(*sp, "restricted in this bound");
1616 crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
1617 let current_limit = self.tcx.sess.recursion_limit.get();
1618 let suggested_limit = current_limit * 2;
1620 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
1626 /// Suggest restricting a type param with a new bound.
1627 pub fn suggest_constraining_type_param(
1628 generics: &hir::Generics<'_>,
1629 err: &mut DiagnosticBuilder<'_>,
1632 source_map: &SourceMap,
1635 let restrict_msg = "consider further restricting this bound";
1636 if let Some(param) =
1637 generics.params.iter().filter(|p| p.name.ident().as_str() == param_name).next()
1639 if param_name.starts_with("impl ") {
1640 // `impl Trait` in argument:
1641 // `fn foo(x: impl Trait) {}` → `fn foo(t: impl Trait + Trait2) {}`
1642 err.span_suggestion(
1645 // `impl CurrentTrait + MissingTrait`
1646 format!("{} + {}", param_name, constraint),
1647 Applicability::MachineApplicable,
1649 } else if generics.where_clause.predicates.is_empty() && param.bounds.is_empty() {
1650 // If there are no bounds whatsoever, suggest adding a constraint
1651 // to the type parameter:
1652 // `fn foo<T>(t: T) {}` → `fn foo<T: Trait>(t: T) {}`
1653 err.span_suggestion(
1655 "consider restricting this bound",
1656 format!("{}: {}", param_name, constraint),
1657 Applicability::MachineApplicable,
1659 } else if !generics.where_clause.predicates.is_empty() {
1660 // There is a `where` clause, so suggest expanding it:
1661 // `fn foo<T>(t: T) where T: Debug {}` →
1662 // `fn foo<T>(t: T) where T: Debug, T: Trait {}`
1663 err.span_suggestion(
1664 generics.where_clause.span().unwrap().shrink_to_hi(),
1665 &format!("consider further restricting type parameter `{}`", param_name),
1666 format!(", {}: {}", param_name, constraint),
1667 Applicability::MachineApplicable,
1670 // If there is no `where` clause lean towards constraining to the
1672 // `fn foo<X: Bar, T>(t: T, x: X) {}` → `fn foo<T: Trait>(t: T) {}`
1673 // `fn foo<T: Bar>(t: T) {}` → `fn foo<T: Bar + Trait>(t: T) {}`
1674 let sp = param.span.with_hi(span.hi());
1675 let span = source_map.span_through_char(sp, ':');
1676 if sp != param.span && sp != span {
1677 // Only suggest if we have high certainty that the span
1678 // covers the colon in `foo<T: Trait>`.
1679 err.span_suggestion(
1682 format!("{}: {} + ", param_name, constraint),
1683 Applicability::MachineApplicable,
1688 &format!("consider adding a `where {}: {}` bound", param_name, constraint),
1697 /// Collect all the returned expressions within the input expression.
1698 /// Used to point at the return spans when we want to suggest some change to them.
1700 struct ReturnsVisitor<'v> {
1701 returns: Vec<&'v hir::Expr<'v>>,
1702 in_block_tail: bool,
1705 impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
1706 type Map = rustc::hir::map::Map<'v>;
1708 fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
1709 hir::intravisit::NestedVisitorMap::None
1712 fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
1713 // Visit every expression to detect `return` paths, either through the function's tail
1714 // expression or `return` statements. We walk all nodes to find `return` statements, but
1715 // we only care about tail expressions when `in_block_tail` is `true`, which means that
1716 // they're in the return path of the function body.
1718 hir::ExprKind::Ret(Some(ex)) => {
1719 self.returns.push(ex);
1721 hir::ExprKind::Block(block, _) if self.in_block_tail => {
1722 self.in_block_tail = false;
1723 for stmt in block.stmts {
1724 hir::intravisit::walk_stmt(self, stmt);
1726 self.in_block_tail = true;
1727 if let Some(expr) = block.expr {
1728 self.visit_expr(expr);
1731 hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
1733 self.visit_expr(arm.body);
1736 // We need to walk to find `return`s in the entire body.
1737 _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
1738 _ => self.returns.push(ex),
1742 fn visit_body(&mut self, body: &'v hir::Body<'v>) {
1743 assert!(!self.in_block_tail);
1744 if body.generator_kind().is_none() {
1745 if let hir::ExprKind::Block(block, None) = body.value.kind {
1746 if block.expr.is_some() {
1747 self.in_block_tail = true;
1751 hir::intravisit::walk_body(self, body);