]> git.lizzy.rs Git - rust.git/blob - src/librustc/infer/error_reporting/mod.rs
remove ROOT_CODE_EXTENT and DUMMY_CODE_EXTENT
[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 catalogue 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, TyCtxt, TypeFoldable};
70 use ty::{Region, Issue32330};
71 use ty::error::TypeError;
72 use syntax::ast::DUMMY_NODE_ID;
73 use syntax_pos::{Pos, Span};
74 use errors::{DiagnosticBuilder, DiagnosticStyledString};
75
76 mod note;
77
78 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
79     pub fn note_and_explain_region(self,
80                                    err: &mut DiagnosticBuilder,
81                                    prefix: &str,
82                                    region: &'tcx ty::Region,
83                                    suffix: &str) {
84         fn item_scope_tag(item: &hir::Item) -> &'static str {
85             match item.node {
86                 hir::ItemImpl(..) => "impl",
87                 hir::ItemStruct(..) => "struct",
88                 hir::ItemUnion(..) => "union",
89                 hir::ItemEnum(..) => "enum",
90                 hir::ItemTrait(..) => "trait",
91                 hir::ItemFn(..) => "function body",
92                 _ => "item"
93             }
94         }
95
96         fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str {
97             match item.node {
98                 hir::TraitItemKind::Method(..) => "method body",
99                 hir::TraitItemKind::Const(..) |
100                 hir::TraitItemKind::Type(..) => "associated item"
101             }
102         }
103
104         fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str {
105             match item.node {
106                 hir::ImplItemKind::Method(..) => "method body",
107                 hir::ImplItemKind::Const(..) |
108                 hir::ImplItemKind::Type(_) => "associated item"
109             }
110         }
111
112         fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
113                                         heading: &str, span: Span)
114                                         -> (String, Option<Span>) {
115             let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
116             (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
117              Some(span))
118         }
119
120         let (description, span) = match *region {
121             ty::ReScope(scope) => {
122                 let new_string;
123                 let unknown_scope = || {
124                     format!("{}unknown scope: {:?}{}.  Please report a bug.",
125                             prefix, scope, suffix)
126                 };
127                 let span = match scope.span(&self.region_maps(), &self.hir) {
128                     Some(s) => s,
129                     None => {
130                         err.note(&unknown_scope());
131                         return;
132                     }
133                 };
134                 let tag = match self.hir.find(scope.node_id(&self.region_maps())) {
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 self.region_maps().code_extent_data(scope) {
155                     region::CodeExtentData::Misc(_) => tag,
156                     region::CodeExtentData::CallSiteScope { .. } => {
157                         "scope of call-site for function"
158                     }
159                     region::CodeExtentData::ParameterScope { .. } => {
160                         "scope of function body"
161                     }
162                     region::CodeExtentData::DestructionScope(_) => {
163                         new_string = format!("destruction scope surrounding {}", tag);
164                         &new_string[..]
165                     }
166                     region::CodeExtentData::Remainder(r) => {
167                         new_string = format!("block suffix following statement {}",
168                                              r.first_statement_index);
169                         &new_string[..]
170                     }
171                 };
172                 explain_span(self, scope_decorated_tag, span)
173             }
174
175             ty::ReFree(ref fr) => {
176                 let prefix = match fr.bound_region {
177                     ty::BrAnon(idx) => {
178                         format!("the anonymous lifetime #{} defined on", idx + 1)
179                     }
180                     ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
181                     _ => {
182                         format!("the lifetime {} as defined on",
183                                 fr.bound_region)
184                     }
185                 };
186
187                 let node = fr.scope.map(|s| s.node_id(&self.region_maps()))
188                                    .unwrap_or(DUMMY_NODE_ID);
189                 let unknown;
190                 let tag = match self.hir.find(node) {
191                     Some(hir_map::NodeBlock(_)) |
192                     Some(hir_map::NodeExpr(_)) => "body",
193                     Some(hir_map::NodeItem(it)) => item_scope_tag(&it),
194                     Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it),
195                     Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it),
196
197                     // this really should not happen, but it does:
198                     // FIXME(#27942)
199                     Some(_) => {
200                         unknown = format!("unexpected node ({}) for scope {:?}.  \
201                                            Please report a bug.",
202                                           self.hir.node_to_string(node), fr.scope);
203                         &unknown
204                     }
205                     None => {
206                         unknown = format!("unknown node for scope {:?}.  \
207                                            Please report a bug.", fr.scope);
208                         &unknown
209                     }
210                 };
211                 let (msg, opt_span) = explain_span(self, tag, self.hir.span(node));
212                 (format!("{} {}", prefix, msg), opt_span)
213             }
214
215             ty::ReStatic => ("the static lifetime".to_owned(), None),
216
217             ty::ReEmpty => ("the empty lifetime".to_owned(), None),
218
219             ty::ReEarlyBound(ref data) => (data.name.to_string(), None),
220
221             // FIXME(#13998) ReSkolemized should probably print like
222             // ReFree rather than dumping Debug output on the user.
223             //
224             // We shouldn't really be having unification failures with ReVar
225             // and ReLateBound though.
226             ty::ReSkolemized(..) |
227             ty::ReVar(_) |
228             ty::ReLateBound(..) |
229             ty::ReErased => {
230                 (format!("lifetime {:?}", region), None)
231             }
232         };
233         let message = format!("{}{}{}", prefix, description, suffix);
234         if let Some(span) = span {
235             err.span_note(span, &message);
236         } else {
237             err.note(&message);
238         }
239     }
240 }
241
242 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
243     pub fn report_region_errors(&self,
244                                 errors: &Vec<RegionResolutionError<'tcx>>) {
245         debug!("report_region_errors(): {} errors to start", errors.len());
246
247         // try to pre-process the errors, which will group some of them
248         // together into a `ProcessedErrors` group:
249         let errors = self.process_errors(errors);
250
251         debug!("report_region_errors: {} errors after preprocessing", errors.len());
252
253         for error in errors {
254             debug!("report_region_errors: error = {:?}", error);
255             match error.clone() {
256                 ConcreteFailure(origin, sub, sup) => {
257                     self.report_concrete_failure(origin, sub, sup).emit();
258                 }
259
260                 GenericBoundFailure(kind, param_ty, sub) => {
261                     self.report_generic_bound_failure(kind, param_ty, sub);
262                 }
263
264                 SubSupConflict(var_origin,
265                                sub_origin, sub_r,
266                                sup_origin, sup_r) => {
267                     self.report_sub_sup_conflict(var_origin,
268                                                  sub_origin, sub_r,
269                                                  sup_origin, sup_r);
270                 }
271             }
272         }
273     }
274
275     // This method goes through all the errors and try to group certain types
276     // of error together, for the purpose of suggesting explicit lifetime
277     // parameters to the user. This is done so that we can have a more
278     // complete view of what lifetimes should be the same.
279     // If the return value is an empty vector, it means that processing
280     // failed (so the return value of this method should not be used).
281     //
282     // The method also attempts to weed out messages that seem like
283     // duplicates that will be unhelpful to the end-user. But
284     // obviously it never weeds out ALL errors.
285     fn process_errors(&self, errors: &Vec<RegionResolutionError<'tcx>>)
286                       -> Vec<RegionResolutionError<'tcx>> {
287         debug!("process_errors()");
288
289         // We want to avoid reporting generic-bound failures if we can
290         // avoid it: these have a very high rate of being unhelpful in
291         // practice. This is because they are basically secondary
292         // checks that test the state of the region graph after the
293         // rest of inference is done, and the other kinds of errors
294         // indicate that the region constraint graph is internally
295         // inconsistent, so these test results are likely to be
296         // meaningless.
297         //
298         // Therefore, we filter them out of the list unless they are
299         // the only thing in the list.
300
301         let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e {
302             ConcreteFailure(..) => false,
303             SubSupConflict(..) => false,
304             GenericBoundFailure(..) => true,
305         };
306
307         if errors.iter().all(|e| is_bound_failure(e)) {
308             errors.clone()
309         } else {
310             errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect()
311         }
312     }
313
314     /// Adds a note if the types come from similarly named crates
315     fn check_and_note_conflicting_crates(&self,
316                                          err: &mut DiagnosticBuilder,
317                                          terr: &TypeError<'tcx>,
318                                          sp: Span) {
319         let report_path_match = |err: &mut DiagnosticBuilder, did1: DefId, did2: DefId| {
320             // Only external crates, if either is from a local
321             // module we could have false positives
322             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
323                 let exp_path = self.tcx.item_path_str(did1);
324                 let found_path = self.tcx.item_path_str(did2);
325                 // We compare strings because DefPath can be different
326                 // for imported and non-imported crates
327                 if exp_path == found_path {
328                     let crate_name = self.tcx.sess.cstore.crate_name(did1.krate);
329                     err.span_note(sp, &format!("Perhaps two different versions \
330                                                 of crate `{}` are being used?",
331                                                crate_name));
332                 }
333             }
334         };
335         match *terr {
336             TypeError::Sorts(ref exp_found) => {
337                 // if they are both "path types", there's a chance of ambiguity
338                 // due to different versions of the same crate
339                 match (&exp_found.expected.sty, &exp_found.found.sty) {
340                     (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => {
341                         report_path_match(err, exp_adt.did, found_adt.did);
342                     },
343                     _ => ()
344                 }
345             },
346             TypeError::Traits(ref exp_found) => {
347                 report_path_match(err, exp_found.expected, exp_found.found);
348             },
349             _ => () // FIXME(#22750) handle traits and stuff
350         }
351     }
352
353     fn note_error_origin(&self,
354                          err: &mut DiagnosticBuilder<'tcx>,
355                          cause: &ObligationCause<'tcx>)
356     {
357         match cause.code {
358             ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source {
359                 hir::MatchSource::IfLetDesugar {..} => {
360                     err.span_note(arm_span, "`if let` arm with an incompatible type");
361                 }
362                 _ => {
363                     err.span_note(arm_span, "match arm with an incompatible type");
364                 }
365             },
366             _ => ()
367         }
368     }
369
370     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
371     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
372     /// populate `other_value` with `other_ty`.
373     ///
374     /// ```text
375     /// Foo<Bar<Qux>>
376     /// ^^^^--------^ this is highlighted
377     /// |   |
378     /// |   this type argument is exactly the same as the other type, not highlighted
379     /// this is highlighted
380     /// Bar<Qux>
381     /// -------- this type is the same as a type argument in the other type, not highlighted
382     /// ```
383     fn highlight_outer(&self,
384                        mut value: &mut DiagnosticStyledString,
385                        mut other_value: &mut DiagnosticStyledString,
386                        name: String,
387                        sub: &ty::subst::Substs<'tcx>,
388                        pos: usize,
389                        other_ty: &ty::Ty<'tcx>) {
390         // `value` and `other_value` hold two incomplete type representation for display.
391         // `name` is the path of both types being compared. `sub`
392         value.push_highlighted(name);
393         let len = sub.len();
394         if len > 0 {
395             value.push_highlighted("<");
396         }
397
398         // Output the lifetimes fot the first type
399         let lifetimes = sub.regions().map(|lifetime| {
400             let s = format!("{}", lifetime);
401             if s.is_empty() {
402                 "'_".to_string()
403             } else {
404                 s
405             }
406         }).collect::<Vec<_>>().join(", ");
407         if !lifetimes.is_empty() {
408             if sub.regions().count() < len {
409                 value.push_normal(lifetimes + &", ");
410             } else {
411                 value.push_normal(lifetimes);
412             }
413         }
414
415         // Highlight all the type arguments that aren't at `pos` and compare the type argument at
416         // `pos` and `other_ty`.
417         for (i, type_arg) in sub.types().enumerate() {
418             if i == pos {
419                 let values = self.cmp(type_arg, other_ty);
420                 value.0.extend((values.0).0);
421                 other_value.0.extend((values.1).0);
422             } else {
423                 value.push_highlighted(format!("{}", type_arg));
424             }
425
426             if len > 0 && i != len - 1 {
427                 value.push_normal(", ");
428             }
429             //self.push_comma(&mut value, &mut other_value, len, i);
430         }
431         if len > 0 {
432             value.push_highlighted(">");
433         }
434     }
435
436     /// If `other_ty` is the same as a type argument present in `sub`, highlight `path` in `t1_out`,
437     /// as that is the difference to the other type.
438     ///
439     /// For the following code:
440     ///
441     /// ```norun
442     /// let x: Foo<Bar<Qux>> = foo::<Bar<Qux>>();
443     /// ```
444     ///
445     /// The type error output will behave in the following way:
446     ///
447     /// ```text
448     /// Foo<Bar<Qux>>
449     /// ^^^^--------^ this is highlighted
450     /// |   |
451     /// |   this type argument is exactly the same as the other type, not highlighted
452     /// this is highlighted
453     /// Bar<Qux>
454     /// -------- this type is the same as a type argument in the other type, not highlighted
455     /// ```
456     fn cmp_type_arg(&self,
457                     mut t1_out: &mut DiagnosticStyledString,
458                     mut t2_out: &mut DiagnosticStyledString,
459                     path: String,
460                     sub: &ty::subst::Substs<'tcx>,
461                     other_path: String,
462                     other_ty: &ty::Ty<'tcx>) -> Option<()> {
463         for (i, ta) in sub.types().enumerate() {
464             if &ta == other_ty {
465                 self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
466                 return Some(());
467             }
468             if let &ty::TyAdt(def, _) = &ta.sty {
469                 let path_ = self.tcx.item_path_str(def.did.clone());
470                 if path_ == other_path {
471                     self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty);
472                     return Some(());
473                 }
474             }
475         }
476         None
477     }
478
479     /// Add a `,` to the type representation only if it is appropriate.
480     fn push_comma(&self,
481                   value: &mut DiagnosticStyledString,
482                   other_value: &mut DiagnosticStyledString,
483                   len: usize,
484                   pos: usize) {
485         if len > 0 && pos != len - 1 {
486             value.push_normal(", ");
487             other_value.push_normal(", ");
488         }
489     }
490
491     /// Compare two given types, eliding parts that are the same between them and highlighting
492     /// relevant differences, and return two representation of those types for highlighted printing.
493     fn cmp(&self, t1: ty::Ty<'tcx>, t2: ty::Ty<'tcx>)
494         -> (DiagnosticStyledString, DiagnosticStyledString)
495     {
496         match (&t1.sty, &t2.sty) {
497             (&ty::TyAdt(def1, sub1), &ty::TyAdt(def2, sub2)) => {
498                 let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new());
499                 let path1 = self.tcx.item_path_str(def1.did.clone());
500                 let path2 = self.tcx.item_path_str(def2.did.clone());
501                 if def1.did == def2.did {
502                     // Easy case. Replace same types with `_` to shorten the output and highlight
503                     // the differing ones.
504                     //     let x: Foo<Bar, Qux> = y::<Foo<Quz, Qux>>();
505                     //     Foo<Bar, _>
506                     //     Foo<Quz, _>
507                     //         ---  ^ type argument elided
508                     //         |
509                     //         highlighted in output
510                     values.0.push_normal(path1);
511                     values.1.push_normal(path2);
512
513                     // Only draw `<...>` if there're lifetime/type arguments.
514                     let len = sub1.len();
515                     if len > 0 {
516                         values.0.push_normal("<");
517                         values.1.push_normal("<");
518                     }
519
520                     fn lifetime_display(lifetime: &Region) -> String {
521                         let s = format!("{}", lifetime);
522                         if s.is_empty() {
523                             "'_".to_string()
524                         } else {
525                             s
526                         }
527                     }
528                     // At one point we'd like to elide all lifetimes here, they are irrelevant for
529                     // all diagnostics that use this output
530                     //
531                     //     Foo<'x, '_, Bar>
532                     //     Foo<'y, '_, Qux>
533                     //         ^^  ^^  --- type arguments are not elided
534                     //         |   |
535                     //         |   elided as they were the same
536                     //         not elided, they were different, but irrelevant
537                     let lifetimes = sub1.regions().zip(sub2.regions());
538                     for (i, lifetimes) in lifetimes.enumerate() {
539                         let l1 = lifetime_display(lifetimes.0);
540                         let l2 = lifetime_display(lifetimes.1);
541                         if l1 == l2 {
542                             values.0.push_normal("'_");
543                             values.1.push_normal("'_");
544                         } else {
545                             values.0.push_highlighted(l1);
546                             values.1.push_highlighted(l2);
547                         }
548                         self.push_comma(&mut values.0, &mut values.1, len, i);
549                     }
550
551                     // We're comparing two types with the same path, so we compare the type
552                     // arguments for both. If they are the same, do not highlight and elide from the
553                     // output.
554                     //     Foo<_, Bar>
555                     //     Foo<_, Qux>
556                     //         ^ elided type as this type argument was the same in both sides
557                     let type_arguments = sub1.types().zip(sub2.types());
558                     let regions_len = sub1.regions().collect::<Vec<_>>().len();
559                     for (i, (ta1, ta2)) in type_arguments.enumerate() {
560                         let i = i + regions_len;
561                         if ta1 == ta2 {
562                             values.0.push_normal("_");
563                             values.1.push_normal("_");
564                         } else {
565                             let (x1, x2) = self.cmp(ta1, ta2);
566                             (values.0).0.extend(x1.0);
567                             (values.1).0.extend(x2.0);
568                         }
569                         self.push_comma(&mut values.0, &mut values.1, len, i);
570                     }
571
572                     // Close the type argument bracket.
573                     // Only draw `<...>` if there're lifetime/type arguments.
574                     if len > 0 {
575                         values.0.push_normal(">");
576                         values.1.push_normal(">");
577                     }
578                     values
579                 } else {
580                     // Check for case:
581                     //     let x: Foo<Bar<Qux> = foo::<Bar<Qux>>();
582                     //     Foo<Bar<Qux>
583                     //         ------- this type argument is exactly the same as the other type
584                     //     Bar<Qux>
585                     if self.cmp_type_arg(&mut values.0,
586                                          &mut values.1,
587                                          path1.clone(),
588                                          sub1,
589                                          path2.clone(),
590                                          &t2).is_some() {
591                         return values;
592                     }
593                     // Check for case:
594                     //     let x: Bar<Qux> = y:<Foo<Bar<Qux>>>();
595                     //     Bar<Qux>
596                     //     Foo<Bar<Qux>>
597                     //         ------- this type argument is exactly the same as the other type
598                     if self.cmp_type_arg(&mut values.1,
599                                          &mut values.0,
600                                          path2,
601                                          sub2,
602                                          path1,
603                                          &t1).is_some() {
604                         return values;
605                     }
606
607                     // We couldn't find anything in common, highlight everything.
608                     //     let x: Bar<Qux> = y::<Foo<Zar>>();
609                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
610                      DiagnosticStyledString::highlighted(format!("{}", t2)))
611                 }
612             }
613             _ => {
614                 if t1 == t2 {
615                     // The two types are the same, elide and don't highlight.
616                     (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_"))
617                 } else {
618                     // We couldn't find anything in common, highlight everything.
619                     (DiagnosticStyledString::highlighted(format!("{}", t1)),
620                      DiagnosticStyledString::highlighted(format!("{}", t2)))
621                 }
622             }
623         }
624     }
625
626     pub fn note_type_err(&self,
627                          diag: &mut DiagnosticBuilder<'tcx>,
628                          cause: &ObligationCause<'tcx>,
629                          secondary_span: Option<(Span, String)>,
630                          values: Option<ValuePairs<'tcx>>,
631                          terr: &TypeError<'tcx>)
632     {
633         let (expected_found, is_simple_error) = match values {
634             None => (None, false),
635             Some(values) => {
636                 let is_simple_error = match values {
637                     ValuePairs::Types(exp_found) => {
638                         exp_found.expected.is_primitive() && exp_found.found.is_primitive()
639                     }
640                     _ => false,
641                 };
642                 let vals = match self.values_str(&values) {
643                     Some((expected, found)) => Some((expected, found)),
644                     None => {
645                         // Derived error. Cancel the emitter.
646                         self.tcx.sess.diagnostic().cancel(diag);
647                         return
648                     }
649                 };
650                 (vals, is_simple_error)
651             }
652         };
653
654         let span = cause.span;
655
656         if let Some((expected, found)) = expected_found {
657             match (terr, is_simple_error, expected == found) {
658                 (&TypeError::Sorts(ref values), false, true) => {
659                     diag.note_expected_found_extra(
660                         &"type", expected, found,
661                         &format!(" ({})", values.expected.sort_string(self.tcx)),
662                         &format!(" ({})", values.found.sort_string(self.tcx)));
663                 }
664                 (_, false,  _) => {
665                     diag.note_expected_found(&"type", expected, found);
666                 }
667                 _ => (),
668             }
669         }
670
671         diag.span_label(span, &terr);
672         if let Some((sp, msg)) = secondary_span {
673             diag.span_label(sp, &msg);
674         }
675
676         self.note_error_origin(diag, &cause);
677         self.check_and_note_conflicting_crates(diag, terr, span);
678         self.tcx.note_and_explain_type_err(diag, terr, span);
679     }
680
681     pub fn note_issue_32330(&self,
682                             diag: &mut DiagnosticBuilder<'tcx>,
683                             terr: &TypeError<'tcx>)
684     {
685         debug!("note_issue_32330: terr={:?}", terr);
686         match *terr {
687             TypeError::RegionsInsufficientlyPolymorphic(_, _, Some(box Issue32330 {
688                 fn_def_id, region_name
689             })) |
690             TypeError::RegionsOverlyPolymorphic(_, _, Some(box Issue32330 {
691                 fn_def_id, region_name
692             })) => {
693                 diag.note(
694                     &format!("lifetime parameter `{0}` declared on fn `{1}` \
695                               appears only in the return type, \
696                               but here is required to be higher-ranked, \
697                               which means that `{0}` must appear in both \
698                               argument and return types",
699                              region_name,
700                              self.tcx.item_path_str(fn_def_id)));
701                 diag.note(
702                     &format!("this error is the result of a recent bug fix; \
703                               for more information, see issue #33685 \
704                               <https://github.com/rust-lang/rust/issues/33685>"));
705             }
706             _ => {}
707         }
708     }
709
710     pub fn report_and_explain_type_error(&self,
711                                          trace: TypeTrace<'tcx>,
712                                          terr: &TypeError<'tcx>)
713                                          -> DiagnosticBuilder<'tcx>
714     {
715         let span = trace.cause.span;
716         let failure_str = trace.cause.as_failure_str();
717         let mut diag = match trace.cause.code {
718             ObligationCauseCode::IfExpressionWithNoElse => {
719                 struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str)
720             }
721             ObligationCauseCode::MainFunctionType => {
722                 struct_span_err!(self.tcx.sess, span, E0580, "{}", failure_str)
723             }
724             _ => {
725                 struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str)
726             }
727         };
728         self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr);
729         self.note_issue_32330(&mut diag, terr);
730         diag
731     }
732
733     fn values_str(&self, values: &ValuePairs<'tcx>)
734         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
735     {
736         match *values {
737             infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found),
738             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
739             infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
740         }
741     }
742
743     fn expected_found_str_ty(&self,
744                              exp_found: &ty::error::ExpectedFound<ty::Ty<'tcx>>)
745                              -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
746         let exp_found = self.resolve_type_vars_if_possible(exp_found);
747         if exp_found.references_error() {
748             return None;
749         }
750
751         Some(self.cmp(exp_found.expected, exp_found.found))
752     }
753
754     /// Returns a string of the form "expected `{}`, found `{}`".
755     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
756         &self,
757         exp_found: &ty::error::ExpectedFound<T>)
758         -> Option<(DiagnosticStyledString, DiagnosticStyledString)>
759     {
760         let exp_found = self.resolve_type_vars_if_possible(exp_found);
761         if exp_found.references_error() {
762             return None;
763         }
764
765         Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)),
766               DiagnosticStyledString::highlighted(format!("{}", exp_found.found))))
767     }
768
769     fn report_generic_bound_failure(&self,
770                                     origin: SubregionOrigin<'tcx>,
771                                     bound_kind: GenericKind<'tcx>,
772                                     sub: &'tcx Region)
773     {
774         // FIXME: it would be better to report the first error message
775         // with the span of the parameter itself, rather than the span
776         // where the error was detected. But that span is not readily
777         // accessible.
778
779         let labeled_user_string = match bound_kind {
780             GenericKind::Param(ref p) =>
781                 format!("the parameter type `{}`", p),
782             GenericKind::Projection(ref p) =>
783                 format!("the associated type `{}`", p),
784         };
785
786         if let SubregionOrigin::CompareImplMethodObligation {
787             span, item_name, impl_item_def_id, trait_item_def_id, lint_id
788         } = origin {
789             self.report_extra_impl_obligation(span,
790                                               item_name,
791                                               impl_item_def_id,
792                                               trait_item_def_id,
793                                               &format!("`{}: {}`", bound_kind, sub),
794                                               lint_id)
795                 .emit();
796             return;
797         }
798
799         let mut err = match *sub {
800             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
801                 // Does the required lifetime have a nice name we can print?
802                 let mut err = struct_span_err!(self.tcx.sess,
803                                                origin.span(),
804                                                E0309,
805                                                "{} may not live long enough",
806                                                labeled_user_string);
807                 err.help(&format!("consider adding an explicit lifetime bound `{}: {}`...",
808                          bound_kind,
809                          sub));
810                 err
811             }
812
813             ty::ReStatic => {
814                 // Does the required lifetime have a nice name we can print?
815                 let mut err = struct_span_err!(self.tcx.sess,
816                                                origin.span(),
817                                                E0310,
818                                                "{} may not live long enough",
819                                                labeled_user_string);
820                 err.help(&format!("consider adding an explicit lifetime \
821                                    bound `{}: 'static`...",
822                                   bound_kind));
823                 err
824             }
825
826             _ => {
827                 // If not, be less specific.
828                 let mut err = struct_span_err!(self.tcx.sess,
829                                                origin.span(),
830                                                E0311,
831                                                "{} may not live long enough",
832                                                labeled_user_string);
833                 err.help(&format!("consider adding an explicit lifetime bound for `{}`",
834                                   bound_kind));
835                 self.tcx.note_and_explain_region(
836                     &mut err,
837                     &format!("{} must be valid for ", labeled_user_string),
838                     sub,
839                     "...");
840                 err
841             }
842         };
843
844         self.note_region_origin(&mut err, &origin);
845         err.emit();
846     }
847
848     fn report_sub_sup_conflict(&self,
849                                var_origin: RegionVariableOrigin,
850                                sub_origin: SubregionOrigin<'tcx>,
851                                sub_region: &'tcx Region,
852                                sup_origin: SubregionOrigin<'tcx>,
853                                sup_region: &'tcx Region) {
854         let mut err = self.report_inference_failure(var_origin);
855
856         self.tcx.note_and_explain_region(&mut err,
857             "first, the lifetime cannot outlive ",
858             sup_region,
859             "...");
860
861         self.note_region_origin(&mut err, &sup_origin);
862
863         self.tcx.note_and_explain_region(&mut err,
864             "but, the lifetime must be valid for ",
865             sub_region,
866             "...");
867
868         self.note_region_origin(&mut err, &sub_origin);
869         err.emit();
870     }
871 }
872
873 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
874     fn report_inference_failure(&self,
875                                 var_origin: RegionVariableOrigin)
876                                 -> DiagnosticBuilder<'tcx> {
877         let br_string = |br: ty::BoundRegion| {
878             let mut s = br.to_string();
879             if !s.is_empty() {
880                 s.push_str(" ");
881             }
882             s
883         };
884         let var_description = match var_origin {
885             infer::MiscVariable(_) => "".to_string(),
886             infer::PatternRegion(_) => " for pattern".to_string(),
887             infer::AddrOfRegion(_) => " for borrow expression".to_string(),
888             infer::Autoref(_) => " for autoref".to_string(),
889             infer::Coercion(_) => " for automatic coercion".to_string(),
890             infer::LateBoundRegion(_, br, infer::FnCall) => {
891                 format!(" for lifetime parameter {}in function call",
892                         br_string(br))
893             }
894             infer::LateBoundRegion(_, br, infer::HigherRankedType) => {
895                 format!(" for lifetime parameter {}in generic type", br_string(br))
896             }
897             infer::LateBoundRegion(_, br, infer::AssocTypeProjection(type_name)) => {
898                 format!(" for lifetime parameter {}in trait containing associated type `{}`",
899                         br_string(br), type_name)
900             }
901             infer::EarlyBoundRegion(_, name, _) => {
902                 format!(" for lifetime parameter `{}`",
903                         name)
904             }
905             infer::BoundRegionInCoherence(name) => {
906                 format!(" for lifetime parameter `{}` in coherence check",
907                         name)
908             }
909             infer::UpvarRegion(ref upvar_id, _) => {
910                 format!(" for capture of `{}` by closure",
911                         self.tcx.local_var_name_str(upvar_id.var_id).to_string())
912             }
913         };
914
915         struct_span_err!(self.tcx.sess, var_origin.span(), E0495,
916                   "cannot infer an appropriate lifetime{} \
917                    due to conflicting requirements",
918                   var_description)
919     }
920 }
921
922 impl<'tcx> ObligationCause<'tcx> {
923     fn as_failure_str(&self) -> &'static str {
924         use traits::ObligationCauseCode::*;
925         match self.code {
926             CompareImplMethodObligation { .. } => "method not compatible with trait",
927             MatchExpressionArm { source, .. } => match source {
928                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
929                 _ => "match arms have incompatible types",
930             },
931             IfExpression => "if and else have incompatible types",
932             IfExpressionWithNoElse => "if may be missing an else clause",
933             EquatePredicate => "equality predicate not satisfied",
934             MainFunctionType => "main function has wrong type",
935             StartFunctionType => "start function has wrong type",
936             IntrinsicType => "intrinsic has wrong type",
937             MethodReceiver => "mismatched method receiver",
938             _ => "mismatched types",
939         }
940     }
941
942     fn as_requirement_str(&self) -> &'static str {
943         use traits::ObligationCauseCode::*;
944         match self.code {
945             CompareImplMethodObligation { .. } => "method type is compatible with trait",
946             ExprAssignable => "expression is assignable",
947             MatchExpressionArm { source, .. } => match source {
948                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types",
949                 _ => "match arms have compatible types",
950             },
951             IfExpression => "if and else have compatible types",
952             IfExpressionWithNoElse => "if missing an else returns ()",
953             EquatePredicate => "equality where clause is satisfied",
954             MainFunctionType => "`main` function has the correct type",
955             StartFunctionType => "`start` function has the correct type",
956             IntrinsicType => "intrinsic has the correct type",
957             MethodReceiver => "method receiver has the correct type",
958             _ => "types are compatible",
959         }
960     }
961 }