]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/mod.rs
Rollup merge of #47547 - varkor:infinite-iterators-warning-doc, r=frewsxcv
[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_constraints::GenericKind;
61 use super::lexical_region_resolve::RegionResolutionError;
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 pub mod nice_region_error;
82
83 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
84     pub fn note_and_explain_region(self,
85                                    region_scope_tree: &region::ScopeTree,
86                                    err: &mut DiagnosticBuilder,
87                                    prefix: &str,
88                                    region: ty::Region<'tcx>,
89                                    suffix: &str) {
90         fn item_scope_tag(item: &hir::Item) -> &'static str {
91             match item.node {
92                 hir::ItemImpl(..) => "impl",
93                 hir::ItemStruct(..) => "struct",
94                 hir::ItemUnion(..) => "union",
95                 hir::ItemEnum(..) => "enum",
96                 hir::ItemTrait(..) => "trait",
97                 hir::ItemFn(..) => "function body",
98                 _ => "item"
99             }
100         }
101
102         fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
103             match item.node {
104                 hir::TraitItemKind::Method(..) => "method body",
105                 hir::TraitItemKind::Const(..) |
106                 hir::TraitItemKind::Type(..) => "associated item"
107             }
108         }
109
110         fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
111             match item.node {
112                 hir::ImplItemKind::Method(..) => "method body",
113                 hir::ImplItemKind::Const(..) |
114                 hir::ImplItemKind::Type(_) => "associated item"
115             }
116         }
117
118         fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
119                                         heading: &str, span: Span)
120                                         -> (String, Option<Span>) {
121             let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo());
122             (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1),
123              Some(span))
124         }
125
126         let (description, span) = match *region {
127             ty::ReScope(scope) => {
128                 let new_string;
129                 let unknown_scope = || {
130                     format!("{}unknown scope: {:?}{}.  Please report a bug.",
131                             prefix, scope, suffix)
132                 };
133                 let span = scope.span(self, region_scope_tree);
134                 let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) {
135                     Some(hir_map::NodeBlock(_)) => "block",
136                     Some(hir_map::NodeExpr(expr)) => match expr.node {
137                         hir::ExprCall(..) => "call",
138                         hir::ExprMethodCall(..) => "method call",
139                         hir::ExprMatch(.., hir::MatchSource::IfLetDesugar { .. }) => "if let",
140                         hir::ExprMatch(.., hir::MatchSource::WhileLetDesugar) =>  "while let",
141                         hir::ExprMatch(.., hir::MatchSource::ForLoopDesugar) =>  "for",
142                         hir::ExprMatch(..) => "match",
143                         _ => "expression",
144                     },
145                     Some(hir_map::NodeStmt(_)) => "statement",
146                     Some(hir_map::NodeItem(it)) => item_scope_tag(&it),
147                     Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
148                     Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
149                     Some(_) | None => {
150                         err.span_note(span, &unknown_scope());
151                         return;
152                     }
153                 };
154                 let scope_decorated_tag = match scope.data() {
155                     region::ScopeData::Node(_) => tag,
156                     region::ScopeData::CallSite(_) => {
157                         "scope of call-site for function"
158                     }
159                     region::ScopeData::Arguments(_) => {
160                         "scope of function body"
161                     }
162                     region::ScopeData::Destruction(_) => {
163                         new_string = format!("destruction scope surrounding {}", tag);
164                         &new_string[..]
165                     }
166                     region::ScopeData::Remainder(r) => {
167                         new_string = format!("block suffix following statement {}",
168                                              r.first_statement_index.index());
169                         &new_string[..]
170                     }
171                 };
172                 explain_span(self, scope_decorated_tag, span)
173             }
174
175             ty::ReEarlyBound(_) |
176             ty::ReFree(_) => {
177                 let scope = region.free_region_binding_scope(self);
178                 let node = self.hir.as_local_node_id(scope)
179                                    .unwrap_or(DUMMY_NODE_ID);
180                 let unknown;
181                 let tag = match self.hir.find(node) {
182                     Some(hir_map::NodeBlock(_)) |
183                     Some(hir_map::NodeExpr(_)) => "body",
184                     Some(hir_map::NodeItem(it)) => item_scope_tag(&it),
185                     Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
186                     Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
187
188                     // this really should not happen, but it does:
189                     // FIXME(#27942)
190                     Some(_) => {
191                         unknown = format!("unexpected node ({}) for scope {:?}.  \
192                                            Please report a bug.",
193                                           self.hir.node_to_string(node), scope);
194                         &unknown
195                     }
196                     None => {
197                         unknown = format!("unknown node for scope {:?}.  \
198                                            Please report a bug.", scope);
199                         &unknown
200                     }
201                 };
202                 let (prefix, span) = match *region {
203                     ty::ReEarlyBound(ref br) => {
204                         (format!("the lifetime {} as defined on", br.name),
205                          self.sess.codemap().def_span(self.hir.span(node)))
206                     }
207                     ty::ReFree(ref fr) => {
208                         match fr.bound_region {
209                             ty::BrAnon(idx) => {
210                                 (format!("the anonymous lifetime #{} defined on", idx + 1),
211                                  self.hir.span(node))
212                             }
213                             ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(),
214                                                self.hir.span(node)),
215                             _ => (format!("the lifetime {} as defined on", fr.bound_region),
216                                   self.sess.codemap().def_span(self.hir.span(node))),
217                         }
218                     }
219                     _ => bug!()
220                 };
221                 let (msg, opt_span) = explain_span(self, tag, span);
222                 (format!("{} {}", prefix, msg), opt_span)
223             }
224
225             ty::ReStatic => ("the static lifetime".to_owned(), None),
226
227             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
228
229             // FIXME(#13998) ReSkolemized should probably print like
230             // ReFree rather than dumping Debug output on the user.
231             //
232             // We shouldn't really be having unification failures with ReVar
233             // and ReLateBound though.
234             ty::ReSkolemized(..) |
235             ty::ReVar(_) |
236             ty::ReLateBound(..) |
237             ty::ReErased => {
238                 (format!("lifetime {:?}", region), None)
239             }
240
241             // We shouldn't encounter an error message with ReClosureBound.
242             ty::ReClosureBound(..) => {
243                 bug!(
244                     "encountered unexpected ReClosureBound: {:?}",
245                     region,
246                 );
247             }
248         };
249         let message = format!("{}{}{}", prefix, description, suffix);
250         if let Some(span) = span {
251             err.span_note(span, &message);
252         } else {
253             err.note(&message);
254         }
255     }
256 }
257
258 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
259     pub fn report_region_errors(&self,
260                                 region_scope_tree: &region::ScopeTree,
261                                 errors: &Vec<RegionResolutionError<'tcx>>,
262                                 will_later_be_reported_by_nll: bool) {
263         debug!("report_region_errors(): {} errors to start", errors.len());
264
265         if will_later_be_reported_by_nll && self.tcx.sess.nll() {
266             // With `#![feature(nll)]`, we want to present a nice user
267             // experience, so don't even mention the errors from the
268             // AST checker.
269             if self.tcx.sess.features.borrow().nll {
270                 return;
271             }
272
273             // But with -Znll, it's nice to have some note for later.
274             for error in errors {
275                 match *error {
276                     RegionResolutionError::ConcreteFailure(ref origin, ..) |
277                     RegionResolutionError::GenericBoundFailure(ref origin, ..) => {
278                         self.tcx.sess.span_warn(
279                             origin.span(),
280                             "not reporting region error due to -Znll");
281                     }
282
283                     RegionResolutionError::SubSupConflict(ref rvo, ..) => {
284                         self.tcx.sess.span_warn(
285                             rvo.span(),
286                             "not reporting region error due to -Znll");
287                     }
288                 }
289             }
290
291             return;
292         }
293
294         // try to pre-process the errors, which will group some of them
295         // together into a `ProcessedErrors` group:
296         let errors = self.process_errors(errors);
297
298         debug!("report_region_errors: {} errors after preprocessing", errors.len());
299
300         for error in errors {
301             debug!("report_region_errors: error = {:?}", error);
302
303             if !self.try_report_nice_region_error(&error) {
304                 match error.clone() {
305                     // These errors could indicate all manner of different
306                     // problems with many different solutions. Rather
307                     // than generate a "one size fits all" error, what we
308                     // attempt to do is go through a number of specific
309                     // scenarios and try to find the best way to present
310                     // the error. If all of these fails, we fall back to a rather
311                     // general bit of code that displays the error information
312                     RegionResolutionError::ConcreteFailure(origin, sub, sup) => {
313                         self.report_concrete_failure(region_scope_tree, origin, sub, sup).emit();
314                     }
315
316                     RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => {
317                         self.report_generic_bound_failure(
318                             region_scope_tree,
319                             origin.span(),
320                             Some(origin),
321                             param_ty,
322                             sub,
323                         );
324                     }
325
326                     RegionResolutionError::SubSupConflict(var_origin,
327                                                           sub_origin,
328                                                           sub_r,
329                                                           sup_origin,
330                                                           sup_r) => {
331                         self.report_sub_sup_conflict(region_scope_tree,
332                                                      var_origin,
333                                                      sub_origin,
334                                                      sub_r,
335                                                      sup_origin,
336                                                      sup_r);
337                     }
338                 }
339             }
340         }
341     }
342
343     // This method goes through all the errors and try to group certain types
344     // of error together, for the purpose of suggesting explicit lifetime
345     // parameters to the user. This is done so that we can have a more
346     // complete view of what lifetimes should be the same.
347     // If the return value is an empty vector, it means that processing
348     // failed (so the return value of this method should not be used).
349     //
350     // The method also attempts to weed out messages that seem like
351     // duplicates that will be unhelpful to the end-user. But
352     // obviously it never weeds out ALL errors.
353     fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
354                       -> Vec<RegionResolutionError<'tcx>> {
355         debug!("process_errors()");
356
357         // We want to avoid reporting generic-bound failures if we can
358         // avoid it: these have a very high rate of being unhelpful in
359         // practice. This is because they are basically secondary
360         // checks that test the state of the region graph after the
361         // rest of inference is done, and the other kinds of errors
362         // indicate that the region constraint graph is internally
363         // inconsistent, so these test results are likely to be
364         // meaningless.
365         //
366         // Therefore, we filter them out of the list unless they are
367         // the only thing in the list.
368
369         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
370             RegionResolutionError::GenericBoundFailure(..) => true,
371             RegionResolutionError::ConcreteFailure(..) |
372             RegionResolutionError::SubSupConflict(..) => false,
373         };
374
375
376         let mut errors = if errors.iter().all(|e| is_bound_failure(e)) {
377             errors.clone()
378         } else {
379             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
380         };
381
382         // sort the errors by span, for better error message stability.
383         errors.sort_by_key(|u| match *u {
384             RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(),
385             RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(),
386             RegionResolutionError::SubSupConflict(ref rvo, _, _, _, _) => rvo.span(),
387         });
388         errors
389     }
390
391     /// Adds a note if the types come from similarly named crates
392     fn check_and_note_conflicting_crates(&self,
393                                          err: &mut DiagnosticBuilder,
394                                          terr: &TypeError<'tcx>,
395                                          sp: Span) {
396         let report_path_match = |err: &mut DiagnosticBuilder, did1: DefId, did2: DefId| {
397             // Only external crates, if either is from a local
398             // module we could have false positives
399             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
400                 let exp_path = self.tcx.item_path_str(did1);
401                 let found_path = self.tcx.item_path_str(did2);
402                 let exp_abs_path = self.tcx.absolute_item_path_str(did1);
403                 let found_abs_path = self.tcx.absolute_item_path_str(did2);
404                 // We compare strings because DefPath can be different
405                 // for imported and non-imported crates
406                 if exp_path == found_path
407                 || exp_abs_path == found_abs_path {
408                     let crate_name = self.tcx.crate_name(did1.krate);
409                     err.span_note(sp, &format!("Perhaps two different versions \
410                                                 of crate `{}` are being used?",
411                                                crate_name));
412                 }
413             }
414         };
415         match *terr {
416             TypeError::Sorts(ref exp_found) => {
417                 // if they are both "path types", there's a chance of ambiguity
418                 // due to different versions of the same crate
419                 match (&exp_found.expected.sty, &exp_found.found.sty) {
420                     (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
421                         report_path_match(err, exp_adt.did, found_adt.did);
422                     },
423                     _ => ()
424                 }
425             },
426             TypeError::Traits(ref exp_found) => {
427                 report_path_match(err, exp_found.expected, exp_found.found);
428             },
429             _ => () // FIXME(#22750) handle traits and stuff
430         }
431     }
432
433     fn note_error_origin(&self,
434                          err: &mut DiagnosticBuilder<'tcx>,
435                          cause: &ObligationCause<'tcx>)
436     {
437         match cause.code {
438             ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
439                 hir::MatchSource::IfLetDesugar {..} => {
440                     let msg = "`if let` arm with an incompatible type";
441                     if self.tcx.sess.codemap().is_multiline(arm_span) {
442                         err.span_note(arm_span, msg);
443                     } else {
444                         err.span_label(arm_span, msg);
445                     }
446                 }
447                 _ => {
448                     let msg = "match arm with an incompatible type";
449                     if self.tcx.sess.codemap().is_multiline(arm_span) {
450                         err.span_note(arm_span, msg);
451                     } else {
452                         err.span_label(arm_span, msg);
453                     }
454                 }
455             },
456             _ => ()
457         }
458     }
459
460     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
461     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
462     /// populate `other_value` with `other_ty`.
463     ///
464     /// ```text
465     /// Foo<Bar<Qux>>
466     /// ^^^^--------^ this is highlighted
467     /// |   |
468     /// |   this type argument is exactly the same as the other type, not highlighted
469     /// this is highlighted
470     /// Bar<Qux>
471     /// -------- this type is the same as a type argument in the other type, not highlighted
472     /// ```
473     fn highlight_outer(&self,
474                        value: &mut DiagnosticStyledString,
475                        other_value: &mut DiagnosticStyledString,
476                        name: String,
477                        sub: &ty::subst::Substs<'tcx>,
478                        pos: usize,
479                        other_ty: &Ty<'tcx>) {
480         // `value` and `other_value` hold two incomplete type representation for display.
481         // `name` is the path of both types being compared. `sub`
482         value.push_highlighted(name);
483         let len = sub.len();
484         if len > 0 {
485             value.push_highlighted("<");
486         }
487
488         // Output the lifetimes fot the first type
489         let lifetimes = sub.regions().map(|lifetime| {
490             let s = format!("{}", lifetime);
491             if s.is_empty() {
492                 "'_".to_string()
493             } else {
494                 s
495             }
496         }).collect::<Vec<_>>().join(", ");
497         if !lifetimes.is_empty() {
498             if sub.regions().count() < len {
499                 value.push_normal(lifetimes + &", ");
500             } else {
501                 value.push_normal(lifetimes);
502             }
503         }
504
505         // Highlight all the type arguments that aren't at `pos` and compare the type argument at
506         // `pos` and `other_ty`.
507         for (i, type_arg) in sub.types().enumerate() {
508             if i == pos {
509                 let values = self.cmp(type_arg, other_ty);
510                 value.0.extend((values.0).0);
511                 other_value.0.extend((values.1).0);
512             } else {
513                 value.push_highlighted(format!("{}", type_arg));
514             }
515
516             if len > 0 && i != len - 1 {
517                 value.push_normal(", ");
518             }
519             //self.push_comma(&mut value, &mut other_value, len, i);
520         }
521         if len > 0 {
522             value.push_highlighted(">");
523         }
524     }
525
526     /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
527     /// as that is the difference to the other type.
528     ///
529     /// For the following code:
530     ///
531     /// ```norun
532     /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
533     /// ```
534     ///
535     /// The type error output will behave in the following way:
536     ///
537     /// ```text
538     /// Foo<Bar<Qux>>
539     /// ^^^^--------^ this is highlighted
540     /// |   |
541     /// |   this type argument is exactly the same as the other type, not highlighted
542     /// this is highlighted
543     /// Bar<Qux>
544     /// -------- this type is the same as a type argument in the other type, not highlighted
545     /// ```
546     fn cmp_type_arg(&self,
547                     mut t1_out: &mut DiagnosticStyledString,
548                     mut t2_out: &mut DiagnosticStyledString,
549                     path: String,
550                     sub: &ty::subst::Substs<'tcx>,
551                     other_path: String,
552                     other_ty: &Ty<'tcx>) -> Option<()> {
553         for (i, ta) in sub.types().enumerate() {
554             if &ta == other_ty {
555                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
556                 return Some(());
557             }
558             if let &ty::TyAdt(def, _) = &ta.sty {
559                 let path_ = self.tcx.item_path_str(def.did.clone());
560                 if path_ == other_path {
561                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
562                     return Some(());
563                 }
564             }
565         }
566         None
567     }
568
569     /// Add a `,` to the type representation only if it is appropriate.
570     fn push_comma(&self,
571                   value: &mut DiagnosticStyledString,
572                   other_value: &mut DiagnosticStyledString,
573                   len: usize,
574                   pos: usize) {
575         if len > 0 && pos != len - 1 {
576             value.push_normal(", ");
577             other_value.push_normal(", ");
578         }
579     }
580
581     /// Compare two given types, eliding parts that are the same between them and highlighting
582     /// relevant differences, and return two representation of those types for highlighted printing.
583     fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>)
584         -> (DiagnosticStyledString, DiagnosticStyledString)
585     {
586         fn equals<'tcx>(a: &Ty<'tcx>, b: &Ty<'tcx>) -> bool {
587             match (&a.sty, &b.sty) {
588                 (a, b) if *a == *b => true,
589                 (&ty::TyInt(_), &ty::TyInfer(ty::InferTy::IntVar(_))) |
590                 (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInt(_)) |
591                 (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInfer(ty::InferTy::IntVar(_))) |
592                 (&ty::TyFloat(_), &ty::TyInfer(ty::InferTy::FloatVar(_))) |
593                 (&ty::TyInfer(ty::InferTy::FloatVar(_)), &ty::TyFloat(_)) |
594                 (&ty::TyInfer(ty::InferTy::FloatVar(_)),
595                  &ty::TyInfer(ty::InferTy::FloatVar(_))) => true,
596                 _ => false,
597             }
598         }
599
600         fn push_ty_ref<'tcx>(r: &ty::Region<'tcx>,
601                              tnm: &ty::TypeAndMut<'tcx>,
602                              s: &mut DiagnosticStyledString) {
603             let r = &format!("{}", r);
604             s.push_highlighted(format!("&{}{}{}",
605                                        r,
606                                        if r == "" {
607                                            ""
608                                        } else {
609                                            " "
610                                        },
611                                        if tnm.mutbl == hir::MutMutable {
612                                           "mut "
613                                        } else {
614                                            ""
615                                        }));
616             s.push_normal(format!("{}", tnm.ty));
617         }
618
619         match (&t1.sty, &t2.sty) {
620             (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
621                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
622                 let path1 = self.tcx.item_path_str(def1.did.clone());
623                 let path2 = self.tcx.item_path_str(def2.did.clone());
624                 if def1.did == def2.did {
625                     // Easy case. Replace same types with `_` to shorten the output and highlight
626                     // the differing ones.
627                     //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
628                     //     Foo<Bar, _>
629                     //     Foo<Quz, _>
630                     //         ---  ^ type argument elided
631                     //         |
632                     //         highlighted in output
633                     values.0.push_normal(path1);
634                     values.1.push_normal(path2);
635
636                     // Only draw `<...>` if there're lifetime/type arguments.
637                     let len = sub1.len();
638                     if len > 0 {
639                         values.0.push_normal("<");
640                         values.1.push_normal("<");
641                     }
642
643                     fn lifetime_display(lifetime: Region) -> String {
644                         let s = format!("{}", lifetime);
645                         if s.is_empty() {
646                             "'_".to_string()
647                         } else {
648                             s
649                         }
650                     }
651                     // At one point we'd like to elide all lifetimes here, they are irrelevant for
652                     // all diagnostics that use this output
653                     //
654                     //     Foo<'x, '_, Bar>
655                     //     Foo<'y, '_, Qux>
656                     //         ^^  ^^  --- type arguments are not elided
657                     //         |   |
658                     //         |   elided as they were the same
659                     //         not elided, they were different, but irrelevant
660                     let lifetimes = sub1.regions().zip(sub2.regions());
661                     for (i, lifetimes) in lifetimes.enumerate() {
662                         let l1 = lifetime_display(lifetimes.0);
663                         let l2 = lifetime_display(lifetimes.1);
664                         if l1 == l2 {
665                             values.0.push_normal("'_");
666                             values.1.push_normal("'_");
667                         } else {
668                             values.0.push_highlighted(l1);
669                             values.1.push_highlighted(l2);
670                         }
671                         self.push_comma(&mut values.0, &mut values.1, len, i);
672                     }
673
674                     // We're comparing two types with the same path, so we compare the type
675                     // arguments for both. If they are the same, do not highlight and elide from the
676                     // output.
677                     //     Foo<_, Bar>
678                     //     Foo<_, Qux>
679                     //         ^ elided type as this type argument was the same in both sides
680                     let type_arguments = sub1.types().zip(sub2.types());
681                     let regions_len = sub1.regions().collect::<Vec<_>>().len();
682                     for (i, (ta1, ta2)) in type_arguments.enumerate() {
683                         let i = i + regions_len;
684                         if ta1 == ta2 {
685                             values.0.push_normal("_");
686                             values.1.push_normal("_");
687                         } else {
688                             let (x1, x2) = self.cmp(ta1, ta2);
689                             (values.0).0.extend(x1.0);
690                             (values.1).0.extend(x2.0);
691                         }
692                         self.push_comma(&mut values.0, &mut values.1, len, i);
693                     }
694
695                     // Close the type argument bracket.
696                     // Only draw `<...>` if there're lifetime/type arguments.
697                     if len > 0 {
698                         values.0.push_normal(">");
699                         values.1.push_normal(">");
700                     }
701                     values
702                 } else {
703                     // Check for case:
704                     //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
705                     //     Foo<Bar<Qux>
706                     //         ------- this type argument is exactly the same as the other type
707                     //     Bar<Qux>
708                     if self.cmp_type_arg(&mut values.0,
709                                          &mut values.1,
710                                          path1.clone(),
711                                          sub1,
712                                          path2.clone(),
713                                          &t2).is_some() {
714                         return values;
715                     }
716                     // Check for case:
717                     //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
718                     //     Bar<Qux>
719                     //     Foo<Bar<Qux>>
720                     //         ------- this type argument is exactly the same as the other type
721                     if self.cmp_type_arg(&mut values.1,
722                                          &mut values.0,
723                                          path2,
724                                          sub2,
725                                          path1,
726                                          &t1).is_some() {
727                         return values;
728                     }
729
730                     // We couldn't find anything in common, highlight everything.
731                     //     let x: Bar<Qux> = y::<Foo<Zar>>();
732                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
733                      DiagnosticStyledString::highlighted(format!("{}", t2)))
734                 }
735             }
736
737             // When finding T != &T, hightlight only the borrow
738             (&ty::TyRef(r1, ref tnm1), _) if equals(&tnm1.ty, &t2) => {
739                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
740                 push_ty_ref(&r1, tnm1, &mut values.0);
741                 values.1.push_normal(format!("{}", t2));
742                 values
743             }
744             (_, &ty::TyRef(r2, ref tnm2)) if equals(&t1, &tnm2.ty) => {
745                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
746                 values.0.push_normal(format!("{}", t1));
747                 push_ty_ref(&r2, tnm2, &mut values.1);
748                 values
749             }
750
751             // When encountering &T != &mut T, highlight only the borrow
752             (&ty::TyRef(r1, ref tnm1), &ty::TyRef(r2, ref tnm2)) if equals(&tnm1.ty, &tnm2.ty) => {
753                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
754                 push_ty_ref(&r1, tnm1, &mut values.0);
755                 push_ty_ref(&r2, tnm2, &mut values.1);
756                 values
757             }
758
759             _ => {
760                 if t1 == t2 {
761                     // The two types are the same, elide and don't highlight.
762                     (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
763                 } else {
764                     // We couldn't find anything in common, highlight everything.
765                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
766                      DiagnosticStyledString::highlighted(format!("{}", t2)))
767                 }
768             }
769         }
770     }
771
772     pub fn note_type_err(&self,
773                          diag: &mut DiagnosticBuilder<'tcx>,
774                          cause: &ObligationCause<'tcx>,
775                          secondary_span: Option<(Span, String)>,
776                          mut values: Option<ValuePairs<'tcx>>,
777                          terr: &TypeError<'tcx>)
778     {
779         // For some types of errors, expected-found does not make
780         // sense, so just ignore the values we were given.
781         match terr {
782             TypeError::CyclicTy(_) => { values = None; }
783             _ => { }
784         }
785
786         let (expected_found, exp_found, is_simple_error) = match values {
787             None => (None, None, false),
788             Some(values) => {
789                 let (is_simple_error, exp_found) = match values {
790                     ValuePairs::Types(exp_found) => {
791                         let is_simple_err = exp_found.expected.is_primitive()
792                             && exp_found.found.is_primitive();
793
794                         (is_simple_err, Some(exp_found))
795                     }
796                     _ => (false, None),
797                 };
798                 let vals = match self.values_str(&values) {
799                     Some((expected, found)) => Some((expected, found)),
800                     None => {
801                         // Derived error. Cancel the emitter.
802                         self.tcx.sess.diagnostic().cancel(diag);
803                         return
804                     }
805                 };
806                 (vals, exp_found, is_simple_error)
807             }
808         };
809
810         let span = cause.span(&self.tcx);
811
812         diag.span_label(span, terr.to_string());
813         if let Some((sp, msg)) = secondary_span {
814             diag.span_label(sp, msg);
815         }
816
817         if let Some((expected, found)) = expected_found {
818             match (terr, is_simple_error, expected == found) {
819                 (&TypeError::Sorts(ref values), false, true) => {
820                     diag.note_expected_found_extra(
821                         &"type", expected, found,
822                         &format!(" ({})", values.expected.sort_string(self.tcx)),
823                         &format!(" ({})", values.found.sort_string(self.tcx)));
824                 }
825                 (_, false, _) => {
826                     if let Some(exp_found) = exp_found {
827                         let (def_id, ret_ty) = match exp_found.found.sty {
828                             TypeVariants::TyFnDef(def, _) => {
829                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
830                             }
831                             _ => (None, None)
832                         };
833
834                         let exp_is_struct = match exp_found.expected.sty {
835                             TypeVariants::TyAdt(def, _) => def.is_struct(),
836                             _ => false
837                         };
838
839                         if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) {
840                             if exp_is_struct && exp_found.expected == ret_ty.0 {
841                                 let message = format!(
842                                     "did you mean `{}(/* fields */)`?",
843                                     self.tcx.item_path_str(def_id)
844                                 );
845                                 diag.span_label(span, message);
846                             }
847                         }
848                     }
849
850                     diag.note_expected_found(&"type", expected, found);
851                 }
852                 _ => (),
853             }
854         }
855
856         self.check_and_note_conflicting_crates(diag, terr, span);
857         self.tcx.note_and_explain_type_err(diag, terr, span);
858
859         // It reads better to have the error origin as the final
860         // thing.
861         self.note_error_origin(diag, &cause);
862     }
863
864     pub fn report_and_explain_type_error(&self,
865                                          trace: TypeTrace<'tcx>,
866                                          terr: &TypeError<'tcx>)
867                                          -> DiagnosticBuilder<'tcx>
868     {
869         debug!("report_and_explain_type_error(trace={:?}, terr={:?})",
870                trace,
871                terr);
872
873         let span = trace.cause.span(&self.tcx);
874         let failure_code = trace.cause.as_failure_code(terr);
875         let mut diag = match failure_code {
876             FailureCode::Error0317(failure_str) => {
877                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
878             }
879             FailureCode::Error0580(failure_str) => {
880                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
881             }
882             FailureCode::Error0308(failure_str) => {
883                 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
884             }
885             FailureCode::Error0644(failure_str) => {
886                 struct_span_err!(self.tcx.sess, span, E0644, "{}", failure_str)
887             }
888         };
889         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
890         diag
891     }
892
893     fn values_str(&self, values: &ValuePairs<'tcx>)
894         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
895     {
896         match *values {
897             infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
898             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
899             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
900         }
901     }
902
903     fn expected_found_str_ty(&self,
904                              exp_found: &ty::error::ExpectedFound<Ty<'tcx>>)
905                              -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
906         let exp_found = self.resolve_type_vars_if_possible(exp_found);
907         if exp_found.references_error() {
908             return None;
909         }
910
911         Some(self.cmp(exp_found.expected, exp_found.found))
912     }
913
914     /// Returns a string of the form "expected `{}`, found `{}`".
915     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
916         &self,
917         exp_found: &ty::error::ExpectedFound<T>)
918         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
919     {
920         let exp_found = self.resolve_type_vars_if_possible(exp_found);
921         if exp_found.references_error() {
922             return None;
923         }
924
925         Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)),
926               DiagnosticStyledString::highlighted(format!("{}", exp_found.found))))
927     }
928
929     pub fn report_generic_bound_failure(&self,
930                                         region_scope_tree: &region::ScopeTree,
931                                         span: Span,
932                                         origin: Option<SubregionOrigin<'tcx>>,
933                                         bound_kind: GenericKind<'tcx>,
934                                         sub: Region<'tcx>)
935     {
936         // Attempt to obtain the span of the parameter so we can
937         // suggest adding an explicit lifetime bound to it.
938         let type_param_span = match (self.in_progress_tables, bound_kind) {
939             (Some(ref table), GenericKind::Param(ref param)) => {
940                 let table = table.borrow();
941                 table.local_id_root.and_then(|did| {
942                     let generics = self.tcx.generics_of(did);
943                     // Account for the case where `did` corresponds to `Self`, which doesn't have
944                     // the expected type argument.
945                     if !param.is_self() {
946                         let type_param = generics.type_param(param, self.tcx);
947                         let hir = &self.tcx.hir;
948                         hir.as_local_node_id(type_param.def_id).map(|id| {
949                             // Get the `hir::TyParam` to verify wether it already has any bounds.
950                             // We do this to avoid suggesting code that ends up as `T: 'a'b`,
951                             // instead we suggest `T: 'a + 'b` in that case.
952                             let has_lifetimes = if let hir_map::NodeTyParam(ref p) = hir.get(id) {
953                                 p.bounds.len() > 0
954                             } else {
955                                 false
956                             };
957                             let sp = hir.span(id);
958                             // `sp` only covers `T`, change it so that it covers
959                             // `T:` when appropriate
960                             let sp = if has_lifetimes {
961                                 sp.to(self.tcx.sess.codemap().next_point(
962                                         self.tcx.sess.codemap().next_point(sp)))
963                             } else {
964                                 sp
965                             };
966                             (sp, has_lifetimes)
967                         })
968                     } else {
969                         None
970                     }
971                 })
972             }
973             _ => None,
974         };
975
976         let labeled_user_string = match bound_kind {
977             GenericKind::Param(ref p) =>
978                 format!("the parameter type `{}`", p),
979             GenericKind::Projection(ref p) =>
980                 format!("the associated type `{}`", p),
981         };
982
983         if let Some(SubregionOrigin::CompareImplMethodObligation {
984             span, item_name, impl_item_def_id, trait_item_def_id,
985         }) = origin {
986             self.report_extra_impl_obligation(span,
987                                               item_name,
988                                               impl_item_def_id,
989                                               trait_item_def_id,
990                                               &format!("`{}: {}`", bound_kind, sub))
991                 .emit();
992             return;
993         }
994
995         fn binding_suggestion<'tcx, S: fmt::Display>(err: &mut DiagnosticBuilder<'tcx>,
996                                                      type_param_span: Option<(Span, bool)>,
997                                                      bound_kind: GenericKind<'tcx>,
998                                                      sub: S) {
999             let consider = &format!("consider adding an explicit lifetime bound `{}: {}`...",
1000                                     bound_kind,
1001                                     sub);
1002             if let Some((sp, has_lifetimes)) = type_param_span {
1003                 let tail = if has_lifetimes {
1004                     " + "
1005                 } else {
1006                     ""
1007                 };
1008                 let suggestion = format!("{}: {}{}", bound_kind, sub, tail);
1009                 err.span_suggestion_short(sp, consider, suggestion);
1010             } else {
1011                 err.help(consider);
1012             }
1013         }
1014
1015         let mut err = match *sub {
1016             ty::ReEarlyBound(_) |
1017             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
1018                 // Does the required lifetime have a nice name we can print?
1019                 let mut err = struct_span_err!(self.tcx.sess,
1020                                                span,
1021                                                E0309,
1022                                                "{} may not live long enough",
1023                                                labeled_user_string);
1024                 binding_suggestion(&mut err, type_param_span, bound_kind, sub);
1025                 err
1026             }
1027
1028             ty::ReStatic => {
1029                 // Does the required lifetime have a nice name we can print?
1030                 let mut err = struct_span_err!(self.tcx.sess,
1031                                                span,
1032                                                E0310,
1033                                                "{} may not live long enough",
1034                                                labeled_user_string);
1035                 binding_suggestion(&mut err, type_param_span, bound_kind, "'static");
1036                 err
1037             }
1038
1039             _ => {
1040                 // If not, be less specific.
1041                 let mut err = struct_span_err!(self.tcx.sess,
1042                                                span,
1043                                                E0311,
1044                                                "{} may not live long enough",
1045                                                labeled_user_string);
1046                 err.help(&format!("consider adding an explicit lifetime bound for `{}`",
1047                                   bound_kind));
1048                 self.tcx.note_and_explain_region(
1049                     region_scope_tree,
1050                     &mut err,
1051                     &format!("{} must be valid for ", labeled_user_string),
1052                     sub,
1053                     "...");
1054                 err
1055             }
1056         };
1057
1058         if let Some(origin) = origin {
1059             self.note_region_origin(&mut err, &origin);
1060         }
1061         err.emit();
1062     }
1063
1064     fn report_sub_sup_conflict(&self,
1065                                region_scope_tree: &region::ScopeTree,
1066                                var_origin: RegionVariableOrigin,
1067                                sub_origin: SubregionOrigin<'tcx>,
1068                                sub_region: Region<'tcx>,
1069                                sup_origin: SubregionOrigin<'tcx>,
1070                                sup_region: Region<'tcx>) {
1071
1072         let mut err = self.report_inference_failure(var_origin);
1073
1074         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
1075             "first, the lifetime cannot outlive ",
1076             sup_region,
1077             "...");
1078
1079         match (&sup_origin, &sub_origin) {
1080             (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => {
1081                 if let (Some((sup_expected, sup_found)),
1082                         Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values),
1083                                                             self.values_str(&sub_trace.values)) {
1084                     if sub_expected == sup_expected && sub_found == sup_found {
1085                         self.tcx.note_and_explain_region(
1086                             region_scope_tree,
1087                             &mut err,
1088                             "...but the lifetime must also be valid for ",
1089                             sub_region,
1090                             "...",
1091                         );
1092                         err.note(&format!("...so that the {}:\nexpected {}\n   found {}",
1093                                           sup_trace.cause.as_requirement_str(),
1094                                           sup_expected.content(),
1095                                           sup_found.content()));
1096                         err.emit();
1097                         return;
1098                     }
1099                 }
1100             }
1101             _ => {}
1102         }
1103
1104         self.note_region_origin(&mut err, &sup_origin);
1105
1106         self.tcx.note_and_explain_region(region_scope_tree, &mut err,
1107             "but, the lifetime must be valid for ",
1108             sub_region,
1109             "...");
1110
1111         self.note_region_origin(&mut err, &sub_origin);
1112         err.emit();
1113     }
1114 }
1115
1116 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1117     fn report_inference_failure(&self,
1118                                 var_origin: RegionVariableOrigin)
1119                                 -> DiagnosticBuilder<'tcx> {
1120         let br_string = |br: ty::BoundRegion| {
1121             let mut s = br.to_string();
1122             if !s.is_empty() {
1123                 s.push_str(" ");
1124             }
1125             s
1126         };
1127         let var_description = match var_origin {
1128             infer::MiscVariable(_) => "".to_string(),
1129             infer::PatternRegion(_) => " for pattern".to_string(),
1130             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
1131             infer::Autoref(_) => " for autoref".to_string(),
1132             infer::Coercion(_) => " for automatic coercion".to_string(),
1133             infer::LateBoundRegion(_, br, infer::FnCall) => {
1134                 format!(" for lifetime parameter {}in function call",
1135                         br_string(br))
1136             }
1137             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
1138                 format!(" for lifetime parameter {}in generic type", br_string(br))
1139             }
1140             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => {
1141                 format!(" for lifetime parameter {}in trait containing associated type `{}`",
1142                         br_string(br), self.tcx.associated_item(def_id).name)
1143             }
1144             infer::EarlyBoundRegion(_, name) => {
1145                 format!(" for lifetime parameter `{}`",
1146                         name)
1147             }
1148             infer::BoundRegionInCoherence(name) => {
1149                 format!(" for lifetime parameter `{}` in coherence check",
1150                         name)
1151             }
1152             infer::UpvarRegion(ref upvar_id, _) => {
1153                 let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id);
1154                 let var_name = self.tcx.hir.name(var_node_id);
1155                 format!(" for capture of `{}` by closure", var_name)
1156             }
1157             infer::NLL(..) => bug!("NLL variable found in lexical phase"),
1158         };
1159
1160         struct_span_err!(self.tcx.sess, var_origin.span(), E0495,
1161                   "cannot infer an appropriate lifetime{} \
1162                    due to conflicting requirements",
1163                   var_description)
1164     }
1165 }
1166
1167 enum FailureCode {
1168     Error0317(&'static str),
1169     Error0580(&'static str),
1170     Error0308(&'static str),
1171     Error0644(&'static str),
1172 }
1173
1174 impl<'tcx> ObligationCause<'tcx> {
1175     fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode {
1176         use self::FailureCode::*;
1177         use traits::ObligationCauseCode::*;
1178         match self.code {
1179             CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"),
1180             MatchExpressionArm { source, .. } => Error0308(match source {
1181                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
1182                 _ => "match arms have incompatible types",
1183             }),
1184             IfExpression => Error0308("if and else have incompatible types"),
1185             IfExpressionWithNoElse => Error0317("if may be missing an else clause"),
1186             EquatePredicate => Error0308("equality predicate not satisfied"),
1187             MainFunctionType => Error0580("main function has wrong type"),
1188             StartFunctionType => Error0308("start function has wrong type"),
1189             IntrinsicType => Error0308("intrinsic has wrong type"),
1190             MethodReceiver => Error0308("mismatched method receiver"),
1191
1192             // In the case where we have no more specific thing to
1193             // say, also take a look at the error code, maybe we can
1194             // tailor to that.
1195             _ => match terr {
1196                 TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() =>
1197                     Error0644("closure/generator type that references itself"),
1198                 _ =>
1199                     Error0308("mismatched types"),
1200             }
1201         }
1202     }
1203
1204     fn as_requirement_str(&self) -> &'static str {
1205         use traits::ObligationCauseCode::*;
1206         match self.code {
1207             CompareImplMethodObligation { .. } => "method type is compatible with trait",
1208             ExprAssignable => "expression is assignable",
1209             MatchExpressionArm { source, .. } => match source {
1210                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types",
1211                 _ => "match arms have compatible types",
1212             },
1213             IfExpression => "if and else have compatible types",
1214             IfExpressionWithNoElse => "if missing an else returns ()",
1215             EquatePredicate => "equality where clause is satisfied",
1216             MainFunctionType => "`main` function has the correct type",
1217             StartFunctionType => "`start` function has the correct type",
1218             IntrinsicType => "intrinsic has the correct type",
1219             MethodReceiver => "method receiver has the correct type",
1220             _ => "types are compatible",
1221         }
1222     }
1223 }