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
::infer
::InferCtxt
;
28 use middle
::ty
::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef}
;
29 use middle
::ty_fold
::TypeFoldable
;
30 use std
::collections
::HashMap
;
32 use syntax
::codemap
::{DUMMY_SP, Span}
;
33 use syntax
::attr
::{AttributeMethods, AttrMetaMethods}
;
35 pub fn report_fulfillment_errors
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
36 errors
: &Vec
<FulfillmentError
<'tcx
>>) {
38 report_fulfillment_error(infcx
, error
);
42 fn report_fulfillment_error
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
43 error
: &FulfillmentError
<'tcx
>) {
45 FulfillmentErrorCode
::CodeSelectionError(ref e
) => {
46 report_selection_error(infcx
, &error
.obligation
, e
);
48 FulfillmentErrorCode
::CodeProjectionError(ref e
) => {
49 report_projection_error(infcx
, &error
.obligation
, e
);
51 FulfillmentErrorCode
::CodeAmbiguity
=> {
52 maybe_report_ambiguity(infcx
, &error
.obligation
);
57 pub fn report_projection_error
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
58 obligation
: &PredicateObligation
<'tcx
>,
59 error
: &MismatchedProjectionTypes
<'tcx
>)
62 infcx
.resolve_type_vars_if_possible(&obligation
.predicate
);
63 // The TyError created by normalize_to_error can end up being unified
64 // into all obligations: for example, if our obligation is something
65 // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
66 // then $X will be unified with TyError, but the error still needs to be
68 if !infcx
.tcx
.sess
.has_errors() || !predicate
.references_error() {
69 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0271
,
70 "type mismatch resolving `{}`: {}",
73 note_obligation_cause(infcx
, obligation
);
77 fn report_on_unimplemented
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
78 trait_ref
: &TraitRef
<'tcx
>,
79 span
: Span
) -> Option
<String
> {
80 let def_id
= trait_ref
.def_id
;
81 let mut report
= None
;
82 for item
in ty
::get_attrs(infcx
.tcx
, def_id
).iter() {
83 if item
.check_name("rustc_on_unimplemented") {
84 let err_sp
= if item
.meta().span
== DUMMY_SP
{
89 let def
= ty
::lookup_trait_def(infcx
.tcx
, def_id
);
90 let trait_str
= def
.trait_ref
.to_string();
91 if let Some(ref istring
) = item
.value_str() {
92 let mut generic_map
= def
.generics
.types
.iter_enumerated()
93 .map(|(param
, i
, gen
)| {
94 (gen
.name
.as_str().to_string(),
95 trait_ref
.substs
.types
.get(param
, i
)
97 }).collect
::<HashMap
<String
, String
>>();
98 generic_map
.insert("Self".to_string(),
99 trait_ref
.self_ty().to_string());
100 let parser
= Parser
::new(&istring
);
101 let mut errored
= false;
102 let err
: String
= parser
.filter_map(|p
| {
104 Piece
::String(s
) => Some(s
),
105 Piece
::NextArgument(a
) => match a
.position
{
106 Position
::ArgumentNamed(s
) => match generic_map
.get(s
) {
107 Some(val
) => Some(val
),
109 span_err
!(infcx
.tcx
.sess
, err_sp
, E0272
,
110 "the #[rustc_on_unimplemented] \
112 trait definition for {} refers to \
113 non-existent type parameter {}",
120 span_err
!(infcx
.tcx
.sess
, err_sp
, E0273
,
121 "the #[rustc_on_unimplemented] \
123 trait definition for {} must have named \
125 eg `#[rustc_on_unimplemented = \
134 // Report only if the format string checks out
139 span_err
!(infcx
.tcx
.sess
, err_sp
, E0274
,
140 "the #[rustc_on_unimplemented] attribute on \
141 trait definition for {} must have a value, \
142 eg `#[rustc_on_unimplemented = \"foo\"]`",
151 /// Reports that an overflow has occurred and halts compilation. We
152 /// halt compilation unconditionally because it is important that
153 /// overflows never be masked -- they basically represent computations
154 /// whose result could not be truly determined and thus we can't say
155 /// if the program type checks or not -- and they are unusual
156 /// occurrences in any case.
157 pub fn report_overflow_error
<'a
, 'tcx
, T
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
158 obligation
: &Obligation
<'tcx
, T
>)
160 where T
: fmt
::Display
+ TypeFoldable
<'tcx
>
163 infcx
.resolve_type_vars_if_possible(&obligation
.predicate
);
164 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0275
,
165 "overflow evaluating the requirement `{}`",
168 suggest_new_overflow_limit(infcx
.tcx
, obligation
.cause
.span
);
170 note_obligation_cause(infcx
, obligation
);
172 infcx
.tcx
.sess
.abort_if_errors();
176 pub fn report_selection_error
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
177 obligation
: &PredicateObligation
<'tcx
>,
178 error
: &SelectionError
<'tcx
>)
181 SelectionError
::Unimplemented
=> {
182 match &obligation
.cause
.code
{
183 &ObligationCauseCode
::CompareImplMethodObligation
=> {
184 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0276
,
185 "the requirement `{}` appears on the impl \
186 method but not on the corresponding trait method",
187 obligation
.predicate
);;
190 match obligation
.predicate
{
191 ty
::Predicate
::Trait(ref trait_predicate
) => {
192 let trait_predicate
=
193 infcx
.resolve_type_vars_if_possible(trait_predicate
);
195 if !infcx
.tcx
.sess
.has_errors() ||
196 !trait_predicate
.references_error() {
197 let trait_ref
= trait_predicate
.to_poly_trait_ref();
198 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0277
,
199 "the trait `{}` is not implemented for the type `{}`",
201 trait_ref
.self_ty());
202 // Check if it has a custom "#[rustc_on_unimplemented]"
203 // error message, report with that message if it does
204 let custom_note
= report_on_unimplemented(infcx
, &trait_ref
.0,
205 obligation
.cause
.span
);
206 if let Some(s
) = custom_note
{
207 infcx
.tcx
.sess
.span_note(obligation
.cause
.span
,
213 ty
::Predicate
::Equate(ref predicate
) => {
214 let predicate
= infcx
.resolve_type_vars_if_possible(predicate
);
215 let err
= infcx
.equality_predicate(obligation
.cause
.span
,
216 &predicate
).err().unwrap();
217 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0278
,
218 "the requirement `{}` is not satisfied (`{}`)",
223 ty
::Predicate
::RegionOutlives(ref predicate
) => {
224 let predicate
= infcx
.resolve_type_vars_if_possible(predicate
);
225 let err
= infcx
.region_outlives_predicate(obligation
.cause
.span
,
226 &predicate
).err().unwrap();
227 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0279
,
228 "the requirement `{}` is not satisfied (`{}`)",
233 ty
::Predicate
::Projection(..) | ty
::Predicate
::TypeOutlives(..) => {
235 infcx
.resolve_type_vars_if_possible(&obligation
.predicate
);
236 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0280
,
237 "the requirement `{}` is not satisfied",
245 OutputTypeParameterMismatch(ref expected_trait_ref
, ref actual_trait_ref
, ref e
) => {
246 let expected_trait_ref
= infcx
.resolve_type_vars_if_possible(&*expected_trait_ref
);
247 let actual_trait_ref
= infcx
.resolve_type_vars_if_possible(&*actual_trait_ref
);
248 if !ty
::type_is_error(actual_trait_ref
.self_ty()) {
249 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0281
,
250 "type mismatch: the type `{}` implements the trait `{}`, \
251 but the trait `{}` is required ({})",
252 expected_trait_ref
.self_ty(),
256 note_obligation_cause(infcx
, obligation
);
260 TraitNotObjectSafe(did
) => {
261 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0038
,
262 "cannot convert to a trait object because trait `{}` is not object-safe",
263 ty
::item_path_str(infcx
.tcx
, did
));
265 for violation
in object_safety_violations(infcx
.tcx
, did
) {
267 ObjectSafetyViolation
::SizedSelf
=> {
268 infcx
.tcx
.sess
.span_note(
269 obligation
.cause
.span
,
270 "the trait cannot require that `Self : Sized`");
273 ObjectSafetyViolation
::SupertraitSelf
=> {
274 infcx
.tcx
.sess
.span_note(
275 obligation
.cause
.span
,
276 "the trait cannot use `Self` as a type parameter \
277 in the supertrait listing");
280 ObjectSafetyViolation
::Method(method
,
281 MethodViolationCode
::StaticMethod
) => {
282 infcx
.tcx
.sess
.span_note(
283 obligation
.cause
.span
,
284 &format
!("method `{}` has no receiver",
288 ObjectSafetyViolation
::Method(method
,
289 MethodViolationCode
::ReferencesSelf
) => {
290 infcx
.tcx
.sess
.span_note(
291 obligation
.cause
.span
,
292 &format
!("method `{}` references the `Self` type \
293 in its arguments or return type",
297 ObjectSafetyViolation
::Method(method
,
298 MethodViolationCode
::Generic
) => {
299 infcx
.tcx
.sess
.span_note(
300 obligation
.cause
.span
,
301 &format
!("method `{}` has generic type parameters",
310 pub fn maybe_report_ambiguity
<'a
, 'tcx
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
311 obligation
: &PredicateObligation
<'tcx
>) {
312 // Unable to successfully determine, probably means
313 // insufficient type information, but could mean
314 // ambiguous impls. The latter *ought* to be a
315 // coherence violation, so we don't report it here.
317 let predicate
= infcx
.resolve_type_vars_if_possible(&obligation
.predicate
);
319 debug
!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
324 ty
::Predicate
::Trait(ref data
) => {
325 let trait_ref
= data
.to_poly_trait_ref();
326 let self_ty
= trait_ref
.self_ty();
327 let all_types
= &trait_ref
.substs().types
;
328 if all_types
.iter().any(|&t
| ty
::type_is_error(t
)) {
329 } else if all_types
.iter().any(|&t
| ty
::type_needs_infer(t
)) {
330 // This is kind of a hack: it frequently happens that some earlier
331 // error prevents types from being fully inferred, and then we get
332 // a bunch of uninteresting errors saying something like "<generic
333 // #0> doesn't implement Sized". It may even be true that we
334 // could just skip over all checks where the self-ty is an
335 // inference variable, but I was afraid that there might be an
336 // inference variable created, registered as an obligation, and
337 // then never forced by writeback, and hence by skipping here we'd
338 // be ignoring the fact that we don't KNOW the type works
339 // out. Though even that would probably be harmless, given that
340 // we're only talking about builtin traits, which are known to be
341 // inhabited. But in any case I just threw in this check for
342 // has_errors() to be sure that compilation isn't happening
343 // anyway. In that case, why inundate the user.
344 if !infcx
.tcx
.sess
.has_errors() {
346 infcx
.tcx
.lang_items
.sized_trait()
347 .map_or(false, |sized_id
| sized_id
== trait_ref
.def_id())
349 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0282
,
350 "unable to infer enough type information about `{}`; \
351 type annotations or generic parameter binding required",
354 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0283
,
355 "type annotations required: cannot resolve `{}`",
357 note_obligation_cause(infcx
, obligation
);
360 } else if !infcx
.tcx
.sess
.has_errors() {
361 // Ambiguity. Coherence should have reported an error.
362 infcx
.tcx
.sess
.span_bug(
363 obligation
.cause
.span
,
365 "coherence failed to report ambiguity: \
366 cannot locate the impl of the trait `{}` for \
374 if !infcx
.tcx
.sess
.has_errors() {
375 span_err
!(infcx
.tcx
.sess
, obligation
.cause
.span
, E0284
,
376 "type annotations required: cannot resolve `{}`",
378 note_obligation_cause(infcx
, obligation
);
384 fn note_obligation_cause
<'a
, 'tcx
, T
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
385 obligation
: &Obligation
<'tcx
, T
>)
386 where T
: fmt
::Display
388 note_obligation_cause_code(infcx
,
389 &obligation
.predicate
,
390 obligation
.cause
.span
,
391 &obligation
.cause
.code
);
394 fn note_obligation_cause_code
<'a
, 'tcx
, T
>(infcx
: &InferCtxt
<'a
, 'tcx
>,
397 cause_code
: &ObligationCauseCode
<'tcx
>)
398 where T
: fmt
::Display
402 ObligationCauseCode
::MiscObligation
=> { }
403 ObligationCauseCode
::ItemObligation(item_def_id
) => {
404 let item_name
= ty
::item_path_str(tcx
, item_def_id
);
407 &format
!("required by `{}`", item_name
));
409 ObligationCauseCode
::ObjectCastObligation(object_ty
) => {
413 "required for the cast to the object type `{}`",
414 infcx
.ty_to_string(object_ty
)));
416 ObligationCauseCode
::RepeatVec
=> {
419 "the `Copy` trait is required because the \
420 repeated element will be copied");
422 ObligationCauseCode
::VariableType(_
) => {
425 "all local variables must have a statically known size");
427 ObligationCauseCode
::ReturnType
=> {
430 "the return type of a function must have a \
431 statically known size");
433 ObligationCauseCode
::AssignmentLhsSized
=> {
436 "the left-hand-side of an assignment must have a statically known size");
438 ObligationCauseCode
::StructInitializerSized
=> {
441 "structs must have a statically known size to be initialized");
443 ObligationCauseCode
::ClosureCapture(var_id
, closure_span
, builtin_bound
) => {
444 let def_id
= tcx
.lang_items
.from_builtin_kind(builtin_bound
).unwrap();
445 let trait_name
= ty
::item_path_str(tcx
, def_id
);
446 let name
= ty
::local_var_name_str(tcx
, var_id
);
447 span_note
!(tcx
.sess
, closure_span
,
448 "the closure that captures `{}` requires that all captured variables \
449 implement the trait `{}`",
453 ObligationCauseCode
::FieldSized
=> {
454 span_note
!(tcx
.sess
, cause_span
,
455 "only the last field of a struct or enum variant \
456 may have a dynamically sized type")
458 ObligationCauseCode
::SharedStatic
=> {
459 span_note
!(tcx
.sess
, cause_span
,
460 "shared static variables must have a type that implements `Sync`");
462 ObligationCauseCode
::BuiltinDerivedObligation(ref data
) => {
463 let parent_trait_ref
= infcx
.resolve_type_vars_if_possible(&data
.parent_trait_ref
);
464 span_note
!(tcx
.sess
, cause_span
,
465 "required because it appears within the type `{}`",
466 parent_trait_ref
.0.self_ty());
467 let parent_predicate
= parent_trait_ref
.as_predicate();
468 note_obligation_cause_code(infcx
, &parent_predicate
, cause_span
, &*data
.parent_code
);
470 ObligationCauseCode
::ImplDerivedObligation(ref data
) => {
471 let parent_trait_ref
= infcx
.resolve_type_vars_if_possible(&data
.parent_trait_ref
);
472 span_note
!(tcx
.sess
, cause_span
,
473 "required because of the requirements on the impl of `{}` for `{}`",
475 parent_trait_ref
.0.self_ty());
476 let parent_predicate
= parent_trait_ref
.as_predicate();
477 note_obligation_cause_code(infcx
, &parent_predicate
, cause_span
, &*data
.parent_code
);
479 ObligationCauseCode
::CompareImplMethodObligation
=> {
480 span_note
!(tcx
.sess
, cause_span
,
481 "the requirement `{}` appears on the impl method \
482 but not on the corresponding trait method",
488 pub fn suggest_new_overflow_limit(tcx
: &ty
::ctxt
, span
: Span
) {
489 let current_limit
= tcx
.sess
.recursion_limit
.get();
490 let suggested_limit
= current_limit
* 2;
494 "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",