]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/traits/error_reporting.rs
Rollup merge of #31061 - brson:bib, r=steveklabnik
[rust.git] / src / librustc / middle / traits / error_reporting.rs
1 // Copyright 2014 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 use super::{
12     FulfillmentError,
13     FulfillmentErrorCode,
14     MismatchedProjectionTypes,
15     Obligation,
16     ObligationCauseCode,
17     OutputTypeParameterMismatch,
18     TraitNotObjectSafe,
19     PredicateObligation,
20     SelectionError,
21     ObjectSafetyViolation,
22     MethodViolationCode,
23     object_safety_violations,
24 };
25
26 use fmt_macros::{Parser, Piece, Position};
27 use middle::def_id::DefId;
28 use middle::infer::InferCtxt;
29 use middle::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, Ty, TypeFoldable};
30 use middle::ty::fast_reject;
31 use util::nodemap::{FnvHashMap, FnvHashSet};
32
33 use std::cmp;
34 use std::fmt;
35 use syntax::attr::{AttributeMethods, AttrMetaMethods};
36 use syntax::codemap::Span;
37 use syntax::errors::DiagnosticBuilder;
38
39 #[derive(Debug, PartialEq, Eq, Hash)]
40 pub struct TraitErrorKey<'tcx> {
41     span: Span,
42     predicate: ty::Predicate<'tcx>
43 }
44
45 impl<'tcx> TraitErrorKey<'tcx> {
46     fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>,
47                       e: &FulfillmentError<'tcx>) -> Self {
48         let predicate =
49             infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
50         TraitErrorKey {
51             span: e.obligation.cause.span,
52             predicate: infcx.tcx.erase_regions(&predicate)
53         }
54     }
55 }
56
57 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
58                                            errors: &Vec<FulfillmentError<'tcx>>) {
59     for error in errors {
60         report_fulfillment_error(infcx, error);
61     }
62 }
63
64 fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
65                                       error: &FulfillmentError<'tcx>) {
66     let error_key = TraitErrorKey::from_error(infcx, error);
67     debug!("report_fulfillment_errors({:?}) - key={:?}",
68            error, error_key);
69     if !infcx.reported_trait_errors.borrow_mut().insert(error_key) {
70         debug!("report_fulfillment_errors: skipping duplicate");
71         return;
72     }
73     match error.code {
74         FulfillmentErrorCode::CodeSelectionError(ref e) => {
75             report_selection_error(infcx, &error.obligation, e);
76         }
77         FulfillmentErrorCode::CodeProjectionError(ref e) => {
78             report_projection_error(infcx, &error.obligation, e);
79         }
80         FulfillmentErrorCode::CodeAmbiguity => {
81             maybe_report_ambiguity(infcx, &error.obligation);
82         }
83     }
84 }
85
86 pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
87                                          obligation: &PredicateObligation<'tcx>,
88                                          error: &MismatchedProjectionTypes<'tcx>)
89 {
90     let predicate =
91         infcx.resolve_type_vars_if_possible(&obligation.predicate);
92
93     // The TyError created by normalize_to_error can end up being unified
94     // into all obligations: for example, if our obligation is something
95     // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
96     // then $X will be unified with TyError, but the error still needs to be
97     // reported.
98     if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
99         let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
100             "type mismatch resolving `{}`: {}",
101             predicate,
102             error.err);
103         note_obligation_cause(infcx, &mut err, obligation);
104         err.emit();
105     }
106 }
107
108 fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
109                                      trait_ref: &TraitRef<'tcx>,
110                                      span: Span) -> Option<String> {
111     let def_id = trait_ref.def_id;
112     let mut report = None;
113     for item in infcx.tcx.get_attrs(def_id).iter() {
114         if item.check_name("rustc_on_unimplemented") {
115             let err_sp = item.meta().span.substitute_dummy(span);
116             let def = infcx.tcx.lookup_trait_def(def_id);
117             let trait_str = def.trait_ref.to_string();
118             if let Some(ref istring) = item.value_str() {
119                 let mut generic_map = def.generics.types.iter_enumerated()
120                                          .map(|(param, i, gen)| {
121                                                (gen.name.as_str().to_string(),
122                                                 trait_ref.substs.types.get(param, i)
123                                                          .to_string())
124                                               }).collect::<FnvHashMap<String, String>>();
125                 generic_map.insert("Self".to_string(),
126                                    trait_ref.self_ty().to_string());
127                 let parser = Parser::new(&istring);
128                 let mut errored = false;
129                 let err: String = parser.filter_map(|p| {
130                     match p {
131                         Piece::String(s) => Some(s),
132                         Piece::NextArgument(a) => match a.position {
133                             Position::ArgumentNamed(s) => match generic_map.get(s) {
134                                 Some(val) => Some(val),
135                                 None => {
136                                     span_err!(infcx.tcx.sess, err_sp, E0272,
137                                                    "the #[rustc_on_unimplemented] \
138                                                             attribute on \
139                                                             trait definition for {} refers to \
140                                                             non-existent type parameter {}",
141                                                            trait_str, s);
142                                     errored = true;
143                                     None
144                                 }
145                             },
146                             _ => {
147                                      span_err!(infcx.tcx.sess, err_sp, E0273,
148                                                "the #[rustc_on_unimplemented] \
149                                                         attribute on \
150                                                         trait definition for {} must have named \
151                                                         format arguments, \
152                                                         eg `#[rustc_on_unimplemented = \
153                                                         \"foo {{T}}\"]`",
154                                                        trait_str);
155                                 errored = true;
156                                 None
157                             }
158                         }
159                     }
160                 }).collect();
161                 // Report only if the format string checks out
162                 if !errored {
163                     report = Some(err);
164                 }
165             } else {
166                 span_err!(infcx.tcx.sess, err_sp, E0274,
167                                         "the #[rustc_on_unimplemented] attribute on \
168                                                  trait definition for {} must have a value, \
169                                                  eg `#[rustc_on_unimplemented = \"foo\"]`",
170                                                  trait_str);
171             }
172             break;
173         }
174     }
175     report
176 }
177
178 /// Reports that an overflow has occurred and halts compilation. We
179 /// halt compilation unconditionally because it is important that
180 /// overflows never be masked -- they basically represent computations
181 /// whose result could not be truly determined and thus we can't say
182 /// if the program type checks or not -- and they are unusual
183 /// occurrences in any case.
184 pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
185                                           obligation: &Obligation<'tcx, T>,
186                                           suggest_increasing_limit: bool)
187                                           -> !
188     where T: fmt::Display + TypeFoldable<'tcx>
189 {
190     let predicate =
191         infcx.resolve_type_vars_if_possible(&obligation.predicate);
192     let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
193                                    "overflow evaluating the requirement `{}`",
194                                    predicate);
195
196     if suggest_increasing_limit {
197         suggest_new_overflow_limit(infcx.tcx, &mut err, obligation.cause.span);
198     }
199
200     note_obligation_cause(infcx, &mut err, obligation);
201
202     err.emit();
203     infcx.tcx.sess.abort_if_errors();
204     unreachable!();
205 }
206
207 /// Reports that a cycle was detected which led to overflow and halts
208 /// compilation. This is equivalent to `report_overflow_error` except
209 /// that we can give a more helpful error message (and, in particular,
210 /// we do not suggest increasing the overflow limit, which is not
211 /// going to help).
212 pub fn report_overflow_error_cycle<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
213                                              cycle: &Vec<PredicateObligation<'tcx>>)
214                                              -> !
215 {
216     assert!(cycle.len() > 1);
217
218     debug!("report_overflow_error_cycle(cycle length = {})", cycle.len());
219
220     let cycle = infcx.resolve_type_vars_if_possible(cycle);
221
222     debug!("report_overflow_error_cycle: cycle={:?}", cycle);
223
224     assert_eq!(&cycle[0].predicate, &cycle.last().unwrap().predicate);
225
226     try_report_overflow_error_type_of_infinite_size(infcx, &cycle);
227     report_overflow_error(infcx, &cycle[0], false);
228 }
229
230 /// If a cycle results from evaluated whether something is Sized, that
231 /// is a particular special case that always results from a struct or
232 /// enum definition that lacks indirection (e.g., `struct Foo { x: Foo
233 /// }`). We wish to report a targeted error for this case.
234 pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
235     infcx: &InferCtxt<'a, 'tcx>,
236     cycle: &[PredicateObligation<'tcx>])
237 {
238     let sized_trait = match infcx.tcx.lang_items.sized_trait() {
239         Some(v) => v,
240         None => return,
241     };
242     let top_is_sized = {
243         match cycle[0].predicate {
244             ty::Predicate::Trait(ref data) => data.def_id() == sized_trait,
245             _ => false,
246         }
247     };
248     if !top_is_sized {
249         return;
250     }
251
252     // The only way to have a type of infinite size is to have,
253     // somewhere, a struct/enum type involved. Identify all such types
254     // and report the cycle to the user.
255
256     let struct_enum_tys: Vec<_> =
257         cycle.iter()
258              .flat_map(|obligation| match obligation.predicate {
259                  ty::Predicate::Trait(ref data) => {
260                      assert_eq!(data.def_id(), sized_trait);
261                      let self_ty = data.skip_binder().trait_ref.self_ty(); // (*)
262                      // (*) ok to skip binder because this is just
263                      // error reporting and regions don't really
264                      // matter
265                      match self_ty.sty {
266                          ty::TyEnum(..) | ty::TyStruct(..) => Some(self_ty),
267                          _ => None,
268                      }
269                  }
270                  _ => {
271                      infcx.tcx.sess.span_bug(obligation.cause.span,
272                                              &format!("Sized cycle involving non-trait-ref: {:?}",
273                                                       obligation.predicate));
274                  }
275              })
276              .collect();
277
278     assert!(!struct_enum_tys.is_empty());
279
280     // This is a bit tricky. We want to pick a "main type" in the
281     // listing that is local to the current crate, so we can give a
282     // good span to the user. But it might not be the first one in our
283     // cycle list. So find the first one that is local and then
284     // rotate.
285     let (main_index, main_def_id) =
286         struct_enum_tys.iter()
287                        .enumerate()
288                        .filter_map(|(index, ty)| match ty.sty {
289                            ty::TyEnum(adt_def, _) | ty::TyStruct(adt_def, _)
290                                if adt_def.did.is_local() =>
291                                Some((index, adt_def.did)),
292                            _ =>
293                                None,
294                        })
295                        .next()
296                        .unwrap(); // should always be SOME local type involved!
297
298     // Rotate so that the "main" type is at index 0.
299     let struct_enum_tys: Vec<_> =
300         struct_enum_tys.iter()
301                        .cloned()
302                        .skip(main_index)
303                        .chain(struct_enum_tys.iter().cloned().take(main_index))
304                        .collect();
305
306     let tcx = infcx.tcx;
307     let mut err = recursive_type_with_infinite_size_error(tcx, main_def_id);
308     let len = struct_enum_tys.len();
309     if len > 2 {
310         let span = tcx.map.span_if_local(main_def_id).unwrap();
311         err.fileline_note(span,
312                           &format!("type `{}` is embedded within `{}`...",
313                                    struct_enum_tys[0],
314                                    struct_enum_tys[1]));
315         for &next_ty in &struct_enum_tys[1..len-1] {
316             err.fileline_note(span,
317                               &format!("...which in turn is embedded within `{}`...", next_ty));
318         }
319         err.fileline_note(span,
320                           &format!("...which in turn is embedded within `{}`, \
321                                     completing the cycle.",
322                                    struct_enum_tys[len-1]));
323     }
324     err.emit();
325     infcx.tcx.sess.abort_if_errors();
326     unreachable!();
327 }
328
329 pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &ty::ctxt<'tcx>,
330                                                      type_def_id: DefId)
331                                                      -> DiagnosticBuilder<'tcx>
332 {
333     assert!(type_def_id.is_local());
334     let span = tcx.map.span_if_local(type_def_id).unwrap();
335     let mut err = struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size",
336                                    tcx.item_path_str(type_def_id));
337     err.fileline_help(span, &format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
338                                       at some point to make `{}` representable",
339                                      tcx.item_path_str(type_def_id)));
340     err
341 }
342
343 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
344                                         obligation: &PredicateObligation<'tcx>,
345                                         error: &SelectionError<'tcx>)
346 {
347     match *error {
348         SelectionError::Unimplemented => {
349             if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
350                 span_err!(
351                     infcx.tcx.sess, obligation.cause.span, E0276,
352                     "the requirement `{}` appears on the impl \
353                      method but not on the corresponding trait method",
354                     obligation.predicate);
355             } else {
356                 match obligation.predicate {
357                     ty::Predicate::Trait(ref trait_predicate) => {
358                         let trait_predicate =
359                             infcx.resolve_type_vars_if_possible(trait_predicate);
360
361                         if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
362                             let trait_ref = trait_predicate.to_poly_trait_ref();
363                             let mut err = struct_span_err!(
364                                 infcx.tcx.sess, obligation.cause.span, E0277,
365                                 "the trait `{}` is not implemented for the type `{}`",
366                                 trait_ref, trait_ref.self_ty());
367
368                             // Check if it has a custom "#[rustc_on_unimplemented]"
369                             // error message, report with that message if it does
370                             let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
371                                                                       obligation.cause.span);
372                             if let Some(s) = custom_note {
373                                 err.fileline_note(obligation.cause.span, &s);
374                             } else {
375                                 let simp = fast_reject::simplify_type(infcx.tcx,
376                                                                       trait_ref.self_ty(),
377                                                                       true);
378                                 let mut impl_candidates = Vec::new();
379                                 let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
380
381                                 match simp {
382                                     Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
383                                         let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
384                                         let imp_simp = fast_reject::simplify_type(infcx.tcx,
385                                                                                   imp.self_ty(),
386                                                                                   true);
387                                         if let Some(imp_simp) = imp_simp {
388                                             if simp != imp_simp {
389                                                 return;
390                                             }
391                                         }
392                                         impl_candidates.push(imp);
393                                     }),
394                                     None => trait_def.for_each_impl(infcx.tcx, |def_id| {
395                                         impl_candidates.push(
396                                             infcx.tcx.impl_trait_ref(def_id).unwrap());
397                                     })
398                                 };
399
400                                 if impl_candidates.len() > 0 {
401                                     err.fileline_help(
402                                         obligation.cause.span,
403                                         &format!("the following implementations were found:"));
404
405                                     let end = cmp::min(4, impl_candidates.len());
406                                     for candidate in &impl_candidates[0..end] {
407                                         err.fileline_help(obligation.cause.span,
408                                                           &format!("  {:?}", candidate));
409                                     }
410                                     if impl_candidates.len() > 4 {
411                                         err.fileline_help(obligation.cause.span,
412                                                           &format!("and {} others",
413                                                                    impl_candidates.len()-4));
414                                     }
415                                 }
416                             }
417                             note_obligation_cause(infcx, &mut err, obligation);
418                             err.emit();
419                         }
420                     },
421                     ty::Predicate::Equate(ref predicate) => {
422                         let predicate = infcx.resolve_type_vars_if_possible(predicate);
423                         let err = infcx.equality_predicate(obligation.cause.span,
424                                                            &predicate).err().unwrap();
425                         let mut err = struct_span_err!(
426                             infcx.tcx.sess, obligation.cause.span, E0278,
427                             "the requirement `{}` is not satisfied (`{}`)",
428                             predicate,
429                             err);
430                         note_obligation_cause(infcx, &mut err, obligation);
431                         err.emit();
432                     }
433
434                     ty::Predicate::RegionOutlives(ref predicate) => {
435                         let predicate = infcx.resolve_type_vars_if_possible(predicate);
436                         let err = infcx.region_outlives_predicate(obligation.cause.span,
437                                                                   &predicate).err().unwrap();
438                         let mut err = struct_span_err!(
439                             infcx.tcx.sess, obligation.cause.span, E0279,
440                             "the requirement `{}` is not satisfied (`{}`)",
441                             predicate,
442                             err);
443                         note_obligation_cause(infcx, &mut err, obligation);
444                         err.emit();
445                     }
446
447                     ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
448                         let predicate =
449                             infcx.resolve_type_vars_if_possible(&obligation.predicate);
450                         let mut err = struct_span_err!(
451                             infcx.tcx.sess, obligation.cause.span, E0280,
452                             "the requirement `{}` is not satisfied",
453                             predicate);
454                         note_obligation_cause(infcx, &mut err, obligation);
455                         err.emit();
456                     }
457
458                     ty::Predicate::ObjectSafe(trait_def_id) => {
459                         let violations = object_safety_violations(
460                             infcx.tcx, trait_def_id);
461                         let mut err = report_object_safety_error(infcx.tcx,
462                                                                  obligation.cause.span,
463                                                                  trait_def_id,
464                                                                  violations);
465                         note_obligation_cause(infcx, &mut err, obligation);
466                         err.emit();
467                     }
468
469                     ty::Predicate::WellFormed(ty) => {
470                         // WF predicates cannot themselves make
471                         // errors. They can only block due to
472                         // ambiguity; otherwise, they always
473                         // degenerate into other obligations
474                         // (which may fail).
475                         infcx.tcx.sess.span_bug(
476                             obligation.cause.span,
477                             &format!("WF predicate not satisfied for {:?}", ty));
478                     }
479                 }
480             }
481         }
482
483         OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
484             let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
485             let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
486             if !actual_trait_ref.self_ty().references_error() {
487                 let mut err = struct_span_err!(
488                     infcx.tcx.sess, obligation.cause.span, E0281,
489                     "type mismatch: the type `{}` implements the trait `{}`, \
490                      but the trait `{}` is required ({})",
491                     expected_trait_ref.self_ty(),
492                     expected_trait_ref,
493                     actual_trait_ref,
494                     e);
495                 note_obligation_cause(infcx, &mut err, obligation);
496                 err.emit();
497             }
498         }
499
500         TraitNotObjectSafe(did) => {
501             let violations = object_safety_violations(infcx.tcx, did);
502             let mut err = report_object_safety_error(infcx.tcx, obligation.cause.span, did,
503                                                      violations);
504             note_obligation_cause(infcx, &mut err, obligation);
505             err.emit();
506         }
507     }
508 }
509
510 pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
511                                         span: Span,
512                                         trait_def_id: DefId,
513                                         violations: Vec<ObjectSafetyViolation>)
514                                         -> DiagnosticBuilder<'tcx>
515 {
516     let mut err = struct_span_err!(
517         tcx.sess, span, E0038,
518         "the trait `{}` cannot be made into an object",
519         tcx.item_path_str(trait_def_id));
520
521     let mut reported_violations = FnvHashSet();
522     for violation in violations {
523         if !reported_violations.insert(violation.clone()) {
524             continue;
525         }
526         match violation {
527             ObjectSafetyViolation::SizedSelf => {
528                 err.fileline_note(
529                     span,
530                     "the trait cannot require that `Self : Sized`");
531             }
532
533             ObjectSafetyViolation::SupertraitSelf => {
534                 err.fileline_note(
535                     span,
536                     "the trait cannot use `Self` as a type parameter \
537                      in the supertrait listing");
538             }
539
540             ObjectSafetyViolation::Method(method,
541                                           MethodViolationCode::StaticMethod) => {
542                 err.fileline_note(
543                     span,
544                     &format!("method `{}` has no receiver",
545                              method.name));
546             }
547
548             ObjectSafetyViolation::Method(method,
549                                           MethodViolationCode::ReferencesSelf) => {
550                 err.fileline_note(
551                     span,
552                     &format!("method `{}` references the `Self` type \
553                               in its arguments or return type",
554                              method.name));
555             }
556
557             ObjectSafetyViolation::Method(method,
558                                           MethodViolationCode::Generic) => {
559                 err.fileline_note(
560                     span,
561                     &format!("method `{}` has generic type parameters",
562                              method.name));
563             }
564         }
565     }
566     err
567 }
568
569 pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
570                                         obligation: &PredicateObligation<'tcx>) {
571     // Unable to successfully determine, probably means
572     // insufficient type information, but could mean
573     // ambiguous impls. The latter *ought* to be a
574     // coherence violation, so we don't report it here.
575
576     let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
577
578     debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
579            predicate,
580            obligation);
581
582     match predicate {
583         ty::Predicate::Trait(ref data) => {
584             let trait_ref = data.to_poly_trait_ref();
585             let self_ty = trait_ref.self_ty();
586             let all_types = &trait_ref.substs().types;
587             if all_types.references_error() {
588             } else {
589                 // Typically, this ambiguity should only happen if
590                 // there are unresolved type inference variables
591                 // (otherwise it would suggest a coherence
592                 // failure). But given #21974 that is not necessarily
593                 // the case -- we can have multiple where clauses that
594                 // are only distinguished by a region, which results
595                 // in an ambiguity even when all types are fully
596                 // known, since we don't dispatch based on region
597                 // relationships.
598
599                 // This is kind of a hack: it frequently happens that some earlier
600                 // error prevents types from being fully inferred, and then we get
601                 // a bunch of uninteresting errors saying something like "<generic
602                 // #0> doesn't implement Sized".  It may even be true that we
603                 // could just skip over all checks where the self-ty is an
604                 // inference variable, but I was afraid that there might be an
605                 // inference variable created, registered as an obligation, and
606                 // then never forced by writeback, and hence by skipping here we'd
607                 // be ignoring the fact that we don't KNOW the type works
608                 // out. Though even that would probably be harmless, given that
609                 // we're only talking about builtin traits, which are known to be
610                 // inhabited. But in any case I just threw in this check for
611                 // has_errors() to be sure that compilation isn't happening
612                 // anyway. In that case, why inundate the user.
613                 if !infcx.tcx.sess.has_errors() {
614                     if
615                         infcx.tcx.lang_items.sized_trait()
616                         .map_or(false, |sized_id| sized_id == trait_ref.def_id())
617                     {
618                         need_type_info(infcx, obligation.cause.span, self_ty);
619                     } else {
620                         let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
621                                                        "type annotations required: \
622                                                         cannot resolve `{}`",
623                                                        predicate);
624                         note_obligation_cause(infcx, &mut err, obligation);
625                         err.emit();
626                     }
627                 }
628             }
629         }
630
631         ty::Predicate::WellFormed(ty) => {
632             // Same hacky approach as above to avoid deluging user
633             // with error messages.
634             if !ty.references_error() && !infcx.tcx.sess.has_errors() {
635                 need_type_info(infcx, obligation.cause.span, ty);
636             }
637         }
638
639         _ => {
640             if !infcx.tcx.sess.has_errors() {
641                 let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
642                                                "type annotations required: cannot resolve `{}`",
643                                                predicate);
644                 note_obligation_cause(infcx, &mut err, obligation);
645                 err.emit();
646             }
647         }
648     }
649 }
650
651 fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
652                             span: Span,
653                             ty: Ty<'tcx>)
654 {
655     span_err!(infcx.tcx.sess, span, E0282,
656               "unable to infer enough type information about `{}`; \
657                type annotations or generic parameter binding required",
658               ty);
659 }
660
661 fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
662                                       err: &mut DiagnosticBuilder,
663                                       obligation: &Obligation<'tcx, T>)
664     where T: fmt::Display
665 {
666     note_obligation_cause_code(infcx,
667                                err,
668                                &obligation.predicate,
669                                obligation.cause.span,
670                                &obligation.cause.code);
671 }
672
673 fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
674                                            err: &mut DiagnosticBuilder,
675                                            predicate: &T,
676                                            cause_span: Span,
677                                            cause_code: &ObligationCauseCode<'tcx>)
678     where T: fmt::Display
679 {
680     let tcx = infcx.tcx;
681     match *cause_code {
682         ObligationCauseCode::MiscObligation => { }
683         ObligationCauseCode::SliceOrArrayElem => {
684             err.fileline_note(
685                 cause_span,
686                 "slice and array elements must have `Sized` type");
687         }
688         ObligationCauseCode::ProjectionWf(data) => {
689             err.fileline_note(
690                 cause_span,
691                 &format!("required so that the projection `{}` is well-formed",
692                          data));
693         }
694         ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
695             err.fileline_note(
696                 cause_span,
697                 &format!("required so that reference `{}` does not outlive its referent",
698                          ref_ty));
699         }
700         ObligationCauseCode::ItemObligation(item_def_id) => {
701             let item_name = tcx.item_path_str(item_def_id);
702             err.fileline_note(
703                 cause_span,
704                 &format!("required by `{}`", item_name));
705         }
706         ObligationCauseCode::ObjectCastObligation(object_ty) => {
707             err.fileline_note(
708                 cause_span,
709                 &format!(
710                     "required for the cast to the object type `{}`",
711                     infcx.ty_to_string(object_ty)));
712         }
713         ObligationCauseCode::RepeatVec => {
714             err.fileline_note(
715                 cause_span,
716                 "the `Copy` trait is required because the \
717                  repeated element will be copied");
718         }
719         ObligationCauseCode::VariableType(_) => {
720             err.fileline_note(
721                 cause_span,
722                 "all local variables must have a statically known size");
723         }
724         ObligationCauseCode::ReturnType => {
725             err.fileline_note(
726                 cause_span,
727                 "the return type of a function must have a \
728                  statically known size");
729         }
730         ObligationCauseCode::AssignmentLhsSized => {
731             err.fileline_note(
732                 cause_span,
733                 "the left-hand-side of an assignment must have a statically known size");
734         }
735         ObligationCauseCode::StructInitializerSized => {
736             err.fileline_note(
737                 cause_span,
738                 "structs must have a statically known size to be initialized");
739         }
740         ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
741             let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
742             let trait_name = tcx.item_path_str(def_id);
743             let name = tcx.local_var_name_str(var_id);
744             err.fileline_note(
745                 cause_span,
746                 &format!("the closure that captures `{}` requires that all captured variables \
747                           implement the trait `{}`",
748                          name,
749                          trait_name));
750         }
751         ObligationCauseCode::FieldSized => {
752             err.fileline_note(
753                 cause_span,
754                 "only the last field of a struct or enum variant \
755                  may have a dynamically sized type");
756         }
757         ObligationCauseCode::SharedStatic => {
758             err.fileline_note(
759                 cause_span,
760                 "shared static variables must have a type that implements `Sync`");
761         }
762         ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
763             let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
764             err.fileline_note(
765                 cause_span,
766                 &format!("required because it appears within the type `{}`",
767                          parent_trait_ref.0.self_ty()));
768             let parent_predicate = parent_trait_ref.to_predicate();
769             note_obligation_cause_code(infcx,
770                                        err,
771                                        &parent_predicate,
772                                        cause_span,
773                                        &*data.parent_code);
774         }
775         ObligationCauseCode::ImplDerivedObligation(ref data) => {
776             let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
777             err.fileline_note(
778                 cause_span,
779                 &format!("required because of the requirements on the impl of `{}` for `{}`",
780                          parent_trait_ref,
781                          parent_trait_ref.0.self_ty()));
782             let parent_predicate = parent_trait_ref.to_predicate();
783             note_obligation_cause_code(infcx,
784                                        err,
785                                        &parent_predicate,
786                                        cause_span,
787                                        &*data.parent_code);
788         }
789         ObligationCauseCode::CompareImplMethodObligation => {
790             err.fileline_note(
791                 cause_span,
792                 &format!("the requirement `{}` appears on the impl method \
793                           but not on the corresponding trait method",
794                          predicate));
795         }
796     }
797 }
798
799 fn suggest_new_overflow_limit(tcx: &ty::ctxt, err:&mut DiagnosticBuilder, span: Span) {
800     let current_limit = tcx.sess.recursion_limit.get();
801     let suggested_limit = current_limit * 2;
802     err.fileline_note(
803         span,
804         &format!(
805             "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
806             suggested_limit));
807 }