]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/error_reporting/mod.rs
Auto merge of #85806 - ATiltedTree:android-ndk-beta, r=petrochenkov
[rust.git] / compiler / rustc_infer / src / infer / error_reporting / mod.rs
1 //! Error Reporting Code for the inference engine
2 //!
3 //! Because of the way inference, and in particular region inference,
4 //! works, it often happens that errors are not detected until far after
5 //! the relevant line of code has been type-checked. Therefore, there is
6 //! an elaborate system to track why a particular constraint in the
7 //! inference graph arose so that we can explain to the user what gave
8 //! rise to a particular error.
9 //!
10 //! The basis of the system are the "origin" types. An "origin" is the
11 //! reason that a constraint or inference variable arose. There are
12 //! different "origin" enums for different kinds of constraints/variables
13 //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
14 //! a span, but also more information so that we can generate a meaningful
15 //! error message.
16 //!
17 //! Having a catalog of all the different reasons an error can arise is
18 //! also useful for other reasons, like cross-referencing FAQs etc, though
19 //! we are not really taking advantage of this yet.
20 //!
21 //! # Region Inference
22 //!
23 //! Region inference is particularly tricky because it always succeeds "in
24 //! the moment" and simply registers a constraint. Then, at the end, we
25 //! can compute the full graph and report errors, so we need to be able to
26 //! store and later report what gave rise to the conflicting constraints.
27 //!
28 //! # Subtype Trace
29 //!
30 //! Determining whether `T1 <: T2` often involves a number of subtypes and
31 //! subconstraints along the way. A "TypeTrace" is an extended version
32 //! of an origin that traces the types and other values that were being
33 //! compared. It is not necessarily comprehensive (in fact, at the time of
34 //! this writing it only tracks the root values being compared) but I'd
35 //! like to extend it to include significant "waypoints". For example, if
36 //! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
37 //! <: T4` fails, I'd like the trace to include enough information to say
38 //! "in the 2nd element of the tuple". Similarly, failures when comparing
39 //! arguments or return types in fn types should be able to cite the
40 //! specific position, etc.
41 //!
42 //! # Reality vs plan
43 //!
44 //! Of course, there is still a LOT of code in typeck that has yet to be
45 //! ported to this system, and which relies on string concatenation at the
46 //! time of error detection.
47
48 use super::lexical_region_resolve::RegionResolutionError;
49 use super::region_constraints::GenericKind;
50 use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs};
51
52 use crate::infer;
53 use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
54 use crate::traits::error_reporting::report_object_safety_error;
55 use crate::traits::{
56     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
57     StatementAsExpression,
58 };
59
60 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
61 use rustc_errors::{pluralize, struct_span_err};
62 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
63 use rustc_hir as hir;
64 use rustc_hir::def_id::DefId;
65 use rustc_hir::lang_items::LangItem;
66 use rustc_hir::{Item, ItemKind, Node};
67 use rustc_middle::ty::error::TypeError;
68 use rustc_middle::ty::{
69     self,
70     subst::{GenericArgKind, Subst, SubstsRef},
71     Region, Ty, TyCtxt, TypeFoldable,
72 };
73 use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
74 use rustc_target::spec::abi;
75 use std::ops::ControlFlow;
76 use std::{cmp, fmt, iter};
77
78 mod note;
79
80 mod need_type_info;
81 pub use need_type_info::TypeAnnotationNeeded;
82
83 pub mod nice_region_error;
84
85 pub(super) fn note_and_explain_region(
86     tcx: TyCtxt<'tcx>,
87     err: &mut DiagnosticBuilder<'_>,
88     prefix: &str,
89     region: ty::Region<'tcx>,
90     suffix: &str,
91 ) {
92     let (description, span) = match *region {
93         ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
94             msg_span_from_free_region(tcx, region)
95         }
96
97         ty::ReEmpty(ty::UniverseIndex::ROOT) => ("the empty lifetime".to_owned(), None),
98
99         // uh oh, hope no user ever sees THIS
100         ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None),
101
102         ty::RePlaceholder(_) => return,
103
104         // FIXME(#13998) RePlaceholder should probably print like
105         // ReFree rather than dumping Debug output on the user.
106         //
107         // We shouldn't really be having unification failures with ReVar
108         // and ReLateBound though.
109         ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
110             (format!("lifetime {:?}", region), None)
111         }
112     };
113
114     emit_msg_span(err, prefix, description, span, suffix);
115 }
116
117 pub(super) fn note_and_explain_free_region(
118     tcx: TyCtxt<'tcx>,
119     err: &mut DiagnosticBuilder<'_>,
120     prefix: &str,
121     region: ty::Region<'tcx>,
122     suffix: &str,
123 ) {
124     let (description, span) = msg_span_from_free_region(tcx, region);
125
126     emit_msg_span(err, prefix, description, span, suffix);
127 }
128
129 fn msg_span_from_free_region(
130     tcx: TyCtxt<'tcx>,
131     region: ty::Region<'tcx>,
132 ) -> (String, Option<Span>) {
133     match *region {
134         ty::ReEarlyBound(_) | ty::ReFree(_) => {
135             msg_span_from_early_bound_and_free_regions(tcx, region)
136         }
137         ty::ReStatic => ("the static lifetime".to_owned(), None),
138         ty::ReEmpty(ty::UniverseIndex::ROOT) => ("an empty lifetime".to_owned(), None),
139         ty::ReEmpty(ui) => (format!("an empty lifetime in universe {:?}", ui), None),
140         _ => bug!("{:?}", region),
141     }
142 }
143
144 fn msg_span_from_early_bound_and_free_regions(
145     tcx: TyCtxt<'tcx>,
146     region: ty::Region<'tcx>,
147 ) -> (String, Option<Span>) {
148     let sm = tcx.sess.source_map();
149
150     let scope = region.free_region_binding_scope(tcx);
151     let node = tcx.hir().local_def_id_to_hir_id(scope.expect_local());
152     let tag = match tcx.hir().find(node) {
153         Some(Node::Block(_) | Node::Expr(_)) => "body",
154         Some(Node::Item(it)) => item_scope_tag(&it),
155         Some(Node::TraitItem(it)) => trait_item_scope_tag(&it),
156         Some(Node::ImplItem(it)) => impl_item_scope_tag(&it),
157         Some(Node::ForeignItem(it)) => foreign_item_scope_tag(&it),
158         _ => unreachable!(),
159     };
160     let (prefix, span) = match *region {
161         ty::ReEarlyBound(ref br) => {
162             let mut sp = sm.guess_head_span(tcx.hir().span(node));
163             if let Some(param) =
164                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name))
165             {
166                 sp = param.span;
167             }
168             (format!("the lifetime `{}` as defined on", br.name), sp)
169         }
170         ty::ReFree(ty::FreeRegion {
171             bound_region: ty::BoundRegionKind::BrNamed(_, name), ..
172         }) => {
173             let mut sp = sm.guess_head_span(tcx.hir().span(node));
174             if let Some(param) =
175                 tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name))
176             {
177                 sp = param.span;
178             }
179             (format!("the lifetime `{}` as defined on", name), sp)
180         }
181         ty::ReFree(ref fr) => match fr.bound_region {
182             ty::BrAnon(idx) => {
183                 if let Some((ty, _)) = find_anon_type(tcx, region, &fr.bound_region) {
184                     ("the anonymous lifetime defined on".to_string(), ty.span)
185                 } else {
186                     (
187                         format!("the anonymous lifetime #{} defined on", idx + 1),
188                         tcx.hir().span(node),
189                     )
190                 }
191             }
192             _ => (
193                 format!("the lifetime `{}` as defined on", region),
194                 sm.guess_head_span(tcx.hir().span(node)),
195             ),
196         },
197         _ => bug!(),
198     };
199     let (msg, opt_span) = explain_span(tcx, tag, span);
200     (format!("{} {}", prefix, msg), opt_span)
201 }
202
203 fn emit_msg_span(
204     err: &mut DiagnosticBuilder<'_>,
205     prefix: &str,
206     description: String,
207     span: Option<Span>,
208     suffix: &str,
209 ) {
210     let message = format!("{}{}{}", prefix, description, suffix);
211
212     if let Some(span) = span {
213         err.span_note(span, &message);
214     } else {
215         err.note(&message);
216     }
217 }
218
219 fn item_scope_tag(item: &hir::Item<'_>) -> &'static str {
220     match item.kind {
221         hir::ItemKind::Impl { .. } => "impl",
222         hir::ItemKind::Struct(..) => "struct",
223         hir::ItemKind::Union(..) => "union",
224         hir::ItemKind::Enum(..) => "enum",
225         hir::ItemKind::Trait(..) => "trait",
226         hir::ItemKind::Fn(..) => "function body",
227         _ => "item",
228     }
229 }
230
231 fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str {
232     match item.kind {
233         hir::TraitItemKind::Fn(..) => "method body",
234         hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
235     }
236 }
237
238 fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str {
239     match item.kind {
240         hir::ImplItemKind::Fn(..) => "method body",
241         hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(..) => "associated item",
242     }
243 }
244
245 fn foreign_item_scope_tag(item: &hir::ForeignItem<'_>) -> &'static str {
246     match item.kind {
247         hir::ForeignItemKind::Fn(..) => "method body",
248         hir::ForeignItemKind::Static(..) | hir::ForeignItemKind::Type => "associated item",
249     }
250 }
251
252 fn explain_span(tcx: TyCtxt<'tcx>, heading: &str, span: Span) -> (String, Option<Span>) {
253     let lo = tcx.sess.source_map().lookup_char_pos(span.lo());
254     (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), Some(span))
255 }
256
257 pub fn unexpected_hidden_region_diagnostic(
258     tcx: TyCtxt<'tcx>,
259     span: Span,
260     hidden_ty: Ty<'tcx>,
261     hidden_region: ty::Region<'tcx>,
262 ) -> DiagnosticBuilder<'tcx> {
263     let mut err = struct_span_err!(
264         tcx.sess,
265         span,
266         E0700,
267         "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
268     );
269
270     // Explain the region we are capturing.
271     match hidden_region {
272         ty::ReEmpty(ty::UniverseIndex::ROOT) => {
273             // All lifetimes shorter than the function body are `empty` in
274             // lexical region resolution. The default explanation of "an empty
275             // lifetime" isn't really accurate here.
276             let message = format!(
277                 "hidden type `{}` captures lifetime smaller than the function body",
278                 hidden_ty
279             );
280             err.span_note(span, &message);
281         }
282         ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic | ty::ReEmpty(_) => {
283             // Assuming regionck succeeded (*), we ought to always be
284             // capturing *some* region from the fn header, and hence it
285             // ought to be free. So under normal circumstances, we will go
286             // down this path which gives a decent human readable
287             // explanation.
288             //
289             // (*) if not, the `tainted_by_errors` field would be set to
290             // `Some(ErrorReported)` in any case, so we wouldn't be here at all.
291             note_and_explain_free_region(
292                 tcx,
293                 &mut err,
294                 &format!("hidden type `{}` captures ", hidden_ty),
295                 hidden_region,
296                 "",
297             );
298         }
299         _ => {
300             // Ugh. This is a painful case: the hidden region is not one
301             // that we can easily summarize or explain. This can happen
302             // in a case like
303             // `src/test/ui/multiple-lifetimes/ordinary-bounds-unsuited.rs`:
304             //
305             // ```
306             // fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> {
307             //   if condition() { a } else { b }
308             // }
309             // ```
310             //
311             // Here the captured lifetime is the intersection of `'a` and
312             // `'b`, which we can't quite express.
313
314             // We can at least report a really cryptic error for now.
315             note_and_explain_region(
316                 tcx,
317                 &mut err,
318                 &format!("hidden type `{}` captures ", hidden_ty),
319                 hidden_region,
320                 "",
321             );
322         }
323     }
324
325     err
326 }
327
328 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
329     pub fn report_region_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>) {
330         debug!("report_region_errors(): {} errors to start", errors.len());
331
332         // try to pre-process the errors, which will group some of them
333         // together into a `ProcessedErrors` group:
334         let errors = self.process_errors(errors);
335
336         debug!("report_region_errors: {} errors after preprocessing", errors.len());
337
338         for error in errors {
339             debug!("report_region_errors: error = {:?}", error);
340
341             if !self.try_report_nice_region_error(&error) {
342                 match error.clone() {
343                     // These errors could indicate all manner of different
344                     // problems with many different solutions. Rather
345                     // than generate a "one size fits all" error, what we
346                     // attempt to do is go through a number of specific
347                     // scenarios and try to find the best way to present
348                     // the error. If all of these fails, we fall back to a rather
349                     // general bit of code that displays the error information
350                     RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
351                         if sub.is_placeholder() || sup.is_placeholder() {
352                             self.report_placeholder_failure(origin, sub, sup).emit();
353                         } else {
354                             self.report_concrete_failure(origin, sub, sup).emit();
355                         }
356                     }
357
358                     RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
359                         self.report_generic_bound_failure(
360                             origin.span(),
361                             Some(origin),
362                             param_ty,
363                             sub,
364                         );
365                     }
366
367                     RegionResolutionError::SubSupConflict(
368                         _,
369                         var_origin,
370                         sub_origin,
371                         sub_r,
372                         sup_origin,
373                         sup_r,
374                     ) => {
375                         if sub_r.is_placeholder() {
376                             self.report_placeholder_failure(sub_origin, sub_r, sup_r).emit();
377                         } else if sup_r.is_placeholder() {
378                             self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
379                         } else {
380                             self.report_sub_sup_conflict(
381                                 var_origin, sub_origin, sub_r, sup_origin, sup_r,
382                             );
383                         }
384                     }
385
386                     RegionResolutionError::UpperBoundUniverseConflict(
387                         _,
388                         _,
389                         var_universe,
390                         sup_origin,
391                         sup_r,
392                     ) => {
393                         assert!(sup_r.is_placeholder());
394
395                         // Make a dummy value for the "sub region" --
396                         // this is the initial value of the
397                         // placeholder. In practice, we expect more
398                         // tailored errors that don't really use this
399                         // value.
400                         let sub_r = self.tcx.mk_region(ty::ReEmpty(var_universe));
401
402                         self.report_placeholder_failure(sup_origin, sub_r, sup_r).emit();
403                     }
404
405                     RegionResolutionError::MemberConstraintFailure {
406                         hidden_ty,
407                         member_region,
408                         span,
409                     } => {
410                         let hidden_ty = self.resolve_vars_if_possible(hidden_ty);
411                         unexpected_hidden_region_diagnostic(
412                             self.tcx,
413                             span,
414                             hidden_ty,
415                             member_region,
416                         )
417                         .emit();
418                     }
419                 }
420             }
421         }
422     }
423
424     // This method goes through all the errors and try to group certain types
425     // of error together, for the purpose of suggesting explicit lifetime
426     // parameters to the user. This is done so that we can have a more
427     // complete view of what lifetimes should be the same.
428     // If the return value is an empty vector, it means that processing
429     // failed (so the return value of this method should not be used).
430     //
431     // The method also attempts to weed out messages that seem like
432     // duplicates that will be unhelpful to the end-user. But
433     // obviously it never weeds out ALL errors.
434     fn process_errors(
435         &self,
436         errors: &[RegionResolutionError<'tcx>],
437     ) -> Vec<RegionResolutionError<'tcx>> {
438         debug!("process_errors()");
439
440         // We want to avoid reporting generic-bound failures if we can
441         // avoid it: these have a very high rate of being unhelpful in
442         // practice. This is because they are basically secondary
443         // checks that test the state of the region graph after the
444         // rest of inference is done, and the other kinds of errors
445         // indicate that the region constraint graph is internally
446         // inconsistent, so these test results are likely to be
447         // meaningless.
448         //
449         // Therefore, we filter them out of the list unless they are
450         // the only thing in the list.
451
452         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
453             RegionResolutionError::GenericBoundFailure(..) => true,
454             RegionResolutionError::ConcreteFailure(..)
455             | RegionResolutionError::SubSupConflict(..)
456             | RegionResolutionError::UpperBoundUniverseConflict(..)
457             | RegionResolutionError::MemberConstraintFailure { .. } => false,
458         };
459
460         let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
461             errors.to_owned()
462         } else {
463             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
464         };
465
466         // sort the errors by span, for better error message stability.
467         errors.sort_by_key(|u| match *u {
468             RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
469             RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
470             RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
471             RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(),
472             RegionResolutionError::MemberConstraintFailure { span, .. } => span,
473         });
474         errors
475     }
476
477     /// Adds a note if the types come from similarly named crates
478     fn check_and_note_conflicting_crates(
479         &self,
480         err: &mut DiagnosticBuilder<'_>,
481         terr: &TypeError<'tcx>,
482     ) {
483         use hir::def_id::CrateNum;
484         use rustc_hir::definitions::DisambiguatedDefPathData;
485         use ty::print::Printer;
486         use ty::subst::GenericArg;
487
488         struct AbsolutePathPrinter<'tcx> {
489             tcx: TyCtxt<'tcx>,
490         }
491
492         struct NonTrivialPath;
493
494         impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
495             type Error = NonTrivialPath;
496
497             type Path = Vec<String>;
498             type Region = !;
499             type Type = !;
500             type DynExistential = !;
501             type Const = !;
502
503             fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
504                 self.tcx
505             }
506
507             fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
508                 Err(NonTrivialPath)
509             }
510
511             fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
512                 Err(NonTrivialPath)
513             }
514
515             fn print_dyn_existential(
516                 self,
517                 _predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
518             ) -> Result<Self::DynExistential, Self::Error> {
519                 Err(NonTrivialPath)
520             }
521
522             fn print_const(self, _ct: &'tcx ty::Const<'tcx>) -> Result<Self::Const, Self::Error> {
523                 Err(NonTrivialPath)
524             }
525
526             fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
527                 Ok(vec![self.tcx.crate_name(cnum).to_string()])
528             }
529             fn path_qualified(
530                 self,
531                 _self_ty: Ty<'tcx>,
532                 _trait_ref: Option<ty::TraitRef<'tcx>>,
533             ) -> Result<Self::Path, Self::Error> {
534                 Err(NonTrivialPath)
535             }
536
537             fn path_append_impl(
538                 self,
539                 _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
540                 _disambiguated_data: &DisambiguatedDefPathData,
541                 _self_ty: Ty<'tcx>,
542                 _trait_ref: Option<ty::TraitRef<'tcx>>,
543             ) -> Result<Self::Path, Self::Error> {
544                 Err(NonTrivialPath)
545             }
546             fn path_append(
547                 self,
548                 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
549                 disambiguated_data: &DisambiguatedDefPathData,
550             ) -> Result<Self::Path, Self::Error> {
551                 let mut path = print_prefix(self)?;
552                 path.push(disambiguated_data.to_string());
553                 Ok(path)
554             }
555             fn path_generic_args(
556                 self,
557                 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
558                 _args: &[GenericArg<'tcx>],
559             ) -> Result<Self::Path, Self::Error> {
560                 print_prefix(self)
561             }
562         }
563
564         let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
565             // Only external crates, if either is from a local
566             // module we could have false positives
567             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
568                 let abs_path =
569                     |def_id| AbsolutePathPrinter { tcx: self.tcx }.print_def_path(def_id, &[]);
570
571                 // We compare strings because DefPath can be different
572                 // for imported and non-imported crates
573                 let same_path = || -> Result<_, NonTrivialPath> {
574                     Ok(self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2)
575                         || abs_path(did1)? == abs_path(did2)?)
576                 };
577                 if same_path().unwrap_or(false) {
578                     let crate_name = self.tcx.crate_name(did1.krate);
579                     err.note(&format!(
580                         "perhaps two different versions of crate `{}` are being used?",
581                         crate_name
582                     ));
583                 }
584             }
585         };
586         match *terr {
587             TypeError::Sorts(ref exp_found) => {
588                 // if they are both "path types", there's a chance of ambiguity
589                 // due to different versions of the same crate
590                 if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _)) =
591                     (exp_found.expected.kind(), exp_found.found.kind())
592                 {
593                     report_path_match(err, exp_adt.did, found_adt.did);
594                 }
595             }
596             TypeError::Traits(ref exp_found) => {
597                 report_path_match(err, exp_found.expected, exp_found.found);
598             }
599             _ => (), // FIXME(#22750) handle traits and stuff
600         }
601     }
602
603     fn note_error_origin(
604         &self,
605         err: &mut DiagnosticBuilder<'tcx>,
606         cause: &ObligationCause<'tcx>,
607         exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
608     ) {
609         match cause.code {
610             ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
611                 let ty = self.resolve_vars_if_possible(root_ty);
612                 if ty.is_suggestable() {
613                     // don't show type `_`
614                     err.span_label(span, format!("this expression has type `{}`", ty));
615                 }
616                 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
617                     if ty.is_box() && ty.boxed_ty() == found {
618                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
619                             err.span_suggestion(
620                                 span,
621                                 "consider dereferencing the boxed value",
622                                 format!("*{}", snippet),
623                                 Applicability::MachineApplicable,
624                             );
625                         }
626                     }
627                 }
628             }
629             ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
630                 err.span_label(span, "expected due to this");
631             }
632             ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
633                 semi_span,
634                 source,
635                 ref prior_arms,
636                 last_ty,
637                 scrut_hir_id,
638                 opt_suggest_box_span,
639                 arm_span,
640                 scrut_span,
641                 ..
642             }) => match source {
643                 hir::MatchSource::IfLetDesugar { .. } => {
644                     let msg = "`if let` arms have incompatible types";
645                     err.span_label(cause.span, msg);
646                     if let Some(ret_sp) = opt_suggest_box_span {
647                         self.suggest_boxing_for_return_impl_trait(
648                             err,
649                             ret_sp,
650                             prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
651                         );
652                     }
653                 }
654                 hir::MatchSource::TryDesugar => {
655                     if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
656                         let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
657                         let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
658                             let arg_expr = args.first().expect("try desugaring call w/out arg");
659                             self.in_progress_typeck_results.and_then(|typeck_results| {
660                                 typeck_results.borrow().expr_ty_opt(arg_expr)
661                             })
662                         } else {
663                             bug!("try desugaring w/out call expr as scrutinee");
664                         };
665
666                         match scrut_ty {
667                             Some(ty) if expected == ty => {
668                                 let source_map = self.tcx.sess.source_map();
669                                 err.span_suggestion(
670                                     source_map.end_point(cause.span),
671                                     "try removing this `?`",
672                                     "".to_string(),
673                                     Applicability::MachineApplicable,
674                                 );
675                             }
676                             _ => {}
677                         }
678                     }
679                 }
680                 _ => {
681                     // `last_ty` can be `!`, `expected` will have better info when present.
682                     let t = self.resolve_vars_if_possible(match exp_found {
683                         Some(ty::error::ExpectedFound { expected, .. }) => expected,
684                         _ => last_ty,
685                     });
686                     let source_map = self.tcx.sess.source_map();
687                     let mut any_multiline_arm = source_map.is_multiline(arm_span);
688                     if prior_arms.len() <= 4 {
689                         for sp in prior_arms {
690                             any_multiline_arm |= source_map.is_multiline(*sp);
691                             err.span_label(*sp, format!("this is found to be of type `{}`", t));
692                         }
693                     } else if let Some(sp) = prior_arms.last() {
694                         any_multiline_arm |= source_map.is_multiline(*sp);
695                         err.span_label(
696                             *sp,
697                             format!("this and all prior arms are found to be of type `{}`", t),
698                         );
699                     }
700                     let outer_error_span = if any_multiline_arm {
701                         // Cover just `match` and the scrutinee expression, not
702                         // the entire match body, to reduce diagram noise.
703                         cause.span.shrink_to_lo().to(scrut_span)
704                     } else {
705                         cause.span
706                     };
707                     let msg = "`match` arms have incompatible types";
708                     err.span_label(outer_error_span, msg);
709                     if let Some((sp, boxed)) = semi_span {
710                         if let (StatementAsExpression::NeedsBoxing, [.., prior_arm]) =
711                             (boxed, &prior_arms[..])
712                         {
713                             err.multipart_suggestion(
714                                 "consider removing this semicolon and boxing the expressions",
715                                 vec![
716                                     (prior_arm.shrink_to_lo(), "Box::new(".to_string()),
717                                     (prior_arm.shrink_to_hi(), ")".to_string()),
718                                     (arm_span.shrink_to_lo(), "Box::new(".to_string()),
719                                     (arm_span.shrink_to_hi(), ")".to_string()),
720                                     (sp, String::new()),
721                                 ],
722                                 Applicability::HasPlaceholders,
723                             );
724                         } else if matches!(boxed, StatementAsExpression::NeedsBoxing) {
725                             err.span_suggestion_short(
726                                 sp,
727                                 "consider removing this semicolon and boxing the expressions",
728                                 String::new(),
729                                 Applicability::MachineApplicable,
730                             );
731                         } else {
732                             err.span_suggestion_short(
733                                 sp,
734                                 "consider removing this semicolon",
735                                 String::new(),
736                                 Applicability::MachineApplicable,
737                             );
738                         }
739                     }
740                     if let Some(ret_sp) = opt_suggest_box_span {
741                         // Get return type span and point to it.
742                         self.suggest_boxing_for_return_impl_trait(
743                             err,
744                             ret_sp,
745                             prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
746                         );
747                     }
748                 }
749             },
750             ObligationCauseCode::IfExpression(box IfExpressionCause {
751                 then,
752                 else_sp,
753                 outer,
754                 semicolon,
755                 opt_suggest_box_span,
756             }) => {
757                 err.span_label(then, "expected because of this");
758                 if let Some(sp) = outer {
759                     err.span_label(sp, "`if` and `else` have incompatible types");
760                 }
761                 if let Some((sp, boxed)) = semicolon {
762                     if matches!(boxed, StatementAsExpression::NeedsBoxing) {
763                         err.multipart_suggestion(
764                             "consider removing this semicolon and boxing the expression",
765                             vec![
766                                 (then.shrink_to_lo(), "Box::new(".to_string()),
767                                 (then.shrink_to_hi(), ")".to_string()),
768                                 (else_sp.shrink_to_lo(), "Box::new(".to_string()),
769                                 (else_sp.shrink_to_hi(), ")".to_string()),
770                                 (sp, String::new()),
771                             ],
772                             Applicability::MachineApplicable,
773                         );
774                     } else {
775                         err.span_suggestion_short(
776                             sp,
777                             "consider removing this semicolon",
778                             String::new(),
779                             Applicability::MachineApplicable,
780                         );
781                     }
782                 }
783                 if let Some(ret_sp) = opt_suggest_box_span {
784                     self.suggest_boxing_for_return_impl_trait(
785                         err,
786                         ret_sp,
787                         vec![then, else_sp].into_iter(),
788                     );
789                 }
790             }
791             _ => (),
792         }
793     }
794
795     fn suggest_boxing_for_return_impl_trait(
796         &self,
797         err: &mut DiagnosticBuilder<'tcx>,
798         return_sp: Span,
799         arm_spans: impl Iterator<Item = Span>,
800     ) {
801         err.multipart_suggestion(
802             "you could change the return type to be a boxed trait object",
803             vec![
804                 (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
805                 (return_sp.shrink_to_hi(), ">".to_string()),
806             ],
807             Applicability::MaybeIncorrect,
808         );
809         let sugg = arm_spans
810             .flat_map(|sp| {
811                 vec![
812                     (sp.shrink_to_lo(), "Box::new(".to_string()),
813                     (sp.shrink_to_hi(), ")".to_string()),
814                 ]
815                 .into_iter()
816             })
817             .collect::<Vec<_>>();
818         err.multipart_suggestion(
819             "if you change the return type to expect trait objects, box the returned expressions",
820             sugg,
821             Applicability::MaybeIncorrect,
822         );
823     }
824
825     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
826     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
827     /// populate `other_value` with `other_ty`.
828     ///
829     /// ```text
830     /// Foo<Bar<Qux>>
831     /// ^^^^--------^ this is highlighted
832     /// |   |
833     /// |   this type argument is exactly the same as the other type, not highlighted
834     /// this is highlighted
835     /// Bar<Qux>
836     /// -------- this type is the same as a type argument in the other type, not highlighted
837     /// ```
838     fn highlight_outer(
839         &self,
840         value: &mut DiagnosticStyledString,
841         other_value: &mut DiagnosticStyledString,
842         name: String,
843         sub: ty::subst::SubstsRef<'tcx>,
844         pos: usize,
845         other_ty: Ty<'tcx>,
846     ) {
847         // `value` and `other_value` hold two incomplete type representation for display.
848         // `name` is the path of both types being compared. `sub`
849         value.push_highlighted(name);
850         let len = sub.len();
851         if len > 0 {
852             value.push_highlighted("<");
853         }
854
855         // Output the lifetimes for the first type
856         let lifetimes = sub
857             .regions()
858             .map(|lifetime| {
859                 let s = lifetime.to_string();
860                 if s.is_empty() { "'_".to_string() } else { s }
861             })
862             .collect::<Vec<_>>()
863             .join(", ");
864         if !lifetimes.is_empty() {
865             if sub.regions().count() < len {
866                 value.push_normal(lifetimes + ", ");
867             } else {
868                 value.push_normal(lifetimes);
869             }
870         }
871
872         // Highlight all the type arguments that aren't at `pos` and compare the type argument at
873         // `pos` and `other_ty`.
874         for (i, type_arg) in sub.types().enumerate() {
875             if i == pos {
876                 let values = self.cmp(type_arg, other_ty);
877                 value.0.extend((values.0).0);
878                 other_value.0.extend((values.1).0);
879             } else {
880                 value.push_highlighted(type_arg.to_string());
881             }
882
883             if len > 0 && i != len - 1 {
884                 value.push_normal(", ");
885             }
886         }
887         if len > 0 {
888             value.push_highlighted(">");
889         }
890     }
891
892     /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
893     /// as that is the difference to the other type.
894     ///
895     /// For the following code:
896     ///
897     /// ```no_run
898     /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
899     /// ```
900     ///
901     /// The type error output will behave in the following way:
902     ///
903     /// ```text
904     /// Foo<Bar<Qux>>
905     /// ^^^^--------^ this is highlighted
906     /// |   |
907     /// |   this type argument is exactly the same as the other type, not highlighted
908     /// this is highlighted
909     /// Bar<Qux>
910     /// -------- this type is the same as a type argument in the other type, not highlighted
911     /// ```
912     fn cmp_type_arg(
913         &self,
914         mut t1_out: &mut DiagnosticStyledString,
915         mut t2_out: &mut DiagnosticStyledString,
916         path: String,
917         sub: ty::subst::SubstsRef<'tcx>,
918         other_path: String,
919         other_ty: Ty<'tcx>,
920     ) -> Option<()> {
921         for (i, ta) in sub.types().enumerate() {
922             if ta == other_ty {
923                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
924                 return Some(());
925             }
926             if let ty::Adt(def, _) = ta.kind() {
927                 let path_ = self.tcx.def_path_str(def.did);
928                 if path_ == other_path {
929                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
930                     return Some(());
931                 }
932             }
933         }
934         None
935     }
936
937     /// Adds a `,` to the type representation only if it is appropriate.
938     fn push_comma(
939         &self,
940         value: &mut DiagnosticStyledString,
941         other_value: &mut DiagnosticStyledString,
942         len: usize,
943         pos: usize,
944     ) {
945         if len > 0 && pos != len - 1 {
946             value.push_normal(", ");
947             other_value.push_normal(", ");
948         }
949     }
950
951     /// For generic types with parameters with defaults, remove the parameters corresponding to
952     /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
953     fn strip_generic_default_params(
954         &self,
955         def_id: DefId,
956         substs: ty::subst::SubstsRef<'tcx>,
957     ) -> SubstsRef<'tcx> {
958         let generics = self.tcx.generics_of(def_id);
959         let mut num_supplied_defaults = 0;
960
961         let default_params = generics.params.iter().rev().filter_map(|param| match param.kind {
962             ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id),
963             ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id),
964             _ => None,
965         });
966         for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
967             match actual.unpack() {
968                 GenericArgKind::Const(c) => {
969                     if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c {
970                         break;
971                     }
972                 }
973                 GenericArgKind::Type(ty) => {
974                     if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty {
975                         break;
976                     }
977                 }
978                 _ => break,
979             }
980             num_supplied_defaults += 1;
981         }
982         let len = generics.params.len();
983         let mut generics = generics.clone();
984         generics.params.truncate(len - num_supplied_defaults);
985         substs.truncate_to(self.tcx, &generics)
986     }
987
988     /// Given two `fn` signatures highlight only sub-parts that are different.
989     fn cmp_fn_sig(
990         &self,
991         sig1: &ty::PolyFnSig<'tcx>,
992         sig2: &ty::PolyFnSig<'tcx>,
993     ) -> (DiagnosticStyledString, DiagnosticStyledString) {
994         let get_lifetimes = |sig| {
995             use rustc_hir::def::Namespace;
996             let mut s = String::new();
997             let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS)
998                 .name_all_regions(sig)
999                 .unwrap();
1000             let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();
1001             (if lts.is_empty() { String::new() } else { format!("for<{}> ", lts.join(", ")) }, sig)
1002         };
1003
1004         let (lt1, sig1) = get_lifetimes(sig1);
1005         let (lt2, sig2) = get_lifetimes(sig2);
1006
1007         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1008         let mut values = (
1009             DiagnosticStyledString::normal("".to_string()),
1010             DiagnosticStyledString::normal("".to_string()),
1011         );
1012
1013         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1014         // ^^^^^^
1015         values.0.push(sig1.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
1016         values.1.push(sig2.unsafety.prefix_str(), sig1.unsafety != sig2.unsafety);
1017
1018         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1019         //        ^^^^^^^^^^
1020         if sig1.abi != abi::Abi::Rust {
1021             values.0.push(format!("extern {} ", sig1.abi), sig1.abi != sig2.abi);
1022         }
1023         if sig2.abi != abi::Abi::Rust {
1024             values.1.push(format!("extern {} ", sig2.abi), sig1.abi != sig2.abi);
1025         }
1026
1027         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1028         //                   ^^^^^^^^
1029         let lifetime_diff = lt1 != lt2;
1030         values.0.push(lt1, lifetime_diff);
1031         values.1.push(lt2, lifetime_diff);
1032
1033         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1034         //                           ^^^
1035         values.0.push_normal("fn(");
1036         values.1.push_normal("fn(");
1037
1038         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1039         //                              ^^^^^
1040         let len1 = sig1.inputs().len();
1041         let len2 = sig2.inputs().len();
1042         if len1 == len2 {
1043             for (i, (l, r)) in iter::zip(sig1.inputs(), sig2.inputs()).enumerate() {
1044                 let (x1, x2) = self.cmp(l, r);
1045                 (values.0).0.extend(x1.0);
1046                 (values.1).0.extend(x2.0);
1047                 self.push_comma(&mut values.0, &mut values.1, len1, i);
1048             }
1049         } else {
1050             for (i, l) in sig1.inputs().iter().enumerate() {
1051                 values.0.push_highlighted(l.to_string());
1052                 if i != len1 - 1 {
1053                     values.0.push_highlighted(", ");
1054                 }
1055             }
1056             for (i, r) in sig2.inputs().iter().enumerate() {
1057                 values.1.push_highlighted(r.to_string());
1058                 if i != len2 - 1 {
1059                     values.1.push_highlighted(", ");
1060                 }
1061             }
1062         }
1063
1064         if sig1.c_variadic {
1065             if len1 > 0 {
1066                 values.0.push_normal(", ");
1067             }
1068             values.0.push("...", !sig2.c_variadic);
1069         }
1070         if sig2.c_variadic {
1071             if len2 > 0 {
1072                 values.1.push_normal(", ");
1073             }
1074             values.1.push("...", !sig1.c_variadic);
1075         }
1076
1077         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1078         //                                   ^
1079         values.0.push_normal(")");
1080         values.1.push_normal(")");
1081
1082         // unsafe extern "C" for<'a> fn(&'a T) -> &'a T
1083         //                                     ^^^^^^^^
1084         let output1 = sig1.output();
1085         let output2 = sig2.output();
1086         let (x1, x2) = self.cmp(output1, output2);
1087         if !output1.is_unit() {
1088             values.0.push_normal(" -> ");
1089             (values.0).0.extend(x1.0);
1090         }
1091         if !output2.is_unit() {
1092             values.1.push_normal(" -> ");
1093             (values.1).0.extend(x2.0);
1094         }
1095         values
1096     }
1097
1098     /// Compares two given types, eliding parts that are the same between them and highlighting
1099     /// relevant differences, and return two representation of those types for highlighted printing.
1100     fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
1101         debug!("cmp(t1={}, t1.kind={:?}, t2={}, t2.kind={:?})", t1, t1.kind(), t2, t2.kind());
1102
1103         // helper functions
1104         fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
1105             match (a.kind(), b.kind()) {
1106                 (a, b) if *a == *b => true,
1107                 (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
1108                 | (
1109                     &ty::Infer(ty::InferTy::IntVar(_)),
1110                     &ty::Int(_) | &ty::Infer(ty::InferTy::IntVar(_)),
1111                 )
1112                 | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
1113                 | (
1114                     &ty::Infer(ty::InferTy::FloatVar(_)),
1115                     &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
1116                 ) => true,
1117                 _ => false,
1118             }
1119         }
1120
1121         fn push_ty_ref<'tcx>(
1122             region: &ty::Region<'tcx>,
1123             ty: Ty<'tcx>,
1124             mutbl: hir::Mutability,
1125             s: &mut DiagnosticStyledString,
1126         ) {
1127             let mut r = region.to_string();
1128             if r == "'_" {
1129                 r.clear();
1130             } else {
1131                 r.push(' ');
1132             }
1133             s.push_highlighted(format!("&{}{}", r, mutbl.prefix_str()));
1134             s.push_normal(ty.to_string());
1135         }
1136
1137         // process starts here
1138         match (t1.kind(), t2.kind()) {
1139             (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
1140                 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
1141                 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
1142                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1143                 let path1 = self.tcx.def_path_str(def1.did);
1144                 let path2 = self.tcx.def_path_str(def2.did);
1145                 if def1.did == def2.did {
1146                     // Easy case. Replace same types with `_` to shorten the output and highlight
1147                     // the differing ones.
1148                     //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
1149                     //     Foo<Bar, _>
1150                     //     Foo<Quz, _>
1151                     //         ---  ^ type argument elided
1152                     //         |
1153                     //         highlighted in output
1154                     values.0.push_normal(path1);
1155                     values.1.push_normal(path2);
1156
1157                     // Avoid printing out default generic parameters that are common to both
1158                     // types.
1159                     let len1 = sub_no_defaults_1.len();
1160                     let len2 = sub_no_defaults_2.len();
1161                     let common_len = cmp::min(len1, len2);
1162                     let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
1163                     let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
1164                     let common_default_params =
1165                         iter::zip(remainder1.iter().rev(), remainder2.iter().rev())
1166                             .filter(|(a, b)| a == b)
1167                             .count();
1168                     let len = sub1.len() - common_default_params;
1169                     let consts_offset = len - sub1.consts().count();
1170
1171                     // Only draw `<...>` if there're lifetime/type arguments.
1172                     if len > 0 {
1173                         values.0.push_normal("<");
1174                         values.1.push_normal("<");
1175                     }
1176
1177                     fn lifetime_display(lifetime: Region<'_>) -> String {
1178                         let s = lifetime.to_string();
1179                         if s.is_empty() { "'_".to_string() } else { s }
1180                     }
1181                     // At one point we'd like to elide all lifetimes here, they are irrelevant for
1182                     // all diagnostics that use this output
1183                     //
1184                     //     Foo<'x, '_, Bar>
1185                     //     Foo<'y, '_, Qux>
1186                     //         ^^  ^^  --- type arguments are not elided
1187                     //         |   |
1188                     //         |   elided as they were the same
1189                     //         not elided, they were different, but irrelevant
1190                     let lifetimes = sub1.regions().zip(sub2.regions());
1191                     for (i, lifetimes) in lifetimes.enumerate() {
1192                         let l1 = lifetime_display(lifetimes.0);
1193                         let l2 = lifetime_display(lifetimes.1);
1194                         if lifetimes.0 == lifetimes.1 {
1195                             values.0.push_normal("'_");
1196                             values.1.push_normal("'_");
1197                         } else {
1198                             values.0.push_highlighted(l1);
1199                             values.1.push_highlighted(l2);
1200                         }
1201                         self.push_comma(&mut values.0, &mut values.1, len, i);
1202                     }
1203
1204                     // We're comparing two types with the same path, so we compare the type
1205                     // arguments for both. If they are the same, do not highlight and elide from the
1206                     // output.
1207                     //     Foo<_, Bar>
1208                     //     Foo<_, Qux>
1209                     //         ^ elided type as this type argument was the same in both sides
1210                     let type_arguments = sub1.types().zip(sub2.types());
1211                     let regions_len = sub1.regions().count();
1212                     let num_display_types = consts_offset - regions_len;
1213                     for (i, (ta1, ta2)) in type_arguments.take(num_display_types).enumerate() {
1214                         let i = i + regions_len;
1215                         if ta1 == ta2 {
1216                             values.0.push_normal("_");
1217                             values.1.push_normal("_");
1218                         } else {
1219                             let (x1, x2) = self.cmp(ta1, ta2);
1220                             (values.0).0.extend(x1.0);
1221                             (values.1).0.extend(x2.0);
1222                         }
1223                         self.push_comma(&mut values.0, &mut values.1, len, i);
1224                     }
1225
1226                     // Do the same for const arguments, if they are equal, do not highlight and
1227                     // elide them from the output.
1228                     let const_arguments = sub1.consts().zip(sub2.consts());
1229                     for (i, (ca1, ca2)) in const_arguments.enumerate() {
1230                         let i = i + consts_offset;
1231                         if ca1 == ca2 {
1232                             values.0.push_normal("_");
1233                             values.1.push_normal("_");
1234                         } else {
1235                             values.0.push_highlighted(ca1.to_string());
1236                             values.1.push_highlighted(ca2.to_string());
1237                         }
1238                         self.push_comma(&mut values.0, &mut values.1, len, i);
1239                     }
1240
1241                     // Close the type argument bracket.
1242                     // Only draw `<...>` if there're lifetime/type arguments.
1243                     if len > 0 {
1244                         values.0.push_normal(">");
1245                         values.1.push_normal(">");
1246                     }
1247                     values
1248                 } else {
1249                     // Check for case:
1250                     //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
1251                     //     Foo<Bar<Qux>
1252                     //         ------- this type argument is exactly the same as the other type
1253                     //     Bar<Qux>
1254                     if self
1255                         .cmp_type_arg(
1256                             &mut values.0,
1257                             &mut values.1,
1258                             path1.clone(),
1259                             sub_no_defaults_1,
1260                             path2.clone(),
1261                             &t2,
1262                         )
1263                         .is_some()
1264                     {
1265                         return values;
1266                     }
1267                     // Check for case:
1268                     //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
1269                     //     Bar<Qux>
1270                     //     Foo<Bar<Qux>>
1271                     //         ------- this type argument is exactly the same as the other type
1272                     if self
1273                         .cmp_type_arg(
1274                             &mut values.1,
1275                             &mut values.0,
1276                             path2,
1277                             sub_no_defaults_2,
1278                             path1,
1279                             &t1,
1280                         )
1281                         .is_some()
1282                     {
1283                         return values;
1284                     }
1285
1286                     // We can't find anything in common, highlight relevant part of type path.
1287                     //     let x: foo::bar::Baz<Qux> = y:<foo::bar::Bar<Zar>>();
1288                     //     foo::bar::Baz<Qux>
1289                     //     foo::bar::Bar<Zar>
1290                     //               -------- this part of the path is different
1291
1292                     let t1_str = t1.to_string();
1293                     let t2_str = t2.to_string();
1294                     let min_len = t1_str.len().min(t2_str.len());
1295
1296                     const SEPARATOR: &str = "::";
1297                     let separator_len = SEPARATOR.len();
1298                     let split_idx: usize =
1299                         iter::zip(t1_str.split(SEPARATOR), t2_str.split(SEPARATOR))
1300                             .take_while(|(mod1_str, mod2_str)| mod1_str == mod2_str)
1301                             .map(|(mod_str, _)| mod_str.len() + separator_len)
1302                             .sum();
1303
1304                     debug!(
1305                         "cmp: separator_len={}, split_idx={}, min_len={}",
1306                         separator_len, split_idx, min_len
1307                     );
1308
1309                     if split_idx >= min_len {
1310                         // paths are identical, highlight everything
1311                         (
1312                             DiagnosticStyledString::highlighted(t1_str),
1313                             DiagnosticStyledString::highlighted(t2_str),
1314                         )
1315                     } else {
1316                         let (common, uniq1) = t1_str.split_at(split_idx);
1317                         let (_, uniq2) = t2_str.split_at(split_idx);
1318                         debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
1319
1320                         values.0.push_normal(common);
1321                         values.0.push_highlighted(uniq1);
1322                         values.1.push_normal(common);
1323                         values.1.push_highlighted(uniq2);
1324
1325                         values
1326                     }
1327                 }
1328             }
1329
1330             // When finding T != &T, highlight only the borrow
1331             (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
1332                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1333                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1334                 values.1.push_normal(t2.to_string());
1335                 values
1336             }
1337             (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
1338                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1339                 values.0.push_normal(t1.to_string());
1340                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1341                 values
1342             }
1343
1344             // When encountering &T != &mut T, highlight only the borrow
1345             (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
1346                 if equals(&ref_ty1, &ref_ty2) =>
1347             {
1348                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1349                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1350                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1351                 values
1352             }
1353
1354             // When encountering tuples of the same size, highlight only the differing types
1355             (&ty::Tuple(substs1), &ty::Tuple(substs2)) if substs1.len() == substs2.len() => {
1356                 let mut values =
1357                     (DiagnosticStyledString::normal("("), DiagnosticStyledString::normal("("));
1358                 let len = substs1.len();
1359                 for (i, (left, right)) in substs1.types().zip(substs2.types()).enumerate() {
1360                     let (x1, x2) = self.cmp(left, right);
1361                     (values.0).0.extend(x1.0);
1362                     (values.1).0.extend(x2.0);
1363                     self.push_comma(&mut values.0, &mut values.1, len, i);
1364                 }
1365                 if len == 1 {
1366                     // Keep the output for single element tuples as `(ty,)`.
1367                     values.0.push_normal(",");
1368                     values.1.push_normal(",");
1369                 }
1370                 values.0.push_normal(")");
1371                 values.1.push_normal(")");
1372                 values
1373             }
1374
1375             (ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
1376                 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1377                 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1378                 let mut values = self.cmp_fn_sig(&sig1, &sig2);
1379                 let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
1380                 let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
1381                 let same_path = path1 == path2;
1382                 values.0.push(path1, !same_path);
1383                 values.1.push(path2, !same_path);
1384                 values
1385             }
1386
1387             (ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
1388                 let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
1389                 let mut values = self.cmp_fn_sig(&sig1, sig2);
1390                 values.0.push_highlighted(format!(
1391                     " {{{}}}",
1392                     self.tcx.def_path_str_with_substs(*did1, substs1)
1393                 ));
1394                 values
1395             }
1396
1397             (ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
1398                 let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
1399                 let mut values = self.cmp_fn_sig(sig1, &sig2);
1400                 values.1.push_normal(format!(
1401                     " {{{}}}",
1402                     self.tcx.def_path_str_with_substs(*did2, substs2)
1403                 ));
1404                 values
1405             }
1406
1407             (ty::FnPtr(sig1), ty::FnPtr(sig2)) => self.cmp_fn_sig(sig1, sig2),
1408
1409             _ => {
1410                 if t1 == t2 {
1411                     // The two types are the same, elide and don't highlight.
1412                     (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
1413                 } else {
1414                     // We couldn't find anything in common, highlight everything.
1415                     (
1416                         DiagnosticStyledString::highlighted(t1.to_string()),
1417                         DiagnosticStyledString::highlighted(t2.to_string()),
1418                     )
1419                 }
1420             }
1421         }
1422     }
1423
1424     pub fn note_type_err(
1425         &self,
1426         diag: &mut DiagnosticBuilder<'tcx>,
1427         cause: &ObligationCause<'tcx>,
1428         secondary_span: Option<(Span, String)>,
1429         mut values: Option<ValuePairs<'tcx>>,
1430         terr: &TypeError<'tcx>,
1431     ) {
1432         let span = cause.span(self.tcx);
1433         debug!("note_type_err cause={:?} values={:?}, terr={:?}", cause, values, terr);
1434
1435         // For some types of errors, expected-found does not make
1436         // sense, so just ignore the values we were given.
1437         if let TypeError::CyclicTy(_) = terr {
1438             values = None;
1439         }
1440         struct OpaqueTypesVisitor<'tcx> {
1441             types: FxHashMap<TyCategory, FxHashSet<Span>>,
1442             expected: FxHashMap<TyCategory, FxHashSet<Span>>,
1443             found: FxHashMap<TyCategory, FxHashSet<Span>>,
1444             ignore_span: Span,
1445             tcx: TyCtxt<'tcx>,
1446         }
1447
1448         impl<'tcx> OpaqueTypesVisitor<'tcx> {
1449             fn visit_expected_found(
1450                 tcx: TyCtxt<'tcx>,
1451                 expected: Ty<'tcx>,
1452                 found: Ty<'tcx>,
1453                 ignore_span: Span,
1454             ) -> Self {
1455                 let mut types_visitor = OpaqueTypesVisitor {
1456                     types: Default::default(),
1457                     expected: Default::default(),
1458                     found: Default::default(),
1459                     ignore_span,
1460                     tcx,
1461                 };
1462                 // The visitor puts all the relevant encountered types in `self.types`, but in
1463                 // here we want to visit two separate types with no relation to each other, so we
1464                 // move the results from `types` to `expected` or `found` as appropriate.
1465                 expected.visit_with(&mut types_visitor);
1466                 std::mem::swap(&mut types_visitor.expected, &mut types_visitor.types);
1467                 found.visit_with(&mut types_visitor);
1468                 std::mem::swap(&mut types_visitor.found, &mut types_visitor.types);
1469                 types_visitor
1470             }
1471
1472             fn report(&self, err: &mut DiagnosticBuilder<'_>) {
1473                 self.add_labels_for_types(err, "expected", &self.expected);
1474                 self.add_labels_for_types(err, "found", &self.found);
1475             }
1476
1477             fn add_labels_for_types(
1478                 &self,
1479                 err: &mut DiagnosticBuilder<'_>,
1480                 target: &str,
1481                 types: &FxHashMap<TyCategory, FxHashSet<Span>>,
1482             ) {
1483                 for (key, values) in types.iter() {
1484                     let count = values.len();
1485                     let kind = key.descr();
1486                     let mut returned_async_output_error = false;
1487                     for sp in values {
1488                         err.span_label(
1489                             *sp,
1490                             format!(
1491                                 "{}{}{} {}{}",
1492                                 if sp.is_desugaring(DesugaringKind::Async)
1493                                     && !returned_async_output_error
1494                                 {
1495                                     "checked the `Output` of this `async fn`, "
1496                                 } else if count == 1 {
1497                                     "the "
1498                                 } else {
1499                                     ""
1500                                 },
1501                                 if count > 1 { "one of the " } else { "" },
1502                                 target,
1503                                 kind,
1504                                 pluralize!(count),
1505                             ),
1506                         );
1507                         if sp.is_desugaring(DesugaringKind::Async)
1508                             && returned_async_output_error == false
1509                         {
1510                             err.note("while checking the return type of the `async fn`");
1511                             returned_async_output_error = true;
1512                         }
1513                     }
1514                 }
1515             }
1516         }
1517
1518         impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
1519             fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
1520                 if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
1521                     let span = self.tcx.def_span(def_id);
1522                     // Avoid cluttering the output when the "found" and error span overlap:
1523                     //
1524                     // error[E0308]: mismatched types
1525                     //   --> $DIR/issue-20862.rs:2:5
1526                     //    |
1527                     // LL |     |y| x + y
1528                     //    |     ^^^^^^^^^
1529                     //    |     |
1530                     //    |     the found closure
1531                     //    |     expected `()`, found closure
1532                     //    |
1533                     //    = note: expected unit type `()`
1534                     //                 found closure `[closure@$DIR/issue-20862.rs:2:5: 2:14 x:_]`
1535                     if !self.ignore_span.overlaps(span) {
1536                         self.types.entry(kind).or_default().insert(span);
1537                     }
1538                 }
1539                 t.super_visit_with(self)
1540             }
1541         }
1542
1543         debug!("note_type_err(diag={:?})", diag);
1544         enum Mismatch<'a> {
1545             Variable(ty::error::ExpectedFound<Ty<'a>>),
1546             Fixed(&'static str),
1547         }
1548         let (expected_found, exp_found, is_simple_error) = match values {
1549             None => (None, Mismatch::Fixed("type"), false),
1550             Some(values) => {
1551                 let (is_simple_error, exp_found) = match values {
1552                     ValuePairs::Types(exp_found) => {
1553                         let is_simple_err =
1554                             exp_found.expected.is_simple_text() && exp_found.found.is_simple_text();
1555                         OpaqueTypesVisitor::visit_expected_found(
1556                             self.tcx,
1557                             exp_found.expected,
1558                             exp_found.found,
1559                             span,
1560                         )
1561                         .report(diag);
1562
1563                         (is_simple_err, Mismatch::Variable(exp_found))
1564                     }
1565                     ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")),
1566                     _ => (false, Mismatch::Fixed("type")),
1567                 };
1568                 let vals = match self.values_str(values) {
1569                     Some((expected, found)) => Some((expected, found)),
1570                     None => {
1571                         // Derived error. Cancel the emitter.
1572                         diag.cancel();
1573                         return;
1574                     }
1575                 };
1576                 (vals, exp_found, is_simple_error)
1577             }
1578         };
1579
1580         // Ignore msg for object safe coercion
1581         // since E0038 message will be printed
1582         match terr {
1583             TypeError::ObjectUnsafeCoercion(_) => {}
1584             _ => {
1585                 diag.span_label(span, terr.to_string());
1586                 if let Some((sp, msg)) = secondary_span {
1587                     diag.span_label(sp, msg);
1588                 }
1589             }
1590         };
1591         if let Some((expected, found)) = expected_found {
1592             let expected_label = match exp_found {
1593                 Mismatch::Variable(ef) => ef.expected.prefix_string(self.tcx),
1594                 Mismatch::Fixed(s) => s.into(),
1595             };
1596             let found_label = match exp_found {
1597                 Mismatch::Variable(ef) => ef.found.prefix_string(self.tcx),
1598                 Mismatch::Fixed(s) => s.into(),
1599             };
1600             let exp_found = match exp_found {
1601                 Mismatch::Variable(exp_found) => Some(exp_found),
1602                 Mismatch::Fixed(_) => None,
1603             };
1604             match (&terr, expected == found) {
1605                 (TypeError::Sorts(values), extra) => {
1606                     let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
1607                         (true, ty::Opaque(def_id, _)) => {
1608                             let pos = self
1609                                 .tcx
1610                                 .sess
1611                                 .source_map()
1612                                 .lookup_char_pos(self.tcx.def_span(*def_id).lo());
1613                             format!(
1614                                 " (opaque type at <{}:{}:{}>)",
1615                                 pos.file.name.prefer_local(),
1616                                 pos.line,
1617                                 pos.col.to_usize() + 1,
1618                             )
1619                         }
1620                         (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
1621                         (false, _) => "".to_string(),
1622                     };
1623                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
1624                         || (exp_found.map_or(false, |ef| {
1625                             // This happens when the type error is a subset of the expectation,
1626                             // like when you have two references but one is `usize` and the other
1627                             // is `f32`. In those cases we still want to show the `note`. If the
1628                             // value from `ef` is `Infer(_)`, then we ignore it.
1629                             if !ef.expected.is_ty_infer() {
1630                                 ef.expected != values.expected
1631                             } else if !ef.found.is_ty_infer() {
1632                                 ef.found != values.found
1633                             } else {
1634                                 false
1635                             }
1636                         }))
1637                     {
1638                         diag.note_expected_found_extra(
1639                             &expected_label,
1640                             expected,
1641                             &found_label,
1642                             found,
1643                             &sort_string(values.expected),
1644                             &sort_string(values.found),
1645                         );
1646                     }
1647                 }
1648                 (TypeError::ObjectUnsafeCoercion(_), _) => {
1649                     diag.note_unsuccessful_coercion(found, expected);
1650                 }
1651                 (_, _) => {
1652                     debug!(
1653                         "note_type_err: exp_found={:?}, expected={:?} found={:?}",
1654                         exp_found, expected, found
1655                     );
1656                     if !is_simple_error || terr.must_include_note() {
1657                         diag.note_expected_found(&expected_label, expected, &found_label, found);
1658                     }
1659                 }
1660             }
1661         }
1662         let exp_found = match exp_found {
1663             Mismatch::Variable(exp_found) => Some(exp_found),
1664             Mismatch::Fixed(_) => None,
1665         };
1666         let exp_found = match terr {
1667             // `terr` has more accurate type information than `exp_found` in match expressions.
1668             ty::error::TypeError::Sorts(terr)
1669                 if exp_found.map_or(false, |ef| terr.found == ef.found) =>
1670             {
1671                 Some(*terr)
1672             }
1673             _ => exp_found,
1674         };
1675         debug!("exp_found {:?} terr {:?}", exp_found, terr);
1676         if let Some(exp_found) = exp_found {
1677             self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
1678             self.suggest_accessing_field_where_appropriate(cause, &exp_found, diag);
1679             self.suggest_await_on_expect_found(cause, span, &exp_found, diag);
1680         }
1681
1682         // In some (most?) cases cause.body_id points to actual body, but in some cases
1683         // it's a actual definition. According to the comments (e.g. in
1684         // librustc_typeck/check/compare_method.rs:compare_predicate_entailment) the latter
1685         // is relied upon by some other code. This might (or might not) need cleanup.
1686         let body_owner_def_id =
1687             self.tcx.hir().opt_local_def_id(cause.body_id).unwrap_or_else(|| {
1688                 self.tcx.hir().body_owner_def_id(hir::BodyId { hir_id: cause.body_id })
1689             });
1690         self.check_and_note_conflicting_crates(diag, terr);
1691         self.tcx.note_and_explain_type_err(diag, terr, cause, span, body_owner_def_id.to_def_id());
1692
1693         if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values {
1694             if let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind() {
1695                 if let Some(def_id) = def_id.as_local() {
1696                     let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id);
1697                     let span = self.tcx.hir().span(hir_id);
1698                     diag.span_note(span, "this closure does not fulfill the lifetime requirements");
1699                 }
1700             }
1701         }
1702
1703         // It reads better to have the error origin as the final
1704         // thing.
1705         self.note_error_origin(diag, cause, exp_found);
1706     }
1707
1708     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
1709         if let ty::Opaque(def_id, substs) = ty.kind() {
1710             let future_trait = self.tcx.require_lang_item(LangItem::Future, None);
1711             // Future::Output
1712             let item_def_id = self
1713                 .tcx
1714                 .associated_items(future_trait)
1715                 .in_definition_order()
1716                 .next()
1717                 .unwrap()
1718                 .def_id;
1719
1720             let bounds = self.tcx.explicit_item_bounds(*def_id);
1721
1722             for (predicate, _) in bounds {
1723                 let predicate = predicate.subst(self.tcx, substs);
1724                 if let ty::PredicateKind::Projection(projection_predicate) =
1725                     predicate.kind().skip_binder()
1726                 {
1727                     if projection_predicate.projection_ty.item_def_id == item_def_id {
1728                         // We don't account for multiple `Future::Output = Ty` contraints.
1729                         return Some(projection_predicate.ty);
1730                     }
1731                 }
1732             }
1733         }
1734         None
1735     }
1736
1737     /// A possible error is to forget to add `.await` when using futures:
1738     ///
1739     /// ```
1740     /// async fn make_u32() -> u32 {
1741     ///     22
1742     /// }
1743     ///
1744     /// fn take_u32(x: u32) {}
1745     ///
1746     /// async fn foo() {
1747     ///     let x = make_u32();
1748     ///     take_u32(x);
1749     /// }
1750     /// ```
1751     ///
1752     /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
1753     /// expected type. If this is the case, and we are inside of an async body, it suggests adding
1754     /// `.await` to the tail of the expression.
1755     fn suggest_await_on_expect_found(
1756         &self,
1757         cause: &ObligationCause<'tcx>,
1758         exp_span: Span,
1759         exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1760         diag: &mut DiagnosticBuilder<'tcx>,
1761     ) {
1762         debug!(
1763             "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
1764             exp_span, exp_found.expected, exp_found.found,
1765         );
1766
1767         if let ObligationCauseCode::CompareImplMethodObligation { .. } = &cause.code {
1768             return;
1769         }
1770
1771         match (
1772             self.get_impl_future_output_ty(exp_found.expected),
1773             self.get_impl_future_output_ty(exp_found.found),
1774         ) {
1775             (Some(exp), Some(found)) if ty::TyS::same_type(exp, found) => match &cause.code {
1776                 ObligationCauseCode::IfExpression(box IfExpressionCause { then, .. }) => {
1777                     diag.multipart_suggestion(
1778                         "consider `await`ing on both `Future`s",
1779                         vec![
1780                             (then.shrink_to_hi(), ".await".to_string()),
1781                             (exp_span.shrink_to_hi(), ".await".to_string()),
1782                         ],
1783                         Applicability::MaybeIncorrect,
1784                     );
1785                 }
1786                 ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
1787                     prior_arms,
1788                     ..
1789                 }) => {
1790                     if let [.., arm_span] = &prior_arms[..] {
1791                         diag.multipart_suggestion(
1792                             "consider `await`ing on both `Future`s",
1793                             vec![
1794                                 (arm_span.shrink_to_hi(), ".await".to_string()),
1795                                 (exp_span.shrink_to_hi(), ".await".to_string()),
1796                             ],
1797                             Applicability::MaybeIncorrect,
1798                         );
1799                     } else {
1800                         diag.help("consider `await`ing on both `Future`s");
1801                     }
1802                 }
1803                 _ => {
1804                     diag.help("consider `await`ing on both `Future`s");
1805                 }
1806             },
1807             (_, Some(ty)) if ty::TyS::same_type(exp_found.expected, ty) => {
1808                 let span = match cause.code {
1809                     // scrutinee's span
1810                     ObligationCauseCode::Pattern { span: Some(span), .. } => span,
1811                     _ => exp_span,
1812                 };
1813                 diag.span_suggestion_verbose(
1814                     span.shrink_to_hi(),
1815                     "consider `await`ing on the `Future`",
1816                     ".await".to_string(),
1817                     Applicability::MaybeIncorrect,
1818                 );
1819             }
1820             (Some(ty), _) if ty::TyS::same_type(ty, exp_found.found) => {
1821                 let span = match cause.code {
1822                     // scrutinee's span
1823                     ObligationCauseCode::Pattern { span: Some(span), .. } => span,
1824                     _ => exp_span,
1825                 };
1826                 diag.span_suggestion_verbose(
1827                     span.shrink_to_hi(),
1828                     "consider `await`ing on the `Future`",
1829                     ".await".to_string(),
1830                     Applicability::MaybeIncorrect,
1831                 );
1832             }
1833             _ => {}
1834         }
1835     }
1836
1837     fn suggest_accessing_field_where_appropriate(
1838         &self,
1839         cause: &ObligationCause<'tcx>,
1840         exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1841         diag: &mut DiagnosticBuilder<'tcx>,
1842     ) {
1843         debug!(
1844             "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
1845             cause, exp_found
1846         );
1847         if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
1848             if expected_def.is_enum() {
1849                 return;
1850             }
1851
1852             if let Some((name, ty)) = expected_def
1853                 .non_enum_variant()
1854                 .fields
1855                 .iter()
1856                 .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
1857                 .map(|field| (field.ident.name, field.ty(self.tcx, expected_substs)))
1858                 .find(|(_, ty)| ty::TyS::same_type(ty, exp_found.found))
1859             {
1860                 if let ObligationCauseCode::Pattern { span: Some(span), .. } = cause.code {
1861                     if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
1862                         let suggestion = if expected_def.is_struct() {
1863                             format!("{}.{}", snippet, name)
1864                         } else if expected_def.is_union() {
1865                             format!("unsafe {{ {}.{} }}", snippet, name)
1866                         } else {
1867                             return;
1868                         };
1869                         diag.span_suggestion(
1870                             span,
1871                             &format!(
1872                                 "you might have meant to use field `{}` whose type is `{}`",
1873                                 name, ty
1874                             ),
1875                             suggestion,
1876                             Applicability::MaybeIncorrect,
1877                         );
1878                     }
1879                 }
1880             }
1881         }
1882     }
1883
1884     /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
1885     /// suggests it.
1886     fn suggest_as_ref_where_appropriate(
1887         &self,
1888         span: Span,
1889         exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1890         diag: &mut DiagnosticBuilder<'tcx>,
1891     ) {
1892         if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
1893             (exp_found.expected.kind(), exp_found.found.kind())
1894         {
1895             if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
1896                 let path_str = format!("{:?}", exp_def);
1897                 if exp_def == &found_def {
1898                     let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
1899                                        `.as_ref()`";
1900                     let result_msg = "you can convert from `&Result<T, E>` to \
1901                                           `Result<&T, &E>` using `.as_ref()`";
1902                     let have_as_ref = &[
1903                         ("std::option::Option", opt_msg),
1904                         ("core::option::Option", opt_msg),
1905                         ("std::result::Result", result_msg),
1906                         ("core::result::Result", result_msg),
1907                     ];
1908                     if let Some(msg) = have_as_ref
1909                         .iter()
1910                         .find_map(|(path, msg)| (&path_str == path).then_some(msg))
1911                     {
1912                         let mut show_suggestion = true;
1913                         for (exp_ty, found_ty) in
1914                             iter::zip(exp_substs.types(), found_substs.types())
1915                         {
1916                             match *exp_ty.kind() {
1917                                 ty::Ref(_, exp_ty, _) => {
1918                                     match (exp_ty.kind(), found_ty.kind()) {
1919                                         (_, ty::Param(_))
1920                                         | (_, ty::Infer(_))
1921                                         | (ty::Param(_), _)
1922                                         | (ty::Infer(_), _) => {}
1923                                         _ if ty::TyS::same_type(exp_ty, found_ty) => {}
1924                                         _ => show_suggestion = false,
1925                                     };
1926                                 }
1927                                 ty::Param(_) | ty::Infer(_) => {}
1928                                 _ => show_suggestion = false,
1929                             }
1930                         }
1931                         if let (Ok(snippet), true) =
1932                             (self.tcx.sess.source_map().span_to_snippet(span), show_suggestion)
1933                         {
1934                             diag.span_suggestion(
1935                                 span,
1936                                 msg,
1937                                 format!("{}.as_ref()", snippet),
1938                                 Applicability::MachineApplicable,
1939                             );
1940                         }
1941                     }
1942                 }
1943             }
1944         }
1945     }
1946
1947     pub fn report_and_explain_type_error(
1948         &self,
1949         trace: TypeTrace<'tcx>,
1950         terr: &TypeError<'tcx>,
1951     ) -> DiagnosticBuilder<'tcx> {
1952         debug!("report_and_explain_type_error(trace={:?}, terr={:?})", trace, terr);
1953
1954         let span = trace.cause.span(self.tcx);
1955         let failure_code = trace.cause.as_failure_code(terr);
1956         let mut diag = match failure_code {
1957             FailureCode::Error0038(did) => {
1958                 let violations = self.tcx.object_safety_violations(did);
1959                 report_object_safety_error(self.tcx, span, did, violations)
1960             }
1961             FailureCode::Error0317(failure_str) => {
1962                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
1963             }
1964             FailureCode::Error0580(failure_str) => {
1965                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
1966             }
1967             FailureCode::Error0308(failure_str) => {
1968                 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
1969             }
1970             FailureCode::Error0644(failure_str) => {
1971                 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
1972             }
1973         };
1974         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
1975         diag
1976     }
1977
1978     fn values_str(
1979         &self,
1980         values: ValuePairs<'tcx>,
1981     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
1982         match values {
1983             infer::Types(exp_found) => self.expected_found_str_ty(exp_found),
1984             infer::Regions(exp_found) => self.expected_found_str(exp_found),
1985             infer::Consts(exp_found) => self.expected_found_str(exp_found),
1986             infer::TraitRefs(exp_found) => {
1987                 let pretty_exp_found = ty::error::ExpectedFound {
1988                     expected: exp_found.expected.print_only_trait_path(),
1989                     found: exp_found.found.print_only_trait_path(),
1990                 };
1991                 self.expected_found_str(pretty_exp_found)
1992             }
1993             infer::PolyTraitRefs(exp_found) => {
1994                 let pretty_exp_found = ty::error::ExpectedFound {
1995                     expected: exp_found.expected.print_only_trait_path(),
1996                     found: exp_found.found.print_only_trait_path(),
1997                 };
1998                 self.expected_found_str(pretty_exp_found)
1999             }
2000         }
2001     }
2002
2003     fn expected_found_str_ty(
2004         &self,
2005         exp_found: ty::error::ExpectedFound<Ty<'tcx>>,
2006     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
2007         let exp_found = self.resolve_vars_if_possible(exp_found);
2008         if exp_found.references_error() {
2009             return None;
2010         }
2011
2012         Some(self.cmp(exp_found.expected, exp_found.found))
2013     }
2014
2015     /// Returns a string of the form "expected `{}`, found `{}`".
2016     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
2017         &self,
2018         exp_found: ty::error::ExpectedFound<T>,
2019     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
2020         let exp_found = self.resolve_vars_if_possible(exp_found);
2021         if exp_found.references_error() {
2022             return None;
2023         }
2024
2025         Some((
2026             DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
2027             DiagnosticStyledString::highlighted(exp_found.found.to_string()),
2028         ))
2029     }
2030
2031     pub fn report_generic_bound_failure(
2032         &self,
2033         span: Span,
2034         origin: Option<SubregionOrigin<'tcx>>,
2035         bound_kind: GenericKind<'tcx>,
2036         sub: Region<'tcx>,
2037     ) {
2038         self.construct_generic_bound_failure(span, origin, bound_kind, sub).emit();
2039     }
2040
2041     pub fn construct_generic_bound_failure(
2042         &self,
2043         span: Span,
2044         origin: Option<SubregionOrigin<'tcx>>,
2045         bound_kind: GenericKind<'tcx>,
2046         sub: Region<'tcx>,
2047     ) -> DiagnosticBuilder<'a> {
2048         let hir = &self.tcx.hir();
2049         // Attempt to obtain the span of the parameter so we can
2050         // suggest adding an explicit lifetime bound to it.
2051         let generics = self
2052             .in_progress_typeck_results
2053             .map(|typeck_results| typeck_results.borrow().hir_owner)
2054             .map(|owner| {
2055                 let hir_id = hir.local_def_id_to_hir_id(owner);
2056                 let parent_id = hir.get_parent_item(hir_id);
2057                 (
2058                     // Parent item could be a `mod`, so we check the HIR before calling:
2059                     if let Some(Node::Item(Item {
2060                         kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
2061                         ..
2062                     })) = hir.find(parent_id)
2063                     {
2064                         Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
2065                     } else {
2066                         None
2067                     },
2068                     self.tcx.generics_of(owner.to_def_id()),
2069                 )
2070             });
2071         let type_param_span = match (generics, bound_kind) {
2072             (Some((_, ref generics)), GenericKind::Param(ref param)) => {
2073                 // Account for the case where `param` corresponds to `Self`,
2074                 // which doesn't have the expected type argument.
2075                 if !(generics.has_self && param.index == 0) {
2076                     let type_param = generics.type_param(param, self.tcx);
2077                     type_param.def_id.as_local().map(|def_id| {
2078                         // Get the `hir::Param` to verify whether it already has any bounds.
2079                         // We do this to avoid suggesting code that ends up as `T: 'a'b`,
2080                         // instead we suggest `T: 'a + 'b` in that case.
2081                         let id = hir.local_def_id_to_hir_id(def_id);
2082                         let mut has_bounds = false;
2083                         if let Node::GenericParam(param) = hir.get(id) {
2084                             has_bounds = !param.bounds.is_empty();
2085                         }
2086                         let sp = hir.span(id);
2087                         // `sp` only covers `T`, change it so that it covers
2088                         // `T:` when appropriate
2089                         let is_impl_trait = bound_kind.to_string().starts_with("impl ");
2090                         let sp = if has_bounds && !is_impl_trait {
2091                             sp.to(self
2092                                 .tcx
2093                                 .sess
2094                                 .source_map()
2095                                 .next_point(self.tcx.sess.source_map().next_point(sp)))
2096                         } else {
2097                             sp
2098                         };
2099                         (sp, has_bounds, is_impl_trait)
2100                     })
2101                 } else {
2102                     None
2103                 }
2104             }
2105             _ => None,
2106         };
2107         let new_lt = generics
2108             .as_ref()
2109             .and_then(|(parent_g, g)| {
2110                 let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect();
2111                 let mut lts_names = g
2112                     .params
2113                     .iter()
2114                     .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
2115                     .map(|p| p.name.as_str())
2116                     .collect::<Vec<_>>();
2117                 if let Some(g) = parent_g {
2118                     lts_names.extend(
2119                         g.params
2120                             .iter()
2121                             .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
2122                             .map(|p| p.name.as_str()),
2123                     );
2124                 }
2125                 let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
2126                 possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str()))
2127             })
2128             .unwrap_or("'lt".to_string());
2129         let add_lt_sugg = generics
2130             .as_ref()
2131             .and_then(|(_, g)| g.params.first())
2132             .and_then(|param| param.def_id.as_local())
2133             .map(|def_id| {
2134                 (
2135                     hir.span(hir.local_def_id_to_hir_id(def_id)).shrink_to_lo(),
2136                     format!("{}, ", new_lt),
2137                 )
2138             });
2139
2140         let labeled_user_string = match bound_kind {
2141             GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
2142             GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
2143         };
2144
2145         if let Some(SubregionOrigin::CompareImplMethodObligation {
2146             span,
2147             item_name,
2148             impl_item_def_id,
2149             trait_item_def_id,
2150         }) = origin
2151         {
2152             return self.report_extra_impl_obligation(
2153                 span,
2154                 item_name,
2155                 impl_item_def_id,
2156                 trait_item_def_id,
2157                 &format!("`{}: {}`", bound_kind, sub),
2158             );
2159         }
2160
2161         fn binding_suggestion<'tcx, S: fmt::Display>(
2162             err: &mut DiagnosticBuilder<'tcx>,
2163             type_param_span: Option<(Span, bool, bool)>,
2164             bound_kind: GenericKind<'tcx>,
2165             sub: S,
2166         ) {
2167             let msg = "consider adding an explicit lifetime bound";
2168             if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
2169                 let suggestion = if is_impl_trait {
2170                     format!("{} + {}", bound_kind, sub)
2171                 } else {
2172                     let tail = if has_lifetimes { " + " } else { "" };
2173                     format!("{}: {}{}", bound_kind, sub, tail)
2174                 };
2175                 err.span_suggestion(
2176                     sp,
2177                     &format!("{}...", msg),
2178                     suggestion,
2179                     Applicability::MaybeIncorrect, // Issue #41966
2180                 );
2181             } else {
2182                 let consider = format!(
2183                     "{} {}...",
2184                     msg,
2185                     if type_param_span.map_or(false, |(_, _, is_impl_trait)| is_impl_trait) {
2186                         format!(" `{}` to `{}`", sub, bound_kind)
2187                     } else {
2188                         format!("`{}: {}`", bound_kind, sub)
2189                     },
2190                 );
2191                 err.help(&consider);
2192             }
2193         }
2194
2195         let new_binding_suggestion =
2196             |err: &mut DiagnosticBuilder<'tcx>,
2197              type_param_span: Option<(Span, bool, bool)>,
2198              bound_kind: GenericKind<'tcx>| {
2199                 let msg = "consider introducing an explicit lifetime bound";
2200                 if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
2201                     let suggestion = if is_impl_trait {
2202                         (sp.shrink_to_hi(), format!(" + {}", new_lt))
2203                     } else {
2204                         let tail = if has_lifetimes { " +" } else { "" };
2205                         (sp, format!("{}: {}{}", bound_kind, new_lt, tail))
2206                     };
2207                     let mut sugg =
2208                         vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))];
2209                     if let Some(lt) = add_lt_sugg {
2210                         sugg.push(lt);
2211                         sugg.rotate_right(1);
2212                     }
2213                     // `MaybeIncorrect` due to issue #41966.
2214                     err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
2215                 }
2216             };
2217
2218         let mut err = match *sub {
2219             ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
2220             | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => {
2221                 // Does the required lifetime have a nice name we can print?
2222                 let mut err = struct_span_err!(
2223                     self.tcx.sess,
2224                     span,
2225                     E0309,
2226                     "{} may not live long enough",
2227                     labeled_user_string
2228                 );
2229                 // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl
2230                 // for the bound is not suitable for suggestions when `-Zverbose` is set because it
2231                 // uses `Debug` output, so we handle it specially here so that suggestions are
2232                 // always correct.
2233                 binding_suggestion(&mut err, type_param_span, bound_kind, name);
2234                 err
2235             }
2236
2237             ty::ReStatic => {
2238                 // Does the required lifetime have a nice name we can print?
2239                 let mut err = struct_span_err!(
2240                     self.tcx.sess,
2241                     span,
2242                     E0310,
2243                     "{} may not live long enough",
2244                     labeled_user_string
2245                 );
2246                 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
2247                 err
2248             }
2249
2250             _ => {
2251                 // If not, be less specific.
2252                 let mut err = struct_span_err!(
2253                     self.tcx.sess,
2254                     span,
2255                     E0311,
2256                     "{} may not live long enough",
2257                     labeled_user_string
2258                 );
2259                 note_and_explain_region(
2260                     self.tcx,
2261                     &mut err,
2262                     &format!("{} must be valid for ", labeled_user_string),
2263                     sub,
2264                     "...",
2265                 );
2266                 if let Some(infer::RelateParamBound(_, t)) = origin {
2267                     let return_impl_trait = self
2268                         .in_progress_typeck_results
2269                         .map(|typeck_results| typeck_results.borrow().hir_owner)
2270                         .and_then(|owner| self.tcx.return_type_impl_trait(owner))
2271                         .is_some();
2272                     let t = self.resolve_vars_if_possible(t);
2273                     match t.kind() {
2274                         // We've got:
2275                         // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
2276                         // suggest:
2277                         // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
2278                         ty::Closure(_, _substs) | ty::Opaque(_, _substs) if return_impl_trait => {
2279                             new_binding_suggestion(&mut err, type_param_span, bound_kind);
2280                         }
2281                         _ => {
2282                             binding_suggestion(&mut err, type_param_span, bound_kind, new_lt);
2283                         }
2284                     }
2285                 }
2286                 err
2287             }
2288         };
2289
2290         if let Some(origin) = origin {
2291             self.note_region_origin(&mut err, &origin);
2292         }
2293         err
2294     }
2295
2296     fn report_sub_sup_conflict(
2297         &self,
2298         var_origin: RegionVariableOrigin,
2299         sub_origin: SubregionOrigin<'tcx>,
2300         sub_region: Region<'tcx>,
2301         sup_origin: SubregionOrigin<'tcx>,
2302         sup_region: Region<'tcx>,
2303     ) {
2304         let mut err = self.report_inference_failure(var_origin);
2305
2306         note_and_explain_region(
2307             self.tcx,
2308             &mut err,
2309             "first, the lifetime cannot outlive ",
2310             sup_region,
2311             "...",
2312         );
2313
2314         debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
2315         debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
2316         debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
2317         debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
2318         debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
2319
2320         if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
2321             (&sup_origin, &sub_origin)
2322         {
2323             debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
2324             debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
2325             debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
2326             debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
2327
2328             if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
2329                 (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
2330             {
2331                 if sub_expected == sup_expected && sub_found == sup_found {
2332                     note_and_explain_region(
2333                         self.tcx,
2334                         &mut err,
2335                         "...but the lifetime must also be valid for ",
2336                         sub_region,
2337                         "...",
2338                     );
2339                     err.span_note(
2340                         sup_trace.cause.span,
2341                         &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
2342                     );
2343
2344                     err.note_expected_found(&"", sup_expected, &"", sup_found);
2345                     err.emit();
2346                     return;
2347                 }
2348             }
2349         }
2350
2351         self.note_region_origin(&mut err, &sup_origin);
2352
2353         note_and_explain_region(
2354             self.tcx,
2355             &mut err,
2356             "but, the lifetime must be valid for ",
2357             sub_region,
2358             "...",
2359         );
2360
2361         self.note_region_origin(&mut err, &sub_origin);
2362         err.emit();
2363     }
2364
2365     /// Determine whether an error associated with the given span and definition
2366     /// should be treated as being caused by the implicit `From` conversion
2367     /// within `?` desugaring.
2368     pub fn is_try_conversion(&self, span: Span, trait_def_id: DefId) -> bool {
2369         span.is_desugaring(DesugaringKind::QuestionMark)
2370             && self.tcx.is_diagnostic_item(sym::from_trait, trait_def_id)
2371     }
2372 }
2373
2374 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
2375     fn report_inference_failure(
2376         &self,
2377         var_origin: RegionVariableOrigin,
2378     ) -> DiagnosticBuilder<'tcx> {
2379         let br_string = |br: ty::BoundRegionKind| {
2380             let mut s = match br {
2381                 ty::BrNamed(_, name) => name.to_string(),
2382                 _ => String::new(),
2383             };
2384             if !s.is_empty() {
2385                 s.push(' ');
2386             }
2387             s
2388         };
2389         let var_description = match var_origin {
2390             infer::MiscVariable(_) => String::new(),
2391             infer::PatternRegion(_) => " for pattern".to_string(),
2392             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
2393             infer::Autoref(_, _) => " for autoref".to_string(),
2394             infer::Coercion(_) => " for automatic coercion".to_string(),
2395             infer::LateBoundRegion(_, br, infer::FnCall) => {
2396                 format!(" for lifetime parameter {}in function call", br_string(br))
2397             }
2398             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
2399                 format!(" for lifetime parameter {}in generic type", br_string(br))
2400             }
2401             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
2402                 " for lifetime parameter {}in trait containing associated type `{}`",
2403                 br_string(br),
2404                 self.tcx.associated_item(def_id).ident
2405             ),
2406             infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name),
2407             infer::UpvarRegion(ref upvar_id, _) => {
2408                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
2409                 format!(" for capture of `{}` by closure", var_name)
2410             }
2411             infer::Nll(..) => bug!("NLL variable found in lexical phase"),
2412         };
2413
2414         struct_span_err!(
2415             self.tcx.sess,
2416             var_origin.span(),
2417             E0495,
2418             "cannot infer an appropriate lifetime{} due to conflicting requirements",
2419             var_description
2420         )
2421     }
2422 }
2423
2424 enum FailureCode {
2425     Error0038(DefId),
2426     Error0317(&'static str),
2427     Error0580(&'static str),
2428     Error0308(&'static str),
2429     Error0644(&'static str),
2430 }
2431
2432 trait ObligationCauseExt<'tcx> {
2433     fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode;
2434     fn as_requirement_str(&self) -> &'static str;
2435 }
2436
2437 impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> {
2438     fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
2439         use self::FailureCode::*;
2440         use crate::traits::ObligationCauseCode::*;
2441         match self.code {
2442             CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
2443             CompareImplTypeObligation { .. } => Error0308("type not compatible with trait"),
2444             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => {
2445                 Error0308(match source {
2446                     hir::MatchSource::IfLetDesugar { .. } => {
2447                         "`if let` arms have incompatible types"
2448                     }
2449                     hir::MatchSource::TryDesugar => {
2450                         "try expression alternatives have incompatible types"
2451                     }
2452                     _ => "`match` arms have incompatible types",
2453                 })
2454             }
2455             IfExpression { .. } => Error0308("`if` and `else` have incompatible types"),
2456             IfExpressionWithNoElse => Error0317("`if` may be missing an `else` clause"),
2457             MainFunctionType => Error0580("`main` function has wrong type"),
2458             StartFunctionType => Error0308("`#[start]` function has wrong type"),
2459             IntrinsicType => Error0308("intrinsic has wrong type"),
2460             MethodReceiver => Error0308("mismatched `self` parameter type"),
2461
2462             // In the case where we have no more specific thing to
2463             // say, also take a look at the error code, maybe we can
2464             // tailor to that.
2465             _ => match terr {
2466                 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
2467                     Error0644("closure/generator type that references itself")
2468                 }
2469                 TypeError::IntrinsicCast => {
2470                     Error0308("cannot coerce intrinsics to function pointers")
2471                 }
2472                 TypeError::ObjectUnsafeCoercion(did) => Error0038(*did),
2473                 _ => Error0308("mismatched types"),
2474             },
2475         }
2476     }
2477
2478     fn as_requirement_str(&self) -> &'static str {
2479         use crate::traits::ObligationCauseCode::*;
2480         match self.code {
2481             CompareImplMethodObligation { .. } => "method type is compatible with trait",
2482             CompareImplTypeObligation { .. } => "associated type is compatible with trait",
2483             ExprAssignable => "expression is assignable",
2484             MatchExpressionArm(box MatchExpressionArmCause { source, .. }) => match source {
2485                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
2486                 _ => "`match` arms have compatible types",
2487             },
2488             IfExpression { .. } => "`if` and `else` have incompatible types",
2489             IfExpressionWithNoElse => "`if` missing an `else` returns `()`",
2490             MainFunctionType => "`main` function has the correct type",
2491             StartFunctionType => "`#[start]` function has the correct type",
2492             IntrinsicType => "intrinsic has the correct type",
2493             MethodReceiver => "method receiver has the correct type",
2494             _ => "types are compatible",
2495         }
2496     }
2497 }
2498
2499 /// This is a bare signal of what kind of type we're dealing with. `ty::TyKind` tracks
2500 /// extra information about each type, but we only care about the category.
2501 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
2502 pub enum TyCategory {
2503     Closure,
2504     Opaque,
2505     Generator(hir::GeneratorKind),
2506     Foreign,
2507 }
2508
2509 impl TyCategory {
2510     fn descr(&self) -> &'static str {
2511         match self {
2512             Self::Closure => "closure",
2513             Self::Opaque => "opaque type",
2514             Self::Generator(gk) => gk.descr(),
2515             Self::Foreign => "foreign type",
2516         }
2517     }
2518
2519     pub fn from_ty(tcx: TyCtxt<'_>, ty: Ty<'_>) -> Option<(Self, DefId)> {
2520         match *ty.kind() {
2521             ty::Closure(def_id, _) => Some((Self::Closure, def_id)),
2522             ty::Opaque(def_id, _) => Some((Self::Opaque, def_id)),
2523             ty::Generator(def_id, ..) => {
2524                 Some((Self::Generator(tcx.generator_kind(def_id).unwrap()), def_id))
2525             }
2526             ty::Foreign(def_id) => Some((Self::Foreign, def_id)),
2527             _ => None,
2528         }
2529     }
2530 }