]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/error.rs
Fmt and test revert
[rust.git] / compiler / rustc_middle / src / ty / error.rs
1 use crate::traits::{ObligationCause, ObligationCauseCode};
2 use crate::ty::diagnostics::suggest_constraining_type_param;
3 use crate::ty::print::{FmtPrinter, Printer};
4 use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
5 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
6 use rustc_errors::{pluralize, DiagnosticBuilder};
7 use rustc_hir as hir;
8 use rustc_hir::def_id::DefId;
9 use rustc_span::symbol::{sym, Symbol};
10 use rustc_span::{BytePos, MultiSpan, Span};
11 use rustc_target::spec::abi;
12
13 use std::borrow::Cow;
14 use std::fmt;
15
16 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
17 pub struct ExpectedFound<T> {
18     pub expected: T,
19     pub found: T,
20 }
21
22 impl<T> ExpectedFound<T> {
23     pub fn new(a_is_expected: bool, a: T, b: T) -> Self {
24         if a_is_expected {
25             ExpectedFound { expected: a, found: b }
26         } else {
27             ExpectedFound { expected: b, found: a }
28         }
29     }
30 }
31
32 // Data structures used in type unification
33 #[derive(Clone, Debug, TypeFoldable)]
34 pub enum TypeError<'tcx> {
35     Mismatch,
36     UnsafetyMismatch(ExpectedFound<hir::Unsafety>),
37     AbiMismatch(ExpectedFound<abi::Abi>),
38     Mutability,
39     TupleSize(ExpectedFound<usize>),
40     FixedArraySize(ExpectedFound<u64>),
41     ArgCount,
42
43     RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>),
44     RegionsInsufficientlyPolymorphic(BoundRegionKind, Region<'tcx>),
45     RegionsOverlyPolymorphic(BoundRegionKind, Region<'tcx>),
46     RegionsPlaceholderMismatch,
47
48     Sorts(ExpectedFound<Ty<'tcx>>),
49     IntMismatch(ExpectedFound<ty::IntVarValue>),
50     FloatMismatch(ExpectedFound<ty::FloatTy>),
51     Traits(ExpectedFound<DefId>),
52     VariadicMismatch(ExpectedFound<bool>),
53
54     /// Instantiating a type variable with the given type would have
55     /// created a cycle (because it appears somewhere within that
56     /// type).
57     CyclicTy(Ty<'tcx>),
58     CyclicConst(&'tcx ty::Const<'tcx>),
59     ProjectionMismatched(ExpectedFound<DefId>),
60     ExistentialMismatch(
61         ExpectedFound<&'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>>,
62     ),
63     ObjectUnsafeCoercion(DefId),
64     ConstMismatch(ExpectedFound<&'tcx ty::Const<'tcx>>),
65
66     IntrinsicCast,
67     /// Safe `#[target_feature]` functions are not assignable to safe function pointers.
68     TargetFeatureCast(DefId),
69 }
70
71 pub enum UnconstrainedNumeric {
72     UnconstrainedFloat,
73     UnconstrainedInt,
74     Neither,
75 }
76
77 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
78 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
79 /// afterwards to present additional details, particularly when it comes to lifetime-related
80 /// errors.
81 impl<'tcx> fmt::Display for TypeError<'tcx> {
82     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83         use self::TypeError::*;
84         fn report_maybe_different(
85             f: &mut fmt::Formatter<'_>,
86             expected: &str,
87             found: &str,
88         ) -> fmt::Result {
89             // A naive approach to making sure that we're not reporting silly errors such as:
90             // (expected closure, found closure).
91             if expected == found {
92                 write!(f, "expected {}, found a different {}", expected, found)
93             } else {
94                 write!(f, "expected {}, found {}", expected, found)
95             }
96         }
97
98         let br_string = |br: ty::BoundRegionKind| match br {
99             ty::BrNamed(_, name) => format!(" {}", name),
100             _ => String::new(),
101         };
102
103         match *self {
104             CyclicTy(_) => write!(f, "cyclic type of infinite size"),
105             CyclicConst(_) => write!(f, "encountered a self-referencing constant"),
106             Mismatch => write!(f, "types differ"),
107             UnsafetyMismatch(values) => {
108                 write!(f, "expected {} fn, found {} fn", values.expected, values.found)
109             }
110             AbiMismatch(values) => {
111                 write!(f, "expected {} fn, found {} fn", values.expected, values.found)
112             }
113             Mutability => write!(f, "types differ in mutability"),
114             TupleSize(values) => write!(
115                 f,
116                 "expected a tuple with {} element{}, \
117                            found one with {} element{}",
118                 values.expected,
119                 pluralize!(values.expected),
120                 values.found,
121                 pluralize!(values.found)
122             ),
123             FixedArraySize(values) => write!(
124                 f,
125                 "expected an array with a fixed size of {} element{}, \
126                            found one with {} element{}",
127                 values.expected,
128                 pluralize!(values.expected),
129                 values.found,
130                 pluralize!(values.found)
131             ),
132             ArgCount => write!(f, "incorrect number of function parameters"),
133             RegionsDoesNotOutlive(..) => write!(f, "lifetime mismatch"),
134             RegionsInsufficientlyPolymorphic(br, _) => write!(
135                 f,
136                 "expected bound lifetime parameter{}, found concrete lifetime",
137                 br_string(br)
138             ),
139             RegionsOverlyPolymorphic(br, _) => write!(
140                 f,
141                 "expected concrete lifetime, found bound lifetime parameter{}",
142                 br_string(br)
143             ),
144             RegionsPlaceholderMismatch => write!(f, "one type is more general than the other"),
145             Sorts(values) => ty::tls::with(|tcx| {
146                 report_maybe_different(
147                     f,
148                     &values.expected.sort_string(tcx),
149                     &values.found.sort_string(tcx),
150                 )
151             }),
152             Traits(values) => ty::tls::with(|tcx| {
153                 report_maybe_different(
154                     f,
155                     &format!("trait `{}`", tcx.def_path_str(values.expected)),
156                     &format!("trait `{}`", tcx.def_path_str(values.found)),
157                 )
158             }),
159             IntMismatch(ref values) => {
160                 write!(f, "expected `{:?}`, found `{:?}`", values.expected, values.found)
161             }
162             FloatMismatch(ref values) => {
163                 write!(f, "expected `{:?}`, found `{:?}`", values.expected, values.found)
164             }
165             VariadicMismatch(ref values) => write!(
166                 f,
167                 "expected {} fn, found {} function",
168                 if values.expected { "variadic" } else { "non-variadic" },
169                 if values.found { "variadic" } else { "non-variadic" }
170             ),
171             ProjectionMismatched(ref values) => ty::tls::with(|tcx| {
172                 write!(
173                     f,
174                     "expected {}, found {}",
175                     tcx.def_path_str(values.expected),
176                     tcx.def_path_str(values.found)
177                 )
178             }),
179             ExistentialMismatch(ref values) => report_maybe_different(
180                 f,
181                 &format!("trait `{}`", values.expected),
182                 &format!("trait `{}`", values.found),
183             ),
184             ConstMismatch(ref values) => {
185                 write!(f, "expected `{}`, found `{}`", values.expected, values.found)
186             }
187             IntrinsicCast => write!(f, "cannot coerce intrinsics to function pointers"),
188             TargetFeatureCast(_) => write!(
189                 f,
190                 "cannot coerce functions with `#[target_feature]` to safe function pointers"
191             ),
192             ObjectUnsafeCoercion(_) => write!(f, "coercion to object-unsafe trait object"),
193         }
194     }
195 }
196
197 impl<'tcx> TypeError<'tcx> {
198     pub fn must_include_note(&self) -> bool {
199         use self::TypeError::*;
200         match self {
201             CyclicTy(_) | CyclicConst(_) | UnsafetyMismatch(_) | Mismatch | AbiMismatch(_)
202             | FixedArraySize(_) | Sorts(_) | IntMismatch(_) | FloatMismatch(_)
203             | VariadicMismatch(_) | TargetFeatureCast(_) => false,
204
205             Mutability
206             | TupleSize(_)
207             | ArgCount
208             | RegionsDoesNotOutlive(..)
209             | RegionsInsufficientlyPolymorphic(..)
210             | RegionsOverlyPolymorphic(..)
211             | RegionsPlaceholderMismatch
212             | Traits(_)
213             | ProjectionMismatched(_)
214             | ExistentialMismatch(_)
215             | ConstMismatch(_)
216             | IntrinsicCast
217             | ObjectUnsafeCoercion(_) => true,
218         }
219     }
220 }
221
222 impl<'tcx> ty::TyS<'tcx> {
223     pub fn sort_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
224         match *self.kind() {
225             ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => {
226                 format!("`{}`", self).into()
227             }
228             ty::Tuple(ref tys) if tys.is_empty() => format!("`{}`", self).into(),
229
230             ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(),
231             ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(),
232             ty::Array(t, n) => {
233                 if t.is_simple_ty() {
234                     return format!("array `{}`", self).into();
235                 }
236
237                 let n = tcx.lift(n).unwrap();
238                 if let ty::ConstKind::Value(v) = n.val {
239                     if let Some(n) = v.try_to_machine_usize(tcx) {
240                         return format!("array of {} element{}", n, pluralize!(n)).into();
241                     }
242                 }
243                 "array".into()
244             }
245             ty::Slice(ty) if ty.is_simple_ty() => format!("slice `{}`", self).into(),
246             ty::Slice(_) => "slice".into(),
247             ty::RawPtr(_) => "*-ptr".into(),
248             ty::Ref(_, ty, mutbl) => {
249                 let tymut = ty::TypeAndMut { ty, mutbl };
250                 let tymut_string = tymut.to_string();
251                 if tymut_string != "_"
252                     && (ty.is_simple_text() || tymut_string.len() < "mutable reference".len())
253                 {
254                     format!("`&{}`", tymut_string).into()
255                 } else {
256                     // Unknown type name, it's long or has type arguments
257                     match mutbl {
258                         hir::Mutability::Mut => "mutable reference",
259                         _ => "reference",
260                     }
261                     .into()
262                 }
263             }
264             ty::FnDef(..) => "fn item".into(),
265             ty::FnPtr(_) => "fn pointer".into(),
266             ty::Dynamic(ref inner, ..) => {
267                 if let Some(principal) = inner.principal() {
268                     format!("trait object `dyn {}`", tcx.def_path_str(principal.def_id())).into()
269                 } else {
270                     "trait object".into()
271                 }
272             }
273             ty::Closure(..) => "closure".into(),
274             ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
275             ty::GeneratorWitness(..) => "generator witness".into(),
276             ty::Tuple(..) => "tuple".into(),
277             ty::Infer(ty::TyVar(_)) => "inferred type".into(),
278             ty::Infer(ty::IntVar(_)) => "integer".into(),
279             ty::Infer(ty::FloatVar(_)) => "floating-point number".into(),
280             ty::Placeholder(..) => "placeholder type".into(),
281             ty::Bound(..) => "bound type".into(),
282             ty::Infer(ty::FreshTy(_)) => "fresh type".into(),
283             ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(),
284             ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(),
285             ty::Projection(_) => "associated type".into(),
286             ty::Param(p) => format!("type parameter `{}`", p).into(),
287             ty::Opaque(..) => "opaque type".into(),
288             ty::Error(_) => "type error".into(),
289         }
290     }
291
292     pub fn prefix_string(&self, tcx: TyCtxt<'_>) -> Cow<'static, str> {
293         match *self.kind() {
294             ty::Infer(_)
295             | ty::Error(_)
296             | ty::Bool
297             | ty::Char
298             | ty::Int(_)
299             | ty::Uint(_)
300             | ty::Float(_)
301             | ty::Str
302             | ty::Never => "type".into(),
303             ty::Tuple(ref tys) if tys.is_empty() => "unit type".into(),
304             ty::Adt(def, _) => def.descr().into(),
305             ty::Foreign(_) => "extern type".into(),
306             ty::Array(..) => "array".into(),
307             ty::Slice(_) => "slice".into(),
308             ty::RawPtr(_) => "raw pointer".into(),
309             ty::Ref(.., mutbl) => match mutbl {
310                 hir::Mutability::Mut => "mutable reference",
311                 _ => "reference",
312             }
313             .into(),
314             ty::FnDef(..) => "fn item".into(),
315             ty::FnPtr(_) => "fn pointer".into(),
316             ty::Dynamic(..) => "trait object".into(),
317             ty::Closure(..) => "closure".into(),
318             ty::Generator(def_id, ..) => tcx.generator_kind(def_id).unwrap().descr().into(),
319             ty::GeneratorWitness(..) => "generator witness".into(),
320             ty::Tuple(..) => "tuple".into(),
321             ty::Placeholder(..) => "higher-ranked type".into(),
322             ty::Bound(..) => "bound type variable".into(),
323             ty::Projection(_) => "associated type".into(),
324             ty::Param(_) => "type parameter".into(),
325             ty::Opaque(..) => "opaque type".into(),
326         }
327     }
328 }
329
330 impl<'tcx> TyCtxt<'tcx> {
331     pub fn note_and_explain_type_err(
332         self,
333         db: &mut DiagnosticBuilder<'_>,
334         err: &TypeError<'tcx>,
335         cause: &ObligationCause<'tcx>,
336         sp: Span,
337         body_owner_def_id: DefId,
338     ) {
339         use self::TypeError::*;
340         debug!("note_and_explain_type_err err={:?} cause={:?}", err, cause);
341         match err {
342             Sorts(values) => {
343                 match (values.expected.kind(), values.found.kind()) {
344                     (ty::Closure(..), ty::Closure(..)) => {
345                         db.note("no two closures, even if identical, have the same type");
346                         db.help("consider boxing your closure and/or using it as a trait object");
347                     }
348                     (ty::Opaque(..), ty::Opaque(..)) => {
349                         // Issue #63167
350                         db.note("distinct uses of `impl Trait` result in different opaque types");
351                     }
352                     (ty::Float(_), ty::Infer(ty::IntVar(_))) => {
353                         if let Ok(
354                             // Issue #53280
355                             snippet,
356                         ) = self.sess.source_map().span_to_snippet(sp)
357                         {
358                             if snippet.chars().all(|c| c.is_digit(10) || c == '-' || c == '_') {
359                                 db.span_suggestion(
360                                     sp,
361                                     "use a float literal",
362                                     format!("{}.0", snippet),
363                                     MachineApplicable,
364                                 );
365                             }
366                         }
367                     }
368                     (ty::Param(expected), ty::Param(found)) => {
369                         let generics = self.generics_of(body_owner_def_id);
370                         let e_span = self.def_span(generics.type_param(expected, self).def_id);
371                         if !sp.contains(e_span) {
372                             db.span_label(e_span, "expected type parameter");
373                         }
374                         let f_span = self.def_span(generics.type_param(found, self).def_id);
375                         if !sp.contains(f_span) {
376                             db.span_label(f_span, "found type parameter");
377                         }
378                         db.note(
379                             "a type parameter was expected, but a different one was found; \
380                              you might be missing a type parameter or trait bound",
381                         );
382                         db.note(
383                             "for more information, visit \
384                              https://doc.rust-lang.org/book/ch10-02-traits.html\
385                              #traits-as-parameters",
386                         );
387                     }
388                     (ty::Projection(_), ty::Projection(_)) => {
389                         db.note("an associated type was expected, but a different one was found");
390                     }
391                     (ty::Param(p), ty::Projection(proj)) | (ty::Projection(proj), ty::Param(p)) => {
392                         let generics = self.generics_of(body_owner_def_id);
393                         let p_span = self.def_span(generics.type_param(p, self).def_id);
394                         if !sp.contains(p_span) {
395                             db.span_label(p_span, "this type parameter");
396                         }
397                         let hir = self.hir();
398                         let mut note = true;
399                         if let Some(generics) = generics
400                             .type_param(p, self)
401                             .def_id
402                             .as_local()
403                             .map(|id| hir.local_def_id_to_hir_id(id))
404                             .and_then(|id| self.hir().find(self.hir().get_parent_node(id)))
405                             .as_ref()
406                             .and_then(|node| node.generics())
407                         {
408                             // Synthesize the associated type restriction `Add<Output = Expected>`.
409                             // FIXME: extract this logic for use in other diagnostics.
410                             let (trait_ref, assoc_substs) = proj.trait_ref_and_own_substs(self);
411                             let path =
412                                 self.def_path_str_with_substs(trait_ref.def_id, trait_ref.substs);
413                             let item_name = self.item_name(proj.item_def_id);
414                             let item_args = self.format_generic_args(assoc_substs);
415
416                             let path = if path.ends_with('>') {
417                                 format!(
418                                     "{}, {}{} = {}>",
419                                     &path[..path.len() - 1],
420                                     item_name,
421                                     item_args,
422                                     p
423                                 )
424                             } else {
425                                 format!("{}<{}{} = {}>", path, item_name, item_args, p)
426                             };
427                             note = !suggest_constraining_type_param(
428                                 self,
429                                 generics,
430                                 db,
431                                 &format!("{}", proj.self_ty()),
432                                 &path,
433                                 None,
434                             );
435                         }
436                         if note {
437                             db.note("you might be missing a type parameter or trait bound");
438                         }
439                     }
440                     (ty::Param(p), ty::Dynamic(..) | ty::Opaque(..))
441                     | (ty::Dynamic(..) | ty::Opaque(..), ty::Param(p)) => {
442                         let generics = self.generics_of(body_owner_def_id);
443                         let p_span = self.def_span(generics.type_param(p, self).def_id);
444                         if !sp.contains(p_span) {
445                             db.span_label(p_span, "this type parameter");
446                         }
447                         db.help("type parameters must be constrained to match other types");
448                         if self.sess.teach(&db.get_code().unwrap()) {
449                             db.help(
450                                 "given a type parameter `T` and a method `foo`:
451 ```
452 trait Trait<T> { fn foo(&self) -> T; }
453 ```
454 the only ways to implement method `foo` are:
455 - constrain `T` with an explicit type:
456 ```
457 impl Trait<String> for X {
458     fn foo(&self) -> String { String::new() }
459 }
460 ```
461 - add a trait bound to `T` and call a method on that trait that returns `Self`:
462 ```
463 impl<T: std::default::Default> Trait<T> for X {
464     fn foo(&self) -> T { <T as std::default::Default>::default() }
465 }
466 ```
467 - change `foo` to return an argument of type `T`:
468 ```
469 impl<T> Trait<T> for X {
470     fn foo(&self, x: T) -> T { x }
471 }
472 ```",
473                             );
474                         }
475                         db.note(
476                             "for more information, visit \
477                              https://doc.rust-lang.org/book/ch10-02-traits.html\
478                              #traits-as-parameters",
479                         );
480                     }
481                     (ty::Param(p), ty::Closure(..) | ty::Generator(..)) => {
482                         let generics = self.generics_of(body_owner_def_id);
483                         let p_span = self.def_span(generics.type_param(p, self).def_id);
484                         if !sp.contains(p_span) {
485                             db.span_label(p_span, "this type parameter");
486                         }
487                         db.help(&format!(
488                             "every closure has a distinct type and so could not always match the \
489                              caller-chosen type of parameter `{}`",
490                             p
491                         ));
492                     }
493                     (ty::Param(p), _) | (_, ty::Param(p)) => {
494                         let generics = self.generics_of(body_owner_def_id);
495                         let p_span = self.def_span(generics.type_param(p, self).def_id);
496                         if !sp.contains(p_span) {
497                             db.span_label(p_span, "this type parameter");
498                         }
499                     }
500                     (ty::Projection(proj_ty), _) => {
501                         self.expected_projection(
502                             db,
503                             proj_ty,
504                             values,
505                             body_owner_def_id,
506                             &cause.code,
507                         );
508                     }
509                     (_, ty::Projection(proj_ty)) => {
510                         let msg = format!(
511                             "consider constraining the associated type `{}` to `{}`",
512                             values.found, values.expected,
513                         );
514                         if !self.suggest_constraint(
515                             db,
516                             &msg,
517                             body_owner_def_id,
518                             proj_ty,
519                             values.expected,
520                         ) {
521                             db.help(&msg);
522                             db.note(
523                                 "for more information, visit \
524                                 https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
525                             );
526                         }
527                     }
528                     _ => {}
529                 }
530                 debug!(
531                     "note_and_explain_type_err expected={:?} ({:?}) found={:?} ({:?})",
532                     values.expected,
533                     values.expected.kind(),
534                     values.found,
535                     values.found.kind(),
536                 );
537             }
538             CyclicTy(ty) => {
539                 // Watch out for various cases of cyclic types and try to explain.
540                 if ty.is_closure() || ty.is_generator() {
541                     db.note(
542                         "closures cannot capture themselves or take themselves as argument;\n\
543                          this error may be the result of a recent compiler bug-fix,\n\
544                          see issue #46062 <https://github.com/rust-lang/rust/issues/46062>\n\
545                          for more information",
546                     );
547                 }
548             }
549             TargetFeatureCast(def_id) => {
550                 let attrs = self.get_attrs(*def_id);
551                 let target_spans = attrs
552                     .iter()
553                     .filter(|attr| attr.has_name(sym::target_feature))
554                     .map(|attr| attr.span);
555                 db.note(
556                     "functions with `#[target_feature]` can only be coerced to `unsafe` function pointers"
557                 );
558                 db.span_labels(target_spans, "`#[target_feature]` added here");
559             }
560             _ => {}
561         }
562     }
563
564     fn suggest_constraint(
565         self,
566         db: &mut DiagnosticBuilder<'_>,
567         msg: &str,
568         body_owner_def_id: DefId,
569         proj_ty: &ty::ProjectionTy<'tcx>,
570         ty: Ty<'tcx>,
571     ) -> bool {
572         let assoc = self.associated_item(proj_ty.item_def_id);
573         let (trait_ref, assoc_substs) = proj_ty.trait_ref_and_own_substs(self);
574         if let Some(item) = self.hir().get_if_local(body_owner_def_id) {
575             if let Some(hir_generics) = item.generics() {
576                 // Get the `DefId` for the type parameter corresponding to `A` in `<A as T>::Foo`.
577                 // This will also work for `impl Trait`.
578                 let def_id = if let ty::Param(param_ty) = proj_ty.self_ty().kind() {
579                     let generics = self.generics_of(body_owner_def_id);
580                     generics.type_param(param_ty, self).def_id
581                 } else {
582                     return false;
583                 };
584
585                 // First look in the `where` clause, as this might be
586                 // `fn foo<T>(x: T) where T: Trait`.
587                 for predicate in hir_generics.where_clause.predicates {
588                     if let hir::WherePredicate::BoundPredicate(pred) = predicate {
589                         if let hir::TyKind::Path(hir::QPath::Resolved(None, path)) =
590                             pred.bounded_ty.kind
591                         {
592                             if path.res.opt_def_id() == Some(def_id) {
593                                 // This predicate is binding type param `A` in `<A as T>::Foo` to
594                                 // something, potentially `T`.
595                             } else {
596                                 continue;
597                             }
598                         } else {
599                             continue;
600                         }
601
602                         if self.constrain_generic_bound_associated_type_structured_suggestion(
603                             db,
604                             &trait_ref,
605                             pred.bounds,
606                             &assoc,
607                             assoc_substs,
608                             ty,
609                             msg,
610                         ) {
611                             return true;
612                         }
613                     }
614                 }
615                 for param in hir_generics.params {
616                     if self.hir().opt_local_def_id(param.hir_id).map(|id| id.to_def_id())
617                         == Some(def_id)
618                     {
619                         // This is type param `A` in `<A as T>::Foo`.
620                         return self.constrain_generic_bound_associated_type_structured_suggestion(
621                             db,
622                             &trait_ref,
623                             param.bounds,
624                             &assoc,
625                             assoc_substs,
626                             ty,
627                             msg,
628                         );
629                     }
630                 }
631             }
632         }
633         false
634     }
635
636     /// An associated type was expected and a different type was found.
637     ///
638     /// We perform a few different checks to see what we can suggest:
639     ///
640     ///  - In the current item, look for associated functions that return the expected type and
641     ///    suggest calling them. (Not a structured suggestion.)
642     ///  - If any of the item's generic bounds can be constrained, we suggest constraining the
643     ///    associated type to the found type.
644     ///  - If the associated type has a default type and was expected inside of a `trait`, we
645     ///    mention that this is disallowed.
646     ///  - If all other things fail, and the error is not because of a mismatch between the `trait`
647     ///    and the `impl`, we provide a generic `help` to constrain the assoc type or call an assoc
648     ///    fn that returns the type.
649     fn expected_projection(
650         self,
651         db: &mut DiagnosticBuilder<'_>,
652         proj_ty: &ty::ProjectionTy<'tcx>,
653         values: &ExpectedFound<Ty<'tcx>>,
654         body_owner_def_id: DefId,
655         cause_code: &ObligationCauseCode<'_>,
656     ) {
657         let msg = format!(
658             "consider constraining the associated type `{}` to `{}`",
659             values.expected, values.found
660         );
661         let body_owner = self.hir().get_if_local(body_owner_def_id);
662         let current_method_ident = body_owner.and_then(|n| n.ident()).map(|i| i.name);
663
664         // We don't want to suggest calling an assoc fn in a scope where that isn't feasible.
665         let callable_scope = matches!(
666             body_owner,
667             Some(
668                 hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(..), .. })
669                     | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
670                     | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }),
671             )
672         );
673         let impl_comparison = matches!(
674             cause_code,
675             ObligationCauseCode::CompareImplMethodObligation { .. }
676                 | ObligationCauseCode::CompareImplTypeObligation { .. }
677                 | ObligationCauseCode::CompareImplConstObligation
678         );
679         let assoc = self.associated_item(proj_ty.item_def_id);
680         if !callable_scope || impl_comparison {
681             // We do not want to suggest calling functions when the reason of the
682             // type error is a comparison of an `impl` with its `trait` or when the
683             // scope is outside of a `Body`.
684         } else {
685             // If we find a suitable associated function that returns the expected type, we don't
686             // want the more general suggestion later in this method about "consider constraining
687             // the associated type or calling a method that returns the associated type".
688             let point_at_assoc_fn = self.point_at_methods_that_satisfy_associated_type(
689                 db,
690                 assoc.container.id(),
691                 current_method_ident,
692                 proj_ty.item_def_id,
693                 values.expected,
694             );
695             // Possibly suggest constraining the associated type to conform to the
696             // found type.
697             if self.suggest_constraint(db, &msg, body_owner_def_id, proj_ty, values.found)
698                 || point_at_assoc_fn
699             {
700                 return;
701             }
702         }
703
704         if let ty::Opaque(def_id, _) = *proj_ty.self_ty().kind() {
705             // When the expected `impl Trait` is not defined in the current item, it will come from
706             // a return type. This can occur when dealing with `TryStream` (#71035).
707             if self.constrain_associated_type_structured_suggestion(
708                 db,
709                 self.def_span(def_id),
710                 &assoc,
711                 proj_ty.trait_ref_and_own_substs(self).1,
712                 values.found,
713                 &msg,
714             ) {
715                 return;
716             }
717         }
718
719         if self.point_at_associated_type(db, body_owner_def_id, values.found) {
720             return;
721         }
722
723         if !impl_comparison {
724             // Generic suggestion when we can't be more specific.
725             if callable_scope {
726                 db.help(&format!("{} or calling a method that returns `{}`", msg, values.expected));
727             } else {
728                 db.help(&msg);
729             }
730             db.note(
731                 "for more information, visit \
732                  https://doc.rust-lang.org/book/ch19-03-advanced-traits.html",
733             );
734         }
735         if self.sess.teach(&db.get_code().unwrap()) {
736             db.help(
737                 "given an associated type `T` and a method `foo`:
738 ```
739 trait Trait {
740 type T;
741 fn foo(&self) -> Self::T;
742 }
743 ```
744 the only way of implementing method `foo` is to constrain `T` with an explicit associated type:
745 ```
746 impl Trait for X {
747 type T = String;
748 fn foo(&self) -> Self::T { String::new() }
749 }
750 ```",
751             );
752         }
753     }
754
755     fn point_at_methods_that_satisfy_associated_type(
756         self,
757         db: &mut DiagnosticBuilder<'_>,
758         assoc_container_id: DefId,
759         current_method_ident: Option<Symbol>,
760         proj_ty_item_def_id: DefId,
761         expected: Ty<'tcx>,
762     ) -> bool {
763         let items = self.associated_items(assoc_container_id);
764         // Find all the methods in the trait that could be called to construct the
765         // expected associated type.
766         // FIXME: consider suggesting the use of associated `const`s.
767         let methods: Vec<(Span, String)> = items
768             .items
769             .iter()
770             .filter(|(name, item)| {
771                 ty::AssocKind::Fn == item.kind && Some(**name) != current_method_ident
772             })
773             .filter_map(|(_, item)| {
774                 let method = self.fn_sig(item.def_id);
775                 match *method.output().skip_binder().kind() {
776                     ty::Projection(ty::ProjectionTy { item_def_id, .. })
777                         if item_def_id == proj_ty_item_def_id =>
778                     {
779                         Some((
780                             self.sess.source_map().guess_head_span(self.def_span(item.def_id)),
781                             format!("consider calling `{}`", self.def_path_str(item.def_id)),
782                         ))
783                     }
784                     _ => None,
785                 }
786             })
787             .collect();
788         if !methods.is_empty() {
789             // Use a single `help:` to show all the methods in the trait that can
790             // be used to construct the expected associated type.
791             let mut span: MultiSpan =
792                 methods.iter().map(|(sp, _)| *sp).collect::<Vec<Span>>().into();
793             let msg = format!(
794                 "{some} method{s} {are} available that return{r} `{ty}`",
795                 some = if methods.len() == 1 { "a" } else { "some" },
796                 s = pluralize!(methods.len()),
797                 are = if methods.len() == 1 { "is" } else { "are" },
798                 r = if methods.len() == 1 { "s" } else { "" },
799                 ty = expected
800             );
801             for (sp, label) in methods.into_iter() {
802                 span.push_span_label(sp, label);
803             }
804             db.span_help(span, &msg);
805             return true;
806         }
807         false
808     }
809
810     fn point_at_associated_type(
811         self,
812         db: &mut DiagnosticBuilder<'_>,
813         body_owner_def_id: DefId,
814         found: Ty<'tcx>,
815     ) -> bool {
816         let hir_id =
817             match body_owner_def_id.as_local().map(|id| self.hir().local_def_id_to_hir_id(id)) {
818                 Some(hir_id) => hir_id,
819                 None => return false,
820             };
821         // When `body_owner` is an `impl` or `trait` item, look in its associated types for
822         // `expected` and point at it.
823         let parent_id = self.hir().get_parent_item(hir_id);
824         let item = self.hir().find(parent_id);
825         debug!("expected_projection parent item {:?}", item);
826         match item {
827             Some(hir::Node::Item(hir::Item { kind: hir::ItemKind::Trait(.., items), .. })) => {
828                 // FIXME: account for `#![feature(specialization)]`
829                 for item in &items[..] {
830                     match item.kind {
831                         hir::AssocItemKind::Type => {
832                             // FIXME: account for returning some type in a trait fn impl that has
833                             // an assoc type as a return type (#72076).
834                             if let hir::Defaultness::Default { has_value: true } = item.defaultness
835                             {
836                                 if self.type_of(item.id.def_id) == found {
837                                     db.span_label(
838                                         item.span,
839                                         "associated type defaults can't be assumed inside the \
840                                             trait defining them",
841                                     );
842                                     return true;
843                                 }
844                             }
845                         }
846                         _ => {}
847                     }
848                 }
849             }
850             Some(hir::Node::Item(hir::Item {
851                 kind: hir::ItemKind::Impl(hir::Impl { items, .. }),
852                 ..
853             })) => {
854                 for item in &items[..] {
855                     if let hir::AssocItemKind::Type = item.kind {
856                         if self.type_of(item.id.def_id) == found {
857                             db.span_label(item.span, "expected this associated type");
858                             return true;
859                         }
860                     }
861                 }
862             }
863             _ => {}
864         }
865         false
866     }
867
868     /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
869     /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
870     fn constrain_generic_bound_associated_type_structured_suggestion(
871         self,
872         db: &mut DiagnosticBuilder<'_>,
873         trait_ref: &ty::TraitRef<'tcx>,
874         bounds: hir::GenericBounds<'_>,
875         assoc: &ty::AssocItem,
876         assoc_substs: &[ty::GenericArg<'tcx>],
877         ty: Ty<'tcx>,
878         msg: &str,
879     ) -> bool {
880         // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
881         bounds.iter().any(|bound| match bound {
882             hir::GenericBound::Trait(ptr, hir::TraitBoundModifier::None) => {
883                 // Relate the type param against `T` in `<A as T>::Foo`.
884                 ptr.trait_ref.trait_def_id() == Some(trait_ref.def_id)
885                     && self.constrain_associated_type_structured_suggestion(
886                         db,
887                         ptr.span,
888                         assoc,
889                         assoc_substs,
890                         ty,
891                         msg,
892                     )
893             }
894             _ => false,
895         })
896     }
897
898     /// Given a span corresponding to a bound, provide a structured suggestion to set an
899     /// associated type to a given type `ty`.
900     fn constrain_associated_type_structured_suggestion(
901         self,
902         db: &mut DiagnosticBuilder<'_>,
903         span: Span,
904         assoc: &ty::AssocItem,
905         assoc_substs: &[ty::GenericArg<'tcx>],
906         ty: Ty<'tcx>,
907         msg: &str,
908     ) -> bool {
909         if let Ok(has_params) =
910             self.sess.source_map().span_to_snippet(span).map(|snippet| snippet.ends_with('>'))
911         {
912             let (span, sugg) = if has_params {
913                 let pos = span.hi() - BytePos(1);
914                 let span = Span::new(pos, pos, span.ctxt());
915                 (span, format!(", {} = {}", assoc.ident, ty))
916             } else {
917                 let item_args = self.format_generic_args(assoc_substs);
918                 (span.shrink_to_hi(), format!("<{}{} = {}>", assoc.ident, item_args, ty))
919             };
920             db.span_suggestion_verbose(span, msg, sugg, MaybeIncorrect);
921             return true;
922         }
923         false
924     }
925
926     fn format_generic_args(self, args: &[ty::GenericArg<'tcx>]) -> String {
927         let mut item_args = String::new();
928         FmtPrinter::new(self, &mut item_args, hir::def::Namespace::TypeNS)
929             .path_generic_args(Ok, args)
930             .expect("could not write to `String`.");
931         item_args
932     }
933 }