2 ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode,
6 use crate::infer::InferCtxt;
7 use crate::traits::error_reporting::suggest_constraining_type_param;
8 use crate::traits::object_safety::object_safety_violations;
10 use rustc::ty::TypeckTables;
11 use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
13 error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style,
16 use rustc_hir::def::DefKind;
17 use rustc_hir::def_id::DefId;
18 use rustc_hir::intravisit::Visitor;
20 use rustc_span::symbol::{kw, sym};
21 use rustc_span::{MultiSpan, Span, DUMMY_SP};
24 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
25 crate fn suggest_restricting_param_bound(
27 mut err: &mut DiagnosticBuilder<'_>,
28 trait_ref: &ty::PolyTraitRef<'_>,
31 let self_ty = trait_ref.self_ty();
32 let (param_ty, projection) = match &self_ty.kind {
33 ty::Param(_) => (true, None),
34 ty::Projection(projection) => (false, Some(projection)),
38 let suggest_restriction =
39 |generics: &hir::Generics<'_>, msg, err: &mut DiagnosticBuilder<'_>| {
40 let span = generics.where_clause.span_for_predicates_or_empty_place();
41 if !span.from_expansion() && span.desugaring_kind().is_none() {
43 generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(),
44 &format!("consider further restricting {}", msg),
47 if !generics.where_clause.predicates.is_empty() {
52 trait_ref.without_const().to_predicate(),
54 Applicability::MachineApplicable,
59 // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we
60 // don't suggest `T: Sized + ?Sized`.
61 let mut hir_id = body_id;
62 while let Some(node) = self.tcx.hir().find(hir_id) {
64 hir::Node::TraitItem(hir::TraitItem {
66 kind: hir::TraitItemKind::Method(..),
68 }) if param_ty && self_ty == self.tcx.types.self_param => {
69 // Restricting `Self` for a single method.
70 suggest_restriction(&generics, "`Self`", err);
74 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. })
75 | hir::Node::TraitItem(hir::TraitItem {
77 kind: hir::TraitItemKind::Method(..),
80 | hir::Node::ImplItem(hir::ImplItem {
82 kind: hir::ImplItemKind::Method(..),
85 | hir::Node::Item(hir::Item {
86 kind: hir::ItemKind::Trait(_, _, generics, _, _),
89 | hir::Node::Item(hir::Item {
90 kind: hir::ItemKind::Impl { generics, .. }, ..
91 }) if projection.is_some() => {
92 // Missing associated type bound.
93 suggest_restriction(&generics, "the associated type", err);
97 hir::Node::Item(hir::Item {
98 kind: hir::ItemKind::Struct(_, generics),
102 | hir::Node::Item(hir::Item {
103 kind: hir::ItemKind::Enum(_, generics), span, ..
105 | hir::Node::Item(hir::Item {
106 kind: hir::ItemKind::Union(_, generics),
110 | hir::Node::Item(hir::Item {
111 kind: hir::ItemKind::Trait(_, _, generics, ..),
115 | hir::Node::Item(hir::Item {
116 kind: hir::ItemKind::Impl { generics, .. },
120 | hir::Node::Item(hir::Item {
121 kind: hir::ItemKind::Fn(_, generics, _),
125 | hir::Node::Item(hir::Item {
126 kind: hir::ItemKind::TyAlias(_, generics),
130 | hir::Node::Item(hir::Item {
131 kind: hir::ItemKind::TraitAlias(generics, _),
135 | hir::Node::Item(hir::Item {
136 kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }),
140 | hir::Node::TraitItem(hir::TraitItem { generics, span, .. })
141 | hir::Node::ImplItem(hir::ImplItem { generics, span, .. })
144 // Missing generic type parameter bound.
145 let param_name = self_ty.to_string();
146 let constraint = trait_ref.print_only_trait_path().to_string();
147 if suggest_constraining_type_param(
153 self.tcx.sess.source_map(),
155 Some(trait_ref.def_id()),
161 hir::Node::Crate => return,
166 hir_id = self.tcx.hir().get_parent_item(hir_id);
170 /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a
171 /// suggestion to borrow the initializer in order to use have a slice instead.
172 crate fn suggest_borrow_on_unsized_slice(
174 code: &ObligationCauseCode<'tcx>,
175 err: &mut DiagnosticBuilder<'tcx>,
177 if let &ObligationCauseCode::VariableType(hir_id) = code {
178 let parent_node = self.tcx.hir().get_parent_node(hir_id);
179 if let Some(Node::Local(ref local)) = self.tcx.hir().find(parent_node) {
180 if let Some(ref expr) = local.init {
181 if let hir::ExprKind::Index(_, _) = expr.kind {
182 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(expr.span) {
185 "consider borrowing here",
186 format!("&{}", snippet),
187 Applicability::MachineApplicable,
196 /// Given a closure's `DefId`, return the given name of the closure.
198 /// This doesn't account for reassignments, but it's only used for suggestions.
199 crate fn get_closure_name(
202 err: &mut DiagnosticBuilder<'_>,
204 ) -> Option<String> {
206 |err: &mut DiagnosticBuilder<'_>, kind: &hir::PatKind<'_>| -> Option<String> {
207 // Get the local name of this closure. This can be inaccurate because
208 // of the possibility of reassignment, but this should be good enough.
210 hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, name, None) => {
211 Some(format!("{}", name))
220 let hir = self.tcx.hir();
221 let hir_id = hir.as_local_hir_id(def_id)?;
222 let parent_node = hir.get_parent_node(hir_id);
223 match hir.find(parent_node) {
224 Some(hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. })) => {
225 get_name(err, &local.pat.kind)
227 // Different to previous arm because one is `&hir::Local` and the other
228 // is `P<hir::Local>`.
229 Some(hir::Node::Local(local)) => get_name(err, &local.pat.kind),
234 /// We tried to apply the bound to an `fn` or closure. Check whether calling it would
235 /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling
236 /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`.
237 crate fn suggest_fn_call(
239 obligation: &PredicateObligation<'tcx>,
240 err: &mut DiagnosticBuilder<'_>,
241 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
244 let self_ty = trait_ref.self_ty();
245 let (def_id, output_ty, callable) = match self_ty.kind {
246 ty::Closure(def_id, substs) => {
247 (def_id, self.closure_sig(def_id, substs).output(), "closure")
249 ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
252 let msg = format!("use parentheses to call the {}", callable);
254 let obligation = self.mk_obligation_for_def_id(
256 output_ty.skip_binder(),
257 obligation.cause.clone(),
258 obligation.param_env,
261 match self.evaluate_obligation(&obligation) {
262 Ok(EvaluationResult::EvaluatedToOk)
263 | Ok(EvaluationResult::EvaluatedToOkModuloRegions)
264 | Ok(EvaluationResult::EvaluatedToAmbig) => {}
267 let hir = self.tcx.hir();
268 // Get the name of the callable and the arguments to be used in the suggestion.
269 let snippet = match hir.get_if_local(def_id) {
270 Some(hir::Node::Expr(hir::Expr {
271 kind: hir::ExprKind::Closure(_, decl, _, span, ..),
274 err.span_label(*span, "consider calling this closure");
275 let name = match self.get_closure_name(def_id, err, &msg) {
279 let args = decl.inputs.iter().map(|_| "_").collect::<Vec<_>>().join(", ");
280 format!("{}({})", name, args)
282 Some(hir::Node::Item(hir::Item {
284 kind: hir::ItemKind::Fn(.., body_id),
287 err.span_label(ident.span, "consider calling this function");
288 let body = hir.body(*body_id);
292 .map(|arg| match &arg.pat.kind {
293 hir::PatKind::Binding(_, _, ident, None)
294 // FIXME: provide a better suggestion when encountering `SelfLower`, it
295 // should suggest a method call.
296 if ident.name != kw::SelfLower => ident.to_string(),
297 _ => "_".to_string(),
301 format!("{}({})", ident, args)
306 // When the obligation error has been ensured to have been caused by
307 // an argument, the `obligation.cause.span` points at the expression
308 // of the argument, so we can provide a suggestion. This is signaled
309 // by `points_at_arg`. Otherwise, we give a more general note.
311 obligation.cause.span,
314 Applicability::HasPlaceholders,
317 err.help(&format!("{}: `{}`", msg, snippet));
321 crate fn suggest_add_reference_to_arg(
323 obligation: &PredicateObligation<'tcx>,
324 err: &mut DiagnosticBuilder<'tcx>,
325 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
327 has_custom_message: bool,
333 let span = obligation.cause.span;
334 let param_env = obligation.param_env;
335 let trait_ref = trait_ref.skip_binder();
337 if let ObligationCauseCode::ImplDerivedObligation(obligation) = &obligation.cause.code {
338 // Try to apply the original trait binding obligation by borrowing.
339 let self_ty = trait_ref.self_ty();
340 let found = self_ty.to_string();
341 let new_self_ty = self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, self_ty);
342 let substs = self.tcx.mk_substs_trait(new_self_ty, &[]);
343 let new_trait_ref = ty::TraitRef::new(obligation.parent_trait_ref.def_id(), substs);
344 let new_obligation = Obligation::new(
345 ObligationCause::dummy(),
347 new_trait_ref.without_const().to_predicate(),
349 if self.predicate_must_hold_modulo_regions(&new_obligation) {
350 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
351 // We have a very specific type of error, where just borrowing this argument
352 // might solve the problem. In cases like this, the important part is the
353 // original type obligation, not the last one that failed, which is arbitrary.
354 // Because of this, we modify the error to refer to the original obligation and
355 // return early in the caller.
357 "the trait bound `{}: {}` is not satisfied",
359 obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
361 if has_custom_message {
364 err.message = vec![(msg, Style::NoStyle)];
366 if snippet.starts_with('&') {
367 // This is already a literal borrow and the obligation is failing
368 // somewhere else in the obligation chain. Do not suggest non-sense.
374 "expected an implementor of trait `{}`",
375 obligation.parent_trait_ref.skip_binder().print_only_trait_path(),
380 "consider borrowing here",
381 format!("&{}", snippet),
382 Applicability::MaybeIncorrect,
391 /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`,
392 /// suggest removing these references until we reach a type that implements the trait.
393 crate fn suggest_remove_reference(
395 obligation: &PredicateObligation<'tcx>,
396 err: &mut DiagnosticBuilder<'tcx>,
397 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
399 let trait_ref = trait_ref.skip_binder();
400 let span = obligation.cause.span;
402 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
404 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
406 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
408 // Do not suggest removal of borrow from type arguments.
412 let mut trait_type = trait_ref.self_ty();
414 for refs_remaining in 0..refs_number {
415 if let ty::Ref(_, t_type, _) = trait_type.kind {
418 let new_obligation = self.mk_obligation_for_def_id(
421 ObligationCause::dummy(),
422 obligation.param_env,
425 if self.predicate_may_hold(&new_obligation) {
430 .span_take_while(span, |c| c.is_whitespace() || *c == '&');
432 let remove_refs = refs_remaining + 1;
434 let msg = if remove_refs == 1 {
435 "consider removing the leading `&`-reference".to_string()
437 format!("consider removing {} leading `&`-references", remove_refs)
440 err.span_suggestion_short(
444 Applicability::MachineApplicable,
455 /// Check if the trait bound is implemented for a different mutability and note it in the
457 crate fn suggest_change_mut(
459 obligation: &PredicateObligation<'tcx>,
460 err: &mut DiagnosticBuilder<'tcx>,
461 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
464 let span = obligation.cause.span;
465 if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
467 snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count();
469 snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next()
471 // Do not suggest removal of borrow from type arguments.
474 let trait_ref = self.resolve_vars_if_possible(trait_ref);
475 if trait_ref.has_infer_types() {
476 // Do not ICE while trying to find if a reborrow would succeed on a trait with
477 // unresolved bindings.
481 if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind {
482 let trait_type = match mutability {
483 hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type),
484 hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type),
487 let new_obligation = self.mk_obligation_for_def_id(
488 trait_ref.skip_binder().def_id,
490 ObligationCause::dummy(),
491 obligation.param_env,
494 if self.evaluate_obligation_no_overflow(&new_obligation).must_apply_modulo_regions()
500 .span_take_while(span, |c| c.is_whitespace() || *c == '&');
501 if points_at_arg && mutability == hir::Mutability::Not && refs_number > 0 {
504 "consider changing this borrow's mutability",
506 Applicability::MachineApplicable,
510 "`{}` is implemented for `{:?}`, but not for `{:?}`",
511 trait_ref.print_only_trait_path(),
513 trait_ref.skip_binder().self_ty(),
521 crate fn suggest_semicolon_removal(
523 obligation: &PredicateObligation<'tcx>,
524 err: &mut DiagnosticBuilder<'tcx>,
526 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
528 let hir = self.tcx.hir();
529 let parent_node = hir.get_parent_node(obligation.cause.body_id);
530 let node = hir.find(parent_node);
531 if let Some(hir::Node::Item(hir::Item {
532 kind: hir::ItemKind::Fn(sig, _, body_id), ..
535 let body = hir.body(*body_id);
536 if let hir::ExprKind::Block(blk, _) = &body.value.kind {
537 if sig.decl.output.span().overlaps(span)
538 && blk.expr.is_none()
539 && "()" == &trait_ref.self_ty().to_string()
541 // FIXME(estebank): When encountering a method with a trait
542 // bound not satisfied in the return type with a body that has
543 // no return, suggest removal of semicolon on last statement.
544 // Once that is added, close #54771.
545 if let Some(ref stmt) = blk.stmts.last() {
546 let sp = self.tcx.sess.source_map().end_point(stmt.span);
547 err.span_label(sp, "consider removing this semicolon");
554 /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if
555 /// applicable and signal that the error has been expanded appropriately and needs to be
557 crate fn suggest_impl_trait(
559 err: &mut DiagnosticBuilder<'tcx>,
561 obligation: &PredicateObligation<'tcx>,
562 trait_ref: &ty::Binder<ty::TraitRef<'tcx>>,
564 match obligation.cause.code.peel_derives() {
565 // Only suggest `impl Trait` if the return type is unsized because it is `dyn Trait`.
566 ObligationCauseCode::SizedReturnType => {}
570 let hir = self.tcx.hir();
571 let parent_node = hir.get_parent_node(obligation.cause.body_id);
572 let node = hir.find(parent_node);
573 let (sig, body_id) = if let Some(hir::Node::Item(hir::Item {
574 kind: hir::ItemKind::Fn(sig, _, body_id),
582 let body = hir.body(*body_id);
583 let trait_ref = self.resolve_vars_if_possible(trait_ref);
584 let ty = trait_ref.skip_binder().self_ty();
585 let is_object_safe = match ty.kind {
586 ty::Dynamic(predicates, _) => {
587 // If the `dyn Trait` is not object safe, do not suggest `Box<dyn Trait>`.
590 .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty())
592 // We only want to suggest `impl Trait` to `dyn Trait`s.
593 // For example, `fn foo() -> str` needs to be filtered out.
597 let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output {
603 // Use `TypeVisitor` instead of the output type directly to find the span of `ty` for
604 // cases like `fn foo() -> (dyn Trait, i32) {}`.
605 // Recursively look for `TraitObject` types and if there's only one, use that span to
606 // suggest `impl Trait`.
608 // Visit to make sure there's a single `return` type to suggest `impl Trait`,
609 // otherwise suggest using `Box<dyn Trait>` or an enum.
610 let mut visitor = ReturnsVisitor::default();
611 visitor.visit_body(&body);
613 let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
615 let mut ret_types = visitor
618 .filter_map(|expr| tables.node_type_opt(expr.hir_id))
619 .map(|ty| self.resolve_vars_if_possible(&ty));
620 let (last_ty, all_returns_have_same_type) = ret_types.clone().fold(
622 |(last_ty, mut same): (std::option::Option<Ty<'_>>, bool), ty| {
623 let ty = self.resolve_vars_if_possible(&ty);
624 same &= last_ty.map_or(true, |last_ty| last_ty == ty) && ty.kind != ty::Error;
628 let all_returns_conform_to_trait =
629 if let Some(ty_ret_ty) = tables.node_type_opt(ret_ty.hir_id) {
630 match ty_ret_ty.kind {
631 ty::Dynamic(predicates, _) => {
632 let cause = ObligationCause::misc(ret_ty.span, ret_ty.hir_id);
633 let param_env = ty::ParamEnv::empty();
634 ret_types.all(|returned_ty| {
635 predicates.iter().all(|predicate| {
636 let pred = predicate.with_self_ty(self.tcx, returned_ty);
637 let obl = Obligation::new(cause.clone(), param_env, pred);
638 self.predicate_may_hold(&obl)
648 let (snippet, last_ty) =
649 if let (true, hir::TyKind::TraitObject(..), Ok(snippet), true, Some(last_ty)) = (
650 // Verify that we're dealing with a return `dyn Trait`
651 ret_ty.span.overlaps(span),
653 self.tcx.sess.source_map().span_to_snippet(ret_ty.span),
654 // If any of the return types does not conform to the trait, then we can't
655 // suggest `impl Trait` nor trait objects, it is a type mismatch error.
656 all_returns_conform_to_trait,
663 err.code(error_code!(E0746));
664 err.set_primary_message("return type cannot have an unboxed trait object");
665 err.children.clear();
666 let impl_trait_msg = "for information on `impl Trait`, see \
667 <https://doc.rust-lang.org/book/ch10-02-traits.html\
668 #returning-types-that-implement-traits>";
669 let trait_obj_msg = "for information on trait objects, see \
670 <https://doc.rust-lang.org/book/ch17-02-trait-objects.html\
671 #using-trait-objects-that-allow-for-values-of-different-types>";
672 let has_dyn = snippet.split_whitespace().next().map_or(false, |s| s == "dyn");
673 let trait_obj = if has_dyn { &snippet[4..] } else { &snippet[..] };
674 if all_returns_have_same_type {
675 // Suggest `-> impl Trait`.
679 "return `impl {1}` instead, as all return paths are of type `{}`, \
680 which implements `{1}`",
683 format!("impl {}", trait_obj),
684 Applicability::MachineApplicable,
686 err.note(impl_trait_msg);
689 // Suggest `-> Box<dyn Trait>` and `Box::new(returned_value)`.
690 // Get all the return values and collect their span and suggestion.
691 let mut suggestions = visitor
699 self.tcx.sess.source_map().span_to_snippet(expr.span).unwrap()
703 .collect::<Vec<_>>();
704 // Add the suggestion for the return type.
705 suggestions.push((ret_ty.span, format!("Box<dyn {}>", trait_obj)));
706 err.multipart_suggestion(
707 "return a boxed trait object instead",
709 Applicability::MaybeIncorrect,
712 // This is currently not possible to trigger because E0038 takes precedence, but
713 // leave it in for completeness in case anything changes in an earlier stage.
715 "if trait `{}` was object safe, you could return a trait object",
719 err.note(trait_obj_msg);
721 "if all the returned values were of the same type you could use \
722 `impl {}` as the return type",
725 err.note(impl_trait_msg);
726 err.note("you can create a new `enum` with a variant for each returned type");
731 crate fn point_at_returns_when_relevant(
733 err: &mut DiagnosticBuilder<'tcx>,
734 obligation: &PredicateObligation<'tcx>,
736 match obligation.cause.code.peel_derives() {
737 ObligationCauseCode::SizedReturnType => {}
741 let hir = self.tcx.hir();
742 let parent_node = hir.get_parent_node(obligation.cause.body_id);
743 let node = hir.find(parent_node);
744 if let Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) =
747 let body = hir.body(*body_id);
748 // Point at all the `return`s in the function as they have failed trait bounds.
749 let mut visitor = ReturnsVisitor::default();
750 visitor.visit_body(&body);
751 let tables = self.in_progress_tables.map(|t| t.borrow()).unwrap();
752 for expr in &visitor.returns {
753 if let Some(returned_ty) = tables.node_type_opt(expr.hir_id) {
754 let ty = self.resolve_vars_if_possible(&returned_ty);
755 err.span_label(expr.span, &format!("this returned value is of type `{}`", ty));
761 /// Given some node representing a fn-like thing in the HIR map,
762 /// returns a span and `ArgKind` information that describes the
763 /// arguments it expects. This can be supplied to
764 /// `report_arg_count_mismatch`.
765 pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
767 Node::Expr(&hir::Expr {
768 kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
771 self.tcx.sess.source_map().def_span(span),
778 if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
789 .span_to_snippet(pat.span)
791 (snippet, "_".to_owned())
793 .collect::<Vec<_>>(),
797 self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
798 ArgKind::Arg(name, "_".to_owned())
801 .collect::<Vec<ArgKind>>(),
803 Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
804 | Node::ImplItem(&hir::ImplItem {
806 kind: hir::ImplItemKind::Method(ref sig, _),
809 | Node::TraitItem(&hir::TraitItem {
811 kind: hir::TraitItemKind::Method(ref sig, _),
814 self.tcx.sess.source_map().def_span(span),
818 .map(|arg| match arg.clone().kind {
819 hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
821 vec![("_".to_owned(), "_".to_owned()); tys.len()],
823 _ => ArgKind::empty(),
825 .collect::<Vec<ArgKind>>(),
827 Node::Ctor(ref variant_data) => {
828 let span = variant_data
830 .map(|hir_id| self.tcx.hir().span(hir_id))
831 .unwrap_or(DUMMY_SP);
832 let span = self.tcx.sess.source_map().def_span(span);
834 (span, vec![ArgKind::empty(); variant_data.fields().len()])
836 _ => panic!("non-FnLike node found: {:?}", node),
840 /// Reports an error when the number of arguments needed by a
841 /// trait match doesn't match the number that the expression
843 pub fn report_arg_count_mismatch(
846 found_span: Option<Span>,
847 expected_args: Vec<ArgKind>,
848 found_args: Vec<ArgKind>,
850 ) -> DiagnosticBuilder<'tcx> {
851 let kind = if is_closure { "closure" } else { "function" };
853 let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
854 let arg_length = arguments.len();
855 let distinct = match &other[..] {
856 &[ArgKind::Tuple(..)] => true,
859 match (arg_length, arguments.get(0)) {
860 (1, Some(&ArgKind::Tuple(_, ref fields))) => {
861 format!("a single {}-tuple as argument", fields.len())
866 if distinct && arg_length > 1 { "distinct " } else { "" },
867 pluralize!(arg_length)
872 let expected_str = args_str(&expected_args, &found_args);
873 let found_str = args_str(&found_args, &expected_args);
875 let mut err = struct_span_err!(
879 "{} is expected to take {}, but it takes {}",
885 err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
887 if let Some(found_span) = found_span {
888 err.span_label(found_span, format!("takes {}", found_str));
891 // ^^^^^^^^-- def_span
895 let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
899 if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
901 // Suggest to take and ignore the arguments with expected_args_length `_`s if
902 // found arguments is empty (assume the user just wants to ignore args in this case).
903 // For example, if `expected_args_length` is 2, suggest `|_, _|`.
904 if found_args.is_empty() && is_closure {
905 let underscores = vec!["_"; expected_args.len()].join(", ");
909 "consider changing the closure to take and ignore the expected argument{}",
910 if expected_args.len() < 2 { "" } else { "s" }
912 format!("|{}|", underscores),
913 Applicability::MachineApplicable,
917 if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
918 if fields.len() == expected_args.len() {
921 .map(|(name, _)| name.to_owned())
922 .collect::<Vec<String>>()
926 "change the closure to take multiple arguments instead of a single tuple",
927 format!("|{}|", sugg),
928 Applicability::MachineApplicable,
932 if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
933 if fields.len() == found_args.len() && is_closure {
938 .map(|arg| match arg {
939 ArgKind::Arg(name, _) => name.to_owned(),
942 .collect::<Vec<String>>()
944 // add type annotations if available
945 if found_args.iter().any(|arg| match arg {
946 ArgKind::Arg(_, ty) => ty != "_",
953 .map(|(_, ty)| ty.to_owned())
954 .collect::<Vec<String>>()
963 "change the closure to accept a tuple instead of individual arguments",
965 Applicability::MachineApplicable,
974 crate fn report_closure_arg_mismatch(
977 found_span: Option<Span>,
978 expected_ref: ty::PolyTraitRef<'tcx>,
979 found: ty::PolyTraitRef<'tcx>,
980 ) -> DiagnosticBuilder<'tcx> {
981 crate fn build_fn_sig_string<'tcx>(
983 trait_ref: &ty::TraitRef<'tcx>,
985 let inputs = trait_ref.substs.type_at(1);
986 let sig = if let ty::Tuple(inputs) = inputs.kind {
988 inputs.iter().map(|k| k.expect_ty()),
989 tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
991 hir::Unsafety::Normal,
992 ::rustc_target::spec::abi::Abi::Rust,
996 ::std::iter::once(inputs),
997 tcx.mk_ty_infer(ty::TyVar(ty::TyVid { index: 0 })),
999 hir::Unsafety::Normal,
1000 ::rustc_target::spec::abi::Abi::Rust,
1003 ty::Binder::bind(sig).to_string()
1006 let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure();
1007 let mut err = struct_span_err!(
1011 "type mismatch in {} arguments",
1012 if argument_is_closure { "closure" } else { "function" }
1015 let found_str = format!(
1016 "expected signature of `{}`",
1017 build_fn_sig_string(self.tcx, found.skip_binder())
1019 err.span_label(span, found_str);
1021 let found_span = found_span.unwrap_or(span);
1022 let expected_str = format!(
1023 "found signature of `{}`",
1024 build_fn_sig_string(self.tcx, expected_ref.skip_binder())
1026 err.span_label(found_span, expected_str);
1032 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1033 crate fn suggest_fully_qualified_path(
1035 err: &mut DiagnosticBuilder<'_>,
1040 if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
1041 if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind {
1043 "{}s cannot be accessed directly on a `trait`, they can only be \
1044 accessed through a specific `impl`",
1045 assoc_item.kind.suggestion_descr(),
1047 err.span_suggestion(
1049 "use the fully qualified path to an implementation",
1050 format!("<Type as {}>::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident),
1051 Applicability::HasPlaceholders,
1057 /// Adds an async-await specific note to the diagnostic when the future does not implement
1058 /// an auto trait because of a captured type.
1060 /// ```ignore (diagnostic)
1061 /// note: future does not implement `Qux` as this value is used across an await
1062 /// --> $DIR/issue-64130-3-other.rs:17:5
1064 /// LL | let x = Foo;
1065 /// | - has type `Foo`
1066 /// LL | baz().await;
1067 /// | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1069 /// | - `x` is later dropped here
1072 /// When the diagnostic does not implement `Send` or `Sync` specifically, then the diagnostic
1073 /// is "replaced" with a different message and a more specific error.
1075 /// ```ignore (diagnostic)
1076 /// error: future cannot be sent between threads safely
1077 /// --> $DIR/issue-64130-2-send.rs:21:5
1079 /// LL | fn is_send<T: Send>(t: T) { }
1080 /// | ------- ---- required by this bound in `is_send`
1082 /// LL | is_send(bar());
1083 /// | ^^^^^^^ future returned by `bar` is not send
1085 /// = help: within `impl std::future::Future`, the trait `std::marker::Send` is not
1086 /// implemented for `Foo`
1087 /// note: future is not send as this value is used across an await
1088 /// --> $DIR/issue-64130-2-send.rs:15:5
1090 /// LL | let x = Foo;
1091 /// | - has type `Foo`
1092 /// LL | baz().await;
1093 /// | ^^^^^^^^^^^ await occurs here, with `x` maybe used later
1095 /// | - `x` is later dropped here
1098 /// Returns `true` if an async-await specific note was added to the diagnostic.
1099 crate fn maybe_note_obligation_cause_for_async_await(
1101 err: &mut DiagnosticBuilder<'_>,
1102 obligation: &PredicateObligation<'tcx>,
1105 "maybe_note_obligation_cause_for_async_await: obligation.predicate={:?} \
1106 obligation.cause.span={:?}",
1107 obligation.predicate, obligation.cause.span
1109 let source_map = self.tcx.sess.source_map();
1111 // Attempt to detect an async-await error by looking at the obligation causes, looking
1112 // for a generator to be present.
1114 // When a future does not implement a trait because of a captured type in one of the
1115 // generators somewhere in the call stack, then the result is a chain of obligations.
1117 // Given a `async fn` A that calls a `async fn` B which captures a non-send type and that
1118 // future is passed as an argument to a function C which requires a `Send` type, then the
1119 // chain looks something like this:
1121 // - `BuiltinDerivedObligation` with a generator witness (B)
1122 // - `BuiltinDerivedObligation` with a generator (B)
1123 // - `BuiltinDerivedObligation` with `std::future::GenFuture` (B)
1124 // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1125 // - `BuiltinDerivedObligation` with `impl std::future::Future` (B)
1126 // - `BuiltinDerivedObligation` with a generator witness (A)
1127 // - `BuiltinDerivedObligation` with a generator (A)
1128 // - `BuiltinDerivedObligation` with `std::future::GenFuture` (A)
1129 // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1130 // - `BuiltinDerivedObligation` with `impl std::future::Future` (A)
1131 // - `BindingObligation` with `impl_send (Send requirement)
1133 // The first obligation in the chain is the most useful and has the generator that captured
1134 // the type. The last generator has information about where the bound was introduced. At
1135 // least one generator should be present for this diagnostic to be modified.
1136 let (mut trait_ref, mut target_ty) = match obligation.predicate {
1137 ty::Predicate::Trait(p, _) => {
1138 (Some(p.skip_binder().trait_ref), Some(p.skip_binder().self_ty()))
1142 let mut generator = None;
1143 let mut last_generator = None;
1144 let mut next_code = Some(&obligation.cause.code);
1145 while let Some(code) = next_code {
1146 debug!("maybe_note_obligation_cause_for_async_await: code={:?}", code);
1148 ObligationCauseCode::BuiltinDerivedObligation(derived_obligation)
1149 | ObligationCauseCode::ImplDerivedObligation(derived_obligation) => {
1150 let ty = derived_obligation.parent_trait_ref.self_ty();
1152 "maybe_note_obligation_cause_for_async_await: \
1153 parent_trait_ref={:?} self_ty.kind={:?}",
1154 derived_obligation.parent_trait_ref, ty.kind
1158 ty::Generator(did, ..) => {
1159 generator = generator.or(Some(did));
1160 last_generator = Some(did);
1162 ty::GeneratorWitness(..) => {}
1163 _ if generator.is_none() => {
1164 trait_ref = Some(*derived_obligation.parent_trait_ref.skip_binder());
1165 target_ty = Some(ty);
1170 next_code = Some(derived_obligation.parent_code.as_ref());
1176 // Only continue if a generator was found.
1178 "maybe_note_obligation_cause_for_async_await: generator={:?} trait_ref={:?} \
1180 generator, trait_ref, target_ty
1182 let (generator_did, trait_ref, target_ty) = match (generator, trait_ref, target_ty) {
1183 (Some(generator_did), Some(trait_ref), Some(target_ty)) => {
1184 (generator_did, trait_ref, target_ty)
1189 let span = self.tcx.def_span(generator_did);
1191 // Do not ICE on closure typeck (#66868).
1192 if self.tcx.hir().as_local_hir_id(generator_did).is_none() {
1196 // Get the tables from the infcx if the generator is the function we are
1197 // currently type-checking; otherwise, get them by performing a query.
1198 // This is needed to avoid cycles.
1199 let in_progress_tables = self.in_progress_tables.map(|t| t.borrow());
1200 let generator_did_root = self.tcx.closure_base_def_id(generator_did);
1202 "maybe_note_obligation_cause_for_async_await: generator_did={:?} \
1203 generator_did_root={:?} in_progress_tables.local_id_root={:?} span={:?}",
1206 in_progress_tables.as_ref().map(|t| t.local_id_root),
1210 let tables: &TypeckTables<'tcx> = match &in_progress_tables {
1211 Some(t) if t.local_id_root == Some(generator_did_root) => t,
1213 query_tables = self.tcx.typeck_tables_of(generator_did);
1218 // Look for a type inside the generator interior that matches the target type to get
1220 let target_ty_erased = self.tcx.erase_regions(&target_ty);
1221 let target_span = tables
1222 .generator_interior_types
1224 .find(|ty::GeneratorInteriorTypeCause { ty, .. }| {
1225 // Careful: the regions for types that appear in the
1226 // generator interior are not generally known, so we
1227 // want to erase them when comparing (and anyway,
1228 // `Send` and other bounds are generally unaffected by
1229 // the choice of region). When erasing regions, we
1230 // also have to erase late-bound regions. This is
1231 // because the types that appear in the generator
1232 // interior generally contain "bound regions" to
1233 // represent regions that are part of the suspended
1234 // generator frame. Bound regions are preserved by
1235 // `erase_regions` and so we must also call
1236 // `erase_late_bound_regions`.
1237 let ty_erased = self.tcx.erase_late_bound_regions(&ty::Binder::bind(*ty));
1238 let ty_erased = self.tcx.erase_regions(&ty_erased);
1239 let eq = ty::TyS::same_type(ty_erased, target_ty_erased);
1241 "maybe_note_obligation_cause_for_async_await: ty_erased={:?} \
1242 target_ty_erased={:?} eq={:?}",
1243 ty_erased, target_ty_erased, eq
1247 .map(|ty::GeneratorInteriorTypeCause { span, scope_span, expr, .. }| {
1248 (span, source_map.span_to_snippet(*span), scope_span, expr)
1252 "maybe_note_obligation_cause_for_async_await: target_ty={:?} \
1253 generator_interior_types={:?} target_span={:?}",
1254 target_ty, tables.generator_interior_types, target_span
1256 if let Some((target_span, Ok(snippet), scope_span, expr)) = target_span {
1257 self.note_obligation_cause_for_async_await(
1277 /// Unconditionally adds the diagnostic note described in
1278 /// `maybe_note_obligation_cause_for_async_await`'s documentation comment.
1279 crate fn note_obligation_cause_for_async_await(
1281 err: &mut DiagnosticBuilder<'_>,
1283 scope_span: &Option<Span>,
1284 expr: Option<hir::HirId>,
1286 first_generator: DefId,
1287 last_generator: Option<DefId>,
1288 trait_ref: ty::TraitRef<'_>,
1289 target_ty: Ty<'tcx>,
1290 tables: &ty::TypeckTables<'_>,
1291 obligation: &PredicateObligation<'tcx>,
1292 next_code: Option<&ObligationCauseCode<'tcx>>,
1294 let source_map = self.tcx.sess.source_map();
1296 let is_async_fn = self
1298 .parent(first_generator)
1299 .map(|parent_did| self.tcx.asyncness(parent_did))
1300 .map(|parent_asyncness| parent_asyncness == hir::IsAsync::Async)
1302 let is_async_move = self
1305 .as_local_hir_id(first_generator)
1306 .and_then(|hir_id| self.tcx.hir().maybe_body_owned_by(hir_id))
1307 .map(|body_id| self.tcx.hir().body(body_id))
1308 .and_then(|body| body.generator_kind())
1309 .map(|generator_kind| match generator_kind {
1310 hir::GeneratorKind::Async(..) => true,
1314 let await_or_yield = if is_async_fn || is_async_move { "await" } else { "yield" };
1316 // Special case the primary error message when send or sync is the trait that was
1318 let is_send = self.tcx.is_diagnostic_item(sym::send_trait, trait_ref.def_id);
1319 let is_sync = self.tcx.is_diagnostic_item(sym::sync_trait, trait_ref.def_id);
1320 let hir = self.tcx.hir();
1321 let trait_explanation = if is_send || is_sync {
1322 let (trait_name, trait_verb) =
1323 if is_send { ("`Send`", "sent") } else { ("`Sync`", "shared") };
1326 err.set_primary_message(format!(
1327 "future cannot be {} between threads safely",
1331 let original_span = err.span.primary_span().unwrap();
1332 let mut span = MultiSpan::from_span(original_span);
1334 let message = if let Some(name) = last_generator
1335 .and_then(|generator_did| self.tcx.parent(generator_did))
1336 .and_then(|parent_did| hir.as_local_hir_id(parent_did))
1337 .and_then(|parent_hir_id| hir.opt_name(parent_hir_id))
1339 format!("future returned by `{}` is not {}", name, trait_name)
1341 format!("future is not {}", trait_name)
1344 span.push_span_label(original_span, message);
1347 format!("is not {}", trait_name)
1349 format!("does not implement `{}`", trait_ref.print_only_trait_path())
1352 // Look at the last interior type to get a span for the `.await`.
1353 let await_span = tables.generator_interior_types.iter().map(|t| t.span).last().unwrap();
1354 let mut span = MultiSpan::from_span(await_span);
1355 span.push_span_label(
1357 format!("{} occurs here, with `{}` maybe used later", await_or_yield, snippet),
1360 span.push_span_label(target_span, format!("has type `{}`", target_ty));
1362 // If available, use the scope span to annotate the drop location.
1363 if let Some(scope_span) = scope_span {
1364 span.push_span_label(
1365 source_map.end_point(*scope_span),
1366 format!("`{}` is later dropped here", snippet),
1373 "future {} as this value is used across an {}",
1374 trait_explanation, await_or_yield,
1378 if let Some(expr_id) = expr {
1379 let expr = hir.expect_expr(expr_id);
1380 debug!("target_ty evaluated from {:?}", expr);
1382 let parent = hir.get_parent_node(expr_id);
1383 if let Some(hir::Node::Expr(e)) = hir.find(parent) {
1384 let parent_span = hir.span(parent);
1385 let parent_did = parent.owner_def_id();
1388 // fn foo(&self) -> i32 {}
1391 // ^^^^^^^ a temporary `&T` created inside this method call due to `&self`
1394 let is_region_borrow =
1395 tables.expr_adjustments(expr).iter().any(|adj| adj.is_region_borrow());
1398 // struct Foo(*const u8);
1399 // bar(Foo(std::ptr::null())).await;
1400 // ^^^^^^^^^^^^^^^^^^^^^ raw-ptr `*T` created inside this struct ctor.
1402 debug!("parent_def_kind: {:?}", self.tcx.def_kind(parent_did));
1403 let is_raw_borrow_inside_fn_like_call = match self.tcx.def_kind(parent_did) {
1404 Some(DefKind::Fn) | Some(DefKind::Ctor(..)) => target_ty.is_unsafe_ptr(),
1408 if (tables.is_method_call(e) && is_region_borrow)
1409 || is_raw_borrow_inside_fn_like_call
1413 "consider moving this into a `let` \
1414 binding to create a shorter lived borrow",
1420 // Add a note for the item obligation that remains - normally a note pointing to the
1421 // bound that introduced the obligation (e.g. `T: Send`).
1422 debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code);
1423 self.note_obligation_cause_code(
1425 &obligation.predicate,
1431 crate fn note_obligation_cause_code<T>(
1433 err: &mut DiagnosticBuilder<'_>,
1435 cause_code: &ObligationCauseCode<'tcx>,
1436 obligated_types: &mut Vec<&ty::TyS<'tcx>>,
1442 ObligationCauseCode::ExprAssignable
1443 | ObligationCauseCode::MatchExpressionArm { .. }
1444 | ObligationCauseCode::Pattern { .. }
1445 | ObligationCauseCode::IfExpression { .. }
1446 | ObligationCauseCode::IfExpressionWithNoElse
1447 | ObligationCauseCode::MainFunctionType
1448 | ObligationCauseCode::StartFunctionType
1449 | ObligationCauseCode::IntrinsicType
1450 | ObligationCauseCode::MethodReceiver
1451 | ObligationCauseCode::ReturnNoExpression
1452 | ObligationCauseCode::MiscObligation => {}
1453 ObligationCauseCode::SliceOrArrayElem => {
1454 err.note("slice and array elements must have `Sized` type");
1456 ObligationCauseCode::TupleElem => {
1457 err.note("only the last element of a tuple may have a dynamically sized type");
1459 ObligationCauseCode::ProjectionWf(data) => {
1460 err.note(&format!("required so that the projection `{}` is well-formed", data,));
1462 ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
1464 "required so that reference `{}` does not outlive its referent",
1468 ObligationCauseCode::ObjectTypeBound(object_ty, region) => {
1470 "required so that the lifetime bound of `{}` for `{}` is satisfied",
1474 ObligationCauseCode::ItemObligation(item_def_id) => {
1475 let item_name = tcx.def_path_str(item_def_id);
1476 let msg = format!("required by `{}`", item_name);
1478 if let Some(sp) = tcx.hir().span_if_local(item_def_id) {
1479 let sp = tcx.sess.source_map().def_span(sp);
1480 err.span_label(sp, &msg);
1485 ObligationCauseCode::BindingObligation(item_def_id, span) => {
1486 let item_name = tcx.def_path_str(item_def_id);
1487 let msg = format!("required by this bound in `{}`", item_name);
1488 if let Some(ident) = tcx.opt_item_name(item_def_id) {
1489 err.span_label(ident.span, "");
1491 if span != DUMMY_SP {
1492 err.span_label(span, &msg);
1497 ObligationCauseCode::ObjectCastObligation(object_ty) => {
1499 "required for the cast to the object type `{}`",
1500 self.ty_to_string(object_ty)
1503 ObligationCauseCode::Coercion { source: _, target } => {
1504 err.note(&format!("required by cast to type `{}`", self.ty_to_string(target)));
1506 ObligationCauseCode::RepeatVec(suggest_const_in_array_repeat_expressions) => {
1508 "the `Copy` trait is required because the repeated element will be copied",
1510 if suggest_const_in_array_repeat_expressions {
1512 "this array initializer can be evaluated at compile-time, see issue \
1513 #48147 <https://github.com/rust-lang/rust/issues/49147> \
1514 for more information",
1516 if tcx.sess.opts.unstable_features.is_nightly_build() {
1518 "add `#![feature(const_in_array_repeat_expressions)]` to the \
1519 crate attributes to enable",
1524 ObligationCauseCode::VariableType(_) => {
1525 err.note("all local variables must have a statically known size");
1526 if !self.tcx.features().unsized_locals {
1527 err.help("unsized locals are gated as an unstable feature");
1530 ObligationCauseCode::SizedArgumentType => {
1531 err.note("all function arguments must have a statically known size");
1532 if !self.tcx.features().unsized_locals {
1533 err.help("unsized locals are gated as an unstable feature");
1536 ObligationCauseCode::SizedReturnType => {
1537 err.note("the return type of a function must have a statically known size");
1539 ObligationCauseCode::SizedYieldType => {
1540 err.note("the yield type of a generator must have a statically known size");
1542 ObligationCauseCode::AssignmentLhsSized => {
1543 err.note("the left-hand-side of an assignment must have a statically known size");
1545 ObligationCauseCode::TupleInitializerSized => {
1546 err.note("tuples must have a statically known size to be initialized");
1548 ObligationCauseCode::StructInitializerSized => {
1549 err.note("structs must have a statically known size to be initialized");
1551 ObligationCauseCode::FieldSized { adt_kind: ref item, last } => match *item {
1552 AdtKind::Struct => {
1555 "the last field of a packed struct may only have a \
1556 dynamically sized type if it does not need drop to be run",
1560 "only the last field of a struct may have a dynamically sized type",
1565 err.note("no field of a union may have a dynamically sized type");
1568 err.note("no field of an enum variant may have a dynamically sized type");
1571 ObligationCauseCode::ConstSized => {
1572 err.note("constant expressions must have a statically known size");
1574 ObligationCauseCode::ConstPatternStructural => {
1575 err.note("constants used for pattern-matching must derive `PartialEq` and `Eq`");
1577 ObligationCauseCode::SharedStatic => {
1578 err.note("shared static variables must have a type that implements `Sync`");
1580 ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
1581 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1582 let ty = parent_trait_ref.skip_binder().self_ty();
1583 err.note(&format!("required because it appears within the type `{}`", ty));
1584 obligated_types.push(ty);
1586 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1587 if !self.is_recursive_obligation(obligated_types, &data.parent_code) {
1588 self.note_obligation_cause_code(
1596 ObligationCauseCode::ImplDerivedObligation(ref data) => {
1597 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1599 "required because of the requirements on the impl of `{}` for `{}`",
1600 parent_trait_ref.print_only_trait_path(),
1601 parent_trait_ref.skip_binder().self_ty()
1603 let parent_predicate = parent_trait_ref.without_const().to_predicate();
1604 self.note_obligation_cause_code(
1611 ObligationCauseCode::CompareImplMethodObligation { .. } => {
1613 "the requirement `{}` appears on the impl method \
1614 but not on the corresponding trait method",
1618 ObligationCauseCode::CompareImplTypeObligation { .. } => {
1620 "the requirement `{}` appears on the associated impl type \
1621 but not on the corresponding associated trait type",
1625 ObligationCauseCode::ReturnType
1626 | ObligationCauseCode::ReturnValue(_)
1627 | ObligationCauseCode::BlockTailExpression(_) => (),
1628 ObligationCauseCode::TrivialBound => {
1629 err.help("see issue #48214");
1630 if tcx.sess.opts.unstable_features.is_nightly_build() {
1631 err.help("add `#![feature(trivial_bounds)]` to the crate attributes to enable");
1634 ObligationCauseCode::AssocTypeBound(ref data) => {
1635 err.span_label(data.original, "associated type defined here");
1636 if let Some(sp) = data.impl_span {
1637 err.span_label(sp, "in this `impl` item");
1639 for sp in &data.bounds {
1640 err.span_label(*sp, "restricted in this bound");
1646 crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) {
1647 let current_limit = self.tcx.sess.recursion_limit.get();
1648 let suggested_limit = current_limit * 2;
1650 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)",
1651 suggested_limit, self.tcx.crate_name,
1656 /// Collect all the returned expressions within the input expression.
1657 /// Used to point at the return spans when we want to suggest some change to them.
1659 struct ReturnsVisitor<'v> {
1660 returns: Vec<&'v hir::Expr<'v>>,
1661 in_block_tail: bool,
1664 impl<'v> Visitor<'v> for ReturnsVisitor<'v> {
1665 type Map = rustc::hir::map::Map<'v>;
1667 fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> {
1668 hir::intravisit::NestedVisitorMap::None
1671 fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
1672 // Visit every expression to detect `return` paths, either through the function's tail
1673 // expression or `return` statements. We walk all nodes to find `return` statements, but
1674 // we only care about tail expressions when `in_block_tail` is `true`, which means that
1675 // they're in the return path of the function body.
1677 hir::ExprKind::Ret(Some(ex)) => {
1678 self.returns.push(ex);
1680 hir::ExprKind::Block(block, _) if self.in_block_tail => {
1681 self.in_block_tail = false;
1682 for stmt in block.stmts {
1683 hir::intravisit::walk_stmt(self, stmt);
1685 self.in_block_tail = true;
1686 if let Some(expr) = block.expr {
1687 self.visit_expr(expr);
1690 hir::ExprKind::Match(_, arms, _) if self.in_block_tail => {
1692 self.visit_expr(arm.body);
1695 // We need to walk to find `return`s in the entire body.
1696 _ if !self.in_block_tail => hir::intravisit::walk_expr(self, ex),
1697 _ => self.returns.push(ex),
1701 fn visit_body(&mut self, body: &'v hir::Body<'v>) {
1702 assert!(!self.in_block_tail);
1703 if body.generator_kind().is_none() {
1704 if let hir::ExprKind::Block(block, None) = body.value.kind {
1705 if block.expr.is_some() {
1706 self.in_block_tail = true;
1710 hir::intravisit::walk_body(self, body);