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_data_structures
::fx
::FxHashMap
;
15 use rustc_errors
::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}
;
17 use rustc_hir
::def_id
::{DefId, LOCAL_CRATE}
;
18 use rustc_hir
::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate}
;
19 use rustc_middle
::mir
::interpret
::ErrorHandled
;
20 use rustc_middle
::ty
::error
::ExpectedFound
;
21 use rustc_middle
::ty
::fast_reject
;
22 use rustc_middle
::ty
::fold
::TypeFolder
;
23 use rustc_middle
::ty
::SubtypePredicate
;
24 use rustc_middle
::ty
::{
25 self, AdtKind
, ToPolyTraitRef
, ToPredicate
, Ty
, TyCtxt
, TypeFoldable
, WithConstness
,
27 use rustc_session
::DiagnosticMessageId
;
28 use rustc_span
::{BytePos, ExpnKind, Span, DUMMY_SP}
;
31 use crate::traits
::query
::evaluate_obligation
::InferCtxtExt
as _
;
32 use crate::traits
::query
::normalize
::AtExt
as _
;
33 use on_unimplemented
::InferCtxtExt
as _
;
34 use suggestions
::InferCtxtExt
as _
;
36 pub use rustc_infer
::traits
::error_reporting
::*;
38 pub trait InferCtxtExt
<'tcx
> {
39 fn report_fulfillment_errors(
41 errors
: &[FulfillmentError
<'tcx
>],
42 body_id
: Option
<hir
::BodyId
>,
43 fallback_has_occurred
: bool
,
46 fn report_overflow_error
<T
>(
48 obligation
: &Obligation
<'tcx
, T
>,
49 suggest_increasing_limit
: bool
,
52 T
: fmt
::Display
+ TypeFoldable
<'tcx
>;
54 fn report_overflow_error_cycle(&self, cycle
: &[PredicateObligation
<'tcx
>]) -> !;
56 fn report_selection_error(
58 obligation
: &PredicateObligation
<'tcx
>,
59 error
: &SelectionError
<'tcx
>,
60 fallback_has_occurred
: bool
,
64 /// Given some node representing a fn-like thing in the HIR map,
65 /// returns a span and `ArgKind` information that describes the
66 /// arguments it expects. This can be supplied to
67 /// `report_arg_count_mismatch`.
68 fn get_fn_like_arguments(&self, node
: Node
<'_
>) -> Option
<(Span
, Vec
<ArgKind
>)>;
70 /// Reports an error when the number of arguments needed by a
71 /// trait match doesn't match the number that the expression
73 fn report_arg_count_mismatch(
76 found_span
: Option
<Span
>,
77 expected_args
: Vec
<ArgKind
>,
78 found_args
: Vec
<ArgKind
>,
80 ) -> DiagnosticBuilder
<'tcx
>;
83 impl<'a
, 'tcx
> InferCtxtExt
<'tcx
> for InferCtxt
<'a
, 'tcx
> {
84 fn report_fulfillment_errors(
86 errors
: &[FulfillmentError
<'tcx
>],
87 body_id
: Option
<hir
::BodyId
>,
88 fallback_has_occurred
: bool
,
91 struct ErrorDescriptor
<'tcx
> {
92 predicate
: ty
::Predicate
<'tcx
>,
93 index
: Option
<usize>, // None if this is an old error
96 let mut error_map
: FxHashMap
<_
, Vec
<_
>> = self
97 .reported_trait_errors
100 .map(|(&span
, predicates
)| {
105 .map(|&predicate
| ErrorDescriptor { predicate, index: None }
)
111 for (index
, error
) in errors
.iter().enumerate() {
112 // We want to ignore desugarings here: spans are equivalent even
113 // if one is the result of a desugaring and the other is not.
114 let mut span
= error
.obligation
.cause
.span
;
115 let expn_data
= span
.ctxt().outer_expn_data();
116 if let ExpnKind
::Desugaring(_
) = expn_data
.kind
{
117 span
= expn_data
.call_site
;
120 error_map
.entry(span
).or_default().push(ErrorDescriptor
{
121 predicate
: error
.obligation
.predicate
,
125 self.reported_trait_errors
129 .push(error
.obligation
.predicate
);
132 // We do this in 2 passes because we want to display errors in order, though
133 // maybe it *is* better to sort errors by span or something.
134 let mut is_suppressed
= vec
![false; errors
.len()];
135 for (_
, error_set
) in error_map
.iter() {
136 // We want to suppress "duplicate" errors with the same span.
137 for error
in error_set
{
138 if let Some(index
) = error
.index
{
139 // Suppress errors that are either:
140 // 1) strictly implied by another error.
141 // 2) implied by an error with a smaller index.
142 for error2
in error_set
{
143 if error2
.index
.map_or(false, |index2
| is_suppressed
[index2
]) {
144 // Avoid errors being suppressed by already-suppressed
145 // errors, to prevent all errors from being suppressed
150 if self.error_implies(&error2
.predicate
, &error
.predicate
)
151 && !(error2
.index
>= error
.index
152 && self.error_implies(&error
.predicate
, &error2
.predicate
))
154 info
!("skipping {:?} (implied by {:?})", error
, error2
);
155 is_suppressed
[index
] = true;
163 for (error
, suppressed
) in errors
.iter().zip(is_suppressed
) {
165 self.report_fulfillment_error(error
, body_id
, fallback_has_occurred
);
170 /// Reports that an overflow has occurred and halts compilation. We
171 /// halt compilation unconditionally because it is important that
172 /// overflows never be masked -- they basically represent computations
173 /// whose result could not be truly determined and thus we can't say
174 /// if the program type checks or not -- and they are unusual
175 /// occurrences in any case.
176 fn report_overflow_error
<T
>(
178 obligation
: &Obligation
<'tcx
, T
>,
179 suggest_increasing_limit
: bool
,
182 T
: fmt
::Display
+ TypeFoldable
<'tcx
>,
184 let predicate
= self.resolve_vars_if_possible(&obligation
.predicate
);
185 let mut err
= struct_span_err
!(
187 obligation
.cause
.span
,
189 "overflow evaluating the requirement `{}`",
193 if suggest_increasing_limit
{
194 self.suggest_new_overflow_limit(&mut err
);
197 self.note_obligation_cause_code(
199 &obligation
.predicate
,
200 &obligation
.cause
.code
,
205 self.tcx
.sess
.abort_if_errors();
209 /// Reports that a cycle was detected which led to overflow and halts
210 /// compilation. This is equivalent to `report_overflow_error` except
211 /// that we can give a more helpful error message (and, in particular,
212 /// we do not suggest increasing the overflow limit, which is not
214 fn report_overflow_error_cycle(&self, cycle
: &[PredicateObligation
<'tcx
>]) -> ! {
215 let cycle
= self.resolve_vars_if_possible(&cycle
.to_owned());
216 assert
!(!cycle
.is_empty());
218 debug
!("report_overflow_error_cycle: cycle={:?}", cycle
);
220 self.report_overflow_error(&cycle
[0], false);
223 fn report_selection_error(
225 obligation
: &PredicateObligation
<'tcx
>,
226 error
: &SelectionError
<'tcx
>,
227 fallback_has_occurred
: bool
,
231 let span
= obligation
.cause
.span
;
233 let mut err
= match *error
{
234 SelectionError
::Unimplemented
=> {
235 if let ObligationCauseCode
::CompareImplMethodObligation
{
240 | ObligationCauseCode
::CompareImplTypeObligation
{
244 } = obligation
.cause
.code
246 self.report_extra_impl_obligation(
251 &format
!("`{}`", obligation
.predicate
),
256 match obligation
.predicate
{
257 ty
::Predicate
::Trait(ref trait_predicate
, _
) => {
258 let trait_predicate
= self.resolve_vars_if_possible(trait_predicate
);
260 if self.tcx
.sess
.has_errors() && trait_predicate
.references_error() {
263 let trait_ref
= trait_predicate
.to_poly_trait_ref();
264 let (post_message
, pre_message
, type_def
) = self
265 .get_parent_trait_ref(&obligation
.cause
.code
)
268 format
!(" in `{}`", t
),
269 format
!("within `{}`, ", t
),
270 s
.map(|s
| (format
!("within this `{}`", t
), s
)),
273 .unwrap_or_default();
275 let OnUnimplementedNote { message, label, note, enclosing_scope }
=
276 self.on_unimplemented_note(trait_ref
, obligation
);
277 let have_alt_message
= message
.is_some() || label
.is_some();
282 .span_to_snippet(span
)
285 let is_from
= format
!("{}", trait_ref
.print_only_trait_path())
286 .starts_with("std::convert::From<");
287 let (message
, note
) = if is_try
&& is_from
{
290 "`?` couldn't convert the error to `{}`",
294 "the question mark operation (`?`) implicitly performs a \
295 conversion on the error value using the `From` trait"
303 let mut err
= struct_span_err
!(
308 message
.unwrap_or_else(|| format
!(
309 "the trait bound `{}` is not satisfied{}",
310 trait_ref
.without_const().to_predicate(),
315 let should_convert_option_to_result
=
316 format
!("{}", trait_ref
.print_only_trait_path())
317 .starts_with("std::convert::From<std::option::NoneError");
318 let should_convert_result_to_option
= format
!("{}", trait_ref
)
319 .starts_with("<std::option::NoneError as std::convert::From<");
320 if is_try
&& is_from
&& should_convert_option_to_result
{
321 err
.span_suggestion_verbose(
323 "consider converting the `Option<T>` into a `Result<T, _>` using `Option::ok_or` or `Option::ok_or_else`",
324 ".ok_or_else(|| /* error value */)".to_string(),
325 Applicability
::HasPlaceholders
,
327 } else if is_try
&& is_from
&& should_convert_result_to_option
{
328 err
.span_suggestion_verbose(
330 "consider converting the `Result<T, _>` into an `Option<T>` using `Result::ok`",
332 Applicability
::MachineApplicable
,
337 if obligation
.cause
.code
== ObligationCauseCode
::MainFunctionType
{
338 "consider using `()`, or a `Result`".to_owned()
341 "{}the trait `{}` is not implemented for `{}`",
343 trait_ref
.print_only_trait_path(),
348 if self.suggest_add_reference_to_arg(
355 self.note_obligation_cause(&mut err
, obligation
);
359 if let Some(ref s
) = label
{
360 // If it has a custom `#[rustc_on_unimplemented]`
361 // error message, let's display it as the label!
362 err
.span_label(span
, s
.as_str());
363 err
.help(&explanation
);
365 err
.span_label(span
, explanation
);
367 if let Some((msg
, span
)) = type_def
{
368 err
.span_label(span
, &msg
);
370 if let Some(ref s
) = note
{
371 // If it has a custom `#[rustc_on_unimplemented]` note, let's display it
372 err
.note(s
.as_str());
374 if let Some(ref s
) = enclosing_scope
{
375 let enclosing_scope_span
= tcx
.def_span(
377 .opt_local_def_id(obligation
.cause
.body_id
)
379 tcx
.hir().body_owner_def_id(hir
::BodyId
{
380 hir_id
: obligation
.cause
.body_id
,
386 err
.span_label(enclosing_scope_span
, s
.as_str());
389 self.suggest_borrow_on_unsized_slice(&obligation
.cause
.code
, &mut err
);
390 self.suggest_fn_call(&obligation
, &mut err
, &trait_ref
, points_at_arg
);
391 self.suggest_remove_reference(&obligation
, &mut err
, &trait_ref
);
392 self.suggest_semicolon_removal(&obligation
, &mut err
, span
, &trait_ref
);
393 self.note_version_mismatch(&mut err
, &trait_ref
);
394 if self.suggest_impl_trait(&mut err
, span
, &obligation
, &trait_ref
) {
399 // Try to report a help message
400 if !trait_ref
.has_infer_types_or_consts()
401 && self.predicate_can_apply(obligation
.param_env
, trait_ref
)
403 // If a where-clause may be useful, remind the
404 // user that they can add it.
406 // don't display an on-unimplemented note, as
407 // these notes will often be of the form
408 // "the type `T` can't be frobnicated"
409 // which is somewhat confusing.
410 self.suggest_restricting_param_bound(
413 obligation
.cause
.body_id
,
416 if !have_alt_message
{
417 // Can't show anything else useful, try to find similar impls.
418 let impl_candidates
= self.find_similar_impl_candidates(trait_ref
);
419 self.report_similar_impl_candidates(impl_candidates
, &mut err
);
421 self.suggest_change_mut(
429 // If this error is due to `!: Trait` not implemented but `(): Trait` is
430 // implemented, and fallback has occurred, then it could be due to a
431 // variable that used to fallback to `()` now falling back to `!`. Issue a
432 // note informing about the change in behaviour.
433 if trait_predicate
.skip_binder().self_ty().is_never()
434 && fallback_has_occurred
436 let predicate
= trait_predicate
.map_bound(|mut trait_pred
| {
437 trait_pred
.trait_ref
.substs
= self.tcx
.mk_substs_trait(
439 &trait_pred
.trait_ref
.substs
[1..],
443 let unit_obligation
= Obligation
{
444 predicate
: ty
::Predicate
::Trait(
446 hir
::Constness
::NotConst
,
450 if self.predicate_may_hold(&unit_obligation
) {
452 "the trait is implemented for `()`. \
453 Possibly this error has been caused by changes to \
454 Rust's type-inference algorithm (see issue #48950 \
455 <https://github.com/rust-lang/rust/issues/48950> \
456 for more information). Consider whether you meant to use \
457 the type `()` here instead.",
465 ty
::Predicate
::Subtype(ref predicate
) => {
466 // Errors for Subtype predicates show up as
467 // `FulfillmentErrorCode::CodeSubtypeError`,
468 // not selection error.
469 span_bug
!(span
, "subtype requirement gave wrong error: `{:?}`", predicate
)
472 ty
::Predicate
::RegionOutlives(ref predicate
) => {
473 let predicate
= self.resolve_vars_if_possible(predicate
);
475 .region_outlives_predicate(&obligation
.cause
, &predicate
)
482 "the requirement `{}` is not satisfied (`{}`)",
488 ty
::Predicate
::Projection(..) | ty
::Predicate
::TypeOutlives(..) => {
489 let predicate
= self.resolve_vars_if_possible(&obligation
.predicate
);
494 "the requirement `{}` is not satisfied",
499 ty
::Predicate
::ObjectSafe(trait_def_id
) => {
500 let violations
= self.tcx
.object_safety_violations(trait_def_id
);
501 report_object_safety_error(self.tcx
, span
, trait_def_id
, violations
)
504 ty
::Predicate
::ClosureKind(closure_def_id
, closure_substs
, kind
) => {
505 let found_kind
= self.closure_kind(closure_substs
).unwrap();
507 self.tcx
.sess
.source_map().guess_head_span(
508 self.tcx
.hir().span_if_local(closure_def_id
).unwrap(),
510 let hir_id
= self.tcx
.hir().as_local_hir_id(closure_def_id
).unwrap();
511 let mut err
= struct_span_err
!(
515 "expected a closure that implements the `{}` trait, \
516 but this closure only implements `{}`",
523 format
!("this closure implements `{}`, not `{}`", found_kind
, kind
),
526 obligation
.cause
.span
,
527 format
!("the requirement to implement `{}` derives from here", kind
),
530 // Additional context information explaining why the closure only implements
531 // a particular trait.
532 if let Some(tables
) = self.in_progress_tables
{
533 let tables
= tables
.borrow();
534 match (found_kind
, tables
.closure_kind_origins().get(hir_id
)) {
535 (ty
::ClosureKind
::FnOnce
, Some((span
, name
))) => {
539 "closure is `FnOnce` because it moves the \
540 variable `{}` out of its environment",
545 (ty
::ClosureKind
::FnMut
, Some((span
, name
))) => {
549 "closure is `FnMut` because it mutates the \
563 ty
::Predicate
::WellFormed(ty
) => {
564 // WF predicates cannot themselves make
565 // errors. They can only block due to
566 // ambiguity; otherwise, they always
567 // degenerate into other obligations
569 span_bug
!(span
, "WF predicate not satisfied for {:?}", ty
);
572 ty
::Predicate
::ConstEvaluatable(..) => {
573 // Errors for `ConstEvaluatable` predicates show up as
574 // `SelectionError::ConstEvalFailure`,
575 // not `Unimplemented`.
578 "const-evaluatable requirement gave wrong error: `{:?}`",
585 OutputTypeParameterMismatch(ref found_trait_ref
, ref expected_trait_ref
, _
) => {
586 let found_trait_ref
= self.resolve_vars_if_possible(&*found_trait_ref
);
587 let expected_trait_ref
= self.resolve_vars_if_possible(&*expected_trait_ref
);
589 if expected_trait_ref
.self_ty().references_error() {
593 let found_trait_ty
= found_trait_ref
.self_ty();
595 let found_did
= match found_trait_ty
.kind
{
596 ty
::Closure(did
, _
) | ty
::Foreign(did
) | ty
::FnDef(did
, _
) => Some(did
),
597 ty
::Adt(def
, _
) => Some(def
.did
),
601 let found_span
= found_did
602 .and_then(|did
| self.tcx
.hir().span_if_local(did
))
603 .map(|sp
| self.tcx
.sess
.source_map().guess_head_span(sp
)); // the sp could be an fn def
605 if self.reported_closure_mismatch
.borrow().contains(&(span
, found_span
)) {
606 // We check closures twice, with obligations flowing in different directions,
607 // but we want to complain about them only once.
611 self.reported_closure_mismatch
.borrow_mut().insert((span
, found_span
));
613 let found
= match found_trait_ref
.skip_binder().substs
.type_at(1).kind
{
614 ty
::Tuple(ref tys
) => vec
![ArgKind
::empty(); tys
.len()],
615 _
=> vec
![ArgKind
::empty()],
618 let expected_ty
= expected_trait_ref
.skip_binder().substs
.type_at(1);
619 let expected
= match expected_ty
.kind
{
620 ty
::Tuple(ref tys
) => tys
622 .map(|t
| ArgKind
::from_expected_ty(t
.expect_ty(), Some(span
)))
624 _
=> vec
![ArgKind
::Arg("_".to_owned(), expected_ty
.to_string())],
627 if found
.len() == expected
.len() {
628 self.report_closure_arg_mismatch(
635 let (closure_span
, found
) = found_did
637 let node
= self.tcx
.hir().get_if_local(did
)?
;
638 let (found_span
, found
) = self.get_fn_like_arguments(node
)?
;
639 Some((Some(found_span
), found
))
641 .unwrap_or((found_span
, found
));
643 self.report_arg_count_mismatch(
648 found_trait_ty
.is_closure(),
653 TraitNotObjectSafe(did
) => {
654 let violations
= self.tcx
.object_safety_violations(did
);
655 report_object_safety_error(self.tcx
, span
, did
, violations
)
658 ConstEvalFailure(ErrorHandled
::TooGeneric
) => {
659 // In this instance, we have a const expression containing an unevaluated
660 // generic parameter. We have no idea whether this expression is valid or
661 // not (e.g. it might result in an error), but we don't want to just assume
662 // that it's okay, because that might result in post-monomorphisation time
663 // errors. The onus is really on the caller to provide values that it can
664 // prove are well-formed.
668 .struct_span_err(span
, "constant expression depends on a generic parameter");
669 // FIXME(const_generics): we should suggest to the user how they can resolve this
670 // issue. However, this is currently not actually possible
671 // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083).
672 err
.note("this may fail depending on what value the parameter takes");
676 // Already reported in the query.
677 ConstEvalFailure(ErrorHandled
::Reported(ErrorReported
)) => {
678 // FIXME(eddyb) remove this once `ErrorReported` becomes a proof token.
679 self.tcx
.sess
.delay_span_bug(span
, "`ErrorReported` without an error");
683 // Already reported in the query, but only as a lint.
684 // This shouldn't actually happen for constants used in types, modulo
685 // bugs. The `delay_span_bug` here ensures it won't be ignored.
686 ConstEvalFailure(ErrorHandled
::Linted
) => {
687 self.tcx
.sess
.delay_span_bug(span
, "constant in type had error reported as lint");
692 bug
!("overflow should be handled before the `report_selection_error` path");
696 self.note_obligation_cause(&mut err
, obligation
);
697 self.point_at_returns_when_relevant(&mut err
, &obligation
);
702 /// Given some node representing a fn-like thing in the HIR map,
703 /// returns a span and `ArgKind` information that describes the
704 /// arguments it expects. This can be supplied to
705 /// `report_arg_count_mismatch`.
706 fn get_fn_like_arguments(&self, node
: Node
<'_
>) -> Option
<(Span
, Vec
<ArgKind
>)> {
707 let sm
= self.tcx
.sess
.source_map();
708 let hir
= self.tcx
.hir();
710 Node
::Expr(&hir
::Expr
{
711 kind
: hir
::ExprKind
::Closure(_
, ref _decl
, id
, span
, _
),
714 sm
.guess_head_span(span
),
719 if let hir
::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. }
=
726 sm
.span_to_snippet(pat
.span
)
728 .map(|snippet
| (snippet
, "_".to_owned()))
730 .collect
::<Option
<Vec
<_
>>>()?
,
733 let name
= sm
.span_to_snippet(arg
.pat
.span
).ok()?
;
734 Some(ArgKind
::Arg(name
, "_".to_owned()))
737 .collect
::<Option
<Vec
<ArgKind
>>>()?
,
739 Node
::Item(&hir
::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }
)
740 | Node
::ImplItem(&hir
::ImplItem
{
742 kind
: hir
::ImplItemKind
::Fn(ref sig
, _
),
745 | Node
::TraitItem(&hir
::TraitItem
{
747 kind
: hir
::TraitItemKind
::Fn(ref sig
, _
),
750 sm
.guess_head_span(span
),
754 .map(|arg
| match arg
.clone().kind
{
755 hir
::TyKind
::Tup(ref tys
) => ArgKind
::Tuple(
757 vec
![("_".to_owned(), "_".to_owned()); tys
.len()],
759 _
=> ArgKind
::empty(),
761 .collect
::<Vec
<ArgKind
>>(),
763 Node
::Ctor(ref variant_data
) => {
764 let span
= variant_data
.ctor_hir_id().map(|id
| hir
.span(id
)).unwrap_or(DUMMY_SP
);
765 let span
= sm
.guess_head_span(span
);
766 (span
, vec
![ArgKind
::empty(); variant_data
.fields().len()])
768 _
=> panic
!("non-FnLike node found: {:?}", node
),
772 /// Reports an error when the number of arguments needed by a
773 /// trait match doesn't match the number that the expression
775 fn report_arg_count_mismatch(
778 found_span
: Option
<Span
>,
779 expected_args
: Vec
<ArgKind
>,
780 found_args
: Vec
<ArgKind
>,
782 ) -> DiagnosticBuilder
<'tcx
> {
783 let kind
= if is_closure { "closure" }
else { "function" }
;
785 let args_str
= |arguments
: &[ArgKind
], other
: &[ArgKind
]| {
786 let arg_length
= arguments
.len();
787 let distinct
= match &other
[..] {
788 &[ArgKind
::Tuple(..)] => true,
791 match (arg_length
, arguments
.get(0)) {
792 (1, Some(&ArgKind
::Tuple(_
, ref fields
))) => {
793 format
!("a single {}-tuple as argument", fields
.len())
798 if distinct
&& arg_length
> 1 { "distinct " }
else { "" }
,
799 pluralize
!(arg_length
)
804 let expected_str
= args_str(&expected_args
, &found_args
);
805 let found_str
= args_str(&found_args
, &expected_args
);
807 let mut err
= struct_span_err
!(
811 "{} is expected to take {}, but it takes {}",
817 err
.span_label(span
, format
!("expected {} that takes {}", kind
, expected_str
));
819 if let Some(found_span
) = found_span
{
820 err
.span_label(found_span
, format
!("takes {}", found_str
));
823 // ^^^^^^^^-- def_span
827 let prefix_span
= self.tcx
.sess
.source_map().span_until_non_whitespace(found_span
);
831 if let Some(span
) = found_span
.trim_start(prefix_span
) { span }
else { found_span }
;
833 // Suggest to take and ignore the arguments with expected_args_length `_`s if
834 // found arguments is empty (assume the user just wants to ignore args in this case).
835 // For example, if `expected_args_length` is 2, suggest `|_, _|`.
836 if found_args
.is_empty() && is_closure
{
837 let underscores
= vec
!["_"; expected_args
.len()].join(", ");
838 err
.span_suggestion_verbose(
841 "consider changing the closure to take and ignore the expected argument{}",
842 pluralize
!(expected_args
.len())
844 format
!("|{}|", underscores
),
845 Applicability
::MachineApplicable
,
849 if let &[ArgKind
::Tuple(_
, ref fields
)] = &found_args
[..] {
850 if fields
.len() == expected_args
.len() {
853 .map(|(name
, _
)| name
.to_owned())
854 .collect
::<Vec
<String
>>()
856 err
.span_suggestion_verbose(
858 "change the closure to take multiple arguments instead of a single tuple",
859 format
!("|{}|", sugg
),
860 Applicability
::MachineApplicable
,
864 if let &[ArgKind
::Tuple(_
, ref fields
)] = &expected_args
[..] {
865 if fields
.len() == found_args
.len() && is_closure
{
870 .map(|arg
| match arg
{
871 ArgKind
::Arg(name
, _
) => name
.to_owned(),
874 .collect
::<Vec
<String
>>()
876 // add type annotations if available
877 if found_args
.iter().any(|arg
| match arg
{
878 ArgKind
::Arg(_
, ty
) => ty
!= "_",
885 .map(|(_
, ty
)| ty
.to_owned())
886 .collect
::<Vec
<String
>>()
893 err
.span_suggestion_verbose(
895 "change the closure to accept a tuple instead of individual arguments",
897 Applicability
::MachineApplicable
,
907 trait InferCtxtPrivExt
<'tcx
> {
908 // returns if `cond` not occurring implies that `error` does not occur - i.e., that
909 // `error` occurring implies that `cond` occurs.
910 fn error_implies(&self, cond
: &ty
::Predicate
<'tcx
>, error
: &ty
::Predicate
<'tcx
>) -> bool
;
912 fn report_fulfillment_error(
914 error
: &FulfillmentError
<'tcx
>,
915 body_id
: Option
<hir
::BodyId
>,
916 fallback_has_occurred
: bool
,
919 fn report_projection_error(
921 obligation
: &PredicateObligation
<'tcx
>,
922 error
: &MismatchedProjectionTypes
<'tcx
>,
925 fn fuzzy_match_tys(&self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> bool
;
927 fn describe_generator(&self, body_id
: hir
::BodyId
) -> Option
<&'
static str>;
929 fn find_similar_impl_candidates(
931 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
932 ) -> Vec
<ty
::TraitRef
<'tcx
>>;
934 fn report_similar_impl_candidates(
936 impl_candidates
: Vec
<ty
::TraitRef
<'tcx
>>,
937 err
: &mut DiagnosticBuilder
<'_
>,
940 /// Gets the parent trait chain start
941 fn get_parent_trait_ref(
943 code
: &ObligationCauseCode
<'tcx
>,
944 ) -> Option
<(String
, Option
<Span
>)>;
946 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
947 /// with the same path as `trait_ref`, a help message about
948 /// a probable version mismatch is added to `err`
949 fn note_version_mismatch(
951 err
: &mut DiagnosticBuilder
<'_
>,
952 trait_ref
: &ty
::PolyTraitRef
<'tcx
>,
955 fn mk_obligation_for_def_id(
959 cause
: ObligationCause
<'tcx
>,
960 param_env
: ty
::ParamEnv
<'tcx
>,
961 ) -> PredicateObligation
<'tcx
>;
963 fn maybe_report_ambiguity(
965 obligation
: &PredicateObligation
<'tcx
>,
966 body_id
: Option
<hir
::BodyId
>,
969 fn predicate_can_apply(
971 param_env
: ty
::ParamEnv
<'tcx
>,
972 pred
: ty
::PolyTraitRef
<'tcx
>,
975 fn note_obligation_cause(
977 err
: &mut DiagnosticBuilder
<'_
>,
978 obligation
: &PredicateObligation
<'tcx
>,
981 fn suggest_unsized_bound_if_applicable(
983 err
: &mut DiagnosticBuilder
<'_
>,
984 obligation
: &PredicateObligation
<'tcx
>,
987 fn is_recursive_obligation(
989 obligated_types
: &mut Vec
<&ty
::TyS
<'tcx
>>,
990 cause_code
: &ObligationCauseCode
<'tcx
>,
994 impl<'a
, 'tcx
> InferCtxtPrivExt
<'tcx
> for InferCtxt
<'a
, 'tcx
> {
995 // returns if `cond` not occurring implies that `error` does not occur - i.e., that
996 // `error` occurring implies that `cond` occurs.
997 fn error_implies(&self, cond
: &ty
::Predicate
<'tcx
>, error
: &ty
::Predicate
<'tcx
>) -> bool
{
1002 let (cond
, error
) = match (cond
, error
) {
1003 (&ty
::Predicate
::Trait(..), &ty
::Predicate
::Trait(ref error
, _
)) => (cond
, error
),
1005 // FIXME: make this work in other cases too.
1010 for obligation
in super::elaborate_predicates(self.tcx
, std
::iter
::once(*cond
)) {
1011 if let ty
::Predicate
::Trait(implication
, _
) = obligation
.predicate
{
1012 let error
= error
.to_poly_trait_ref();
1013 let implication
= implication
.to_poly_trait_ref();
1014 // FIXME: I'm just not taking associated types at all here.
1015 // Eventually I'll need to implement param-env-aware
1016 // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic.
1017 let param_env
= ty
::ParamEnv
::empty();
1018 if self.can_sub(param_env
, error
, implication
).is_ok() {
1019 debug
!("error_implies: {:?} -> {:?} -> {:?}", cond
, error
, implication
);
1028 fn report_fulfillment_error(
1030 error
: &FulfillmentError
<'tcx
>,
1031 body_id
: Option
<hir
::BodyId
>,
1032 fallback_has_occurred
: bool
,
1034 debug
!("report_fulfillment_error({:?})", error
);
1036 FulfillmentErrorCode
::CodeSelectionError(ref selection_error
) => {
1037 self.report_selection_error(
1040 fallback_has_occurred
,
1041 error
.points_at_arg_span
,
1044 FulfillmentErrorCode
::CodeProjectionError(ref e
) => {
1045 self.report_projection_error(&error
.obligation
, e
);
1047 FulfillmentErrorCode
::CodeAmbiguity
=> {
1048 self.maybe_report_ambiguity(&error
.obligation
, body_id
);
1050 FulfillmentErrorCode
::CodeSubtypeError(ref expected_found
, ref err
) => {
1051 self.report_mismatched_types(
1052 &error
.obligation
.cause
,
1053 expected_found
.expected
,
1054 expected_found
.found
,
1062 fn report_projection_error(
1064 obligation
: &PredicateObligation
<'tcx
>,
1065 error
: &MismatchedProjectionTypes
<'tcx
>,
1067 let predicate
= self.resolve_vars_if_possible(&obligation
.predicate
);
1069 if predicate
.references_error() {
1075 let mut err
= &error
.err
;
1076 let mut values
= None
;
1078 // try to find the mismatched types to report the error with.
1080 // this can fail if the problem was higher-ranked, in which
1081 // cause I have no idea for a good error message.
1082 if let ty
::Predicate
::Projection(ref data
) = predicate
{
1083 let mut selcx
= SelectionContext
::new(self);
1084 let (data
, _
) = self.replace_bound_vars_with_fresh_vars(
1085 obligation
.cause
.span
,
1086 infer
::LateBoundRegionConversionTime
::HigherRankedType
,
1089 let mut obligations
= vec
![];
1090 let normalized_ty
= super::normalize_projection_type(
1092 obligation
.param_env
,
1094 obligation
.cause
.clone(),
1100 "report_projection_error obligation.cause={:?} obligation.param_env={:?}",
1101 obligation
.cause
, obligation
.param_env
1105 "report_projection_error normalized_ty={:?} data.ty={:?}",
1106 normalized_ty
, data
.ty
1109 let is_normalized_ty_expected
= match &obligation
.cause
.code
{
1110 ObligationCauseCode
::ItemObligation(_
)
1111 | ObligationCauseCode
::BindingObligation(_
, _
)
1112 | ObligationCauseCode
::ObjectCastObligation(_
) => false,
1116 if let Err(error
) = self.at(&obligation
.cause
, obligation
.param_env
).eq_exp(
1117 is_normalized_ty_expected
,
1121 values
= Some(infer
::ValuePairs
::Types(ExpectedFound
::new(
1122 is_normalized_ty_expected
,
1132 let msg
= format
!("type mismatch resolving `{}`", predicate
);
1133 let error_id
= (DiagnosticMessageId
::ErrorId(271), Some(obligation
.cause
.span
), msg
);
1134 let fresh
= self.tcx
.sess
.one_time_diagnostics
.borrow_mut().insert(error_id
);
1136 let mut diag
= struct_span_err
!(
1138 obligation
.cause
.span
,
1140 "type mismatch resolving `{}`",
1143 self.note_type_err(&mut diag
, &obligation
.cause
, None
, values
, err
);
1144 self.note_obligation_cause(&mut diag
, obligation
);
1150 fn fuzzy_match_tys(&self, a
: Ty
<'tcx
>, b
: Ty
<'tcx
>) -> bool
{
1151 /// returns the fuzzy category of a given type, or None
1152 /// if the type can be equated to any type.
1153 fn type_category(t
: Ty
<'_
>) -> Option
<u32> {
1155 ty
::Bool
=> Some(0),
1156 ty
::Char
=> Some(1),
1158 ty
::Int(..) | ty
::Uint(..) | ty
::Infer(ty
::IntVar(..)) => Some(3),
1159 ty
::Float(..) | ty
::Infer(ty
::FloatVar(..)) => Some(4),
1160 ty
::Ref(..) | ty
::RawPtr(..) => Some(5),
1161 ty
::Array(..) | ty
::Slice(..) => Some(6),
1162 ty
::FnDef(..) | ty
::FnPtr(..) => Some(7),
1163 ty
::Dynamic(..) => Some(8),
1164 ty
::Closure(..) => Some(9),
1165 ty
::Tuple(..) => Some(10),
1166 ty
::Projection(..) => Some(11),
1167 ty
::Param(..) => Some(12),
1168 ty
::Opaque(..) => Some(13),
1169 ty
::Never
=> Some(14),
1170 ty
::Adt(adt
, ..) => match adt
.adt_kind() {
1171 AdtKind
::Struct
=> Some(15),
1172 AdtKind
::Union
=> Some(16),
1173 AdtKind
::Enum
=> Some(17),
1175 ty
::Generator(..) => Some(18),
1176 ty
::Foreign(..) => Some(19),
1177 ty
::GeneratorWitness(..) => Some(20),
1178 ty
::Placeholder(..) | ty
::Bound(..) | ty
::Infer(..) | ty
::Error
=> None
,
1179 ty
::UnnormalizedProjection(..) => bug
!("only used with chalk-engine"),
1183 match (type_category(a
), type_category(b
)) {
1184 (Some(cat_a
), Some(cat_b
)) => match (&a
.kind
, &b
.kind
) {
1185 (&ty
::Adt(def_a
, _
), &ty
::Adt(def_b
, _
)) => def_a
== def_b
,
1186 _
=> cat_a
== cat_b
,
1188 // infer and error can be equated to all types
1193 fn describe_generator(&self, body_id
: hir
::BodyId
) -> Option
<&'
static str> {
1194 self.tcx
.hir().body(body_id
).generator_kind
.map(|gen_kind
| match gen_kind
{
1195 hir
::GeneratorKind
::Gen
=> "a generator",
1196 hir
::GeneratorKind
::Async(hir
::AsyncGeneratorKind
::Block
) => "an async block",
1197 hir
::GeneratorKind
::Async(hir
::AsyncGeneratorKind
::Fn
) => "an async function",
1198 hir
::GeneratorKind
::Async(hir
::AsyncGeneratorKind
::Closure
) => "an async closure",
1202 fn find_similar_impl_candidates(
1204 trait_ref
: ty
::PolyTraitRef
<'tcx
>,
1205 ) -> Vec
<ty
::TraitRef
<'tcx
>> {
1206 let simp
= fast_reject
::simplify_type(self.tcx
, trait_ref
.skip_binder().self_ty(), true);
1207 let all_impls
= self.tcx
.all_impls(trait_ref
.def_id());
1210 Some(simp
) => all_impls
1211 .filter_map(|def_id
| {
1212 let imp
= self.tcx
.impl_trait_ref(def_id
).unwrap();
1213 let imp_simp
= fast_reject
::simplify_type(self.tcx
, imp
.self_ty(), true);
1214 if let Some(imp_simp
) = imp_simp
{
1215 if simp
!= imp_simp
{
1222 None
=> all_impls
.map(|def_id
| self.tcx
.impl_trait_ref(def_id
).unwrap()).collect(),
1226 fn report_similar_impl_candidates(
1228 impl_candidates
: Vec
<ty
::TraitRef
<'tcx
>>,
1229 err
: &mut DiagnosticBuilder
<'_
>,
1231 if impl_candidates
.is_empty() {
1235 let len
= impl_candidates
.len();
1236 let end
= if impl_candidates
.len() <= 5 { impl_candidates.len() }
else { 4 }
;
1238 let normalize
= |candidate
| {
1239 self.tcx
.infer_ctxt().enter(|ref infcx
| {
1240 let normalized
= infcx
1241 .at(&ObligationCause
::dummy(), ty
::ParamEnv
::empty())
1242 .normalize(candidate
)
1245 Some(normalized
) => format
!("\n {:?}", normalized
.value
),
1246 None
=> format
!("\n {:?}", candidate
),
1251 // Sort impl candidates so that ordering is consistent for UI tests.
1252 let mut normalized_impl_candidates
=
1253 impl_candidates
.iter().map(normalize
).collect
::<Vec
<String
>>();
1255 // Sort before taking the `..end` range,
1256 // because the ordering of `impl_candidates` may not be deterministic:
1257 // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507
1258 normalized_impl_candidates
.sort();
1261 "the following implementations were found:{}{}",
1262 normalized_impl_candidates
[..end
].join(""),
1263 if len
> 5 { format!("\nand {} others
", len - 4) } else { String::new() }
1267 /// Gets the parent trait chain start
1268 fn get_parent_trait_ref(
1270 code: &ObligationCauseCode<'tcx>,
1271 ) -> Option<(String, Option<Span>)> {
1273 &ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
1274 let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref);
1275 match self.get_parent_trait_ref(&data.parent_code) {
1278 let ty = parent_trait_ref.skip_binder().self_ty();
1280 TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id));
1281 Some((ty.to_string(), span))
1289 /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait
1290 /// with the same path as `trait_ref`, a help message about
1291 /// a probable version mismatch is added to `err`
1292 fn note_version_mismatch(
1294 err: &mut DiagnosticBuilder<'_>,
1295 trait_ref: &ty::PolyTraitRef<'tcx>,
1297 let get_trait_impl = |trait_def_id| {
1298 let mut trait_impl = None;
1299 self.tcx.for_each_relevant_impl(trait_def_id, trait_ref.self_ty(), |impl_def_id| {
1300 if trait_impl.is_none() {
1301 trait_impl = Some(impl_def_id);
1306 let required_trait_path = self.tcx.def_path_str(trait_ref.def_id());
1307 let all_traits = self.tcx.all_traits(LOCAL_CRATE);
1308 let traits_with_same_path: std::collections::BTreeSet<_> = all_traits
1310 .filter(|trait_def_id| **trait_def_id != trait_ref.def_id())
1311 .filter(|trait_def_id| self.tcx.def_path_str(**trait_def_id) == required_trait_path)
1313 for trait_with_same_path in traits_with_same_path {
1314 if let Some(impl_def_id) = get_trait_impl(*trait_with_same_path) {
1315 let impl_span = self.tcx.def_span(impl_def_id);
1316 err.span_help(impl_span, "trait impl with same name found
");
1317 let trait_crate = self.tcx.crate_name(trait_with_same_path.krate);
1318 let crate_msg = format!(
1319 "perhaps two different versions of
crate `{}` are being used?
",
1322 err.note(&crate_msg);
1327 fn mk_obligation_for_def_id(
1330 output_ty: Ty<'tcx>,
1331 cause: ObligationCause<'tcx>,
1332 param_env: ty::ParamEnv<'tcx>,
1333 ) -> PredicateObligation<'tcx> {
1335 ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) };
1336 Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate())
1339 fn maybe_report_ambiguity(
1341 obligation: &PredicateObligation<'tcx>,
1342 body_id: Option<hir::BodyId>,
1344 // Unable to successfully determine, probably means
1345 // insufficient type information, but could mean
1346 // ambiguous impls. The latter *ought* to be a
1347 // coherence violation, so we don't report it here.
1349 let predicate = self.resolve_vars_if_possible(&obligation.predicate);
1350 let span = obligation.cause.span;
1353 "maybe_report_ambiguity(predicate
={:?}
, obligation
={:?} body_id
={:?}
, code
={:?}
)",
1354 predicate, obligation, body_id, obligation.cause.code,
1357 // Ambiguity errors are often caused as fallout from earlier
1358 // errors. So just ignore them if this infcx is tainted.
1359 if self.is_tainted_by_errors() {
1363 let mut err = match predicate {
1364 ty::Predicate::Trait(ref data, _) => {
1365 let trait_ref = data.to_poly_trait_ref();
1366 let self_ty = trait_ref.self_ty();
1367 debug!("self_ty {:?} {:?} trait_ref {:?}
", self_ty, self_ty.kind, trait_ref);
1369 if predicate.references_error() {
1372 // Typically, this ambiguity should only happen if
1373 // there are unresolved type inference variables
1374 // (otherwise it would suggest a coherence
1375 // failure). But given #21974 that is not necessarily
1376 // the case -- we can have multiple where clauses that
1377 // are only distinguished by a region, which results
1378 // in an ambiguity even when all types are fully
1379 // known, since we don't dispatch based on region
1382 // This is kind of a hack: it frequently happens that some earlier
1383 // error prevents types from being fully inferred, and then we get
1384 // a bunch of uninteresting errors saying something like "<generic
1385 // #0> doesn't implement Sized". It may even be true that we
1386 // could just skip over all checks where the self-ty is an
1387 // inference variable, but I was afraid that there might be an
1388 // inference variable created, registered as an obligation, and
1389 // then never forced by writeback, and hence by skipping here we'd
1390 // be ignoring the fact that we don't KNOW the type works
1391 // out. Though even that would probably be harmless, given that
1392 // we're only talking about builtin traits, which are known to be
1393 // inhabited. We used to check for `self.tcx.sess.has_errors()` to
1394 // avoid inundating the user with unnecessary errors, but we now
1395 // check upstream for type errors and don't add the obligations to
1396 // begin with in those cases.
1401 .map_or(false, |sized_id
| sized_id
== trait_ref
.def_id())
1403 self.need_type_info_err(body_id
, span
, self_ty
, ErrorCode
::E0282
).emit();
1406 let mut err
= self.need_type_info_err(body_id
, span
, self_ty
, ErrorCode
::E0283
);
1407 err
.note(&format
!("cannot satisfy `{}`", predicate
));
1408 if let ObligationCauseCode
::ItemObligation(def_id
) = obligation
.cause
.code
{
1409 self.suggest_fully_qualified_path(&mut err
, def_id
, span
, trait_ref
.def_id());
1412 ObligationCauseCode
::BindingObligation(ref def_id
, _
),
1414 (self.tcx
.sess
.source_map().span_to_snippet(span
), &obligation
.cause
.code
)
1416 let generics
= self.tcx
.generics_of(*def_id
);
1417 if generics
.params
.iter().any(|p
| p
.name
.as_str() != "Self")
1418 && !snippet
.ends_with('
>'
)
1420 // FIXME: To avoid spurious suggestions in functions where type arguments
1421 // where already supplied, we check the snippet to make sure it doesn't
1422 // end with a turbofish. Ideally we would have access to a `PathSegment`
1423 // instead. Otherwise we would produce the following output:
1425 // error[E0283]: type annotations needed
1426 // --> $DIR/issue-54954.rs:3:24
1428 // LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
1429 // | ^^^^^^^^^^^^^^^^^^^^^^^^^^
1431 // | cannot infer type
1432 // | help: consider specifying the type argument
1433 // | in the function call:
1434 // | `Tt::const_val::<[i8; 123]>::<T>`
1436 // LL | const fn const_val<T: Sized>() -> usize {
1437 // | - required by this bound in `Tt::const_val`
1439 // = note: cannot satisfy `_: Tt`
1441 err
.span_suggestion_verbose(
1442 span
.shrink_to_hi(),
1444 "consider specifying the type argument{} in the function call",
1445 pluralize
!(generics
.params
.len()),
1452 .map(|p
| p
.name
.to_string())
1453 .collect
::<Vec
<String
>>()
1456 Applicability
::HasPlaceholders
,
1463 ty
::Predicate
::WellFormed(ty
) => {
1464 // Same hacky approach as above to avoid deluging user
1465 // with error messages.
1466 if ty
.references_error() || self.tcx
.sess
.has_errors() {
1469 self.need_type_info_err(body_id
, span
, ty
, ErrorCode
::E0282
)
1472 ty
::Predicate
::Subtype(ref data
) => {
1473 if data
.references_error() || self.tcx
.sess
.has_errors() {
1474 // no need to overload user in such cases
1477 let &SubtypePredicate { a_is_expected: _, a, b }
= data
.skip_binder();
1478 // both must be type variables, or the other would've been instantiated
1479 assert
!(a
.is_ty_var() && b
.is_ty_var());
1480 self.need_type_info_err(body_id
, span
, a
, ErrorCode
::E0282
)
1482 ty
::Predicate
::Projection(ref data
) => {
1483 let trait_ref
= data
.to_poly_trait_ref(self.tcx
);
1484 let self_ty
= trait_ref
.self_ty();
1485 let ty
= data
.skip_binder().ty
;
1486 if predicate
.references_error() {
1489 if self_ty
.needs_infer() && ty
.needs_infer() {
1490 // We do this for the `foo.collect()?` case to produce a suggestion.
1491 let mut err
= self.need_type_info_err(body_id
, span
, self_ty
, ErrorCode
::E0284
);
1492 err
.note(&format
!("cannot satisfy `{}`", predicate
));
1495 let mut err
= struct_span_err
!(
1499 "type annotations needed: cannot satisfy `{}`",
1502 err
.span_label(span
, &format
!("cannot satisfy `{}`", predicate
));
1508 if self.tcx
.sess
.has_errors() {
1511 let mut err
= struct_span_err
!(
1515 "type annotations needed: cannot satisfy `{}`",
1518 err
.span_label(span
, &format
!("cannot satisfy `{}`", predicate
));
1522 self.note_obligation_cause(&mut err
, obligation
);
1526 /// Returns `true` if the trait predicate may apply for *some* assignment
1527 /// to the type parameters.
1528 fn predicate_can_apply(
1530 param_env
: ty
::ParamEnv
<'tcx
>,
1531 pred
: ty
::PolyTraitRef
<'tcx
>,
1533 struct ParamToVarFolder
<'a
, 'tcx
> {
1534 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
1535 var_map
: FxHashMap
<Ty
<'tcx
>, Ty
<'tcx
>>,
1538 impl<'a
, 'tcx
> TypeFolder
<'tcx
> for ParamToVarFolder
<'a
, 'tcx
> {
1539 fn tcx
<'b
>(&'b
self) -> TyCtxt
<'tcx
> {
1543 fn fold_ty(&mut self, ty
: Ty
<'tcx
>) -> Ty
<'tcx
> {
1544 if let ty
::Param(ty
::ParamTy { name, .. }
) = ty
.kind
{
1545 let infcx
= self.infcx
;
1546 self.var_map
.entry(ty
).or_insert_with(|| {
1547 infcx
.next_ty_var(TypeVariableOrigin
{
1548 kind
: TypeVariableOriginKind
::TypeParameterDefinition(name
, None
),
1553 ty
.super_fold_with(self)
1559 let mut selcx
= SelectionContext
::new(self);
1562 pred
.fold_with(&mut ParamToVarFolder { infcx: self, var_map: Default::default() }
);
1564 let cleaned_pred
= super::project
::normalize(
1567 ObligationCause
::dummy(),
1572 let obligation
= Obligation
::new(
1573 ObligationCause
::dummy(),
1575 cleaned_pred
.without_const().to_predicate(),
1578 self.predicate_may_hold(&obligation
)
1582 fn note_obligation_cause(
1584 err
: &mut DiagnosticBuilder
<'_
>,
1585 obligation
: &PredicateObligation
<'tcx
>,
1587 // First, attempt to add note to this error with an async-await-specific
1588 // message, and fall back to regular note otherwise.
1589 if !self.maybe_note_obligation_cause_for_async_await(err
, obligation
) {
1590 self.note_obligation_cause_code(
1592 &obligation
.predicate
,
1593 &obligation
.cause
.code
,
1596 self.suggest_unsized_bound_if_applicable(err
, obligation
);
1600 fn suggest_unsized_bound_if_applicable(
1602 err
: &mut DiagnosticBuilder
<'_
>,
1603 obligation
: &PredicateObligation
<'tcx
>,
1606 ty
::Predicate
::Trait(pred
, _
),
1607 ObligationCauseCode
::BindingObligation(item_def_id
, span
),
1608 ) = (&obligation
.predicate
, &obligation
.cause
.code
)
1610 if let (Some(generics
), true) = (
1611 self.tcx
.hir().get_if_local(*item_def_id
).as_ref().and_then(|n
| n
.generics()),
1612 Some(pred
.def_id()) == self.tcx
.lang_items().sized_trait(),
1614 for param
in generics
.params
{
1615 if param
.span
== *span
1616 && !param
.bounds
.iter().any(|bound
| {
1617 bound
.trait_ref().and_then(|trait_ref
| trait_ref
.trait_def_id())
1618 == self.tcx
.lang_items().sized_trait()
1621 let (span
, separator
) = match param
.bounds
{
1622 [] => (span
.shrink_to_hi(), ":"),
1623 [.., bound
] => (bound
.span().shrink_to_hi(), " + "),
1625 err
.span_suggestion_verbose(
1627 "consider relaxing the implicit `Sized` restriction",
1628 format
!("{} ?Sized", separator
),
1629 Applicability
::MachineApplicable
,
1638 fn is_recursive_obligation(
1640 obligated_types
: &mut Vec
<&ty
::TyS
<'tcx
>>,
1641 cause_code
: &ObligationCauseCode
<'tcx
>,
1643 if let ObligationCauseCode
::BuiltinDerivedObligation(ref data
) = cause_code
{
1644 let parent_trait_ref
= self.resolve_vars_if_possible(&data
.parent_trait_ref
);
1646 if obligated_types
.iter().any(|ot
| ot
== &parent_trait_ref
.skip_binder().self_ty()) {
1654 pub fn recursive_type_with_infinite_size_error(
1657 ) -> DiagnosticBuilder
<'tcx
> {
1658 assert
!(type_def_id
.is_local());
1659 let span
= tcx
.hir().span_if_local(type_def_id
).unwrap();
1660 let span
= tcx
.sess
.source_map().guess_head_span(span
);
1661 let mut err
= struct_span_err
!(
1665 "recursive type `{}` has infinite size",
1666 tcx
.def_path_str(type_def_id
)
1668 err
.span_label(span
, "recursive type has infinite size");
1670 "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
1671 at some point to make `{}` representable",
1672 tcx
.def_path_str(type_def_id
)
1677 /// Summarizes information
1680 /// An argument of non-tuple type. Parameters are (name, ty)
1681 Arg(String
, String
),
1683 /// An argument of tuple type. For a "found" argument, the span is
1684 /// the locationo in the source of the pattern. For a "expected"
1685 /// argument, it will be None. The vector is a list of (name, ty)
1686 /// strings for the components of the tuple.
1687 Tuple(Option
<Span
>, Vec
<(String
, String
)>),
1691 fn empty() -> ArgKind
{
1692 ArgKind
::Arg("_".to_owned(), "_".to_owned())
1695 /// Creates an `ArgKind` from the expected type of an
1696 /// argument. It has no name (`_`) and an optional source span.
1697 pub fn from_expected_ty(t
: Ty
<'_
>, span
: Option
<Span
>) -> ArgKind
{
1699 ty
::Tuple(ref tys
) => ArgKind
::Tuple(
1701 tys
.iter().map(|ty
| ("_".to_owned(), ty
.to_string())).collect
::<Vec
<_
>>(),
1703 _
=> ArgKind
::Arg("_".to_owned(), t
.to_string()),
1708 /// Suggest restricting a type param with a new bound.
1709 pub fn suggest_constraining_type_param(
1711 generics
: &hir
::Generics
<'_
>,
1712 err
: &mut DiagnosticBuilder
<'_
>,
1715 def_id
: Option
<DefId
>,
1717 let param
= generics
.params
.iter().find(|p
| p
.name
.ident().as_str() == param_name
);
1719 let param
= if let Some(param
) = param
{
1725 const MSG_RESTRICT_BOUND_FURTHER
: &str = "consider further restricting this bound";
1726 let msg_restrict_type
= format
!("consider restricting type parameter `{}`", param_name
);
1727 let msg_restrict_type_further
=
1728 format
!("consider further restricting type parameter `{}`", param_name
);
1730 if def_id
== tcx
.lang_items().sized_trait() {
1731 // Type parameters are already `Sized` by default.
1732 err
.span_label(param
.span
, &format
!("this type parameter needs to be `{}`", constraint
));
1735 let mut suggest_restrict
= |span
| {
1736 err
.span_suggestion_verbose(
1738 MSG_RESTRICT_BOUND_FURTHER
,
1739 format
!(" + {}", constraint
),
1740 Applicability
::MachineApplicable
,
1744 if param_name
.starts_with("impl ") {
1745 // If there's an `impl Trait` used in argument position, suggest
1748 // fn foo(t: impl Foo) { ... }
1751 // help: consider further restricting this bound with `+ Bar`
1753 // Suggestion for tools in this case is:
1755 // fn foo(t: impl Foo) { ... }
1758 // replace with: `impl Foo + Bar`
1760 suggest_restrict(param
.span
.shrink_to_hi());
1764 if generics
.where_clause
.predicates
.is_empty()
1765 // Given `trait Base<T = String>: Super<T>` where `T: Copy`, suggest restricting in the
1766 // `where` clause instead of `trait Base<T: Copy = String>: Super<T>`.
1767 && !matches
!(param
.kind
, hir
::GenericParamKind
::Type { default: Some(_), .. }
)
1769 if let Some(bounds_span
) = param
.bounds_span() {
1770 // If user has provided some bounds, suggest restricting them:
1772 // fn foo<T: Foo>(t: T) { ... }
1775 // help: consider further restricting this bound with `+ Bar`
1777 // Suggestion for tools in this case is:
1779 // fn foo<T: Foo>(t: T) { ... }
1782 // replace with: `T: Bar +`
1783 suggest_restrict(bounds_span
.shrink_to_hi());
1785 // If user hasn't provided any bounds, suggest adding a new one:
1787 // fn foo<T>(t: T) { ... }
1788 // - help: consider restricting this type parameter with `T: Foo`
1789 err
.span_suggestion_verbose(
1790 param
.span
.shrink_to_hi(),
1792 format
!(": {}", constraint
),
1793 Applicability
::MachineApplicable
,
1799 // This part is a bit tricky, because using the `where` clause user can
1800 // provide zero, one or many bounds for the same type parameter, so we
1801 // have following cases to consider:
1803 // 1) When the type parameter has been provided zero bounds
1806 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
1807 // - help: consider restricting this type parameter with `where X: Bar`
1810 // fn foo<X, Y>(x: X, y: Y) where Y: Foo { ... }
1811 // - insert: `, X: Bar`
1814 // 2) When the type parameter has been provided one bound
1817 // fn foo<T>(t: T) where T: Foo { ... }
1820 // help: consider further restricting this bound with `+ Bar`
1823 // fn foo<T>(t: T) where T: Foo { ... }
1826 // replace with: `T: Bar +`
1829 // 3) When the type parameter has been provided many bounds
1832 // fn foo<T>(t: T) where T: Foo, T: Bar {... }
1833 // - help: consider further restricting this type parameter with `where T: Zar`
1836 // fn foo<T>(t: T) where T: Foo, T: Bar {... }
1837 // - insert: `, T: Zar`
1839 let mut param_spans
= Vec
::new();
1841 for predicate
in generics
.where_clause
.predicates
{
1842 if let WherePredicate
::BoundPredicate(WhereBoundPredicate
{
1843 span
, bounded_ty
, ..
1846 if let TyKind
::Path(QPath
::Resolved(_
, path
)) = &bounded_ty
.kind
{
1847 if let Some(segment
) = path
.segments
.first() {
1848 if segment
.ident
.to_string() == param_name
{
1849 param_spans
.push(span
);
1856 let where_clause_span
= generics
.where_clause
.span_for_predicates_or_empty_place();
1857 // Account for `fn foo<T>(t: T) where T: Foo,` so we don't suggest two trailing commas.
1858 let mut trailing_comma
= false;
1859 if let Ok(snippet
) = tcx
.sess
.source_map().span_to_snippet(where_clause_span
) {
1860 trailing_comma
= snippet
.ends_with('
,'
);
1862 let where_clause_span
= if trailing_comma
{
1863 let hi
= where_clause_span
.hi();
1864 Span
::new(hi
- BytePos(1), hi
, where_clause_span
.ctxt())
1866 where_clause_span
.shrink_to_hi()
1869 match ¶m_spans
[..] {
1870 &[¶m_span
] => suggest_restrict(param_span
.shrink_to_hi()),
1872 err
.span_suggestion_verbose(
1874 &msg_restrict_type_further
,
1875 format
!(", {}: {}", param_name
, constraint
),
1876 Applicability
::MachineApplicable
,