]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/mod.rs
Auto merge of #45668 - nikomatsakis:nll-free-region, r=arielb1
[rust.git] / src / librustc / infer / error_reporting / mod.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Error Reporting Code for the inference engine
12 //!
13 //! Because of the way inference, and in particular region inference,
14 //! works, it often happens that errors are not detected until far after
15 //! the relevant line of code has been type-checked. Therefore, there is
16 //! an elaborate system to track why a particular constraint in the
17 //! inference graph arose so that we can explain to the user what gave
18 //! rise to a particular error.
19 //!
20 //! The basis of the system are the "origin" types. An "origin" is the
21 //! reason that a constraint or inference variable arose. There are
22 //! different "origin" enums for different kinds of constraints/variables
23 //! (e.g., `TypeOrigin`, `RegionVariableOrigin`). An origin always has
24 //! a span, but also more information so that we can generate a meaningful
25 //! error message.
26 //!
27 //! Having a catalog of all the different reasons an error can arise is
28 //! also useful for other reasons, like cross-referencing FAQs etc, though
29 //! we are not really taking advantage of this yet.
30 //!
31 //! # Region Inference
32 //!
33 //! Region inference is particularly tricky because it always succeeds "in
34 //! the moment" and simply registers a constraint. Then, at the end, we
35 //! can compute the full graph and report errors, so we need to be able to
36 //! store and later report what gave rise to the conflicting constraints.
37 //!
38 //! # Subtype Trace
39 //!
40 //! Determining whether `T1 <: T2` often involves a number of subtypes and
41 //! subconstraints along the way. A "TypeTrace" is an extended version
42 //! of an origin that traces the types and other values that were being
43 //! compared. It is not necessarily comprehensive (in fact, at the time of
44 //! this writing it only tracks the root values being compared) but I'd
45 //! like to extend it to include significant "waypoints". For example, if
46 //! you are comparing `(T1, T2) <: (T3, T4)`, and the problem is that `T2
47 //! <: T4` fails, I'd like the trace to include enough information to say
48 //! "in the 2nd element of the tuple". Similarly, failures when comparing
49 //! arguments or return types in fn types should be able to cite the
50 //! specific position, etc.
51 //!
52 //! # Reality vs plan
53 //!
54 //! Of course, there is still a LOT of code in typeck that has yet to be
55 //! ported to this system, and which relies on string concatenation at the
56 //! time of error detection.
57
58 use infer;
59 use super::{InferCtxt, TypeTrace, SubregionOrigin, RegionVariableOrigin, ValuePairs};
60 use super::region_inference::{RegionResolutionError, ConcreteFailure, SubSupConflict,
61                               GenericBoundFailure, GenericKind};
62
63 use std::fmt;
64 use hir;
65 use hir::map as hir_map;
66 use hir::def_id::DefId;
67 use middle::region;
68 use traits::{ObligationCause, ObligationCauseCode};
69 use ty::{self, Region, Ty, TyCtxt, TypeFoldable, TypeVariants};
70 use ty::error::TypeError;
71 use syntax::ast::DUMMY_NODE_ID;
72 use syntax_pos::{Pos, Span};
73 use errors::{DiagnosticBuilder, DiagnosticStyledString};
74
75 use rustc_data_structures::indexed_vec::Idx;
76
77 mod note;
78
79 mod need_type_info;
80
81 mod named_anon_conflict;
82 #[macro_use]
83 mod util;
84 mod different_lifetimes;
85
86 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
87     pub fn note_and_explain_region(self,
88                                    region_scope_tree: &region::ScopeTree,
89                                    err: &mut DiagnosticBuilder,
90                                    prefix: &str,
91                                    region: ty::Region<'tcx>,
92                                    suffix: &str) {
93         fn item_scope_tag(item: &hir::Item) -> &'static str {
94             match item.node {
95                 hir::ItemImpl(..) => "impl",
96                 hir::ItemStruct(..) => "struct",
97                 hir::ItemUnion(..) => "union",
98                 hir::ItemEnum(..) => "enum",
99                 hir::ItemTrait(..) => "trait",
100                 hir::ItemFn(..) => "function body",
101                 _ => "item"
102             }
103         }
104
105         fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
106             match item.node {
107                 hir::TraitItemKind::Method(..) => "method body",
108                 hir::TraitItemKind::Const(..) |
109                 hir::TraitItemKind::Type(..) => "associated item"
110             }
111         }
112
113         fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
114             match item.node {
115                 hir::ImplItemKind::Method(..) => "method body",
116                 hir::ImplItemKind::Const(..) |
117                 hir::ImplItemKind::Type(_) => "associated item"
118             }
119         }
120
121         fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
122                                         heading: &str, span: Span)
123                                         -> (String, Option<Span>) {
124             let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo());
125             (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
126              Some(span))
127         }
128
129         let (description, span) = match *region {
130             ty::ReScope(scope) => {
131                 let new_string;
132                 let unknown_scope = || {
133                     format!("{}unknown scope: {:?}{}.  Please report a bug.",
134                             prefix, scope, suffix)
135                 };
136                 let span = scope.span(self, region_scope_tree);
137                 let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) {
138                     Some(hir_map::NodeBlock(_)) => "block",
139                     Some(hir_map::NodeExpr(expr)) => match expr.node {
140                         hir::ExprCall(..) => "call",
141                         hir::ExprMethodCall(..) => "method call",
142                         hir::ExprMatch(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
143                         hir::ExprMatch(.., hir::MatchSource::WhileLetDesugar) =>  "while let",
144                         hir::ExprMatch(.., hir::MatchSource::ForLoopDesugar) =>  "for",
145                         hir::ExprMatch(..) => "match",
146                         _ => "expression",
147                     },
148                     Some(hir_map::NodeStmt(_)) => "statement",
149                     Some(hir_map::NodeItem(it)) => item_scope_tag(&it),
150                     Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
151                     Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
152                     Some(_) | None => {
153                         err.span_note(span, &unknown_scope());
154                         return;
155                     }
156                 };
157                 let scope_decorated_tag = match scope.data() {
158                     region::ScopeData::Node(_) => tag,
159                     region::ScopeData::CallSite(_) => {
160                         "scope of call-site for function"
161                     }
162                     region::ScopeData::Arguments(_) => {
163                         "scope of function body"
164                     }
165                     region::ScopeData::Destruction(_) => {
166                         new_string = format!("destruction scope surrounding {}", tag);
167                         &new_string[..]
168                     }
169                     region::ScopeData::Remainder(r) => {
170                         new_string = format!("block suffix following statement {}",
171                                              r.first_statement_index.index());
172                         &new_string[..]
173                     }
174                 };
175                 explain_span(self, scope_decorated_tag, span)
176             }
177
178             ty::ReEarlyBound(_) |
179             ty::ReFree(_) => {
180                 let scope = match *region {
181                     ty::ReEarlyBound(ref br) => {
182                         self.parent_def_id(br.def_id).unwrap()
183                     }
184                     ty::ReFree(ref fr) => fr.scope,
185                     _ => bug!()
186                 };
187                 let prefix = match *region {
188                     ty::ReEarlyBound(ref br) => {
189                         format!("the lifetime {} as defined on", br.name)
190                     }
191                     ty::ReFree(ref fr) => {
192                         match fr.bound_region {
193                             ty::BrAnon(idx) => {
194                                 format!("the anonymous lifetime #{} defined on", idx + 1)
195                             }
196                             ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
197                             _ => {
198                                 format!("the lifetime {} as defined on",
199                                         fr.bound_region)
200                             }
201                         }
202                     }
203                     _ => bug!()
204                 };
205
206                 let node = self.hir.as_local_node_id(scope)
207                                    .unwrap_or(DUMMY_NODE_ID);
208                 let unknown;
209                 let tag = match self.hir.find(node) {
210                     Some(hir_map::NodeBlock(_)) |
211                     Some(hir_map::NodeExpr(_)) => "body",
212                     Some(hir_map::NodeItem(it)) => item_scope_tag(&it),
213                     Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
214                     Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
215
216                     // this really should not happen, but it does:
217                     // FIXME(#27942)
218                     Some(_) => {
219                         unknown = format!("unexpected node ({}) for scope {:?}.  \
220                                            Please report a bug.",
221                                           self.hir.node_to_string(node), scope);
222                         &unknown
223                     }
224                     None => {
225                         unknown = format!("unknown node for scope {:?}.  \
226                                            Please report a bug.", scope);
227                         &unknown
228                     }
229                 };
230                 let (msg, opt_span) = explain_span(self, tag, self.hir.span(node));
231                 (format!("{} {}", prefix, msg), opt_span)
232             }
233
234             ty::ReStatic => ("the static lifetime".to_owned(), None),
235
236             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
237
238             // FIXME(#13998) ReSkolemized should probably print like
239             // ReFree rather than dumping Debug output on the user.
240             //
241             // We shouldn't really be having unification failures with ReVar
242             // and ReLateBound though.
243             ty::ReSkolemized(..) |
244             ty::ReVar(_) |
245             ty::ReLateBound(..) |
246             ty::ReErased => {
247                 (format!("lifetime {:?}", region), None)
248             }
249         };
250         let message = format!("{}{}{}", prefix, description, suffix);
251         if let Some(span) = span {
252             err.span_note(span, &message);
253         } else {
254             err.note(&message);
255         }
256     }
257 }
258
259 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
260     pub fn report_region_errors(&self,
261                                 region_scope_tree: &region::ScopeTree,
262                                 errors: &Vec<RegionResolutionError<'tcx>>) {
263         debug!("report_region_errors(): {} errors to start", errors.len());
264
265         if self.tcx.sess.opts.debugging_opts.nll {
266             for error in errors {
267                 match *error {
268                     RegionResolutionError::ConcreteFailure(ref origin, ..) |
269                     RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
270                         self.tcx.sess.span_warn(
271                             origin.span(),
272                             "not reporting region error due to -Znll");
273                     }
274
275                     RegionResolutionError::SubSupConflict(ref rvo, ..) => {
276                         self.tcx.sess.span_warn(
277                             rvo.span(),
278                             "not reporting region error due to -Znll");
279                     }
280                 }
281             }
282
283             return;
284         }
285
286         // try to pre-process the errors, which will group some of them
287         // together into a `ProcessedErrors` group:
288         let errors = self.process_errors(errors);
289
290         debug!("report_region_errors: {} errors after preprocessing", errors.len());
291
292         for error in errors {
293             debug!("report_region_errors: error = {:?}", error);
294
295             if !self.try_report_named_anon_conflict(&error) &&
296                !self.try_report_anon_anon_conflict(&error) {
297
298                match error.clone() {
299                   // These errors could indicate all manner of different
300                   // problems with many different solutions. Rather
301                   // than generate a "one size fits all" error, what we
302                   // attempt to do is go through a number of specific
303                   // scenarios and try to find the best way to present
304                   // the error. If all of these fails, we fall back to a rather
305                   // general bit of code that displays the error information
306                   ConcreteFailure(origin, sub, sup) => {
307                       self.report_concrete_failure(region_scope_tree, origin, sub, sup).emit();
308                   }
309
310                   GenericBoundFailure(kind, param_ty, sub) => {
311                       self.report_generic_bound_failure(region_scope_tree, kind, param_ty, sub);
312                   }
313
314                   SubSupConflict(var_origin, sub_origin, sub_r, sup_origin, sup_r) => {
315                         self.report_sub_sup_conflict(region_scope_tree,
316                                                      var_origin,
317                                                      sub_origin,
318                                                      sub_r,
319                                                      sup_origin,
320                                                      sup_r);
321                   }
322                }
323             }
324         }
325     }
326
327     // This method goes through all the errors and try to group certain types
328     // of error together, for the purpose of suggesting explicit lifetime
329     // parameters to the user. This is done so that we can have a more
330     // complete view of what lifetimes should be the same.
331     // If the return value is an empty vector, it means that processing
332     // failed (so the return value of this method should not be used).
333     //
334     // The method also attempts to weed out messages that seem like
335     // duplicates that will be unhelpful to the end-user. But
336     // obviously it never weeds out ALL errors.
337     fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
338                       -> Vec<RegionResolutionError<'tcx>> {
339         debug!("process_errors()");
340
341         // We want to avoid reporting generic-bound failures if we can
342         // avoid it: these have a very high rate of being unhelpful in
343         // practice. This is because they are basically secondary
344         // checks that test the state of the region graph after the
345         // rest of inference is done, and the other kinds of errors
346         // indicate that the region constraint graph is internally
347         // inconsistent, so these test results are likely to be
348         // meaningless.
349         //
350         // Therefore, we filter them out of the list unless they are
351         // the only thing in the list.
352
353         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
354             ConcreteFailure(..) => false,
355             SubSupConflict(..) => false,
356             GenericBoundFailure(..) => true,
357         };
358
359
360         let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
361             errors.clone()
362         } else {
363             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
364         };
365
366         // sort the errors by span, for better error message stability.
367         errors.sort_by_key(|u| match *u {
368             ConcreteFailure(ref sro, _, _) => sro.span(),
369             GenericBoundFailure(ref sro, _, _) => sro.span(),
370             SubSupConflict(ref rvo, _, _, _, _) => rvo.span(),
371         });
372         errors
373     }
374
375     /// Adds a note if the types come from similarly named crates
376     fn check_and_note_conflicting_crates(&self,
377                                          err: &mut DiagnosticBuilder,
378                                          terr: &TypeError<'tcx>,
379                                          sp: Span) {
380         let report_path_match = |err: &mut DiagnosticBuilder, did1: DefId, did2: DefId| {
381             // Only external crates, if either is from a local
382             // module we could have false positives
383             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
384                 let exp_path = self.tcx.item_path_str(did1);
385                 let found_path = self.tcx.item_path_str(did2);
386                 let exp_abs_path = self.tcx.absolute_item_path_str(did1);
387                 let found_abs_path = self.tcx.absolute_item_path_str(did2);
388                 // We compare strings because DefPath can be different
389                 // for imported and non-imported crates
390                 if exp_path == found_path
391                 || exp_abs_path == found_abs_path {
392                     let crate_name = self.tcx.crate_name(did1.krate);
393                     err.span_note(sp, &format!("Perhaps two different versions \
394                                                 of crate `{}` are being used?",
395                                                crate_name));
396                 }
397             }
398         };
399         match *terr {
400             TypeError::Sorts(ref exp_found) => {
401                 // if they are both "path types", there's a chance of ambiguity
402                 // due to different versions of the same crate
403                 match (&exp_found.expected.sty, &exp_found.found.sty) {
404                     (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
405                         report_path_match(err, exp_adt.did, found_adt.did);
406                     },
407                     _ => ()
408                 }
409             },
410             TypeError::Traits(ref exp_found) => {
411                 report_path_match(err, exp_found.expected, exp_found.found);
412             },
413             _ => () // FIXME(#22750) handle traits and stuff
414         }
415     }
416
417     fn note_error_origin(&self,
418                          err: &mut DiagnosticBuilder<'tcx>,
419                          cause: &ObligationCause<'tcx>)
420     {
421         match cause.code {
422             ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
423                 hir::MatchSource::IfLetDesugar {..} => {
424                     err.span_note(arm_span, "`if let` arm with an incompatible type");
425                 }
426                 _ => {
427                     err.span_note(arm_span, "match arm with an incompatible type");
428                 }
429             },
430             _ => ()
431         }
432     }
433
434     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
435     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
436     /// populate `other_value` with `other_ty`.
437     ///
438     /// ```text
439     /// Foo<Bar<Qux>>
440     /// ^^^^--------^ this is highlighted
441     /// |   |
442     /// |   this type argument is exactly the same as the other type, not highlighted
443     /// this is highlighted
444     /// Bar<Qux>
445     /// -------- this type is the same as a type argument in the other type, not highlighted
446     /// ```
447     fn highlight_outer(&self,
448                        value: &mut DiagnosticStyledString,
449                        other_value: &mut DiagnosticStyledString,
450                        name: String,
451                        sub: &ty::subst::Substs<'tcx>,
452                        pos: usize,
453                        other_ty: &Ty<'tcx>) {
454         // `value` and `other_value` hold two incomplete type representation for display.
455         // `name` is the path of both types being compared. `sub`
456         value.push_highlighted(name);
457         let len = sub.len();
458         if len > 0 {
459             value.push_highlighted("<");
460         }
461
462         // Output the lifetimes fot the first type
463         let lifetimes = sub.regions().map(|lifetime| {
464             let s = format!("{}", lifetime);
465             if s.is_empty() {
466                 "'_".to_string()
467             } else {
468                 s
469             }
470         }).collect::<Vec<_>>().join(", ");
471         if !lifetimes.is_empty() {
472             if sub.regions().count() < len {
473                 value.push_normal(lifetimes + &", ");
474             } else {
475                 value.push_normal(lifetimes);
476             }
477         }
478
479         // Highlight all the type arguments that aren't at `pos` and compare the type argument at
480         // `pos` and `other_ty`.
481         for (i, type_arg) in sub.types().enumerate() {
482             if i == pos {
483                 let values = self.cmp(type_arg, other_ty);
484                 value.0.extend((values.0).0);
485                 other_value.0.extend((values.1).0);
486             } else {
487                 value.push_highlighted(format!("{}", type_arg));
488             }
489
490             if len > 0 && i != len - 1 {
491                 value.push_normal(", ");
492             }
493             //self.push_comma(&mut value, &mut other_value, len, i);
494         }
495         if len > 0 {
496             value.push_highlighted(">");
497         }
498     }
499
500     /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
501     /// as that is the difference to the other type.
502     ///
503     /// For the following code:
504     ///
505     /// ```norun
506     /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
507     /// ```
508     ///
509     /// The type error output will behave in the following way:
510     ///
511     /// ```text
512     /// Foo<Bar<Qux>>
513     /// ^^^^--------^ this is highlighted
514     /// |   |
515     /// |   this type argument is exactly the same as the other type, not highlighted
516     /// this is highlighted
517     /// Bar<Qux>
518     /// -------- this type is the same as a type argument in the other type, not highlighted
519     /// ```
520     fn cmp_type_arg(&self,
521                     mut t1_out: &mut DiagnosticStyledString,
522                     mut t2_out: &mut DiagnosticStyledString,
523                     path: String,
524                     sub: &ty::subst::Substs<'tcx>,
525                     other_path: String,
526                     other_ty: &Ty<'tcx>) -> Option<()> {
527         for (i, ta) in sub.types().enumerate() {
528             if &ta == other_ty {
529                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
530                 return Some(());
531             }
532             if let &ty::TyAdt(def, _) = &ta.sty {
533                 let path_ = self.tcx.item_path_str(def.did.clone());
534                 if path_ == other_path {
535                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
536                     return Some(());
537                 }
538             }
539         }
540         None
541     }
542
543     /// Add a `,` to the type representation only if it is appropriate.
544     fn push_comma(&self,
545                   value: &mut DiagnosticStyledString,
546                   other_value: &mut DiagnosticStyledString,
547                   len: usize,
548                   pos: usize) {
549         if len > 0 && pos != len - 1 {
550             value.push_normal(", ");
551             other_value.push_normal(", ");
552         }
553     }
554
555     /// Compare two given types, eliding parts that are the same between them and highlighting
556     /// relevant differences, and return two representation of those types for highlighted printing.
557     fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>)
558         -> (DiagnosticStyledString, DiagnosticStyledString)
559     {
560         match (&t1.sty, &t2.sty) {
561             (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
562                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
563                 let path1 = self.tcx.item_path_str(def1.did.clone());
564                 let path2 = self.tcx.item_path_str(def2.did.clone());
565                 if def1.did == def2.did {
566                     // Easy case. Replace same types with `_` to shorten the output and highlight
567                     // the differing ones.
568                     //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
569                     //     Foo<Bar, _>
570                     //     Foo<Quz, _>
571                     //         ---  ^ type argument elided
572                     //         |
573                     //         highlighted in output
574                     values.0.push_normal(path1);
575                     values.1.push_normal(path2);
576
577                     // Only draw `<...>` if there're lifetime/type arguments.
578                     let len = sub1.len();
579                     if len > 0 {
580                         values.0.push_normal("<");
581                         values.1.push_normal("<");
582                     }
583
584                     fn lifetime_display(lifetime: Region) -> String {
585                         let s = format!("{}", lifetime);
586                         if s.is_empty() {
587                             "'_".to_string()
588                         } else {
589                             s
590                         }
591                     }
592                     // At one point we'd like to elide all lifetimes here, they are irrelevant for
593                     // all diagnostics that use this output
594                     //
595                     //     Foo<'x, '_, Bar>
596                     //     Foo<'y, '_, Qux>
597                     //         ^^  ^^  --- type arguments are not elided
598                     //         |   |
599                     //         |   elided as they were the same
600                     //         not elided, they were different, but irrelevant
601                     let lifetimes = sub1.regions().zip(sub2.regions());
602                     for (i, lifetimes) in lifetimes.enumerate() {
603                         let l1 = lifetime_display(lifetimes.0);
604                         let l2 = lifetime_display(lifetimes.1);
605                         if l1 == l2 {
606                             values.0.push_normal("'_");
607                             values.1.push_normal("'_");
608                         } else {
609                             values.0.push_highlighted(l1);
610                             values.1.push_highlighted(l2);
611                         }
612                         self.push_comma(&mut values.0, &mut values.1, len, i);
613                     }
614
615                     // We're comparing two types with the same path, so we compare the type
616                     // arguments for both. If they are the same, do not highlight and elide from the
617                     // output.
618                     //     Foo<_, Bar>
619                     //     Foo<_, Qux>
620                     //         ^ elided type as this type argument was the same in both sides
621                     let type_arguments = sub1.types().zip(sub2.types());
622                     let regions_len = sub1.regions().collect::<Vec<_>>().len();
623                     for (i, (ta1, ta2)) in type_arguments.enumerate() {
624                         let i = i + regions_len;
625                         if ta1 == ta2 {
626                             values.0.push_normal("_");
627                             values.1.push_normal("_");
628                         } else {
629                             let (x1, x2) = self.cmp(ta1, ta2);
630                             (values.0).0.extend(x1.0);
631                             (values.1).0.extend(x2.0);
632                         }
633                         self.push_comma(&mut values.0, &mut values.1, len, i);
634                     }
635
636                     // Close the type argument bracket.
637                     // Only draw `<...>` if there're lifetime/type arguments.
638                     if len > 0 {
639                         values.0.push_normal(">");
640                         values.1.push_normal(">");
641                     }
642                     values
643                 } else {
644                     // Check for case:
645                     //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
646                     //     Foo<Bar<Qux>
647                     //         ------- this type argument is exactly the same as the other type
648                     //     Bar<Qux>
649                     if self.cmp_type_arg(&mut values.0,
650                                          &mut values.1,
651                                          path1.clone(),
652                                          sub1,
653                                          path2.clone(),
654                                          &t2).is_some() {
655                         return values;
656                     }
657                     // Check for case:
658                     //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
659                     //     Bar<Qux>
660                     //     Foo<Bar<Qux>>
661                     //         ------- this type argument is exactly the same as the other type
662                     if self.cmp_type_arg(&mut values.1,
663                                          &mut values.0,
664                                          path2,
665                                          sub2,
666                                          path1,
667                                          &t1).is_some() {
668                         return values;
669                     }
670
671                     // We couldn't find anything in common, highlight everything.
672                     //     let x: Bar<Qux> = y::<Foo<Zar>>();
673                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
674                      DiagnosticStyledString::highlighted(format!("{}", t2)))
675                 }
676             }
677             _ => {
678                 if t1 == t2 {
679                     // The two types are the same, elide and don't highlight.
680                     (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
681                 } else {
682                     // We couldn't find anything in common, highlight everything.
683                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
684                      DiagnosticStyledString::highlighted(format!("{}", t2)))
685                 }
686             }
687         }
688     }
689
690     pub fn note_type_err(&self,
691                          diag: &mut DiagnosticBuilder<'tcx>,
692                          cause: &ObligationCause<'tcx>,
693                          secondary_span: Option<(Span, String)>,
694                          values: Option<ValuePairs<'tcx>>,
695                          terr: &TypeError<'tcx>)
696     {
697         let (expected_found, exp_found, is_simple_error) = match values {
698             None => (None, None, false),
699             Some(values) => {
700                 let (is_simple_error, exp_found) = match values {
701                     ValuePairs::Types(exp_found) => {
702                         let is_simple_err = exp_found.expected.is_primitive()
703                             && exp_found.found.is_primitive();
704
705                         (is_simple_err, Some(exp_found))
706                     }
707                     _ => (false, None),
708                 };
709                 let vals = match self.values_str(&values) {
710                     Some((expected, found)) => Some((expected, found)),
711                     None => {
712                         // Derived error. Cancel the emitter.
713                         self.tcx.sess.diagnostic().cancel(diag);
714                         return
715                     }
716                 };
717                 (vals, exp_found, is_simple_error)
718             }
719         };
720
721         let span = cause.span;
722
723         diag.span_label(span, terr.to_string());
724         if let Some((sp, msg)) = secondary_span {
725             diag.span_label(sp, msg);
726         }
727
728         if let Some((expected, found)) = expected_found {
729             match (terr, is_simple_error, expected == found) {
730                 (&TypeError::Sorts(ref values), false, true) => {
731                     diag.note_expected_found_extra(
732                         &"type", expected, found,
733                         &format!(" ({})", values.expected.sort_string(self.tcx)),
734                         &format!(" ({})", values.found.sort_string(self.tcx)));
735                 }
736                 (_, false, _) => {
737                     if let Some(exp_found) = exp_found {
738                         let (def_id, ret_ty) = match exp_found.found.sty {
739                             TypeVariants::TyFnDef(def, _) => {
740                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
741                             }
742                             _ => (None, None)
743                         };
744
745                         let exp_is_struct = match exp_found.expected.sty {
746                             TypeVariants::TyAdt(def, _) => def.is_struct(),
747                             _ => false
748                         };
749
750                         if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
751                             if exp_is_struct && exp_found.expected == ret_ty.0 {
752                                 let message = format!(
753                                     "did you mean `{}(/* fields */)`?",
754                                     self.tcx.item_path_str(def_id)
755                                 );
756                                 diag.span_label(cause.span, message);
757                             }
758                         }
759                     }
760
761                     diag.note_expected_found(&"type", expected, found);
762                 }
763                 _ => (),
764             }
765         }
766
767         self.note_error_origin(diag, &cause);
768         self.check_and_note_conflicting_crates(diag, terr, span);
769         self.tcx.note_and_explain_type_err(diag, terr, span);
770     }
771
772     pub fn report_and_explain_type_error(&self,
773                                          trace: TypeTrace<'tcx>,
774                                          terr: &TypeError<'tcx>)
775                                          -> DiagnosticBuilder<'tcx>
776     {
777         let span = trace.cause.span;
778         let failure_str = trace.cause.as_failure_str();
779         let mut diag = match trace.cause.code {
780             ObligationCauseCode::IfExpressionWithNoElse => {
781                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
782             }
783             ObligationCauseCode::MainFunctionType => {
784                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
785             }
786             _ => {
787                 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
788             }
789         };
790         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
791         diag
792     }
793
794     fn values_str(&self, values: &ValuePairs<'tcx>)
795         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
796     {
797         match *values {
798             infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
799             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
800             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
801         }
802     }
803
804     fn expected_found_str_ty(&self,
805                              exp_found: &ty::error::ExpectedFound<Ty<'tcx>>)
806                              -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
807         let exp_found = self.resolve_type_vars_if_possible(exp_found);
808         if exp_found.references_error() {
809             return None;
810         }
811
812         Some(self.cmp(exp_found.expected, exp_found.found))
813     }
814
815     /// Returns a string of the form "expected `{}`, found `{}`".
816     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
817         &self,
818         exp_found: &ty::error::ExpectedFound<T>)
819         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
820     {
821         let exp_found = self.resolve_type_vars_if_possible(exp_found);
822         if exp_found.references_error() {
823             return None;
824         }
825
826         Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)),
827               DiagnosticStyledString::highlighted(format!("{}", exp_found.found))))
828     }
829
830     fn report_generic_bound_failure(&self,
831                                     region_scope_tree: &region::ScopeTree,
832                                     origin: SubregionOrigin<'tcx>,
833                                     bound_kind: GenericKind<'tcx>,
834                                     sub: Region<'tcx>)
835     {
836         // Attempt to obtain the span of the parameter so we can
837         // suggest adding an explicit lifetime bound to it.
838         let type_param_span = match (self.in_progress_tables, bound_kind) {
839             (Some(ref table), GenericKind::Param(ref param)) => {
840                 let table = table.borrow();
841                 table.local_id_root.and_then(|did| {
842                     let generics = self.tcx.generics_of(did);
843                     // Account for the case where `did` corresponds to `Self`, which doesn't have
844                     // the expected type argument.
845                     if !param.is_self() {
846                         let type_param = generics.type_param(param, self.tcx);
847                         let hir = &self.tcx.hir;
848                         hir.as_local_node_id(type_param.def_id).map(|id| {
849                             // Get the `hir::TyParam` to verify wether it already has any bounds.
850                             // We do this to avoid suggesting code that ends up as `T: 'a'b`,
851                             // instead we suggest `T: 'a + 'b` in that case.
852                             let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) {
853                                 p.bounds.len() > 0
854                             } else {
855                                 false
856                             };
857                             let sp = hir.span(id);
858                             // `sp` only covers `T`, change it so that it covers
859                             // `T:` when appropriate
860                             let sp = if has_lifetimes {
861                                 sp.to(sp.next_point().next_point())
862                             } else {
863                                 sp
864                             };
865                             (sp, has_lifetimes)
866                         })
867                     } else {
868                         None
869                     }
870                 })
871             }
872             _ => None,
873         };
874
875         let labeled_user_string = match bound_kind {
876             GenericKind::Param(ref p) =>
877                 format!("the parameter type `{}`", p),
878             GenericKind::Projection(ref p) =>
879                 format!("the associated type `{}`", p),
880         };
881
882         if let SubregionOrigin::CompareImplMethodObligation {
883             span, item_name, impl_item_def_id, trait_item_def_id, lint_id
884         } = origin {
885             self.report_extra_impl_obligation(span,
886                                               item_name,
887                                               impl_item_def_id,
888                                               trait_item_def_id,
889                                               &format!("`{}: {}`", bound_kind, sub),
890                                               lint_id)
891                 .emit();
892             return;
893         }
894
895         fn binding_suggestion<'tcx, S: fmt::Display>(err: &mut DiagnosticBuilder<'tcx>,
896                                                      type_param_span: Option<(Span, bool)>,
897                                                      bound_kind: GenericKind<'tcx>,
898                                                      sub: S) {
899             let consider = &format!("consider adding an explicit lifetime bound `{}: {}`...",
900                                     bound_kind,
901                                     sub);
902             if let Some((sp, has_lifetimes)) = type_param_span {
903                 let tail = if has_lifetimes {
904                     " + "
905                 } else {
906                     ""
907                 };
908                 let suggestion = format!("{}: {}{}", bound_kind, sub, tail);
909                 err.span_suggestion_short(sp, consider, suggestion);
910             } else {
911                 err.help(consider);
912             }
913         }
914
915         let mut err = match *sub {
916             ty::ReEarlyBound(_) |
917             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
918                 // Does the required lifetime have a nice name we can print?
919                 let mut err = struct_span_err!(self.tcx.sess,
920                                                origin.span(),
921                                                E0309,
922                                                "{} may not live long enough",
923                                                labeled_user_string);
924                 binding_suggestion(&mut err, type_param_span, bound_kind, sub);
925                 err
926             }
927
928             ty::ReStatic => {
929                 // Does the required lifetime have a nice name we can print?
930                 let mut err = struct_span_err!(self.tcx.sess,
931                                                origin.span(),
932                                                E0310,
933                                                "{} may not live long enough",
934                                                labeled_user_string);
935                 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
936                 err
937             }
938
939             _ => {
940                 // If not, be less specific.
941                 let mut err = struct_span_err!(self.tcx.sess,
942                                                origin.span(),
943                                                E0311,
944                                                "{} may not live long enough",
945                                                labeled_user_string);
946                 err.help(&format!("consider adding an explicit lifetime bound for `{}`",
947                                   bound_kind));
948                 self.tcx.note_and_explain_region(
949                     region_scope_tree,
950                     &mut err,
951                     &format!("{} must be valid for ", labeled_user_string),
952                     sub,
953                     "...");
954                 err
955             }
956         };
957
958         self.note_region_origin(&mut err, &origin);
959         err.emit();
960     }
961
962     fn report_sub_sup_conflict(&self,
963                                region_scope_tree: &region::ScopeTree,
964                                var_origin: RegionVariableOrigin,
965                                sub_origin: SubregionOrigin<'tcx>,
966                                sub_region: Region<'tcx>,
967                                sup_origin: SubregionOrigin<'tcx>,
968                                sup_region: Region<'tcx>) {
969         let mut err = self.report_inference_failure(var_origin);
970
971         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
972             "first, the lifetime cannot outlive ",
973             sup_region,
974             "...");
975
976         self.note_region_origin(&mut err, &sup_origin);
977
978         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
979             "but, the lifetime must be valid for ",
980             sub_region,
981             "...");
982
983         self.note_region_origin(&mut err, &sub_origin);
984         err.emit();
985     }
986 }
987
988 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
989     fn report_inference_failure(&self,
990                                 var_origin: RegionVariableOrigin)
991                                 -> DiagnosticBuilder<'tcx> {
992         let br_string = |br: ty::BoundRegion| {
993             let mut s = br.to_string();
994             if !s.is_empty() {
995                 s.push_str(" ");
996             }
997             s
998         };
999         let var_description = match var_origin {
1000             infer::MiscVariable(_) => "".to_string(),
1001             infer::PatternRegion(_) => " for pattern".to_string(),
1002             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
1003             infer::Autoref(_) => " for autoref".to_string(),
1004             infer::Coercion(_) => " for automatic coercion".to_string(),
1005             infer::LateBoundRegion(_, br, infer::FnCall) => {
1006                 format!(" for lifetime parameter {}in function call",
1007                         br_string(br))
1008             }
1009             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
1010                 format!(" for lifetime parameter {}in generic type", br_string(br))
1011             }
1012             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => {
1013                 format!(" for lifetime parameter {}in trait containing associated type `{}`",
1014                         br_string(br), self.tcx.associated_item(def_id).name)
1015             }
1016             infer::EarlyBoundRegion(_, name) => {
1017                 format!(" for lifetime parameter `{}`",
1018                         name)
1019             }
1020             infer::BoundRegionInCoherence(name) => {
1021                 format!(" for lifetime parameter `{}` in coherence check",
1022                         name)
1023             }
1024             infer::UpvarRegion(ref upvar_id, _) => {
1025                 let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
1026                 let var_name = self.tcx.hir.name(var_node_id);
1027                 format!(" for capture of `{}` by closure", var_name)
1028             }
1029         };
1030
1031         struct_span_err!(self.tcx.sess, var_origin.span(), E0495,
1032                   "cannot infer an appropriate lifetime{} \
1033                    due to conflicting requirements",
1034                   var_description)
1035     }
1036 }
1037
1038 impl<'tcx> ObligationCause<'tcx> {
1039     fn as_failure_str(&self) -> &'static str {
1040         use traits::ObligationCauseCode::*;
1041         match self.code {
1042             CompareImplMethodObligation { .. } => "method not compatible with trait",
1043             MatchExpressionArm { source, .. } => match source {
1044                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
1045                 _ => "match arms have incompatible types",
1046             },
1047             IfExpression => "if and else have incompatible types",
1048             IfExpressionWithNoElse => "if may be missing an else clause",
1049             EquatePredicate => "equality predicate not satisfied",
1050             MainFunctionType => "main function has wrong type",
1051             StartFunctionType => "start function has wrong type",
1052             IntrinsicType => "intrinsic has wrong type",
1053             MethodReceiver => "mismatched method receiver",
1054             _ => "mismatched types",
1055         }
1056     }
1057
1058     fn as_requirement_str(&self) -> &'static str {
1059         use traits::ObligationCauseCode::*;
1060         match self.code {
1061             CompareImplMethodObligation { .. } => "method type is compatible with trait",
1062             ExprAssignable => "expression is assignable",
1063             MatchExpressionArm { source, .. } => match source {
1064                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types",
1065                 _ => "match arms have compatible types",
1066             },
1067             IfExpression => "if and else have compatible types",
1068             IfExpressionWithNoElse => "if missing an else returns ()",
1069             EquatePredicate => "equality where clause is satisfied",
1070             MainFunctionType => "`main` function has the correct type",
1071             StartFunctionType => "`start` function has the correct type",
1072             IntrinsicType => "intrinsic has the correct type",
1073             MethodReceiver => "method receiver has the correct type",
1074             _ => "types are compatible",
1075         }
1076     }
1077 }