]> git.proxmox.com Git - rustc.git/blob - src/librustc/middle/traits/error_reporting.rs
Imported Upstream version 1.8.0+dfsg1
[rustc.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 }