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 std::collections::HashMap;
33 use syntax::codemap::Span;
34 use syntax::attr::{AttributeMethods, AttrMetaMethods};
36 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
37 errors: &Vec<FulfillmentError<'tcx>>) {
39 report_fulfillment_error(infcx, error);
43 fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
44 error: &FulfillmentError<'tcx>) {
46 FulfillmentErrorCode::CodeSelectionError(ref e) => {
47 report_selection_error(infcx, &error.obligation, e);
49 FulfillmentErrorCode::CodeProjectionError(ref e) => {
50 report_projection_error(infcx, &error.obligation, e);
52 FulfillmentErrorCode::CodeAmbiguity => {
53 maybe_report_ambiguity(infcx, &error.obligation);
58 fn is_warning<T>(obligation: &Obligation<T>) -> bool {
59 obligation.cause.code.is_rfc1214()
62 pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
63 obligation: &PredicateObligation<'tcx>,
64 error: &MismatchedProjectionTypes<'tcx>)
67 infcx.resolve_type_vars_if_possible(&obligation.predicate);
69 // The TyError created by normalize_to_error can end up being unified
70 // into all obligations: for example, if our obligation is something
71 // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
72 // then $X will be unified with TyError, but the error still needs to be
74 if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
76 is_warning(obligation), infcx.tcx.sess, obligation.cause.span, E0271,
77 "type mismatch resolving `{}`: {}",
80 note_obligation_cause(infcx, obligation);
84 fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
85 trait_ref: &TraitRef<'tcx>,
86 span: Span) -> Option<String> {
87 let def_id = trait_ref.def_id;
88 let mut report = None;
89 for item in infcx.tcx.get_attrs(def_id).iter() {
90 if item.check_name("rustc_on_unimplemented") {
91 let err_sp = item.meta().span.substitute_dummy(span);
92 let def = infcx.tcx.lookup_trait_def(def_id);
93 let trait_str = def.trait_ref.to_string();
94 if let Some(ref istring) = item.value_str() {
95 let mut generic_map = def.generics.types.iter_enumerated()
96 .map(|(param, i, gen)| {
97 (gen.name.as_str().to_string(),
98 trait_ref.substs.types.get(param, i)
100 }).collect::<HashMap<String, String>>();
101 generic_map.insert("Self".to_string(),
102 trait_ref.self_ty().to_string());
103 let parser = Parser::new(&istring);
104 let mut errored = false;
105 let err: String = parser.filter_map(|p| {
107 Piece::String(s) => Some(s),
108 Piece::NextArgument(a) => match a.position {
109 Position::ArgumentNamed(s) => match generic_map.get(s) {
110 Some(val) => Some(val),
112 span_err!(infcx.tcx.sess, err_sp, E0272,
113 "the #[rustc_on_unimplemented] \
115 trait definition for {} refers to \
116 non-existent type parameter {}",
123 span_err!(infcx.tcx.sess, err_sp, E0273,
124 "the #[rustc_on_unimplemented] \
126 trait definition for {} must have named \
128 eg `#[rustc_on_unimplemented = \
137 // Report only if the format string checks out
142 span_err!(infcx.tcx.sess, err_sp, E0274,
143 "the #[rustc_on_unimplemented] attribute on \
144 trait definition for {} must have a value, \
145 eg `#[rustc_on_unimplemented = \"foo\"]`",
154 /// Reports that an overflow has occurred and halts compilation. We
155 /// halt compilation unconditionally because it is important that
156 /// overflows never be masked -- they basically represent computations
157 /// whose result could not be truly determined and thus we can't say
158 /// if the program type checks or not -- and they are unusual
159 /// occurrences in any case.
160 pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
161 obligation: &Obligation<'tcx, T>)
163 where T: fmt::Display + TypeFoldable<'tcx> + HasTypeFlags
166 infcx.resolve_type_vars_if_possible(&obligation.predicate);
167 span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
168 "overflow evaluating the requirement `{}`",
171 suggest_new_overflow_limit(infcx.tcx, obligation.cause.span);
173 note_obligation_cause(infcx, obligation);
175 infcx.tcx.sess.abort_if_errors();
179 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
180 obligation: &PredicateObligation<'tcx>,
181 error: &SelectionError<'tcx>)
183 let is_warning = is_warning(obligation);
185 SelectionError::Unimplemented => {
186 if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
188 is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
189 "the requirement `{}` appears on the impl \
190 method but not on the corresponding trait method",
191 obligation.predicate);;
193 match obligation.predicate {
194 ty::Predicate::Trait(ref trait_predicate) => {
195 let trait_predicate =
196 infcx.resolve_type_vars_if_possible(trait_predicate);
198 if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
199 let trait_ref = trait_predicate.to_poly_trait_ref();
201 is_warning, infcx.tcx.sess, obligation.cause.span, E0277,
202 "the trait `{}` is not implemented for the type `{}`",
203 trait_ref, trait_ref.self_ty());
205 // Check if it has a custom "#[rustc_on_unimplemented]"
206 // error message, report with that message if it does
207 let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
208 obligation.cause.span);
209 if let Some(s) = custom_note {
210 infcx.tcx.sess.fileline_note(obligation.cause.span, &s);
212 note_obligation_cause(infcx, obligation);
216 ty::Predicate::Equate(ref predicate) => {
217 let predicate = infcx.resolve_type_vars_if_possible(predicate);
218 let err = infcx.equality_predicate(obligation.cause.span,
219 &predicate).err().unwrap();
221 is_warning, infcx.tcx.sess, obligation.cause.span, E0278,
222 "the requirement `{}` is not satisfied (`{}`)",
225 note_obligation_cause(infcx, obligation);
228 ty::Predicate::RegionOutlives(ref predicate) => {
229 let predicate = infcx.resolve_type_vars_if_possible(predicate);
230 let err = infcx.region_outlives_predicate(obligation.cause.span,
231 &predicate).err().unwrap();
233 is_warning, infcx.tcx.sess, obligation.cause.span, E0279,
234 "the requirement `{}` is not satisfied (`{}`)",
237 note_obligation_cause(infcx, obligation);
240 ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
242 infcx.resolve_type_vars_if_possible(&obligation.predicate);
244 is_warning, infcx.tcx.sess, obligation.cause.span, E0280,
245 "the requirement `{}` is not satisfied",
247 note_obligation_cause(infcx, obligation);
250 ty::Predicate::ObjectSafe(trait_def_id) => {
251 report_object_safety_error(infcx.tcx,
252 obligation.cause.span,
255 note_obligation_cause(infcx, obligation);
258 ty::Predicate::WellFormed(ty) => {
259 // WF predicates cannot themselves make
260 // errors. They can only block due to
261 // ambiguity; otherwise, they always
262 // degenerate into other obligations
264 infcx.tcx.sess.span_bug(
265 obligation.cause.span,
266 &format!("WF predicate not satisfied for {:?}", ty));
272 OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
273 let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
274 let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
275 if !actual_trait_ref.self_ty().references_error() {
277 is_warning, infcx.tcx.sess, obligation.cause.span, E0281,
278 "type mismatch: the type `{}` implements the trait `{}`, \
279 but the trait `{}` is required ({})",
280 expected_trait_ref.self_ty(),
284 note_obligation_cause(infcx, obligation);
288 TraitNotObjectSafe(did) => {
289 report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
290 note_obligation_cause(infcx, obligation);
295 pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
301 is_warning, tcx.sess, span, E0038,
302 "the trait `{}` cannot be made into an object",
303 tcx.item_path_str(trait_def_id));
305 for violation in object_safety_violations(tcx, trait_def_id) {
307 ObjectSafetyViolation::SizedSelf => {
308 tcx.sess.fileline_note(
310 "the trait cannot require that `Self : Sized`");
313 ObjectSafetyViolation::SupertraitSelf => {
314 tcx.sess.fileline_note(
316 "the trait cannot use `Self` as a type parameter \
317 in the supertrait listing");
320 ObjectSafetyViolation::Method(method,
321 MethodViolationCode::StaticMethod) => {
322 tcx.sess.fileline_note(
324 &format!("method `{}` has no receiver",
328 ObjectSafetyViolation::Method(method,
329 MethodViolationCode::ReferencesSelf) => {
330 tcx.sess.fileline_note(
332 &format!("method `{}` references the `Self` type \
333 in its arguments or return type",
337 ObjectSafetyViolation::Method(method,
338 MethodViolationCode::Generic) => {
339 tcx.sess.fileline_note(
341 &format!("method `{}` has generic type parameters",
348 pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
349 obligation: &PredicateObligation<'tcx>) {
350 // Unable to successfully determine, probably means
351 // insufficient type information, but could mean
352 // ambiguous impls. The latter *ought* to be a
353 // coherence violation, so we don't report it here.
355 let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
357 debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
362 ty::Predicate::Trait(ref data) => {
363 let trait_ref = data.to_poly_trait_ref();
364 let self_ty = trait_ref.self_ty();
365 let all_types = &trait_ref.substs().types;
366 if all_types.references_error() {
367 } else if all_types.needs_infer() {
368 // This is kind of a hack: it frequently happens that some earlier
369 // error prevents types from being fully inferred, and then we get
370 // a bunch of uninteresting errors saying something like "<generic
371 // #0> doesn't implement Sized". It may even be true that we
372 // could just skip over all checks where the self-ty is an
373 // inference variable, but I was afraid that there might be an
374 // inference variable created, registered as an obligation, and
375 // then never forced by writeback, and hence by skipping here we'd
376 // be ignoring the fact that we don't KNOW the type works
377 // out. Though even that would probably be harmless, given that
378 // we're only talking about builtin traits, which are known to be
379 // inhabited. But in any case I just threw in this check for
380 // has_errors() to be sure that compilation isn't happening
381 // anyway. In that case, why inundate the user.
382 if !infcx.tcx.sess.has_errors() {
384 infcx.tcx.lang_items.sized_trait()
385 .map_or(false, |sized_id| sized_id == trait_ref.def_id())
387 need_type_info(infcx, obligation.cause.span, self_ty);
389 span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
390 "type annotations required: cannot resolve `{}`",
392 note_obligation_cause(infcx, obligation);
395 } else if !infcx.tcx.sess.has_errors() {
396 // Ambiguity. Coherence should have reported an error.
397 infcx.tcx.sess.span_bug(
398 obligation.cause.span,
400 "coherence failed to report ambiguity: \
401 cannot locate the impl of the trait `{}` for \
408 ty::Predicate::WellFormed(ty) => {
409 // Same hacky approach as above to avoid deluging user
410 // with error messages.
411 if !ty.references_error() && !infcx.tcx.sess.has_errors() {
412 need_type_info(infcx, obligation.cause.span, ty);
417 if !infcx.tcx.sess.has_errors() {
418 span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
419 "type annotations required: cannot resolve `{}`",
421 note_obligation_cause(infcx, obligation);
427 fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
431 span_err!(infcx.tcx.sess, span, E0282,
432 "unable to infer enough type information about `{}`; \
433 type annotations or generic parameter binding required",
437 fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
438 obligation: &Obligation<'tcx, T>)
439 where T: fmt::Display
441 note_obligation_cause_code(infcx,
442 &obligation.predicate,
443 obligation.cause.span,
444 &obligation.cause.code);
447 fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
450 cause_code: &ObligationCauseCode<'tcx>)
451 where T: fmt::Display
455 ObligationCauseCode::MiscObligation => { }
456 ObligationCauseCode::RFC1214(ref subcode) => {
457 tcx.sess.note_rfc_1214(cause_span);
458 note_obligation_cause_code(infcx, predicate, cause_span, subcode);
460 ObligationCauseCode::SliceOrArrayElem => {
461 tcx.sess.fileline_note(
463 &format!("slice and array elements must have `Sized` type"));
465 ObligationCauseCode::ProjectionWf(data) => {
466 tcx.sess.fileline_note(
468 &format!("required so that the projection `{}` is well-formed",
471 ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
472 tcx.sess.fileline_note(
474 &format!("required so that reference `{}` does not outlive its referent",
477 ObligationCauseCode::ItemObligation(item_def_id) => {
478 let item_name = tcx.item_path_str(item_def_id);
479 tcx.sess.fileline_note(
481 &format!("required by `{}`", item_name));
483 ObligationCauseCode::ObjectCastObligation(object_ty) => {
484 tcx.sess.fileline_note(
487 "required for the cast to the object type `{}`",
488 infcx.ty_to_string(object_ty)));
490 ObligationCauseCode::RepeatVec => {
491 tcx.sess.fileline_note(
493 "the `Copy` trait is required because the \
494 repeated element will be copied");
496 ObligationCauseCode::VariableType(_) => {
497 tcx.sess.fileline_note(
499 "all local variables must have a statically known size");
501 ObligationCauseCode::ReturnType => {
502 tcx.sess.fileline_note(
504 "the return type of a function must have a \
505 statically known size");
507 ObligationCauseCode::AssignmentLhsSized => {
508 tcx.sess.fileline_note(
510 "the left-hand-side of an assignment must have a statically known size");
512 ObligationCauseCode::StructInitializerSized => {
513 tcx.sess.fileline_note(
515 "structs must have a statically known size to be initialized");
517 ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => {
518 let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
519 let trait_name = tcx.item_path_str(def_id);
520 let name = tcx.local_var_name_str(var_id);
521 tcx.sess.fileline_note(
523 &format!("the closure that captures `{}` requires that all captured variables \
524 implement the trait `{}`",
528 ObligationCauseCode::FieldSized => {
529 tcx.sess.fileline_note(
531 "only the last field of a struct or enum variant \
532 may have a dynamically sized type");
534 ObligationCauseCode::SharedStatic => {
535 tcx.sess.fileline_note(
537 "shared static variables must have a type that implements `Sync`");
539 ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
540 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
541 tcx.sess.fileline_note(
543 &format!("required because it appears within the type `{}`",
544 parent_trait_ref.0.self_ty()));
545 let parent_predicate = parent_trait_ref.to_predicate();
546 note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
548 ObligationCauseCode::ImplDerivedObligation(ref data) => {
549 let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
550 tcx.sess.fileline_note(
552 &format!("required because of the requirements on the impl of `{}` for `{}`",
554 parent_trait_ref.0.self_ty()));
555 let parent_predicate = parent_trait_ref.to_predicate();
556 note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
558 ObligationCauseCode::CompareImplMethodObligation => {
559 tcx.sess.fileline_note(
561 &format!("the requirement `{}` appears on the impl method \
562 but not on the corresponding trait method",
568 fn suggest_new_overflow_limit(tcx: &ty::ctxt, span: Span) {
569 let current_limit = tcx.sess.recursion_limit.get();
570 let suggested_limit = current_limit * 2;
571 tcx.sess.fileline_note(
574 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",