]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/mod.rs
d1e32b1dbad36761cf7a42b23896322be1334ebc
[rust.git] / src / librustc / 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 use crate::infer::{self, SuppressRegionErrors};
52
53 use crate::hir;
54 use crate::hir::def_id::DefId;
55 use crate::hir::Node;
56 use crate::middle::region;
57 use crate::traits::{ObligationCause, ObligationCauseCode};
58 use crate::ty::error::TypeError;
59 use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
60 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
61 use std::{cmp, fmt};
62 use syntax_pos::{Pos, Span};
63
64 mod note;
65
66 mod need_type_info;
67
68 pub mod nice_region_error;
69
70 impl<'tcx> TyCtxt<'tcx> {
71     pub fn note_and_explain_region(
72         self,
73         region_scope_tree: &region::ScopeTree,
74         err: &mut DiagnosticBuilder<'_>,
75         prefix: &str,
76         region: ty::Region<'tcx>,
77         suffix: &str,
78     ) {
79         let (description, span) = match *region {
80             ty::ReScope(scope) => {
81                 let new_string;
82                 let unknown_scope = || {
83                     format!(
84                         "{}unknown scope: {:?}{}.  Please report a bug.",
85                         prefix, scope, suffix
86                     )
87                 };
88                 let span = scope.span(self, region_scope_tree);
89                 let tag = match self.hir().find_by_hir_id(scope.hir_id(region_scope_tree)) {
90                     Some(Node::Block(_)) => "block",
91                     Some(Node::Expr(expr)) => match expr.node {
92                         hir::ExprKind::Call(..) => "call",
93                         hir::ExprKind::MethodCall(..) => "method call",
94                         hir::ExprKind::Match(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
95                         hir::ExprKind::Match(.., hir::MatchSource::WhileLetDesugar) => "while let",
96                         hir::ExprKind::Match(.., hir::MatchSource::ForLoopDesugar) => "for",
97                         hir::ExprKind::Match(..) => "match",
98                         _ => "expression",
99                     },
100                     Some(Node::Stmt(_)) => "statement",
101                     Some(Node::Item(it)) => Self::item_scope_tag(&it),
102                     Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
103                     Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
104                     Some(_) | None => {
105                         err.span_note(span, &unknown_scope());
106                         return;
107                     }
108                 };
109                 let scope_decorated_tag = match scope.data {
110                     region::ScopeData::Node => tag,
111                     region::ScopeData::CallSite => "scope of call-site for function",
112                     region::ScopeData::Arguments => "scope of function body",
113                     region::ScopeData::Destruction => {
114                         new_string = format!("destruction scope surrounding {}", tag);
115                         &new_string[..]
116                     }
117                     region::ScopeData::Remainder(first_statement_index) => {
118                         new_string = format!(
119                             "block suffix following statement {}",
120                             first_statement_index.index()
121                         );
122                         &new_string[..]
123                     }
124                 };
125                 self.explain_span(scope_decorated_tag, span)
126             }
127
128             ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReStatic => {
129                 self.msg_span_from_free_region(region)
130             }
131
132             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
133
134             ty::RePlaceholder(_) => (format!("any other region"), None),
135
136             // FIXME(#13998) RePlaceholder should probably print like
137             // ReFree rather than dumping Debug output on the user.
138             //
139             // We shouldn't really be having unification failures with ReVar
140             // and ReLateBound though.
141             ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => {
142                 (format!("lifetime {:?}", region), None)
143             }
144
145             // We shouldn't encounter an error message with ReClosureBound.
146             ty::ReClosureBound(..) => {
147                 bug!("encountered unexpected ReClosureBound: {:?}", region,);
148             }
149         };
150
151         TyCtxt::emit_msg_span(err, prefix, description, span, suffix);
152     }
153
154     pub fn note_and_explain_free_region(
155         self,
156         err: &mut DiagnosticBuilder<'_>,
157         prefix: &str,
158         region: ty::Region<'tcx>,
159         suffix: &str,
160     ) {
161         let (description, span) = self.msg_span_from_free_region(region);
162
163         TyCtxt::emit_msg_span(err, prefix, description, span, suffix);
164     }
165
166     fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option<Span>) {
167         match *region {
168             ty::ReEarlyBound(_) | ty::ReFree(_) => {
169                 self.msg_span_from_early_bound_and_free_regions(region)
170             }
171             ty::ReStatic => ("the static lifetime".to_owned(), None),
172             ty::ReEmpty => ("an empty lifetime".to_owned(), None),
173             _ => bug!("{:?}", region),
174         }
175     }
176
177     fn msg_span_from_early_bound_and_free_regions(
178         self,
179         region: ty::Region<'tcx>,
180     ) -> (String, Option<Span>) {
181         let cm = self.sess.source_map();
182
183         let scope = region.free_region_binding_scope(self);
184         let node = self.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID);
185         let tag = match self.hir().find_by_hir_id(node) {
186             Some(Node::Block(_)) | Some(Node::Expr(_)) => "body",
187             Some(Node::Item(it)) => Self::item_scope_tag(&it),
188             Some(Node::TraitItem(it)) => Self::trait_item_scope_tag(&it),
189             Some(Node::ImplItem(it)) => Self::impl_item_scope_tag(&it),
190             _ => unreachable!(),
191         };
192         let (prefix, span) = match *region {
193             ty::ReEarlyBound(ref br) => {
194                 let mut sp = cm.def_span(self.hir().span(node));
195                 if let Some(param) = self.hir()
196                     .get_generics(scope)
197                     .and_then(|generics| generics.get_named(br.name))
198                 {
199                     sp = param.span;
200                 }
201                 (format!("the lifetime {} as defined on", br.name), sp)
202             }
203             ty::ReFree(ty::FreeRegion {
204                 bound_region: ty::BoundRegion::BrNamed(_, name),
205                 ..
206             }) => {
207                 let mut sp = cm.def_span(self.hir().span(node));
208                 if let Some(param) = self.hir()
209                     .get_generics(scope)
210                     .and_then(|generics| generics.get_named(name))
211                 {
212                     sp = param.span;
213                 }
214                 (format!("the lifetime {} as defined on", name), sp)
215             }
216             ty::ReFree(ref fr) => match fr.bound_region {
217                 ty::BrAnon(idx) => (
218                     format!("the anonymous lifetime #{} defined on", idx + 1),
219                     self.hir().span(node),
220                 ),
221                 _ => (
222                     format!("the lifetime {} as defined on", region),
223                     cm.def_span(self.hir().span(node)),
224                 ),
225             },
226             _ => bug!(),
227         };
228         let (msg, opt_span) = self.explain_span(tag, span);
229         (format!("{} {}", prefix, msg), opt_span)
230     }
231
232     fn emit_msg_span(
233         err: &mut DiagnosticBuilder<'_>,
234         prefix: &str,
235         description: String,
236         span: Option<Span>,
237         suffix: &str,
238     ) {
239         let message = format!("{}{}{}", prefix, description, suffix);
240
241         if let Some(span) = span {
242             err.span_note(span, &message);
243         } else {
244             err.note(&message);
245         }
246     }
247
248     fn item_scope_tag(item: &hir::Item) -> &'static str {
249         match item.node {
250             hir::ItemKind::Impl(..) => "impl",
251             hir::ItemKind::Struct(..) => "struct",
252             hir::ItemKind::Union(..) => "union",
253             hir::ItemKind::Enum(..) => "enum",
254             hir::ItemKind::Trait(..) => "trait",
255             hir::ItemKind::Fn(..) => "function body",
256             _ => "item",
257         }
258     }
259
260     fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
261         match item.node {
262             hir::TraitItemKind::Method(..) => "method body",
263             hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item",
264         }
265     }
266
267     fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
268         match item.node {
269             hir::ImplItemKind::Method(..) => "method body",
270             hir::ImplItemKind::Const(..)
271             | hir::ImplItemKind::Existential(..)
272             | hir::ImplItemKind::Type(..) => "associated item",
273         }
274     }
275
276     fn explain_span(self, heading: &str, span: Span) -> (String, Option<Span>) {
277         let lo = self.sess.source_map().lookup_char_pos(span.lo());
278         (
279             format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
280             Some(span),
281         )
282     }
283 }
284
285 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
286     pub fn report_region_errors(
287         &self,
288         region_scope_tree: &region::ScopeTree,
289         errors: &Vec<RegionResolutionError<'tcx>>,
290         suppress: SuppressRegionErrors,
291     ) {
292         debug!(
293             "report_region_errors(): {} errors to start, suppress = {:?}",
294             errors.len(),
295             suppress
296         );
297
298         if suppress.suppressed() {
299             return;
300         }
301
302         // try to pre-process the errors, which will group some of them
303         // together into a `ProcessedErrors` group:
304         let errors = self.process_errors(errors);
305
306         debug!(
307             "report_region_errors: {} errors after preprocessing",
308             errors.len()
309         );
310
311         for error in errors {
312             debug!("report_region_errors: error = {:?}", error);
313
314             if !self.try_report_nice_region_error(&error) {
315                 match error.clone() {
316                     // These errors could indicate all manner of different
317                     // problems with many different solutions. Rather
318                     // than generate a "one size fits all" error, what we
319                     // attempt to do is go through a number of specific
320                     // scenarios and try to find the best way to present
321                     // the error. If all of these fails, we fall back to a rather
322                     // general bit of code that displays the error information
323                     RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
324                         if sub.is_placeholder() || sup.is_placeholder() {
325                             self.report_placeholder_failure(region_scope_tree, origin, sub, sup)
326                                 .emit();
327                         } else {
328                             self.report_concrete_failure(region_scope_tree, origin, sub, sup)
329                                 .emit();
330                         }
331                     }
332
333                     RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
334                         self.report_generic_bound_failure(
335                             region_scope_tree,
336                             origin.span(),
337                             Some(origin),
338                             param_ty,
339                             sub,
340                         );
341                     }
342
343                     RegionResolutionError::SubSupConflict(
344                         _,
345                         var_origin,
346                         sub_origin,
347                         sub_r,
348                         sup_origin,
349                         sup_r,
350                     ) => {
351                         if sub_r.is_placeholder() {
352                             self.report_placeholder_failure(
353                                 region_scope_tree,
354                                 sub_origin,
355                                 sub_r,
356                                 sup_r,
357                             )
358                                 .emit();
359                         } else if sup_r.is_placeholder() {
360                             self.report_placeholder_failure(
361                                 region_scope_tree,
362                                 sup_origin,
363                                 sub_r,
364                                 sup_r,
365                             )
366                                 .emit();
367                         } else {
368                             self.report_sub_sup_conflict(
369                                 region_scope_tree,
370                                 var_origin,
371                                 sub_origin,
372                                 sub_r,
373                                 sup_origin,
374                                 sup_r,
375                             );
376                         }
377                     }
378                 }
379             }
380         }
381     }
382
383     // This method goes through all the errors and try to group certain types
384     // of error together, for the purpose of suggesting explicit lifetime
385     // parameters to the user. This is done so that we can have a more
386     // complete view of what lifetimes should be the same.
387     // If the return value is an empty vector, it means that processing
388     // failed (so the return value of this method should not be used).
389     //
390     // The method also attempts to weed out messages that seem like
391     // duplicates that will be unhelpful to the end-user. But
392     // obviously it never weeds out ALL errors.
393     fn process_errors(
394         &self,
395         errors: &Vec<RegionResolutionError<'tcx>>,
396     ) -> Vec<RegionResolutionError<'tcx>> {
397         debug!("process_errors()");
398
399         // We want to avoid reporting generic-bound failures if we can
400         // avoid it: these have a very high rate of being unhelpful in
401         // practice. This is because they are basically secondary
402         // checks that test the state of the region graph after the
403         // rest of inference is done, and the other kinds of errors
404         // indicate that the region constraint graph is internally
405         // inconsistent, so these test results are likely to be
406         // meaningless.
407         //
408         // Therefore, we filter them out of the list unless they are
409         // the only thing in the list.
410
411         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
412             RegionResolutionError::GenericBoundFailure(..) => true,
413             RegionResolutionError::ConcreteFailure(..)
414             | RegionResolutionError::SubSupConflict(..) => false,
415         };
416
417         let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
418             errors.clone()
419         } else {
420             errors
421             .iter()
422             .filter(|&e| !is_bound_failure(e))
423             .cloned()
424             .collect()
425         };
426
427         // sort the errors by span, for better error message stability.
428         errors.sort_by_key(|u| match *u {
429             RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
430             RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
431             RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _) => rvo.span(),
432         });
433         errors
434     }
435
436     /// Adds a note if the types come from similarly named crates
437     fn check_and_note_conflicting_crates(
438         &self,
439         err: &mut DiagnosticBuilder<'_>,
440         terr: &TypeError<'tcx>,
441         sp: Span,
442     ) {
443         use hir::def_id::CrateNum;
444         use hir::map::DisambiguatedDefPathData;
445         use ty::print::Printer;
446         use ty::subst::Kind;
447
448         struct AbsolutePathPrinter<'tcx> {
449             tcx: TyCtxt<'tcx>,
450         }
451
452         struct NonTrivialPath;
453
454         impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> {
455             type Error = NonTrivialPath;
456
457             type Path = Vec<String>;
458             type Region = !;
459             type Type = !;
460             type DynExistential = !;
461             type Const = !;
462
463             fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
464                 self.tcx
465             }
466
467             fn print_region(
468                 self,
469                 _region: ty::Region<'_>,
470             ) -> Result<Self::Region, Self::Error> {
471                 Err(NonTrivialPath)
472             }
473
474             fn print_type(
475                 self,
476                 _ty: Ty<'tcx>,
477             ) -> Result<Self::Type, Self::Error> {
478                 Err(NonTrivialPath)
479             }
480
481             fn print_dyn_existential(
482                 self,
483                 _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
484             ) -> Result<Self::DynExistential, Self::Error> {
485                 Err(NonTrivialPath)
486             }
487
488             fn print_const(
489                 self,
490                 _ct: &'tcx ty::Const<'tcx>,
491             ) -> Result<Self::Const, Self::Error> {
492                 Err(NonTrivialPath)
493             }
494
495             fn path_crate(
496                 self,
497                 cnum: CrateNum,
498             ) -> Result<Self::Path, Self::Error> {
499                 Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
500             }
501             fn path_qualified(
502                 self,
503                 _self_ty: Ty<'tcx>,
504                 _trait_ref: Option<ty::TraitRef<'tcx>>,
505             ) -> Result<Self::Path, Self::Error> {
506                 Err(NonTrivialPath)
507             }
508
509             fn path_append_impl(
510                 self,
511                 _print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
512                 _disambiguated_data: &DisambiguatedDefPathData,
513                 _self_ty: Ty<'tcx>,
514                 _trait_ref: Option<ty::TraitRef<'tcx>>,
515             ) -> Result<Self::Path, Self::Error> {
516                 Err(NonTrivialPath)
517             }
518             fn path_append(
519                 self,
520                 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
521                 disambiguated_data: &DisambiguatedDefPathData,
522             ) -> Result<Self::Path, Self::Error> {
523                 let mut path = print_prefix(self)?;
524                 path.push(disambiguated_data.data.as_interned_str().to_string());
525                 Ok(path)
526             }
527             fn path_generic_args(
528                 self,
529                 print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
530                 _args: &[Kind<'tcx>],
531             ) -> Result<Self::Path, Self::Error> {
532                 print_prefix(self)
533             }
534         }
535
536         let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| {
537             // Only external crates, if either is from a local
538             // module we could have false positives
539             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
540                 let abs_path = |def_id| {
541                     AbsolutePathPrinter { tcx: self.tcx }
542                         .print_def_path(def_id, &[])
543                 };
544
545                 // We compare strings because DefPath can be different
546                 // for imported and non-imported crates
547                 let same_path = || -> Result<_, NonTrivialPath> {
548                     Ok(
549                         self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) ||
550                         abs_path(did1)? == abs_path(did2)?
551                     )
552                 };
553                 if same_path().unwrap_or(false) {
554                     let crate_name = self.tcx.crate_name(did1.krate);
555                     err.span_note(
556                         sp,
557                         &format!(
558                             "Perhaps two different versions \
559                              of crate `{}` are being used?",
560                             crate_name
561                         ),
562                     );
563                 }
564             }
565         };
566         match *terr {
567             TypeError::Sorts(ref exp_found) => {
568                 // if they are both "path types", there's a chance of ambiguity
569                 // due to different versions of the same crate
570                 if let (&ty::Adt(exp_adt, _), &ty::Adt(found_adt, _))
571                      = (&exp_found.expected.sty, &exp_found.found.sty)
572                 {
573                     report_path_match(err, exp_adt.did, found_adt.did);
574                 }
575             }
576             TypeError::Traits(ref exp_found) => {
577                 report_path_match(err, exp_found.expected, exp_found.found);
578             }
579             _ => (), // FIXME(#22750) handle traits and stuff
580         }
581     }
582
583     fn note_error_origin(
584         &self,
585         err: &mut DiagnosticBuilder<'tcx>,
586         cause: &ObligationCause<'tcx>,
587         exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
588     ) {
589         match cause.code {
590             ObligationCauseCode::MatchExpressionArmPattern { span, ty } => {
591                 if ty.is_suggestable() {  // don't show type `_`
592                     err.span_label(span, format!("this match expression has type `{}`", ty));
593                 }
594                 if let Some(ty::error::ExpectedFound { found, .. }) = exp_found {
595                     if ty.is_box() && ty.boxed_ty() == found {
596                         if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
597                             err.span_suggestion(
598                                 span,
599                                 "consider dereferencing the boxed value",
600                                 format!("*{}", snippet),
601                                 Applicability::MachineApplicable,
602                             );
603                         }
604                     }
605                 }
606             }
607             ObligationCauseCode::MatchExpressionArm {
608                 source,
609                 ref prior_arms,
610                 last_ty,
611                 discrim_hir_id,
612                 ..
613             } => match source {
614                 hir::MatchSource::IfLetDesugar { .. } => {
615                     let msg = "`if let` arms have incompatible types";
616                     err.span_label(cause.span, msg);
617                 }
618                 hir::MatchSource::TryDesugar => {
619                     if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
620                         let discrim_expr = self.tcx.hir().expect_expr(discrim_hir_id);
621                         let discrim_ty = if let hir::ExprKind::Call(_, args) = &discrim_expr.node {
622                             let arg_expr = args.first().expect("try desugaring call w/out arg");
623                             self.in_progress_tables.and_then(|tables| {
624                                 tables.borrow().expr_ty_opt(arg_expr)
625                             })
626                         } else {
627                             bug!("try desugaring w/out call expr as discriminant");
628                         };
629
630                         match discrim_ty {
631                             Some(ty) if expected == ty => {
632                                 let source_map = self.tcx.sess.source_map();
633                                 err.span_suggestion(
634                                     source_map.end_point(cause.span),
635                                     "try removing this `?`",
636                                     "".to_string(),
637                                     Applicability::MachineApplicable,
638                                 );
639                             },
640                             _ => {},
641                         }
642                     }
643                 }
644                 _ => {
645                     let msg = "`match` arms have incompatible types";
646                     err.span_label(cause.span, msg);
647                     if prior_arms.len() <= 4 {
648                         for sp in prior_arms {
649                             err.span_label(*sp, format!(
650                                 "this is found to be of type `{}`",
651                                 self.resolve_vars_if_possible(&last_ty),
652                             ));
653                         }
654                     } else if let Some(sp) = prior_arms.last() {
655                         err.span_label(*sp, format!(
656                             "this and all prior arms are found to be of type `{}`", last_ty,
657                         ));
658                     }
659                 }
660             },
661             ObligationCauseCode::IfExpression { then, outer, semicolon } => {
662                 err.span_label(then, "expected because of this");
663                 outer.map(|sp| err.span_label(sp, "if and else have incompatible types"));
664                 if let Some(sp) = semicolon {
665                     err.span_suggestion_short(
666                         sp,
667                         "consider removing this semicolon",
668                         String::new(),
669                         Applicability::MachineApplicable,
670                     );
671                 }
672             }
673             _ => (),
674         }
675     }
676
677     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
678     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
679     /// populate `other_value` with `other_ty`.
680     ///
681     /// ```text
682     /// Foo<Bar<Qux>>
683     /// ^^^^--------^ this is highlighted
684     /// |   |
685     /// |   this type argument is exactly the same as the other type, not highlighted
686     /// this is highlighted
687     /// Bar<Qux>
688     /// -------- this type is the same as a type argument in the other type, not highlighted
689     /// ```
690     fn highlight_outer(
691         &self,
692         value: &mut DiagnosticStyledString,
693         other_value: &mut DiagnosticStyledString,
694         name: String,
695         sub: ty::subst::SubstsRef<'tcx>,
696         pos: usize,
697         other_ty: Ty<'tcx>,
698     ) {
699         // `value` and `other_value` hold two incomplete type representation for display.
700         // `name` is the path of both types being compared. `sub`
701         value.push_highlighted(name);
702         let len = sub.len();
703         if len > 0 {
704             value.push_highlighted("<");
705         }
706
707         // Output the lifetimes for the first type
708         let lifetimes = sub.regions()
709             .map(|lifetime| {
710                 let s = lifetime.to_string();
711                 if s.is_empty() {
712                     "'_".to_string()
713                 } else {
714                     s
715                 }
716             })
717             .collect::<Vec<_>>()
718             .join(", ");
719         if !lifetimes.is_empty() {
720             if sub.regions().count() < len {
721                 value.push_normal(lifetimes + &", ");
722             } else {
723                 value.push_normal(lifetimes);
724             }
725         }
726
727         // Highlight all the type arguments that aren't at `pos` and compare the type argument at
728         // `pos` and `other_ty`.
729         for (i, type_arg) in sub.types().enumerate() {
730             if i == pos {
731                 let values = self.cmp(type_arg, other_ty);
732                 value.0.extend((values.0).0);
733                 other_value.0.extend((values.1).0);
734             } else {
735                 value.push_highlighted(type_arg.to_string());
736             }
737
738             if len > 0 && i != len - 1 {
739                 value.push_normal(", ");
740             }
741             //self.push_comma(&mut value, &mut other_value, len, i);
742         }
743         if len > 0 {
744             value.push_highlighted(">");
745         }
746     }
747
748     /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
749     /// as that is the difference to the other type.
750     ///
751     /// For the following code:
752     ///
753     /// ```norun
754     /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
755     /// ```
756     ///
757     /// The type error output will behave in the following way:
758     ///
759     /// ```text
760     /// Foo<Bar<Qux>>
761     /// ^^^^--------^ this is highlighted
762     /// |   |
763     /// |   this type argument is exactly the same as the other type, not highlighted
764     /// this is highlighted
765     /// Bar<Qux>
766     /// -------- this type is the same as a type argument in the other type, not highlighted
767     /// ```
768     fn cmp_type_arg(
769         &self,
770         mut t1_out: &mut DiagnosticStyledString,
771         mut t2_out: &mut DiagnosticStyledString,
772         path: String,
773         sub: ty::subst::SubstsRef<'tcx>,
774         other_path: String,
775         other_ty: Ty<'tcx>,
776     ) -> Option<()> {
777         for (i, ta) in sub.types().enumerate() {
778             if ta == other_ty {
779                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
780                 return Some(());
781             }
782             if let &ty::Adt(def, _) = &ta.sty {
783                 let path_ = self.tcx.def_path_str(def.did.clone());
784                 if path_ == other_path {
785                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
786                     return Some(());
787                 }
788             }
789         }
790         None
791     }
792
793     /// Adds a `,` to the type representation only if it is appropriate.
794     fn push_comma(
795         &self,
796         value: &mut DiagnosticStyledString,
797         other_value: &mut DiagnosticStyledString,
798         len: usize,
799         pos: usize,
800     ) {
801         if len > 0 && pos != len - 1 {
802             value.push_normal(", ");
803             other_value.push_normal(", ");
804         }
805     }
806
807     /// For generic types with parameters with defaults, remove the parameters corresponding to
808     /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`.
809     fn strip_generic_default_params(
810         &self,
811         def_id: DefId,
812         substs: ty::subst::SubstsRef<'tcx>,
813     ) -> SubstsRef<'tcx> {
814         let generics = self.tcx.generics_of(def_id);
815         let mut num_supplied_defaults = 0;
816         let mut type_params = generics.params.iter().rev().filter_map(|param| match param.kind {
817             ty::GenericParamDefKind::Lifetime => None,
818             ty::GenericParamDefKind::Type { has_default, .. } => Some((param.def_id, has_default)),
819             ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
820         }).peekable();
821         let has_default = {
822             let has_default = type_params.peek().map(|(_, has_default)| has_default);
823             *has_default.unwrap_or(&false)
824         };
825         if has_default {
826             let types = substs.types().rev();
827             for ((def_id, has_default), actual) in type_params.zip(types) {
828                 if !has_default {
829                     break;
830                 }
831                 if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual {
832                     break;
833                 }
834                 num_supplied_defaults += 1;
835             }
836         }
837         let len = generics.params.len();
838         let mut generics = generics.clone();
839         generics.params.truncate(len - num_supplied_defaults);
840         substs.truncate_to(self.tcx, &generics)
841     }
842
843     /// Compares two given types, eliding parts that are the same between them and highlighting
844     /// relevant differences, and return two representation of those types for highlighted printing.
845     fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) {
846         fn equals<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
847             match (&a.sty, &b.sty) {
848                 (a, b) if *a == *b => true,
849                 (&ty::Int(_), &ty::Infer(ty::InferTy::IntVar(_)))
850                 | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Int(_))
851                 | (&ty::Infer(ty::InferTy::IntVar(_)), &ty::Infer(ty::InferTy::IntVar(_)))
852                 | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
853                 | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Float(_))
854                 | (&ty::Infer(ty::InferTy::FloatVar(_)), &ty::Infer(ty::InferTy::FloatVar(_))) => {
855                     true
856                 }
857                 _ => false,
858             }
859         }
860
861         fn push_ty_ref<'tcx>(
862             r: &ty::Region<'tcx>,
863             ty: Ty<'tcx>,
864             mutbl: hir::Mutability,
865             s: &mut DiagnosticStyledString,
866         ) {
867             let mut r = r.to_string();
868             if r == "'_" {
869                 r.clear();
870             } else {
871                 r.push(' ');
872             }
873             s.push_highlighted(format!(
874                 "&{}{}",
875                 r,
876                 if mutbl == hir::MutMutable { "mut " } else { "" }
877             ));
878             s.push_normal(ty.to_string());
879         }
880
881         match (&t1.sty, &t2.sty) {
882             (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => {
883                 let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1);
884                 let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2);
885                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
886                 let path1 = self.tcx.def_path_str(def1.did.clone());
887                 let path2 = self.tcx.def_path_str(def2.did.clone());
888                 if def1.did == def2.did {
889                     // Easy case. Replace same types with `_` to shorten the output and highlight
890                     // the differing ones.
891                     //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
892                     //     Foo<Bar, _>
893                     //     Foo<Quz, _>
894                     //         ---  ^ type argument elided
895                     //         |
896                     //         highlighted in output
897                     values.0.push_normal(path1);
898                     values.1.push_normal(path2);
899
900                     // Avoid printing out default generic parameters that are common to both
901                     // types.
902                     let len1 = sub_no_defaults_1.len();
903                     let len2 = sub_no_defaults_2.len();
904                     let common_len = cmp::min(len1, len2);
905                     let remainder1: Vec<_> = sub1.types().skip(common_len).collect();
906                     let remainder2: Vec<_> = sub2.types().skip(common_len).collect();
907                     let common_default_params = remainder1
908                         .iter()
909                         .rev()
910                         .zip(remainder2.iter().rev())
911                         .filter(|(a, b)| a == b)
912                         .count();
913                     let len = sub1.len() - common_default_params;
914
915                     // Only draw `<...>` if there're lifetime/type arguments.
916                     if len > 0 {
917                         values.0.push_normal("<");
918                         values.1.push_normal("<");
919                     }
920
921                     fn lifetime_display(lifetime: Region<'_>) -> String {
922                         let s = lifetime.to_string();
923                         if s.is_empty() {
924                             "'_".to_string()
925                         } else {
926                             s
927                         }
928                     }
929                     // At one point we'd like to elide all lifetimes here, they are irrelevant for
930                     // all diagnostics that use this output
931                     //
932                     //     Foo<'x, '_, Bar>
933                     //     Foo<'y, '_, Qux>
934                     //         ^^  ^^  --- type arguments are not elided
935                     //         |   |
936                     //         |   elided as they were the same
937                     //         not elided, they were different, but irrelevant
938                     let lifetimes = sub1.regions().zip(sub2.regions());
939                     for (i, lifetimes) in lifetimes.enumerate() {
940                         let l1 = lifetime_display(lifetimes.0);
941                         let l2 = lifetime_display(lifetimes.1);
942                         if l1 == l2 {
943                             values.0.push_normal("'_");
944                             values.1.push_normal("'_");
945                         } else {
946                             values.0.push_highlighted(l1);
947                             values.1.push_highlighted(l2);
948                         }
949                         self.push_comma(&mut values.0, &mut values.1, len, i);
950                     }
951
952                     // We're comparing two types with the same path, so we compare the type
953                     // arguments for both. If they are the same, do not highlight and elide from the
954                     // output.
955                     //     Foo<_, Bar>
956                     //     Foo<_, Qux>
957                     //         ^ elided type as this type argument was the same in both sides
958                     let type_arguments = sub1.types().zip(sub2.types());
959                     let regions_len = sub1.regions().count();
960                     for (i, (ta1, ta2)) in type_arguments.take(len).enumerate() {
961                         let i = i + regions_len;
962                         if ta1 == ta2 {
963                             values.0.push_normal("_");
964                             values.1.push_normal("_");
965                         } else {
966                             let (x1, x2) = self.cmp(ta1, ta2);
967                             (values.0).0.extend(x1.0);
968                             (values.1).0.extend(x2.0);
969                         }
970                         self.push_comma(&mut values.0, &mut values.1, len, i);
971                     }
972
973                     // Close the type argument bracket.
974                     // Only draw `<...>` if there're lifetime/type arguments.
975                     if len > 0 {
976                         values.0.push_normal(">");
977                         values.1.push_normal(">");
978                     }
979                     values
980                 } else {
981                     // Check for case:
982                     //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
983                     //     Foo<Bar<Qux>
984                     //         ------- this type argument is exactly the same as the other type
985                     //     Bar<Qux>
986                     if self.cmp_type_arg(
987                         &mut values.0,
988                         &mut values.1,
989                         path1.clone(),
990                         sub_no_defaults_1,
991                         path2.clone(),
992                         &t2,
993                     ).is_some()
994                     {
995                         return values;
996                     }
997                     // Check for case:
998                     //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
999                     //     Bar<Qux>
1000                     //     Foo<Bar<Qux>>
1001                     //         ------- this type argument is exactly the same as the other type
1002                     if self.cmp_type_arg(
1003                         &mut values.1,
1004                         &mut values.0,
1005                         path2,
1006                         sub_no_defaults_2,
1007                         path1,
1008                         &t1,
1009                     ).is_some()
1010                     {
1011                         return values;
1012                     }
1013
1014                     // We couldn't find anything in common, highlight everything.
1015                     //     let x: Bar<Qux> = y::<Foo<Zar>>();
1016                     (
1017                         DiagnosticStyledString::highlighted(t1.to_string()),
1018                         DiagnosticStyledString::highlighted(t2.to_string()),
1019                     )
1020                 }
1021             }
1022
1023             // When finding T != &T, highlight only the borrow
1024             (&ty::Ref(r1, ref_ty1, mutbl1), _) if equals(&ref_ty1, &t2) => {
1025                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1026                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1027                 values.1.push_normal(t2.to_string());
1028                 values
1029             }
1030             (_, &ty::Ref(r2, ref_ty2, mutbl2)) if equals(&t1, &ref_ty2) => {
1031                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1032                 values.0.push_normal(t1.to_string());
1033                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1034                 values
1035             }
1036
1037             // When encountering &T != &mut T, highlight only the borrow
1038             (&ty::Ref(r1, ref_ty1, mutbl1), &ty::Ref(r2, ref_ty2, mutbl2))
1039                 if equals(&ref_ty1, &ref_ty2) =>
1040             {
1041                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
1042                 push_ty_ref(&r1, ref_ty1, mutbl1, &mut values.0);
1043                 push_ty_ref(&r2, ref_ty2, mutbl2, &mut values.1);
1044                 values
1045             }
1046
1047             _ => {
1048                 if t1 == t2 {
1049                     // The two types are the same, elide and don't highlight.
1050                     (
1051                         DiagnosticStyledString::normal("_"),
1052                         DiagnosticStyledString::normal("_"),
1053                     )
1054                 } else {
1055                     // We couldn't find anything in common, highlight everything.
1056                     (
1057                         DiagnosticStyledString::highlighted(t1.to_string()),
1058                         DiagnosticStyledString::highlighted(t2.to_string()),
1059                     )
1060                 }
1061             }
1062         }
1063     }
1064
1065     pub fn note_type_err(
1066         &self,
1067         diag: &mut DiagnosticBuilder<'tcx>,
1068         cause: &ObligationCause<'tcx>,
1069         secondary_span: Option<(Span, String)>,
1070         mut values: Option<ValuePairs<'tcx>>,
1071         terr: &TypeError<'tcx>,
1072     ) {
1073         // For some types of errors, expected-found does not make
1074         // sense, so just ignore the values we were given.
1075         match terr {
1076             TypeError::CyclicTy(_) => {
1077                 values = None;
1078             }
1079             _ => {}
1080         }
1081
1082         let (expected_found, exp_found, is_simple_error) = match values {
1083             None => (None, None, false),
1084             Some(values) => {
1085                 let (is_simple_error, exp_found) = match values {
1086                     ValuePairs::Types(exp_found) => {
1087                         let is_simple_err =
1088                             exp_found.expected.is_primitive() && exp_found.found.is_primitive();
1089
1090                         (is_simple_err, Some(exp_found))
1091                     }
1092                     _ => (false, None),
1093                 };
1094                 let vals = match self.values_str(&values) {
1095                     Some((expected, found)) => Some((expected, found)),
1096                     None => {
1097                         // Derived error. Cancel the emitter.
1098                         self.tcx.sess.diagnostic().cancel(diag);
1099                         return;
1100                     }
1101                 };
1102                 (vals, exp_found, is_simple_error)
1103             }
1104         };
1105
1106         let span = cause.span(self.tcx);
1107
1108         diag.span_label(span, terr.to_string());
1109         if let Some((sp, msg)) = secondary_span {
1110             diag.span_label(sp, msg);
1111         }
1112
1113         if let Some((expected, found)) = expected_found {
1114             match (terr, is_simple_error, expected == found) {
1115                 (&TypeError::Sorts(ref values), false, true) => {
1116                     diag.note_expected_found_extra(
1117                         &"type",
1118                         expected,
1119                         found,
1120                         &format!(" ({})", values.expected.sort_string(self.tcx)),
1121                         &format!(" ({})", values.found.sort_string(self.tcx)),
1122                     );
1123                 }
1124                 (_, false, _) => {
1125                     if let Some(exp_found) = exp_found {
1126                         let (def_id, ret_ty) = match exp_found.found.sty {
1127                             ty::FnDef(def, _) => {
1128                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
1129                             }
1130                             _ => (None, None),
1131                         };
1132
1133                         let exp_is_struct = match exp_found.expected.sty {
1134                             ty::Adt(def, _) => def.is_struct(),
1135                             _ => false,
1136                         };
1137
1138                         if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
1139                             if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() {
1140                                 let message = format!(
1141                                     "did you mean `{}(/* fields */)`?",
1142                                     self.tcx.def_path_str(def_id)
1143                                 );
1144                                 diag.span_label(span, message);
1145                             }
1146                         }
1147                         self.suggest_as_ref_where_appropriate(span, &exp_found, diag);
1148                     }
1149
1150                     diag.note_expected_found(&"type", expected, found);
1151                 }
1152                 _ => (),
1153             }
1154         }
1155
1156         self.check_and_note_conflicting_crates(diag, terr, span);
1157         self.tcx.note_and_explain_type_err(diag, terr, span);
1158
1159         // It reads better to have the error origin as the final
1160         // thing.
1161         self.note_error_origin(diag, &cause, exp_found);
1162     }
1163
1164     /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
1165     /// suggest it.
1166     fn suggest_as_ref_where_appropriate(
1167         &self,
1168         span: Span,
1169         exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1170         diag: &mut DiagnosticBuilder<'tcx>,
1171     ) {
1172         match (&exp_found.expected.sty, &exp_found.found.sty) {
1173             (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) => {
1174                 if let ty::Adt(found_def, found_substs) = found_ty.sty {
1175                     let path_str = format!("{:?}", exp_def);
1176                     if exp_def == &found_def {
1177                         let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
1178                                        `.as_ref()`";
1179                         let result_msg = "you can convert from `&Result<T, E>` to \
1180                                           `Result<&T, &E>` using `.as_ref()`";
1181                         let have_as_ref = &[
1182                             ("std::option::Option", opt_msg),
1183                             ("core::option::Option", opt_msg),
1184                             ("std::result::Result", result_msg),
1185                             ("core::result::Result", result_msg),
1186                         ];
1187                         if let Some(msg) = have_as_ref.iter()
1188                             .filter_map(|(path, msg)| if &path_str == path {
1189                                 Some(msg)
1190                             } else {
1191                                 None
1192                             }).next()
1193                         {
1194                             let mut show_suggestion = true;
1195                             for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
1196                                 match exp_ty.sty {
1197                                     ty::Ref(_, exp_ty, _) => {
1198                                         match (&exp_ty.sty, &found_ty.sty) {
1199                                             (_, ty::Param(_)) |
1200                                             (_, ty::Infer(_)) |
1201                                             (ty::Param(_), _) |
1202                                             (ty::Infer(_), _) => {}
1203                                             _ if ty::TyS::same_type(exp_ty, found_ty) => {}
1204                                             _ => show_suggestion = false,
1205                                         };
1206                                     }
1207                                     ty::Param(_) | ty::Infer(_) => {}
1208                                     _ => show_suggestion = false,
1209                                 }
1210                             }
1211                             if let (Ok(snippet), true) = (
1212                                 self.tcx.sess.source_map().span_to_snippet(span),
1213                                 show_suggestion,
1214                             ) {
1215                                 diag.span_suggestion(
1216                                     span,
1217                                     msg,
1218                                     format!("{}.as_ref()", snippet),
1219                                     Applicability::MachineApplicable,
1220                                 );
1221                             }
1222                         }
1223                     }
1224                 }
1225             }
1226             _ => {}
1227         }
1228     }
1229
1230     pub fn report_and_explain_type_error(
1231         &self,
1232         trace: TypeTrace<'tcx>,
1233         terr: &TypeError<'tcx>,
1234     ) -> DiagnosticBuilder<'tcx> {
1235         debug!(
1236             "report_and_explain_type_error(trace={:?}, terr={:?})",
1237             trace, terr
1238         );
1239
1240         let span = trace.cause.span(self.tcx);
1241         let failure_code = trace.cause.as_failure_code(terr);
1242         let mut diag = match failure_code {
1243             FailureCode::Error0317(failure_str) => {
1244                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
1245             }
1246             FailureCode::Error0580(failure_str) => {
1247                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
1248             }
1249             FailureCode::Error0308(failure_str) => {
1250                 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
1251             }
1252             FailureCode::Error0644(failure_str) => {
1253                 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
1254             }
1255         };
1256         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
1257         diag
1258     }
1259
1260     fn values_str(
1261         &self,
1262         values: &ValuePairs<'tcx>,
1263     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
1264         match *values {
1265             infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
1266             infer::Regions(ref exp_found) => self.expected_found_str(exp_found),
1267             infer::Consts(ref exp_found) => self.expected_found_str(exp_found),
1268             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
1269             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
1270         }
1271     }
1272
1273     fn expected_found_str_ty(
1274         &self,
1275         exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
1276     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
1277         let exp_found = self.resolve_vars_if_possible(exp_found);
1278         if exp_found.references_error() {
1279             return None;
1280         }
1281
1282         Some(self.cmp(exp_found.expected, exp_found.found))
1283     }
1284
1285     /// Returns a string of the form "expected `{}`, found `{}`".
1286     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
1287         &self,
1288         exp_found: &ty::error::ExpectedFound<T>,
1289     ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
1290         let exp_found = self.resolve_vars_if_possible(exp_found);
1291         if exp_found.references_error() {
1292             return None;
1293         }
1294
1295         Some((
1296             DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
1297             DiagnosticStyledString::highlighted(exp_found.found.to_string()),
1298         ))
1299     }
1300
1301     pub fn report_generic_bound_failure(
1302         &self,
1303         region_scope_tree: &region::ScopeTree,
1304         span: Span,
1305         origin: Option<SubregionOrigin<'tcx>>,
1306         bound_kind: GenericKind<'tcx>,
1307         sub: Region<'tcx>,
1308     ) {
1309         self.construct_generic_bound_failure(region_scope_tree, span, origin, bound_kind, sub)
1310             .emit()
1311     }
1312
1313     pub fn construct_generic_bound_failure(
1314         &self,
1315         region_scope_tree: &region::ScopeTree,
1316         span: Span,
1317         origin: Option<SubregionOrigin<'tcx>>,
1318         bound_kind: GenericKind<'tcx>,
1319         sub: Region<'tcx>,
1320     ) -> DiagnosticBuilder<'a> {
1321         // Attempt to obtain the span of the parameter so we can
1322         // suggest adding an explicit lifetime bound to it.
1323         let type_param_span = match (self.in_progress_tables, bound_kind) {
1324             (Some(ref table), GenericKind::Param(ref param)) => {
1325                 let table = table.borrow();
1326                 table.local_id_root.and_then(|did| {
1327                     let generics = self.tcx.generics_of(did);
1328                     // Account for the case where `did` corresponds to `Self`, which doesn't have
1329                     // the expected type argument.
1330                     if !param.is_self() {
1331                         let type_param = generics.type_param(param, self.tcx);
1332                         let hir = &self.tcx.hir();
1333                         hir.as_local_hir_id(type_param.def_id).map(|id| {
1334                             // Get the `hir::Param` to verify whether it already has any bounds.
1335                             // We do this to avoid suggesting code that ends up as `T: 'a'b`,
1336                             // instead we suggest `T: 'a + 'b` in that case.
1337                             let mut has_bounds = false;
1338                             if let Node::GenericParam(ref param) = hir.get(id) {
1339                                 has_bounds = !param.bounds.is_empty();
1340                             }
1341                             let sp = hir.span(id);
1342                             // `sp` only covers `T`, change it so that it covers
1343                             // `T:` when appropriate
1344                             let is_impl_trait = bound_kind.to_string().starts_with("impl ");
1345                             let sp = if has_bounds && !is_impl_trait {
1346                                 sp.to(self.tcx
1347                                     .sess
1348                                     .source_map()
1349                                     .next_point(self.tcx.sess.source_map().next_point(sp)))
1350                             } else {
1351                                 sp
1352                             };
1353                             (sp, has_bounds, is_impl_trait)
1354                         })
1355                     } else {
1356                         None
1357                     }
1358                 })
1359             }
1360             _ => None,
1361         };
1362
1363         let labeled_user_string = match bound_kind {
1364             GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
1365             GenericKind::Projection(ref p) => format!("the associated type `{}`", p),
1366         };
1367
1368         if let Some(SubregionOrigin::CompareImplMethodObligation {
1369             span,
1370             item_name,
1371             impl_item_def_id,
1372             trait_item_def_id,
1373         }) = origin
1374         {
1375             return self.report_extra_impl_obligation(
1376                 span,
1377                 item_name,
1378                 impl_item_def_id,
1379                 trait_item_def_id,
1380                 &format!("`{}: {}`", bound_kind, sub),
1381             );
1382         }
1383
1384         fn binding_suggestion<'tcx, S: fmt::Display>(
1385             err: &mut DiagnosticBuilder<'tcx>,
1386             type_param_span: Option<(Span, bool, bool)>,
1387             bound_kind: GenericKind<'tcx>,
1388             sub: S,
1389         ) {
1390             let consider = format!(
1391                 "consider adding an explicit lifetime bound {}",
1392                 if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) {
1393                     format!(" `{}` to `{}`...", sub, bound_kind)
1394                 } else {
1395                     format!("`{}: {}`...", bound_kind, sub)
1396                 },
1397             );
1398             if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
1399                 let suggestion = if is_impl_trait {
1400                     format!("{} + {}", bound_kind, sub)
1401                 } else {
1402                     let tail = if has_lifetimes { " + " } else { "" };
1403                     format!("{}: {}{}", bound_kind, sub, tail)
1404                 };
1405                 err.span_suggestion_short(
1406                     sp,
1407                     &consider,
1408                     suggestion,
1409                     Applicability::MaybeIncorrect, // Issue #41966
1410                 );
1411             } else {
1412                 err.help(&consider);
1413             }
1414         }
1415
1416         let mut err = match *sub {
1417             ty::ReEarlyBound(_)
1418             | ty::ReFree(ty::FreeRegion {
1419                 bound_region: ty::BrNamed(..),
1420                 ..
1421             }) => {
1422                 // Does the required lifetime have a nice name we can print?
1423                 let mut err = struct_span_err!(
1424                     self.tcx.sess,
1425                     span,
1426                     E0309,
1427                     "{} may not live long enough",
1428                     labeled_user_string
1429                 );
1430                 binding_suggestion(&mut err, type_param_span, bound_kind, sub);
1431                 err
1432             }
1433
1434             ty::ReStatic => {
1435                 // Does the required lifetime have a nice name we can print?
1436                 let mut err = struct_span_err!(
1437                     self.tcx.sess,
1438                     span,
1439                     E0310,
1440                     "{} may not live long enough",
1441                     labeled_user_string
1442                 );
1443                 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
1444                 err
1445             }
1446
1447             _ => {
1448                 // If not, be less specific.
1449                 let mut err = struct_span_err!(
1450                     self.tcx.sess,
1451                     span,
1452                     E0311,
1453                     "{} may not live long enough",
1454                     labeled_user_string
1455                 );
1456                 err.help(&format!(
1457                     "consider adding an explicit lifetime bound for `{}`",
1458                     bound_kind
1459                 ));
1460                 self.tcx.note_and_explain_region(
1461                     region_scope_tree,
1462                     &mut err,
1463                     &format!("{} must be valid for ", labeled_user_string),
1464                     sub,
1465                     "...",
1466                 );
1467                 err
1468             }
1469         };
1470
1471         if let Some(origin) = origin {
1472             self.note_region_origin(&mut err, &origin);
1473         }
1474         err
1475     }
1476
1477     fn report_sub_sup_conflict(
1478         &self,
1479         region_scope_tree: &region::ScopeTree,
1480         var_origin: RegionVariableOrigin,
1481         sub_origin: SubregionOrigin<'tcx>,
1482         sub_region: Region<'tcx>,
1483         sup_origin: SubregionOrigin<'tcx>,
1484         sup_region: Region<'tcx>,
1485     ) {
1486         let mut err = self.report_inference_failure(var_origin);
1487
1488         self.tcx.note_and_explain_region(
1489             region_scope_tree,
1490             &mut err,
1491             "first, the lifetime cannot outlive ",
1492             sup_region,
1493             "...",
1494         );
1495
1496         match (&sup_origin, &sub_origin) {
1497             (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => {
1498                 debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
1499                 debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
1500                 debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
1501                 debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
1502                 debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
1503                 debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
1504                 debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
1505                 debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
1506                 debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
1507
1508                 if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = (
1509                     self.values_str(&sup_trace.values),
1510                     self.values_str(&sub_trace.values),
1511                 ) {
1512                     if sub_expected == sup_expected && sub_found == sup_found {
1513                         self.tcx.note_and_explain_region(
1514                             region_scope_tree,
1515                             &mut err,
1516                             "...but the lifetime must also be valid for ",
1517                             sub_region,
1518                             "...",
1519                         );
1520                         err.note(&format!(
1521                             "...so that the {}:\nexpected {}\n   found {}",
1522                             sup_trace.cause.as_requirement_str(),
1523                             sup_expected.content(),
1524                             sup_found.content()
1525                         ));
1526                         err.emit();
1527                         return;
1528                     }
1529                 }
1530             }
1531             _ => {}
1532         }
1533
1534         self.note_region_origin(&mut err, &sup_origin);
1535
1536         self.tcx.note_and_explain_region(
1537             region_scope_tree,
1538             &mut err,
1539             "but, the lifetime must be valid for ",
1540             sub_region,
1541             "...",
1542         );
1543
1544         self.note_region_origin(&mut err, &sub_origin);
1545         err.emit();
1546     }
1547 }
1548
1549 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1550     fn report_inference_failure(
1551         &self,
1552         var_origin: RegionVariableOrigin,
1553     ) -> DiagnosticBuilder<'tcx> {
1554         let br_string = |br: ty::BoundRegion| {
1555             let mut s = match br {
1556                 ty::BrNamed(_, name) => name.to_string(),
1557                 _ => String::new(),
1558             };
1559             if !s.is_empty() {
1560                 s.push_str(" ");
1561             }
1562             s
1563         };
1564         let var_description = match var_origin {
1565             infer::MiscVariable(_) => String::new(),
1566             infer::PatternRegion(_) => " for pattern".to_string(),
1567             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
1568             infer::Autoref(_) => " for autoref".to_string(),
1569             infer::Coercion(_) => " for automatic coercion".to_string(),
1570             infer::LateBoundRegion(_, br, infer::FnCall) => {
1571                 format!(" for lifetime parameter {}in function call", br_string(br))
1572             }
1573             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
1574                 format!(" for lifetime parameter {}in generic type", br_string(br))
1575             }
1576             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!(
1577                 " for lifetime parameter {}in trait containing associated type `{}`",
1578                 br_string(br),
1579                 self.tcx.associated_item(def_id).ident
1580             ),
1581             infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name),
1582             infer::BoundRegionInCoherence(name) => {
1583                 format!(" for lifetime parameter `{}` in coherence check", name)
1584             }
1585             infer::UpvarRegion(ref upvar_id, _) => {
1586                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
1587                 format!(" for capture of `{}` by closure", var_name)
1588             }
1589             infer::NLL(..) => bug!("NLL variable found in lexical phase"),
1590         };
1591
1592         struct_span_err!(
1593             self.tcx.sess,
1594             var_origin.span(),
1595             E0495,
1596             "cannot infer an appropriate lifetime{} \
1597              due to conflicting requirements",
1598             var_description
1599         )
1600     }
1601 }
1602
1603 enum FailureCode {
1604     Error0317(&'static str),
1605     Error0580(&'static str),
1606     Error0308(&'static str),
1607     Error0644(&'static str),
1608 }
1609
1610 impl<'tcx> ObligationCause<'tcx> {
1611     fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
1612         use self::FailureCode::*;
1613         use crate::traits::ObligationCauseCode::*;
1614         match self.code {
1615             CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
1616             MatchExpressionArm { source, .. } => Error0308(match source {
1617                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types",
1618                 hir::MatchSource::TryDesugar => {
1619                     "try expression alternatives have incompatible types"
1620                 }
1621                 _ => "match arms have incompatible types",
1622             }),
1623             IfExpression { .. } => Error0308("if and else have incompatible types"),
1624             IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
1625             MainFunctionType => Error0580("main function has wrong type"),
1626             StartFunctionType => Error0308("start function has wrong type"),
1627             IntrinsicType => Error0308("intrinsic has wrong type"),
1628             MethodReceiver => Error0308("mismatched method receiver"),
1629
1630             // In the case where we have no more specific thing to
1631             // say, also take a look at the error code, maybe we can
1632             // tailor to that.
1633             _ => match terr {
1634                 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => {
1635                     Error0644("closure/generator type that references itself")
1636                 }
1637                 _ => Error0308("mismatched types"),
1638             },
1639         }
1640     }
1641
1642     fn as_requirement_str(&self) -> &'static str {
1643         use crate::traits::ObligationCauseCode::*;
1644         match self.code {
1645             CompareImplMethodObligation { .. } => "method type is compatible with trait",
1646             ExprAssignable => "expression is assignable",
1647             MatchExpressionArm { source, .. } => match source {
1648                 hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types",
1649                 _ => "match arms have compatible types",
1650             },
1651             IfExpression { .. } => "if and else have compatible types",
1652             IfExpressionWithNoElse => "if missing an else returns ()",
1653             MainFunctionType => "`main` function has the correct type",
1654             StartFunctionType => "`start` function has the correct type",
1655             IntrinsicType => "intrinsic has the correct type",
1656             MethodReceiver => "method receiver has the correct type",
1657             _ => "types are compatible",
1658         }
1659     }
1660 }