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.
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.
14 MismatchedProjectionTypes,
17 OutputTypeParameterMismatch,
21 ObjectSafetyViolation,
23 object_safety_violations,
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};
35 use syntax::attr::{AttributeMethods, AttrMetaMethods};
36 use syntax::codemap::Span;
37 use syntax::errors::DiagnosticBuilder;
39 #[derive(Debug, PartialEq, Eq, Hash)]
40 pub struct TraitErrorKey<'tcx> {
42 predicate: ty::Predicate<'tcx>
45 impl<'tcx> TraitErrorKey<'tcx> {
46 fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>,
47 e: &FulfillmentError<'tcx>) -> Self {
49 infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
51 span: e.obligation.cause.span,
52 predicate: infcx.tcx.erase_regions(&predicate)
57 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
58 errors: &Vec<FulfillmentError<'tcx>>) {
60 report_fulfillment_error(infcx, error);
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={:?}",
69 if !infcx.reported_trait_errors.borrow_mut().insert(error_key) {
70 debug!("report_fulfillment_errors: skipping duplicate");
74 FulfillmentErrorCode::CodeSelectionError(ref e) => {
75 report_selection_error(infcx, &error.obligation, e);
77 FulfillmentErrorCode::CodeProjectionError(ref e) => {
78 report_projection_error(infcx, &error.obligation, e);
80 FulfillmentErrorCode::CodeAmbiguity => {
81 maybe_report_ambiguity(infcx, &error.obligation);
86 pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
87 obligation: &PredicateObligation<'tcx>,
88 error: &MismatchedProjectionTypes<'tcx>)
91 infcx.resolve_type_vars_if_possible(&obligation.predicate);
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
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 `{}`: {}",
103 note_obligation_cause(infcx, &mut err, obligation);
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)
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| {
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),
136 span_err!(infcx.tcx.sess, err_sp, E0272,
137 "the #[rustc_on_unimplemented] \
139 trait definition for {} refers to \
140 non-existent type parameter {}",
147 span_err!(infcx.tcx.sess, err_sp, E0273,
148 "the #[rustc_on_unimplemented] \
150 trait definition for {} must have named \
152 eg `#[rustc_on_unimplemented = \
161 // Report only if the format string checks out
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\"]`",
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)
188 where T: fmt::Display + TypeFoldable<'tcx>
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 `{}`",
196 if suggest_increasing_limit {
197 suggest_new_overflow_limit(infcx.tcx, &mut err, obligation.cause.span);
200 note_obligation_cause(infcx, &mut err, obligation);
203 infcx.tcx.sess.abort_if_errors();
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
212 pub fn report_overflow_error_cycle<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
213 cycle: &Vec<PredicateObligation<'tcx>>)
216 assert!(cycle.len() > 1);
218 debug!("report_overflow_error_cycle(cycle length = {})", cycle.len());
220 let cycle = infcx.resolve_type_vars_if_possible(cycle);
222 debug!("report_overflow_error_cycle: cycle={:?}", cycle);
224 assert_eq!(&cycle[0].predicate, &cycle.last().unwrap().predicate);
226 try_report_overflow_error_type_of_infinite_size(infcx, &cycle);
227 report_overflow_error(infcx, &cycle[0], false);
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>])
238 let sized_trait = match infcx.tcx.lang_items.sized_trait() {
243 match cycle[0].predicate {
244 ty::Predicate::Trait(ref data) => data.def_id() == sized_trait,
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.
256 let struct_enum_tys: Vec<_> =
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
266 ty::TyEnum(..) | ty::TyStruct(..) => Some(self_ty),
271 infcx.tcx.sess.span_bug(obligation.cause.span,
272 &format!("Sized cycle involving non-trait-ref: {:?}",
273 obligation.predicate));
278 assert!(!struct_enum_tys.is_empty());
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
285 let (main_index, main_def_id) =
286 struct_enum_tys.iter()
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)),
296 .unwrap(); // should always be SOME local type involved!
298 // Rotate so that the "main" type is at index 0.
299 let struct_enum_tys: Vec<_> =
300 struct_enum_tys.iter()
303 .chain(struct_enum_tys.iter().cloned().take(main_index))
307 let mut err = recursive_type_with_infinite_size_error(tcx, main_def_id);
308 let len = struct_enum_tys.len();
310 let span = tcx.map.span_if_local(main_def_id).unwrap();
311 err.fileline_note(span,
312 &format!("type `{}` is embedded within `{}`...",
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));
319 err.fileline_note(span,
320 &format!("...which in turn is embedded within `{}`, \
321 completing the cycle.",
322 struct_enum_tys[len-1]));
325 infcx.tcx.sess.abort_if_errors();
329 pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &ty::ctxt<'tcx>,
331 -> DiagnosticBuilder<'tcx>
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)));
343 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
344 obligation: &PredicateObligation<'tcx>,
345 error: &SelectionError<'tcx>)
348 SelectionError::Unimplemented => {
349 if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
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);
356 match obligation.predicate {
357 ty::Predicate::Trait(ref trait_predicate) => {
358 let trait_predicate =
359 infcx.resolve_type_vars_if_possible(trait_predicate);
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());
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);
375 let simp = fast_reject::simplify_type(infcx.tcx,
378 let mut impl_candidates = Vec::new();
379 let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
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,
387 if let Some(imp_simp) = imp_simp {
388 if simp != imp_simp {
392 impl_candidates.push(imp);
394 None => trait_def.for_each_impl(infcx.tcx, |def_id| {
395 impl_candidates.push(
396 infcx.tcx.impl_trait_ref(def_id).unwrap());
400 if impl_candidates.len() > 0 {
402 obligation.cause.span,
403 &format!("the following implementations were found:"));
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));
410 if impl_candidates.len() > 4 {
411 err.fileline_help(obligation.cause.span,
412 &format!("and {} others",
413 impl_candidates.len()-4));
417 note_obligation_cause(infcx, &mut err, obligation);
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 (`{}`)",
430 note_obligation_cause(infcx, &mut err, obligation);
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 (`{}`)",
443 note_obligation_cause(infcx, &mut err, obligation);
447 ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
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",
454 note_obligation_cause(infcx, &mut err, obligation);
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,
465 note_obligation_cause(infcx, &mut err, obligation);
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
475 infcx.tcx.sess.span_bug(
476 obligation.cause.span,
477 &format!("WF predicate not satisfied for {:?}", ty));
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(),
495 note_obligation_cause(infcx, &mut err, obligation);
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,
504 note_obligation_cause(infcx, &mut err, obligation);
510 pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
513 violations: Vec<ObjectSafetyViolation>)
514 -> DiagnosticBuilder<'tcx>
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));
521 let mut reported_violations = FnvHashSet();
522 for violation in violations {
523 if !reported_violations.insert(violation.clone()) {
527 ObjectSafetyViolation::SizedSelf => {
530 "the trait cannot require that `Self : Sized`");
533 ObjectSafetyViolation::SupertraitSelf => {
536 "the trait cannot use `Self` as a type parameter \
537 in the supertrait listing");
540 ObjectSafetyViolation::Method(method,
541 MethodViolationCode::StaticMethod) => {
544 &format!("method `{}` has no receiver",
548 ObjectSafetyViolation::Method(method,
549 MethodViolationCode::ReferencesSelf) => {
552 &format!("method `{}` references the `Self` type \
553 in its arguments or return type",
557 ObjectSafetyViolation::Method(method,
558 MethodViolationCode::Generic) => {
561 &format!("method `{}` has generic type parameters",
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.
576 let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
578 debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
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() {
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
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() {
615 infcx.tcx.lang_items.sized_trait()
616 .map_or(false, |sized_id| sized_id == trait_ref.def_id())
618 need_type_info(infcx, obligation.cause.span, self_ty);
620 let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
621 "type annotations required: \
622 cannot resolve `{}`",
624 note_obligation_cause(infcx, &mut err, obligation);
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);
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 `{}`",
644 note_obligation_cause(infcx, &mut err, obligation);
651 fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
655 span_err!(infcx.tcx.sess, span, E0282,
656 "unable to infer enough type information about `{}`; \
657 type annotations or generic parameter binding required",
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
666 note_obligation_cause_code(infcx,
668 &obligation.predicate,
669 obligation.cause.span,
670 &obligation.cause.code);
673 fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
674 err: &mut DiagnosticBuilder,
677 cause_code: &ObligationCauseCode<'tcx>)
678 where T: fmt::Display
682 ObligationCauseCode::MiscObligation => { }
683 ObligationCauseCode::SliceOrArrayElem => {
686 "slice and array elements must have `Sized` type");
688 ObligationCauseCode::ProjectionWf(data) => {
691 &format!("required so that the projection `{}` is well-formed",
694 ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
697 &format!("required so that reference `{}` does not outlive its referent",
700 ObligationCauseCode::ItemObligation(item_def_id) => {
701 let item_name = tcx.item_path_str(item_def_id);
704 &format!("required by `{}`", item_name));
706 ObligationCauseCode::ObjectCastObligation(object_ty) => {
710 "required for the cast to the object type `{}`",
711 infcx.ty_to_string(object_ty)));
713 ObligationCauseCode::RepeatVec => {
716 "the `Copy` trait is required because the \
717 repeated element will be copied");
719 ObligationCauseCode::VariableType(_) => {
722 "all local variables must have a statically known size");
724 ObligationCauseCode::ReturnType => {
727 "the return type of a function must have a \
728 statically known size");
730 ObligationCauseCode::AssignmentLhsSized => {
733 "the left-hand-side of an assignment must have a statically known size");
735 ObligationCauseCode::StructInitializerSized => {
738 "structs must have a statically known size to be initialized");
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);
746 &format!("the closure that captures `{}` requires that all captured variables \
747 implement the trait `{}`",
751 ObligationCauseCode::FieldSized => {
754 "only the last field of a struct or enum variant \
755 may have a dynamically sized type");
757 ObligationCauseCode::SharedStatic => {
760 "shared static variables must have a type that implements `Sync`");
762 ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
763 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
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,
775 ObligationCauseCode::ImplDerivedObligation(ref data) => {
776 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
779 &format!("required because of the requirements on the impl of `{}` for `{}`",
781 parent_trait_ref.0.self_ty()));
782 let parent_predicate = parent_trait_ref.to_predicate();
783 note_obligation_cause_code(infcx,
789 ObligationCauseCode::CompareImplMethodObligation => {
792 &format!("the requirement `{}` appears on the impl method \
793 but not on the corresponding trait method",
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;
805 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",