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, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty};
30 use middle::ty::fold::TypeFoldable;
31 use util::nodemap::{FnvHashMap, FnvHashSet};
34 use syntax::codemap::Span;
35 use syntax::attr::{AttributeMethods, AttrMetaMethods};
37 #[derive(Debug, PartialEq, Eq, Hash)]
38 pub struct TraitErrorKey<'tcx> {
40 predicate: ty::Predicate<'tcx>
43 impl<'tcx> TraitErrorKey<'tcx> {
44 fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>,
45 e: &FulfillmentError<'tcx>) -> Self {
47 infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
49 span: e.obligation.cause.span,
50 predicate: infcx.tcx.erase_regions(&predicate)
55 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
56 errors: &Vec<FulfillmentError<'tcx>>) {
58 report_fulfillment_error(infcx, error);
62 fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
63 error: &FulfillmentError<'tcx>) {
64 let error_key = TraitErrorKey::from_error(infcx, error);
65 debug!("report_fulfillment_errors({:?}) - key={:?}",
67 if !infcx.reported_trait_errors.borrow_mut().insert(error_key) {
68 debug!("report_fulfillment_errors: skipping duplicate");
72 FulfillmentErrorCode::CodeSelectionError(ref e) => {
73 report_selection_error(infcx, &error.obligation, e);
75 FulfillmentErrorCode::CodeProjectionError(ref e) => {
76 report_projection_error(infcx, &error.obligation, e);
78 FulfillmentErrorCode::CodeAmbiguity => {
79 maybe_report_ambiguity(infcx, &error.obligation);
84 pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
85 obligation: &PredicateObligation<'tcx>,
86 error: &MismatchedProjectionTypes<'tcx>)
89 infcx.resolve_type_vars_if_possible(&obligation.predicate);
91 // The TyError created by normalize_to_error can end up being unified
92 // into all obligations: for example, if our obligation is something
93 // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
94 // then $X will be unified with TyError, but the error still needs to be
96 if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
98 infcx.tcx.sess, obligation.cause.span, E0271,
99 "type mismatch resolving `{}`: {}",
102 note_obligation_cause(infcx, obligation);
106 fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
107 trait_ref: &TraitRef<'tcx>,
108 span: Span) -> Option<String> {
109 let def_id = trait_ref.def_id;
110 let mut report = None;
111 for item in infcx.tcx.get_attrs(def_id).iter() {
112 if item.check_name("rustc_on_unimplemented") {
113 let err_sp = item.meta().span.substitute_dummy(span);
114 let def = infcx.tcx.lookup_trait_def(def_id);
115 let trait_str = def.trait_ref.to_string();
116 if let Some(ref istring) = item.value_str() {
117 let mut generic_map = def.generics.types.iter_enumerated()
118 .map(|(param, i, gen)| {
119 (gen.name.as_str().to_string(),
120 trait_ref.substs.types.get(param, i)
122 }).collect::<FnvHashMap<String, String>>();
123 generic_map.insert("Self".to_string(),
124 trait_ref.self_ty().to_string());
125 let parser = Parser::new(&istring);
126 let mut errored = false;
127 let err: String = parser.filter_map(|p| {
129 Piece::String(s) => Some(s),
130 Piece::NextArgument(a) => match a.position {
131 Position::ArgumentNamed(s) => match generic_map.get(s) {
132 Some(val) => Some(val),
134 span_err!(infcx.tcx.sess, err_sp, E0272,
135 "the #[rustc_on_unimplemented] \
137 trait definition for {} refers to \
138 non-existent type parameter {}",
145 span_err!(infcx.tcx.sess, err_sp, E0273,
146 "the #[rustc_on_unimplemented] \
148 trait definition for {} must have named \
150 eg `#[rustc_on_unimplemented = \
159 // Report only if the format string checks out
164 span_err!(infcx.tcx.sess, err_sp, E0274,
165 "the #[rustc_on_unimplemented] attribute on \
166 trait definition for {} must have a value, \
167 eg `#[rustc_on_unimplemented = \"foo\"]`",
176 /// Reports that an overflow has occurred and halts compilation. We
177 /// halt compilation unconditionally because it is important that
178 /// overflows never be masked -- they basically represent computations
179 /// whose result could not be truly determined and thus we can't say
180 /// if the program type checks or not -- and they are unusual
181 /// occurrences in any case.
182 pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
183 obligation: &Obligation<'tcx, T>)
185 where T: fmt::Display + TypeFoldable<'tcx> + HasTypeFlags
188 infcx.resolve_type_vars_if_possible(&obligation.predicate);
189 span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
190 "overflow evaluating the requirement `{}`",
193 suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
195 note_obligation_cause(infcx, obligation);
197 infcx.tcx.sess.abort_if_errors();
201 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
202 obligation: &PredicateObligation<'tcx>,
203 error: &SelectionError<'tcx>)
206 SelectionError::Unimplemented => {
207 if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
209 infcx.tcx.sess, obligation.cause.span, E0276,
210 "the requirement `{}` appears on the impl \
211 method but not on the corresponding trait method",
212 obligation.predicate);
214 match obligation.predicate {
215 ty::Predicate::Trait(ref trait_predicate) => {
216 let trait_predicate =
217 infcx.resolve_type_vars_if_possible(trait_predicate);
219 if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
220 let trait_ref = trait_predicate.to_poly_trait_ref();
222 infcx.tcx.sess, obligation.cause.span, E0277,
223 "the trait `{}` is not implemented for the type `{}`",
224 trait_ref, trait_ref.self_ty());
226 // Check if it has a custom "#[rustc_on_unimplemented]"
227 // error message, report with that message if it does
228 let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
229 obligation.cause.span);
230 if let Some(s) = custom_note {
231 infcx.tcx.sess.fileline_note(obligation.cause.span, &s);
233 note_obligation_cause(infcx, obligation);
237 ty::Predicate::Equate(ref predicate) => {
238 let predicate = infcx.resolve_type_vars_if_possible(predicate);
239 let err = infcx.equality_predicate(obligation.cause.span,
240 &predicate).err().unwrap();
242 infcx.tcx.sess, obligation.cause.span, E0278,
243 "the requirement `{}` is not satisfied (`{}`)",
246 note_obligation_cause(infcx, obligation);
249 ty::Predicate::RegionOutlives(ref predicate) => {
250 let predicate = infcx.resolve_type_vars_if_possible(predicate);
251 let err = infcx.region_outlives_predicate(obligation.cause.span,
252 &predicate).err().unwrap();
254 infcx.tcx.sess, obligation.cause.span, E0279,
255 "the requirement `{}` is not satisfied (`{}`)",
258 note_obligation_cause(infcx, obligation);
261 ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
263 infcx.resolve_type_vars_if_possible(&obligation.predicate);
265 infcx.tcx.sess, obligation.cause.span, E0280,
266 "the requirement `{}` is not satisfied",
268 note_obligation_cause(infcx, obligation);
271 ty::Predicate::ObjectSafe(trait_def_id) => {
272 let violations = object_safety_violations(
273 infcx.tcx, trait_def_id);
274 report_object_safety_error(infcx.tcx,
275 obligation.cause.span,
278 note_obligation_cause(infcx, obligation);
281 ty::Predicate::WellFormed(ty) => {
282 // WF predicates cannot themselves make
283 // errors. They can only block due to
284 // ambiguity; otherwise, they always
285 // degenerate into other obligations
287 infcx.tcx.sess.span_bug(
288 obligation.cause.span,
289 &format!("WF predicate not satisfied for {:?}", ty));
295 OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
296 let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
297 let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
298 if !actual_trait_ref.self_ty().references_error() {
300 infcx.tcx.sess, obligation.cause.span, E0281,
301 "type mismatch: the type `{}` implements the trait `{}`, \
302 but the trait `{}` is required ({})",
303 expected_trait_ref.self_ty(),
307 note_obligation_cause(infcx, obligation);
311 TraitNotObjectSafe(did) => {
312 let violations = object_safety_violations(infcx.tcx, did);
313 report_object_safety_error(infcx.tcx, obligation.cause.span, did, violations);
314 note_obligation_cause(infcx, obligation);
319 pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
322 violations: Vec<ObjectSafetyViolation>)
325 tcx.sess, span, E0038,
326 "the trait `{}` cannot be made into an object",
327 tcx.item_path_str(trait_def_id));
329 let mut reported_violations = FnvHashSet();
330 for violation in violations {
331 if !reported_violations.insert(violation.clone()) {
335 ObjectSafetyViolation::SizedSelf => {
336 tcx.sess.fileline_note(
338 "the trait cannot require that `Self : Sized`");
341 ObjectSafetyViolation::SupertraitSelf => {
342 tcx.sess.fileline_note(
344 "the trait cannot use `Self` as a type parameter \
345 in the supertrait listing");
348 ObjectSafetyViolation::Method(method,
349 MethodViolationCode::StaticMethod) => {
350 tcx.sess.fileline_note(
352 &format!("method `{}` has no receiver",
356 ObjectSafetyViolation::Method(method,
357 MethodViolationCode::ReferencesSelf) => {
358 tcx.sess.fileline_note(
360 &format!("method `{}` references the `Self` type \
361 in its arguments or return type",
365 ObjectSafetyViolation::Method(method,
366 MethodViolationCode::Generic) => {
367 tcx.sess.fileline_note(
369 &format!("method `{}` has generic type parameters",
376 pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
377 obligation: &PredicateObligation<'tcx>) {
378 // Unable to successfully determine, probably means
379 // insufficient type information, but could mean
380 // ambiguous impls. The latter *ought* to be a
381 // coherence violation, so we don't report it here.
383 let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
385 debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
390 ty::Predicate::Trait(ref data) => {
391 let trait_ref = data.to_poly_trait_ref();
392 let self_ty = trait_ref.self_ty();
393 let all_types = &trait_ref.substs().types;
394 if all_types.references_error() {
396 // Typically, this ambiguity should only happen if
397 // there are unresolved type inference variables
398 // (otherwise it would suggest a coherence
399 // failure). But given #21974 that is not necessarily
400 // the case -- we can have multiple where clauses that
401 // are only distinguished by a region, which results
402 // in an ambiguity even when all types are fully
403 // known, since we don't dispatch based on region
406 // This is kind of a hack: it frequently happens that some earlier
407 // error prevents types from being fully inferred, and then we get
408 // a bunch of uninteresting errors saying something like "<generic
409 // #0> doesn't implement Sized". It may even be true that we
410 // could just skip over all checks where the self-ty is an
411 // inference variable, but I was afraid that there might be an
412 // inference variable created, registered as an obligation, and
413 // then never forced by writeback, and hence by skipping here we'd
414 // be ignoring the fact that we don't KNOW the type works
415 // out. Though even that would probably be harmless, given that
416 // we're only talking about builtin traits, which are known to be
417 // inhabited. But in any case I just threw in this check for
418 // has_errors() to be sure that compilation isn't happening
419 // anyway. In that case, why inundate the user.
420 if !infcx.tcx.sess.has_errors() {
422 infcx.tcx.lang_items.sized_trait()
423 .map_or(false, |sized_id| sized_id == trait_ref.def_id())
425 need_type_info(infcx, obligation.cause.span, self_ty);
427 span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
428 "type annotations required: cannot resolve `{}`",
430 note_obligation_cause(infcx, obligation);
436 ty::Predicate::WellFormed(ty) => {
437 // Same hacky approach as above to avoid deluging user
438 // with error messages.
439 if !ty.references_error() && !infcx.tcx.sess.has_errors() {
440 need_type_info(infcx, obligation.cause.span, ty);
445 if !infcx.tcx.sess.has_errors() {
446 span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
447 "type annotations required: cannot resolve `{}`",
449 note_obligation_cause(infcx, obligation);
455 fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
459 span_err!(infcx.tcx.sess, span, E0282,
460 "unable to infer enough type information about `{}`; \
461 type annotations or generic parameter binding required",
465 fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
466 obligation: &Obligation<'tcx, T>)
467 where T: fmt::Display
469 note_obligation_cause_code(infcx,
470 &obligation.predicate,
471 obligation.cause.span,
472 &obligation.cause.code);
475 fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
478 cause_code: &ObligationCauseCode<'tcx>)
479 where T: fmt::Display
483 ObligationCauseCode::MiscObligation => { }
484 ObligationCauseCode::SliceOrArrayElem => {
485 tcx.sess.fileline_note(
487 "slice and array elements must have `Sized` type");
489 ObligationCauseCode::ProjectionWf(data) => {
490 tcx.sess.fileline_note(
492 &format!("required so that the projection `{}` is well-formed",
495 ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
496 tcx.sess.fileline_note(
498 &format!("required so that reference `{}` does not outlive its referent",
501 ObligationCauseCode::ItemObligation(item_def_id) => {
502 let item_name = tcx.item_path_str(item_def_id);
503 tcx.sess.fileline_note(
505 &format!("required by `{}`", item_name));
507 ObligationCauseCode::ObjectCastObligation(object_ty) => {
508 tcx.sess.fileline_note(
511 "required for the cast to the object type `{}`",
512 infcx.ty_to_string(object_ty)));
514 ObligationCauseCode::RepeatVec => {
515 tcx.sess.fileline_note(
517 "the `Copy` trait is required because the \
518 repeated element will be copied");
520 ObligationCauseCode::VariableType(_) => {
521 tcx.sess.fileline_note(
523 "all local variables must have a statically known size");
525 ObligationCauseCode::ReturnType => {
526 tcx.sess.fileline_note(
528 "the return type of a function must have a \
529 statically known size");
531 ObligationCauseCode::AssignmentLhsSized => {
532 tcx.sess.fileline_note(
534 "the left-hand-side of an assignment must have a statically known size");
536 ObligationCauseCode::StructInitializerSized => {
537 tcx.sess.fileline_note(
539 "structs must have a statically known size to be initialized");
541 ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
542 let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
543 let trait_name = tcx.item_path_str(def_id);
544 let name = tcx.local_var_name_str(var_id);
545 tcx.sess.fileline_note(
547 &format!("the closure that captures `{}` requires that all captured variables \
548 implement the trait `{}`",
552 ObligationCauseCode::FieldSized => {
553 tcx.sess.fileline_note(
555 "only the last field of a struct or enum variant \
556 may have a dynamically sized type");
558 ObligationCauseCode::SharedStatic => {
559 tcx.sess.fileline_note(
561 "shared static variables must have a type that implements `Sync`");
563 ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
564 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
565 tcx.sess.fileline_note(
567 &format!("required because it appears within the type `{}`",
568 parent_trait_ref.0.self_ty()));
569 let parent_predicate = parent_trait_ref.to_predicate();
570 note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
572 ObligationCauseCode::ImplDerivedObligation(ref data) => {
573 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
574 tcx.sess.fileline_note(
576 &format!("required because of the requirements on the impl of `{}` for `{}`",
578 parent_trait_ref.0.self_ty()));
579 let parent_predicate = parent_trait_ref.to_predicate();
580 note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
582 ObligationCauseCode::CompareImplMethodObligation => {
583 tcx.sess.fileline_note(
585 &format!("the requirement `{}` appears on the impl method \
586 but not on the corresponding trait method",
592 fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
593 let current_limit = tcx.sess.recursion_limit.get();
594 let suggested_limit = current_limit * 2;
595 tcx.sess.fileline_note(
598 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",