1 pub mod on_unimplemented;
5 ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode,
6 MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode,
7 OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow,
8 PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe,
11 use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode};
12 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
13 use crate::infer::{self, InferCtxt, TyCtxtInferExt};
14 use rustc::mir::interpret::ErrorHandled;
15 use rustc::ty::error::ExpectedFound;
16 use rustc::ty::fast_reject;
17 use rustc::ty::fold::TypeFolder;
18 use rustc::ty::SubtypePredicate;
20 self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness,
22 use rustc_data_structures::fx::FxHashMap;
23 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
25 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
26 use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate};
27 use rustc_session::DiagnosticMessageId;
28 use rustc_span::source_map::SourceMap;
29 use rustc_span::{ExpnKind, Span, DUMMY_SP};
32 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
33 use crate::traits::query::normalize::AtExt as _;
34 use on_unimplemented::InferCtxtExt as _;
35 use suggestions::InferCtxtExt as _;
37 pub use rustc_infer::traits::error_reporting::*;
39 pub trait InferCtxtExt<'tcx> {
40 fn report_fulfillment_errors(
42 errors: &[FulfillmentError<'tcx>],
43 body_id: Option<hir::BodyId>,
44 fallback_has_occurred: bool,
47 fn report_overflow_error<T>(
49 obligation: &Obligation<'tcx, T>,
50 suggest_increasing_limit: bool,
53 T: fmt::Display + TypeFoldable<'tcx>;
55 fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !;
57 fn report_selection_error(
59 obligation: &PredicateObligation<'tcx>,
60 error: &SelectionError<'tcx>,
61 fallback_has_occurred: bool,
65 /// Given some node representing a fn-like thing in the HIR map,
66 /// returns a span and `ArgKind` information that describes the
67 /// arguments it expects. This can be supplied to
68 /// `report_arg_count_mismatch`.
69 fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>);
71 /// Reports an error when the number of arguments needed by a
72 /// trait match doesn't match the number that the expression
74 fn report_arg_count_mismatch(
77 found_span: Option<Span>,
78 expected_args: Vec<ArgKind>,
79 found_args: Vec<ArgKind>,
81 ) -> DiagnosticBuilder<'tcx>;
84 impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
85 fn report_fulfillment_errors(
87 errors: &[FulfillmentError<'tcx>],
88 body_id: Option<hir::BodyId>,
89 fallback_has_occurred: bool,
92 struct ErrorDescriptor<'tcx> {
93 predicate: ty::Predicate<'tcx>,
94 index: Option<usize>, // None if this is an old error
97 let mut error_map: FxHashMap<_, Vec<_>> = self
98 .reported_trait_errors
101 .map(|(&span, predicates)| {
106 .map(|&predicate| ErrorDescriptor { predicate, index: None })
112 for (index, error) in errors.iter().enumerate() {
113 // We want to ignore desugarings here: spans are equivalent even
114 // if one is the result of a desugaring and the other is not.
115 let mut span = error.obligation.cause.span;
116 let expn_data = span.ctxt().outer_expn_data();
117 if let ExpnKind::Desugaring(_) = expn_data.kind {
118 span = expn_data.call_site;
121 error_map.entry(span).or_default().push(ErrorDescriptor {
122 predicate: error.obligation.predicate,
126 self.reported_trait_errors
130 .push(error.obligation.predicate.clone());
133 // We do this in 2 passes because we want to display errors in order, though
134 // maybe it *is* better to sort errors by span or something.
135 let mut is_suppressed = vec![false; errors.len()];
136 for (_, error_set) in error_map.iter() {
137 // We want to suppress "duplicate" errors with the same span.
138 for error in error_set {
139 if let Some(index) = error.index {
140 // Suppress errors that are either:
141 // 1) strictly implied by another error.
142 // 2) implied by an error with a smaller index.
143 for error2 in error_set {
144 if error2.index.map_or(false, |index2| is_suppressed[index2]) {
145 // Avoid errors being suppressed by already-suppressed
146 // errors, to prevent all errors from being suppressed
151 if self.error_implies(&error2.predicate, &error.predicate)
152 && !(error2.index >= error.index
153 && self.error_implies(&error.predicate, &error2.predicate))
155 info!("skipping {:?} (implied by {:?})", error, error2);
156 is_suppressed[index] = true;
164 for (error, suppressed) in errors.iter().zip(is_suppressed) {
166 self.report_fulfillment_error(error, body_id, fallback_has_occurred);
171 /// Reports that an overflow has occurred and halts compilation. We
172 /// halt compilation unconditionally because it is important that
173 /// overflows never be masked -- they basically represent computations
174 /// whose result could not be truly determined and thus we can't say
175 /// if the program type checks or not -- and they are unusual
176 /// occurrences in any case.
177 fn report_overflow_error<T>(
179 obligation: &Obligation<'tcx, T>,
180 suggest_increasing_limit: bool,
183 T: fmt::Display + TypeFoldable<'tcx>,
185 let predicate = self.resolve_vars_if_possible(&obligation.predicate);
186 let mut err = struct_span_err!(
188 obligation.cause.span,
190 "overflow evaluating the requirement `{}`",
194 if suggest_increasing_limit {
195 self.suggest_new_overflow_limit(&mut err);
198 self.note_obligation_cause_code(
200 &obligation.predicate,
201 &obligation.cause.code,
206 self.tcx.sess.abort_if_errors();
210 /// Reports that a cycle was detected which led to overflow and halts
211 /// compilation. This is equivalent to `report_overflow_error` except
212 /// that we can give a more helpful error message (and, in particular,
213 /// we do not suggest increasing the overflow limit, which is not
215 fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! {
216 let cycle = self.resolve_vars_if_possible(&cycle.to_owned());
217 assert!(!cycle.is_empty());
219 debug!("report_overflow_error_cycle: cycle={:?}", cycle);
221 self.report_overflow_error(&cycle[0], false);
224 fn report_selection_error(
226 obligation: &PredicateObligation<'tcx>,
227 error: &SelectionError<'tcx>,
228 fallback_has_occurred: bool,
232 let span = obligation.cause.span;
234 let mut err = match *error {
235 SelectionError::Unimplemented => {
236 if let ObligationCauseCode::CompareImplMethodObligation {
241 | ObligationCauseCode::CompareImplTypeObligation {
245 } = obligation.cause.code
247 self.report_extra_impl_obligation(
252 &format!("`{}`", obligation.predicate),
257 match obligation.predicate {
258 ty::Predicate::Trait(ref trait_predicate, _) => {
259 let trait_predicate = self.resolve_vars_if_possible(trait_predicate);
261 if self.tcx.sess.has_errors() && trait_predicate.references_error() {
264 let trait_ref = trait_predicate.to_poly_trait_ref();
265 let (post_message, pre_message, type_def) = self
266 .get_parent_trait_ref(&obligation.cause.code)
269 format!(" in `{}`", t),
270 format!("within `{}`, ", t),
271 s.map(|s| (format!("within this `{}`", t), s)),
274 .unwrap_or_default();
276 let OnUnimplementedNote { message, label, note, enclosing_scope } =
277 self.on_unimplemented_note(trait_ref, obligation);
278 let have_alt_message = message.is_some() || label.is_some();
283 .span_to_snippet(span)
286 let is_from = format!("{}", trait_ref.print_only_trait_path())
287 .starts_with("std::convert::From<");
288 let (message, note) = if is_try && is_from {
291 "`?` couldn't convert the error to `{}`",
295 "the question mark operation (`?`) implicitly performs a \
296 conversion on the error value using the `From` trait"
304 let mut err = struct_span_err!(
309 message.unwrap_or_else(|| format!(
310 "the trait bound `{}` is not satisfied{}",
311 trait_ref.without_const().to_predicate(),
317 if obligation.cause.code == ObligationCauseCode::MainFunctionType {
318 "consider using `()`, or a `Result`".to_owned()
321 "{}the trait `{}` is not implemented for `{}`",
323 trait_ref.print_only_trait_path(),
328 if self.suggest_add_reference_to_arg(
335 self.note_obligation_cause(&mut err, obligation);
339 if let Some(ref s) = label {
340 // If it has a custom `#[rustc_on_unimplemented]`
341 // error message, let's display it as the label!
342 err.span_label(span, s.as_str());
343 err.help(&explanation);
345 err.span_label(span, explanation);
347 if let Some((msg, span)) = type_def {
348 err.span_label(span, &msg);
350 if let Some(ref s) = note {
351 // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
352 err.note(s.as_str());
354 if let Some(ref s) = enclosing_scope {
355 let enclosing_scope_span = tcx.def_span(
357 .opt_local_def_id(obligation.cause.body_id)
359 tcx.hir().body_owner_def_id(hir::BodyId {
360 hir_id: obligation.cause.body_id,
365 err.span_label(enclosing_scope_span, s.as_str());
368 self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err);
369 self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg);
370 self.suggest_remove_reference(&obligation, &mut err, &trait_ref);
371 self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref);
372 self.note_version_mismatch(&mut err, &trait_ref);
373 if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) {
378 // Try to report a help message
379 if !trait_ref.has_infer_types_or_consts()
380 && self.predicate_can_apply(obligation.param_env, trait_ref)
382 // If a where-clause may be useful, remind the
383 // user that they can add it.
385 // don't display an on-unimplemented note, as
386 // these notes will often be of the form
387 // "the type `T` can't be frobnicated"
388 // which is somewhat confusing.
389 self.suggest_restricting_param_bound(
392 obligation.cause.body_id,
395 if !have_alt_message {
396 // Can't show anything else useful, try to find similar impls.
397 let impl_candidates = self.find_similar_impl_candidates(trait_ref);
398 self.report_similar_impl_candidates(impl_candidates, &mut err);
400 self.suggest_change_mut(
408 // If this error is due to `!: Trait` not implemented but `(): Trait` is
409 // implemented, and fallback has occurred, then it could be due to a
410 // variable that used to fallback to `()` now falling back to `!`. Issue a
411 // note informing about the change in behaviour.
412 if trait_predicate.skip_binder().self_ty().is_never()
413 && fallback_has_occurred
415 let predicate = trait_predicate.map_bound(|mut trait_pred| {
416 trait_pred.trait_ref.substs = self.tcx.mk_substs_trait(
418 &trait_pred.trait_ref.substs[1..],
422 let unit_obligation = Obligation {
423 predicate: ty::Predicate::Trait(
425 hir::Constness::NotConst,
429 if self.predicate_may_hold(&unit_obligation) {
431 "the trait is implemented for `()`. \
432 Possibly this error has been caused by changes to \
433 Rust's type-inference algorithm (see issue #48950 \
434 <https://github.com/rust-lang/rust/issues/48950> \
435 for more information). Consider whether you meant to use \
436 the type `()` here instead.",
444 ty::Predicate::Subtype(ref predicate) => {
445 // Errors for Subtype predicates show up as
446 // `FulfillmentErrorCode::CodeSubtypeError`,
447 // not selection error.
448 span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate)
451 ty::Predicate::RegionOutlives(ref predicate) => {
452 let predicate = self.resolve_vars_if_possible(predicate);
454 .region_outlives_predicate(&obligation.cause, &predicate)
461 "the requirement `{}` is not satisfied (`{}`)",
467 ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
468 let predicate = self.resolve_vars_if_possible(&obligation.predicate);
473 "the requirement `{}` is not satisfied",
478 ty::Predicate::ObjectSafe(trait_def_id) => {
479 let violations = self.tcx.object_safety_violations(trait_def_id);
480 report_object_safety_error(self.tcx, span, trait_def_id, violations)
483 ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
484 let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap();
485 let closure_span = self
489 .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap());
490 let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap();
491 let mut err = struct_span_err!(
495 "expected a closure that implements the `{}` trait, \
496 but this closure only implements `{}`",
503 format!("this closure implements `{}`, not `{}`", found_kind, kind),
506 obligation.cause.span,
507 format!("the requirement to implement `{}` derives from here", kind),
510 // Additional context information explaining why the closure only implements
511 // a particular trait.
512 if let Some(tables) = self.in_progress_tables {
513 let tables = tables.borrow();
514 match (found_kind, tables.closure_kind_origins().get(hir_id)) {
515 (ty::ClosureKind::FnOnce, Some((span, name))) => {
519 "closure is `FnOnce` because it moves the \
520 variable `{}` out of its environment",
525 (ty::ClosureKind::FnMut, Some((span, name))) => {
529 "closure is `FnMut` because it mutates the \
543 ty::Predicate::WellFormed(ty) => {
544 // WF predicates cannot themselves make
545 // errors. They can only block due to
546 // ambiguity; otherwise, they always
547 // degenerate into other obligations
549 span_bug!(span, "WF predicate not satisfied for {:?}", ty);
552 ty::Predicate::ConstEvaluatable(..) => {
553 // Errors for `ConstEvaluatable` predicates show up as
554 // `SelectionError::ConstEvalFailure`,
555 // not `Unimplemented`.
558 "const-evaluatable requirement gave wrong error: `{:?}`",
565 OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => {
566 let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref);
567 let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref);
569 if expected_trait_ref.self_ty().references_error() {
573 let found_trait_ty = found_trait_ref.self_ty();
575 let found_did = match found_trait_ty.kind {
576 ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did),
577 ty::Adt(def, _) => Some(def.did),
581 let found_span = found_did
582 .and_then(|did| self.tcx.hir().span_if_local(did))
583 .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def
585 if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) {
586 // We check closures twice, with obligations flowing in different directions,
587 // but we want to complain about them only once.
591 self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
593 let found = match found_trait_ref.skip_binder().substs.type_at(1).kind {
594 ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
595 _ => vec![ArgKind::empty()],
598 let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
599 let expected = match expected_ty.kind {
600 ty::Tuple(ref tys) => tys
602 .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span)))
604 _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
607 if found.len() == expected.len() {
608 self.report_closure_arg_mismatch(
615 let (closure_span, found) = found_did
616 .and_then(|did| self.tcx.hir().get_if_local(did))
618 let (found_span, found) = self.get_fn_like_arguments(node);
619 (Some(found_span), found)
621 .unwrap_or((found_span, found));
623 self.report_arg_count_mismatch(
628 found_trait_ty.is_closure(),
633 TraitNotObjectSafe(did) => {
634 let violations = self.tcx.object_safety_violations(did);
635 report_object_safety_error(self.tcx, span, did, violations)
638 ConstEvalFailure(ErrorHandled::TooGeneric) => {
639 // In this instance, we have a const expression containing an unevaluated
640 // generic parameter. We have no idea whether this expression is valid or
641 // not (e.g. it might result in an error), but we don't want to just assume
642 // that it's okay, because that might result in post-monomorphisation time
643 // errors. The onus is really on the caller to provide values that it can
644 // prove are well-formed.
648 .struct_span_err(span, "constant expression depends on a generic parameter");
649 // FIXME(const_generics): we should suggest to the user how they can resolve this
650 // issue. However, this is currently not actually possible
651 // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
652 err.note("this may fail depending on what value the parameter takes");
656 // Already reported in the query.
657 ConstEvalFailure(ErrorHandled::Reported) => {
658 self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error");
663 bug!("overflow should be handled before the `report_selection_error` path");
667 self.note_obligation_cause(&mut err, obligation);
668 self.point_at_returns_when_relevant(&mut err, &obligation);
673 /// Given some node representing a fn-like thing in the HIR map,
674 /// returns a span and `ArgKind` information that describes the
675 /// arguments it expects. This can be supplied to
676 /// `report_arg_count_mismatch`.
677 fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec<ArgKind>) {
679 Node::Expr(&hir::Expr {
680 kind: hir::ExprKind::Closure(_, ref _decl, id, span, _),
683 self.tcx.sess.source_map().def_span(span),
690 if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } =
701 .span_to_snippet(pat.span)
703 (snippet, "_".to_owned())
705 .collect::<Vec<_>>(),
709 self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap();
710 ArgKind::Arg(name, "_".to_owned())
713 .collect::<Vec<ArgKind>>(),
715 Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. })
716 | Node::ImplItem(&hir::ImplItem {
718 kind: hir::ImplItemKind::Fn(ref sig, _),
721 | Node::TraitItem(&hir::TraitItem {
723 kind: hir::TraitItemKind::Fn(ref sig, _),
726 self.tcx.sess.source_map().def_span(span),
730 .map(|arg| match arg.clone().kind {
731 hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
733 vec![("_".to_owned(), "_".to_owned()); tys.len()],
735 _ => ArgKind::empty(),
737 .collect::<Vec<ArgKind>>(),
739 Node::Ctor(ref variant_data) => {
740 let span = variant_data
742 .map(|hir_id| self.tcx.hir().span(hir_id))
743 .unwrap_or(DUMMY_SP);
744 let span = self.tcx.sess.source_map().def_span(span);
746 (span, vec![ArgKind::empty(); variant_data.fields().len()])
748 _ => panic!("non-FnLike node found: {:?}", node),
752 /// Reports an error when the number of arguments needed by a
753 /// trait match doesn't match the number that the expression
755 fn report_arg_count_mismatch(
758 found_span: Option<Span>,
759 expected_args: Vec<ArgKind>,
760 found_args: Vec<ArgKind>,
762 ) -> DiagnosticBuilder<'tcx> {
763 let kind = if is_closure { "closure" } else { "function" };
765 let args_str = |arguments: &[ArgKind], other: &[ArgKind]| {
766 let arg_length = arguments.len();
767 let distinct = match &other[..] {
768 &[ArgKind::Tuple(..)] => true,
771 match (arg_length, arguments.get(0)) {
772 (1, Some(&ArgKind::Tuple(_, ref fields))) => {
773 format!("a single {}-tuple as argument", fields.len())
778 if distinct && arg_length > 1 { "distinct " } else { "" },
779 pluralize!(arg_length)
784 let expected_str = args_str(&expected_args, &found_args);
785 let found_str = args_str(&found_args, &expected_args);
787 let mut err = struct_span_err!(
791 "{} is expected to take {}, but it takes {}",
797 err.span_label(span, format!("expected {} that takes {}", kind, expected_str));
799 if let Some(found_span) = found_span {
800 err.span_label(found_span, format!("takes {}", found_str));
803 // ^^^^^^^^-- def_span
807 let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span);
811 if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span };
813 // Suggest to take and ignore the arguments with expected_args_length `_`s if
814 // found arguments is empty (assume the user just wants to ignore args in this case).
815 // For example, if `expected_args_length` is 2, suggest `|_, _|`.
816 if found_args.is_empty() && is_closure {
817 let underscores = vec!["_"; expected_args.len()].join(", ");
821 "consider changing the closure to take and ignore the expected argument{}",
822 if expected_args.len() < 2 { "" } else { "s" }
824 format!("|{}|", underscores),
825 Applicability::MachineApplicable,
829 if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] {
830 if fields.len() == expected_args.len() {
833 .map(|(name, _)| name.to_owned())
834 .collect::<Vec<String>>()
838 "change the closure to take multiple arguments instead of a single tuple",
839 format!("|{}|", sugg),
840 Applicability::MachineApplicable,
844 if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] {
845 if fields.len() == found_args.len() && is_closure {
850 .map(|arg| match arg {
851 ArgKind::Arg(name, _) => name.to_owned(),
854 .collect::<Vec<String>>()
856 // add type annotations if available
857 if found_args.iter().any(|arg| match arg {
858 ArgKind::Arg(_, ty) => ty != "_",
865 .map(|(_, ty)| ty.to_owned())
866 .collect::<Vec<String>>()
875 "change the closure to accept a tuple instead of individual arguments",
877 Applicability::MachineApplicable,
887 trait InferCtxtPrivExt<'tcx> {
888 // returns if `cond` not occurring implies that `error` does not occur - i.e., that
889 // `error` occurring implies that `cond` occurs.
890 fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool;
892 fn report_fulfillment_error(
894 error: &FulfillmentError<'tcx>,
895 body_id: Option<hir::BodyId>,
896 fallback_has_occurred: bool,
899 fn report_projection_error(
901 obligation: &PredicateObligation<'tcx>,
902 error: &MismatchedProjectionTypes<'tcx>,
905 fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool;
907 fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>;
909 fn find_similar_impl_candidates(
911 trait_ref: ty::PolyTraitRef<'tcx>,
912 ) -> Vec<ty::TraitRef<'tcx>>;
914 fn report_similar_impl_candidates(
916 impl_candidates: Vec<ty::TraitRef<'tcx>>,
917 err: &mut DiagnosticBuilder<'_>,
920 /// Gets the parent trait chain start
921 fn get_parent_trait_ref(
923 code: &ObligationCauseCode<'tcx>,
924 ) -> Option<(String, Option<Span>)>;
926 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
927 /// with the same path as `trait_ref`, a help message about
928 /// a probable version mismatch is added to `err`
929 fn note_version_mismatch(
931 err: &mut DiagnosticBuilder<'_>,
932 trait_ref: &ty::PolyTraitRef<'tcx>,
935 fn mk_obligation_for_def_id(
939 cause: ObligationCause<'tcx>,
940 param_env: ty::ParamEnv<'tcx>,
941 ) -> PredicateObligation<'tcx>;
943 fn maybe_report_ambiguity(
945 obligation: &PredicateObligation<'tcx>,
946 body_id: Option<hir::BodyId>,
949 fn predicate_can_apply(
951 param_env: ty::ParamEnv<'tcx>,
952 pred: ty::PolyTraitRef<'tcx>,
955 fn note_obligation_cause(
957 err: &mut DiagnosticBuilder<'_>,
958 obligation: &PredicateObligation<'tcx>,
961 fn suggest_unsized_bound_if_applicable(
963 err: &mut DiagnosticBuilder<'_>,
964 obligation: &PredicateObligation<'tcx>,
967 fn is_recursive_obligation(
969 obligated_types: &mut Vec<&ty::TyS<'tcx>>,
970 cause_code: &ObligationCauseCode<'tcx>,
974 impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
975 // returns if `cond` not occurring implies that `error` does not occur - i.e., that
976 // `error` occurring implies that `cond` occurs.
977 fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool {
982 let (cond, error) = match (cond, error) {
983 (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error),
985 // FIXME: make this work in other cases too.
990 for implication in super::elaborate_predicates(self.tcx, vec![*cond]) {
991 if let ty::Predicate::Trait(implication, _) = implication {
992 let error = error.to_poly_trait_ref();
993 let implication = implication.to_poly_trait_ref();
994 // FIXME: I'm just not taking associated types at all here.
995 // Eventually I'll need to implement param-env-aware
996 // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
997 let param_env = ty::ParamEnv::empty();
998 if self.can_sub(param_env, error, implication).is_ok() {
999 debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication);
1008 fn report_fulfillment_error(
1010 error: &FulfillmentError<'tcx>,
1011 body_id: Option<hir::BodyId>,
1012 fallback_has_occurred: bool,
1014 debug!("report_fulfillment_error({:?})", error);
1016 FulfillmentErrorCode::CodeSelectionError(ref selection_error) => {
1017 self.report_selection_error(
1020 fallback_has_occurred,
1021 error.points_at_arg_span,
1024 FulfillmentErrorCode::CodeProjectionError(ref e) => {
1025 self.report_projection_error(&error.obligation, e);
1027 FulfillmentErrorCode::CodeAmbiguity => {
1028 self.maybe_report_ambiguity(&error.obligation, body_id);
1030 FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => {
1031 self.report_mismatched_types(
1032 &error.obligation.cause,
1033 expected_found.expected,
1034 expected_found.found,
1042 fn report_projection_error(
1044 obligation: &PredicateObligation<'tcx>,
1045 error: &MismatchedProjectionTypes<'tcx>,
1047 let predicate = self.resolve_vars_if_possible(&obligation.predicate);
1049 if predicate.references_error() {
1055 let mut err = &error.err;
1056 let mut values = None;
1058 // try to find the mismatched types to report the error with.
1060 // this can fail if the problem was higher-ranked, in which
1061 // cause I have no idea for a good error message.
1062 if let ty::Predicate::Projection(ref data) = predicate {
1063 let mut selcx = SelectionContext::new(self);
1064 let (data, _) = self.replace_bound_vars_with_fresh_vars(
1065 obligation.cause.span,
1066 infer::LateBoundRegionConversionTime::HigherRankedType,
1069 let mut obligations = vec![];
1070 let normalized_ty = super::normalize_projection_type(
1072 obligation.param_env,
1074 obligation.cause.clone(),
1080 "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
1081 obligation.cause, obligation.param_env
1085 "report_projection_error normalized_ty={:?} data.ty={:?}",
1086 normalized_ty, data.ty
1089 let is_normalized_ty_expected = match &obligation.cause.code {
1090 ObligationCauseCode::ItemObligation(_)
1091 | ObligationCauseCode::BindingObligation(_, _)
1092 | ObligationCauseCode::ObjectCastObligation(_) => false,
1096 if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp(
1097 is_normalized_ty_expected,
1101 values = Some(infer::ValuePairs::Types(ExpectedFound::new(
1102 is_normalized_ty_expected,
1112 let msg = format!("type mismatch resolving `{}`", predicate);
1113 let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg);
1114 let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id);
1116 let mut diag = struct_span_err!(
1118 obligation.cause.span,
1120 "type mismatch resolving `{}`",
1123 self.note_type_err(&mut diag, &obligation.cause, None, values, err);
1124 self.note_obligation_cause(&mut diag, obligation);
1130 fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
1131 /// returns the fuzzy category of a given type, or None
1132 /// if the type can be equated to any type.
1133 fn type_category(t: Ty<'_>) -> Option<u32> {
1135 ty::Bool => Some(0),
1136 ty::Char => Some(1),
1138 ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3),
1139 ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4),
1140 ty::Ref(..) | ty::RawPtr(..) => Some(5),
1141 ty::Array(..) | ty::Slice(..) => Some(6),
1142 ty::FnDef(..) | ty::FnPtr(..) => Some(7),
1143 ty::Dynamic(..) => Some(8),
1144 ty::Closure(..) => Some(9),
1145 ty::Tuple(..) => Some(10),
1146 ty::Projection(..) => Some(11),
1147 ty::Param(..) => Some(12),
1148 ty::Opaque(..) => Some(13),
1149 ty::Never => Some(14),
1150 ty::Adt(adt, ..) => match adt.adt_kind() {
1151 AdtKind::Struct => Some(15),
1152 AdtKind::Union => Some(16),
1153 AdtKind::Enum => Some(17),
1155 ty::Generator(..) => Some(18),
1156 ty::Foreign(..) => Some(19),
1157 ty::GeneratorWitness(..) => Some(20),
1158 ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None,
1159 ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"),
1163 match (type_category(a), type_category(b)) {
1164 (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) {
1165 (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b,
1166 _ => cat_a == cat_b,
1168 // infer and error can be equated to all types
1173 fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
1174 self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind {
1175 hir::GeneratorKind::Gen => "a generator",
1176 hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block",
1177 hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function",
1178 hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure",
1182 fn find_similar_impl_candidates(
1184 trait_ref: ty::PolyTraitRef<'tcx>,
1185 ) -> Vec<ty::TraitRef<'tcx>> {
1186 let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true);
1187 let all_impls = self.tcx.all_impls(trait_ref.def_id());
1190 Some(simp) => all_impls
1192 .filter_map(|&def_id| {
1193 let imp = self.tcx.impl_trait_ref(def_id).unwrap();
1194 let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
1195 if let Some(imp_simp) = imp_simp {
1196 if simp != imp_simp {
1205 all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
1210 fn report_similar_impl_candidates(
1212 impl_candidates: Vec<ty::TraitRef<'tcx>>,
1213 err: &mut DiagnosticBuilder<'_>,
1215 if impl_candidates.is_empty() {
1219 let len = impl_candidates.len();
1220 let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 };
1222 let normalize = |candidate| {
1223 self.tcx.infer_ctxt().enter(|ref infcx| {
1224 let normalized = infcx
1225 .at(&ObligationCause::dummy(), ty::ParamEnv::empty())
1226 .normalize(candidate)
1229 Some(normalized) => format!("\n {:?}", normalized.value),
1230 None => format!("\n {:?}", candidate),
1235 // Sort impl candidates so that ordering is consistent for UI tests.
1236 let mut normalized_impl_candidates =
1237 impl_candidates.iter().map(normalize).collect::<Vec<String>>();
1239 // Sort before taking the `..end` range,
1240 // because the ordering of `impl_candidates` may not be deterministic:
1241 // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
1242 normalized_impl_candidates.sort();
1245 "the following implementations were found:{}{}",
1246 normalized_impl_candidates[..end].join(""),
1247 if len > 5 { format!("\nand {} others", len - 4) } else { String::new() }
1251 /// Gets the parent trait chain start
1252 fn get_parent_trait_ref(
1254 code: &ObligationCauseCode<'tcx>,
1255 ) -> Option<(String, Option<Span>)> {
1257 &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
1258 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1259 match self.get_parent_trait_ref(&data.parent_code) {
1262 let ty = parent_trait_ref.skip_binder().self_ty();
1264 TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
1265 Some((ty.to_string(), span))
1273 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
1274 /// with the same path as `trait_ref`, a help message about
1275 /// a probable version mismatch is added to `err`
1276 fn note_version_mismatch(
1278 err: &mut DiagnosticBuilder<'_>,
1279 trait_ref: &ty::PolyTraitRef<'tcx>,
1281 let get_trait_impl = |trait_def_id| {
1282 let mut trait_impl = None;
1283 self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
1284 if trait_impl.is_none() {
1285 trait_impl = Some(impl_def_id);
1290 let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
1291 let all_traits = self.tcx.all_traits(LOCAL_CRATE);
1292 let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
1294 .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
1295 .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
1297 for trait_with_same_path in traits_with_same_path {
1298 if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
1299 let impl_span = self.tcx.def_span(impl_def_id);
1300 err.span_help(impl_span, "trait impl with same name found");
1301 let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
1302 let crate_msg = format!(
1303 "perhaps two different versions of crate `{}` are being used?",
1306 err.note(&crate_msg);
1311 fn mk_obligation_for_def_id(
1314 output_ty: Ty<'tcx>,
1315 cause: ObligationCause<'tcx>,
1316 param_env: ty::ParamEnv<'tcx>,
1317 ) -> PredicateObligation<'tcx> {
1319 ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
1320 Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
1323 fn maybe_report_ambiguity(
1325 obligation: &PredicateObligation<'tcx>,
1326 body_id: Option<hir::BodyId>,
1328 // Unable to successfully determine, probably means
1329 // insufficient type information, but could mean
1330 // ambiguous impls. The latter *ought* to be a
1331 // coherence violation, so we don't report it here.
1333 let predicate = self.resolve_vars_if_possible(&obligation.predicate);
1334 let span = obligation.cause.span;
1337 "maybe_report_ambiguity(predicate={:?}, obligation={:?} body_id={:?}, code={:?})",
1338 predicate, obligation, body_id, obligation.cause.code,
1341 // Ambiguity errors are often caused as fallout from earlier
1342 // errors. So just ignore them if this infcx is tainted.
1343 if self.is_tainted_by_errors() {
1347 let mut err = match predicate {
1348 ty::Predicate::Trait(ref data, _) => {
1349 let trait_ref = data.to_poly_trait_ref();
1350 let self_ty = trait_ref.self_ty();
1351 debug!("self_ty {:?} {:?} trait_ref {:?}", self_ty, self_ty.kind, trait_ref);
1353 if predicate.references_error() {
1356 // Typically, this ambiguity should only happen if
1357 // there are unresolved type inference variables
1358 // (otherwise it would suggest a coherence
1359 // failure). But given #21974 that is not necessarily
1360 // the case -- we can have multiple where clauses that
1361 // are only distinguished by a region, which results
1362 // in an ambiguity even when all types are fully
1363 // known, since we don't dispatch based on region
1366 // This is kind of a hack: it frequently happens that some earlier
1367 // error prevents types from being fully inferred, and then we get
1368 // a bunch of uninteresting errors saying something like "<generic
1369 // #0> doesn't implement Sized". It may even be true that we
1370 // could just skip over all checks where the self-ty is an
1371 // inference variable, but I was afraid that there might be an
1372 // inference variable created, registered as an obligation, and
1373 // then never forced by writeback, and hence by skipping here we'd
1374 // be ignoring the fact that we don't KNOW the type works
1375 // out. Though even that would probably be harmless, given that
1376 // we're only talking about builtin traits, which are known to be
1377 // inhabited. We used to check for `self.tcx.sess.has_errors()` to
1378 // avoid inundating the user with unnecessary errors, but we now
1379 // check upstream for type errors and don't add the obligations to
1380 // begin with in those cases.
1385 .map_or(false, |sized_id| sized_id == trait_ref.def_id())
1387 self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0282).emit();
1390 let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283);
1391 err.note(&format!("cannot resolve `{}`", predicate));
1392 if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code {
1393 self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
1396 ObligationCauseCode::BindingObligation(ref def_id, _),
1398 (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code)
1400 let generics = self.tcx.generics_of(*def_id);
1401 if !generics.params.is_empty() && !snippet.ends_with('>') {
1402 // FIXME: To avoid spurious suggestions in functions where type arguments
1403 // where already supplied, we check the snippet to make sure it doesn't
1404 // end with a turbofish. Ideally we would have access to a `PathSegment`
1405 // instead. Otherwise we would produce the following output:
1407 // error[E0283]: type annotations needed
1408 // --> $DIR/issue-54954.rs:3:24
1410 // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
1411 // | ^^^^^^^^^^^^^^^^^^^^^^^^^^
1413 // | cannot infer type
1414 // | help: consider specifying the type argument
1415 // | in the function call:
1416 // | `Tt::const_val::<[i8; 123]>::<T>`
1418 // LL | const fn const_val<T: Sized>() -> usize {
1419 // | --------- - required by this bound in `Tt::const_val`
1421 // = note: cannot resolve `_: Tt`
1423 err.span_suggestion(
1426 "consider specifying the type argument{} in the function call",
1427 if generics.params.len() > 1 { "s" } else { "" },
1435 .map(|p| p.name.to_string())
1436 .collect::<Vec<String>>()
1439 Applicability::HasPlaceholders,
1446 ty::Predicate::WellFormed(ty) => {
1447 // Same hacky approach as above to avoid deluging user
1448 // with error messages.
1449 if ty.references_error() || self.tcx.sess.has_errors() {
1452 self.need_type_info_err(body_id, span, ty, ErrorCode::E0282)
1455 ty::Predicate::Subtype(ref data) => {
1456 if data.references_error() || self.tcx.sess.has_errors() {
1457 // no need to overload user in such cases
1460 let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder();
1461 // both must be type variables, or the other would've been instantiated
1462 assert!(a.is_ty_var() && b.is_ty_var());
1463 self.need_type_info_err(body_id, span, a, ErrorCode::E0282)
1465 ty::Predicate::Projection(ref data) => {
1466 let trait_ref = data.to_poly_trait_ref(self.tcx);
1467 let self_ty = trait_ref.self_ty();
1468 if predicate.references_error() {
1471 let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0284);
1472 err.note(&format!("cannot resolve `{}`", predicate));
1477 if self.tcx.sess.has_errors() {
1480 let mut err = struct_span_err!(
1484 "type annotations needed: cannot resolve `{}`",
1487 err.span_label(span, &format!("cannot resolve `{}`", predicate));
1491 self.note_obligation_cause(&mut err, obligation);
1495 /// Returns `true` if the trait predicate may apply for *some* assignment
1496 /// to the type parameters.
1497 fn predicate_can_apply(
1499 param_env: ty::ParamEnv<'tcx>,
1500 pred: ty::PolyTraitRef<'tcx>,
1502 struct ParamToVarFolder<'a, 'tcx> {
1503 infcx: &'a InferCtxt<'a, 'tcx>,
1504 var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>>,
1507 impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx> {
1508 fn tcx<'b>(&'b self) -> TyCtxt<'tcx> {
1512 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1513 if let ty::Param(ty::ParamTy { name, .. }) = ty.kind {
1514 let infcx = self.infcx;
1515 self.var_map.entry(ty).or_insert_with(|| {
1516 infcx.next_ty_var(TypeVariableOrigin {
1517 kind: TypeVariableOriginKind::TypeParameterDefinition(name, None),
1522 ty.super_fold_with(self)
1528 let mut selcx = SelectionContext::new(self);
1531 pred.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() });
1533 let cleaned_pred = super::project::normalize(
1536 ObligationCause::dummy(),
1541 let obligation = Obligation::new(
1542 ObligationCause::dummy(),
1544 cleaned_pred.without_const().to_predicate(),
1547 self.predicate_may_hold(&obligation)
1551 fn note_obligation_cause(
1553 err: &mut DiagnosticBuilder<'_>,
1554 obligation: &PredicateObligation<'tcx>,
1556 // First, attempt to add note to this error with an async-await-specific
1557 // message, and fall back to regular note otherwise.
1558 if !self.maybe_note_obligation_cause_for_async_await(err, obligation) {
1559 self.note_obligation_cause_code(
1561 &obligation.predicate,
1562 &obligation.cause.code,
1565 self.suggest_unsized_bound_if_applicable(err, obligation);
1569 fn suggest_unsized_bound_if_applicable(
1571 err: &mut DiagnosticBuilder<'_>,
1572 obligation: &PredicateObligation<'tcx>,
1575 ty::Predicate::Trait(pred, _),
1576 ObligationCauseCode::BindingObligation(item_def_id, span),
1577 ) = (&obligation.predicate, &obligation.cause.code)
1579 if let (Some(generics), true) = (
1580 self.tcx.hir().get_if_local(*item_def_id).as_ref().and_then(|n| n.generics()),
1581 Some(pred.def_id()) == self.tcx.lang_items().sized_trait(),
1583 for param in generics.params {
1584 if param.span == *span
1585 && !param.bounds.iter().any(|bound| {
1586 bound.trait_def_id() == self.tcx.lang_items().sized_trait()
1589 let (span, separator) = match param.bounds {
1590 [] => (span.shrink_to_hi(), ":"),
1591 [.., bound] => (bound.span().shrink_to_hi(), " + "),
1593 err.span_suggestion(
1595 "consider relaxing the implicit `Sized` restriction",
1596 format!("{} ?Sized", separator),
1597 Applicability::MachineApplicable,
1606 fn is_recursive_obligation(
1608 obligated_types: &mut Vec<&ty::TyS<'tcx>>,
1609 cause_code: &ObligationCauseCode<'tcx>,
1611 if let ObligationCauseCode::BuiltinDerivedObligation(ref data) = cause_code {
1612 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1614 if obligated_types.iter().any(|ot| ot == &parent_trait_ref.skip_binder().self_ty()) {
1622 pub fn recursive_type_with_infinite_size_error(
1625 ) -> DiagnosticBuilder<'tcx> {
1626 assert!(type_def_id.is_local());
1627 let span = tcx.hir().span_if_local(type_def_id).unwrap();
1628 let span = tcx.sess.source_map().def_span(span);
1629 let mut err = struct_span_err!(
1633 "recursive type `{}` has infinite size",
1634 tcx.def_path_str(type_def_id)
1636 err.span_label(span, "recursive type has infinite size");
1638 "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
1639 at some point to make `{}` representable",
1640 tcx.def_path_str(type_def_id)
1645 /// Summarizes information
1648 /// An argument of non-tuple type. Parameters are (name, ty)
1649 Arg(String, String),
1651 /// An argument of tuple type. For a "found" argument, the span is
1652 /// the locationo in the source of the pattern. For a "expected"
1653 /// argument, it will be None. The vector is a list of (name, ty)
1654 /// strings for the components of the tuple.
1655 Tuple(Option<Span>, Vec<(String, String)>),
1659 fn empty() -> ArgKind {
1660 ArgKind::Arg("_".to_owned(), "_".to_owned())
1663 /// Creates an `ArgKind` from the expected type of an
1664 /// argument. It has no name (`_`) and an optional source span.
1665 pub fn from_expected_ty(t: Ty<'_>, span: Option<Span>) -> ArgKind {
1667 ty::Tuple(ref tys) => ArgKind::Tuple(
1669 tys.iter().map(|ty| ("_".to_owned(), ty.to_string())).collect::<Vec<_>>(),
1671 _ => ArgKind::Arg("_".to_owned(), t.to_string()),
1676 /// Suggest restricting a type param with a new bound.
1677 pub fn suggest_constraining_type_param(
1679 generics: &hir::Generics<'_>,
1680 err: &mut DiagnosticBuilder<'_>,
1683 source_map: &SourceMap,
1685 def_id: Option<DefId>,
1687 const MSG_RESTRICT_BOUND_FURTHER: &str = "consider further restricting this bound with";
1688 const MSG_RESTRICT_TYPE: &str = "consider restricting this type parameter with";
1689 const MSG_RESTRICT_TYPE_FURTHER: &str = "consider further restricting this type parameter with";
1691 let param = generics.params.iter().find(|p| p.name.ident().as_str() == param_name);
1693 let param = if let Some(param) = param {
1699 if def_id == tcx.lang_items().sized_trait() {
1700 // Type parameters are already `Sized` by default.
1701 err.span_label(param.span, &format!("this type parameter needs to be `{}`", constraint));
1705 if param_name.starts_with("impl ") {
1706 // If there's an `impl Trait` used in argument position, suggest
1709 // fn foo(t: impl Foo) { ... }
1712 // help: consider further restricting this bound with `+ Bar`
1714 // Suggestion for tools in this case is:
1716 // fn foo(t: impl Foo) { ... }
1719 // replace with: `impl Foo + Bar`
1721 err.span_help(param.span, &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint));
1723 err.tool_only_span_suggestion(
1725 MSG_RESTRICT_BOUND_FURTHER,
1726 format!("{} + {}", param_name, constraint),
1727 Applicability::MachineApplicable,
1733 if generics.where_clause.predicates.is_empty() {
1734 if let Some(bounds_span) = param.bounds_span() {
1735 // If user has provided some bounds, suggest restricting them:
1737 // fn foo<T: Foo>(t: T) { ... }
1740 // help: consider further restricting this bound with `+ Bar`
1742 // Suggestion for tools in this case is:
1744 // fn foo<T: Foo>(t: T) { ... }
1747 // replace with: `T: Bar +`
1751 &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
1754 let span_hi = param.span.with_hi(span.hi());
1755 let span_with_colon = source_map.span_through_char(span_hi, ':');
1757 if span_hi != param.span && span_with_colon != span_hi {
1758 err.tool_only_span_suggestion(
1760 MSG_RESTRICT_BOUND_FURTHER,
1761 format!("{}: {} + ", param_name, constraint),
1762 Applicability::MachineApplicable,
1766 // If user hasn't provided any bounds, suggest adding a new one:
1768 // fn foo<T>(t: T) { ... }
1769 // - help: consider restricting this type parameter with `T: Foo`
1773 &format!("{} `{}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
1776 err.tool_only_span_suggestion(
1779 format!("{}: {}", param_name, constraint),
1780 Applicability::MachineApplicable,
1786 // This part is a bit tricky, because using the `where` clause user can
1787 // provide zero, one or many bounds for the same type parameter, so we
1788 // have following cases to consider:
1790 // 1) When the type parameter has been provided zero bounds
1793 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
1794 // - help: consider restricting this type parameter with `where X: Bar`
1797 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
1798 // - insert: `, X: Bar`
1801 // 2) When the type parameter has been provided one bound
1804 // fn foo<T>(t: T) where T: Foo { ... }
1807 // help: consider further restricting this bound with `+ Bar`
1810 // fn foo<T>(t: T) where T: Foo { ... }
1813 // replace with: `T: Bar +`
1816 // 3) When the type parameter has been provided many bounds
1819 // fn foo<T>(t: T) where T: Foo, T: Bar {... }
1820 // - help: consider further restricting this type parameter with `where T: Zar`
1823 // fn foo<T>(t: T) where T: Foo, T: Bar {... }
1824 // - insert: `, T: Zar`
1826 let mut param_spans = Vec::new();
1828 for predicate in generics.where_clause.predicates {
1829 if let WherePredicate::BoundPredicate(WhereBoundPredicate {
1830 span, bounded_ty, ..
1833 if let TyKind::Path(QPath::Resolved(_, path)) = &bounded_ty.kind {
1834 if let Some(segment) = path.segments.first() {
1835 if segment.ident.to_string() == param_name {
1836 param_spans.push(span);
1843 let where_clause_span =
1844 generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi();
1846 match ¶m_spans[..] {
1850 &format!("{} `where {}: {}`", MSG_RESTRICT_TYPE, param_name, constraint),
1853 err.tool_only_span_suggestion(
1856 format!(", {}: {}", param_name, constraint),
1857 Applicability::MachineApplicable,
1864 &format!("{} `+ {}`", MSG_RESTRICT_BOUND_FURTHER, constraint),
1867 let span_hi = param_span.with_hi(span.hi());
1868 let span_with_colon = source_map.span_through_char(span_hi, ':');
1870 if span_hi != param_span && span_with_colon != span_hi {
1871 err.tool_only_span_suggestion(
1873 MSG_RESTRICT_BOUND_FURTHER,
1874 format!("{}: {} +", param_name, constraint),
1875 Applicability::MachineApplicable,
1884 "{} `where {}: {}`",
1885 MSG_RESTRICT_TYPE_FURTHER, param_name, constraint,
1889 err.tool_only_span_suggestion(
1891 MSG_RESTRICT_BOUND_FURTHER,
1892 format!(", {}: {}", param_name, constraint),
1893 Applicability::MachineApplicable,