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