]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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, | |
c34b1796 | 15 | Obligation, |
1a4d82fc JJ |
16 | ObligationCauseCode, |
17 | OutputTypeParameterMismatch, | |
d9579d0f | 18 | TraitNotObjectSafe, |
1a4d82fc JJ |
19 | PredicateObligation, |
20 | SelectionError, | |
d9579d0f AL |
21 | ObjectSafetyViolation, |
22 | MethodViolationCode, | |
23 | object_safety_violations, | |
1a4d82fc JJ |
24 | }; |
25 | ||
85aaf69f | 26 | use fmt_macros::{Parser, Piece, Position}; |
e9174d1e | 27 | use middle::def_id::DefId; |
1a4d82fc | 28 | use middle::infer::InferCtxt; |
9cc50fc6 SL |
29 | use middle::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, Ty, TypeFoldable}; |
30 | use middle::ty::fast_reject; | |
e9174d1e SL |
31 | use util::nodemap::{FnvHashMap, FnvHashSet}; |
32 | ||
9cc50fc6 | 33 | use std::cmp; |
62682a34 | 34 | use std::fmt; |
b039eaaf | 35 | use syntax::attr::{AttributeMethods, AttrMetaMethods}; |
9cc50fc6 SL |
36 | use syntax::codemap::Span; |
37 | use syntax::errors::DiagnosticBuilder; | |
e9174d1e SL |
38 | |
39 | #[derive(Debug, PartialEq, Eq, Hash)] | |
40 | pub struct TraitErrorKey<'tcx> { | |
e9174d1e SL |
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 { | |
e9174d1e SL |
51 | span: e.obligation.cause.span, |
52 | predicate: infcx.tcx.erase_regions(&predicate) | |
53 | } | |
54 | } | |
55 | } | |
1a4d82fc JJ |
56 | |
57 | pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, | |
58 | errors: &Vec<FulfillmentError<'tcx>>) { | |
85aaf69f | 59 | for error in errors { |
1a4d82fc JJ |
60 | report_fulfillment_error(infcx, error); |
61 | } | |
62 | } | |
63 | ||
64 | fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, | |
65 | error: &FulfillmentError<'tcx>) { | |
e9174d1e SL |
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 | } | |
1a4d82fc JJ |
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); | |
e9174d1e | 92 | |
62682a34 | 93 | // The TyError created by normalize_to_error can end up being unified |
d9579d0f AL |
94 | // into all obligations: for example, if our obligation is something |
95 | // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>, | |
62682a34 | 96 | // then $X will be unified with TyError, but the error still needs to be |
d9579d0f AL |
97 | // reported. |
98 | if !infcx.tcx.sess.has_errors() || !predicate.references_error() { | |
9cc50fc6 | 99 | let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271, |
e9174d1e SL |
100 | "type mismatch resolving `{}`: {}", |
101 | predicate, | |
102 | error.err); | |
9cc50fc6 SL |
103 | note_obligation_cause(infcx, &mut err, obligation); |
104 | err.emit(); | |
1a4d82fc JJ |
105 | } |
106 | } | |
107 | ||
85aaf69f SL |
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; | |
c1a9b12d | 113 | for item in infcx.tcx.get_attrs(def_id).iter() { |
85aaf69f | 114 | if item.check_name("rustc_on_unimplemented") { |
e9174d1e | 115 | let err_sp = item.meta().span.substitute_dummy(span); |
c1a9b12d | 116 | let def = infcx.tcx.lookup_trait_def(def_id); |
62682a34 | 117 | let trait_str = def.trait_ref.to_string(); |
85aaf69f SL |
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) | |
62682a34 | 123 | .to_string()) |
e9174d1e | 124 | }).collect::<FnvHashMap<String, String>>(); |
85aaf69f | 125 | generic_map.insert("Self".to_string(), |
62682a34 | 126 | trait_ref.self_ty().to_string()); |
85aaf69f SL |
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 | ||
c34b1796 AL |
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 | -> ! | |
9cc50fc6 | 187 | where T: fmt::Display + TypeFoldable<'tcx> |
c34b1796 AL |
188 | { |
189 | let predicate = | |
190 | infcx.resolve_type_vars_if_possible(&obligation.predicate); | |
9cc50fc6 SL |
191 | let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0275, |
192 | "overflow evaluating the requirement `{}`", | |
193 | predicate); | |
c34b1796 | 194 | |
9cc50fc6 | 195 | suggest_new_overflow_limit(infcx.tcx, &mut err, obligation.cause.span); |
c34b1796 | 196 | |
9cc50fc6 | 197 | note_obligation_cause(infcx, &mut err, obligation); |
c34b1796 | 198 | |
9cc50fc6 | 199 | err.emit(); |
c34b1796 AL |
200 | infcx.tcx.sess.abort_if_errors(); |
201 | unreachable!(); | |
202 | } | |
203 | ||
1a4d82fc JJ |
204 | pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, |
205 | obligation: &PredicateObligation<'tcx>, | |
206 | error: &SelectionError<'tcx>) | |
207 | { | |
208 | match *error { | |
1a4d82fc | 209 | SelectionError::Unimplemented => { |
e9174d1e | 210 | if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code { |
9cc50fc6 SL |
211 | span_err!( |
212 | infcx.tcx.sess, obligation.cause.span, E0276, | |
e9174d1e SL |
213 | "the requirement `{}` appears on the impl \ |
214 | method but not on the corresponding trait method", | |
b039eaaf | 215 | obligation.predicate); |
e9174d1e SL |
216 | } else { |
217 | match obligation.predicate { | |
218 | ty::Predicate::Trait(ref trait_predicate) => { | |
219 | let trait_predicate = | |
220 | infcx.resolve_type_vars_if_possible(trait_predicate); | |
221 | ||
222 | if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() { | |
223 | let trait_ref = trait_predicate.to_poly_trait_ref(); | |
9cc50fc6 SL |
224 | let mut err = struct_span_err!( |
225 | infcx.tcx.sess, obligation.cause.span, E0277, | |
e9174d1e SL |
226 | "the trait `{}` is not implemented for the type `{}`", |
227 | trait_ref, trait_ref.self_ty()); | |
228 | ||
229 | // Check if it has a custom "#[rustc_on_unimplemented]" | |
230 | // error message, report with that message if it does | |
231 | let custom_note = report_on_unimplemented(infcx, &trait_ref.0, | |
232 | obligation.cause.span); | |
233 | if let Some(s) = custom_note { | |
9cc50fc6 SL |
234 | err.fileline_note(obligation.cause.span, &s); |
235 | } else { | |
236 | let simp = fast_reject::simplify_type(infcx.tcx, | |
237 | trait_ref.self_ty(), | |
238 | true); | |
239 | let mut impl_candidates = Vec::new(); | |
240 | let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id()); | |
241 | ||
242 | match simp { | |
243 | Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| { | |
244 | let imp = infcx.tcx.impl_trait_ref(def_id).unwrap(); | |
245 | let imp_simp = fast_reject::simplify_type(infcx.tcx, | |
246 | imp.self_ty(), | |
247 | true); | |
248 | if let Some(imp_simp) = imp_simp { | |
249 | if simp != imp_simp { | |
250 | return; | |
251 | } | |
252 | } | |
253 | impl_candidates.push(imp); | |
254 | }), | |
255 | None => trait_def.for_each_impl(infcx.tcx, |def_id| { | |
256 | impl_candidates.push( | |
257 | infcx.tcx.impl_trait_ref(def_id).unwrap()); | |
258 | }) | |
259 | }; | |
260 | ||
261 | if impl_candidates.len() > 0 { | |
262 | err.fileline_help( | |
263 | obligation.cause.span, | |
264 | &format!("the following implementations were found:")); | |
265 | ||
266 | let end = cmp::min(4, impl_candidates.len()); | |
267 | for candidate in &impl_candidates[0..end] { | |
268 | err.fileline_help(obligation.cause.span, | |
269 | &format!(" {:?}", candidate)); | |
270 | } | |
271 | if impl_candidates.len() > 4 { | |
272 | err.fileline_help(obligation.cause.span, | |
273 | &format!("and {} others", | |
274 | impl_candidates.len()-4)); | |
275 | } | |
276 | } | |
85aaf69f | 277 | } |
9cc50fc6 SL |
278 | note_obligation_cause(infcx, &mut err, obligation); |
279 | err.emit(); | |
85aaf69f | 280 | } |
9cc50fc6 | 281 | }, |
e9174d1e SL |
282 | ty::Predicate::Equate(ref predicate) => { |
283 | let predicate = infcx.resolve_type_vars_if_possible(predicate); | |
284 | let err = infcx.equality_predicate(obligation.cause.span, | |
285 | &predicate).err().unwrap(); | |
9cc50fc6 SL |
286 | let mut err = struct_span_err!( |
287 | infcx.tcx.sess, obligation.cause.span, E0278, | |
e9174d1e SL |
288 | "the requirement `{}` is not satisfied (`{}`)", |
289 | predicate, | |
290 | err); | |
9cc50fc6 SL |
291 | note_obligation_cause(infcx, &mut err, obligation); |
292 | err.emit(); | |
e9174d1e | 293 | } |
85aaf69f | 294 | |
e9174d1e SL |
295 | ty::Predicate::RegionOutlives(ref predicate) => { |
296 | let predicate = infcx.resolve_type_vars_if_possible(predicate); | |
297 | let err = infcx.region_outlives_predicate(obligation.cause.span, | |
298 | &predicate).err().unwrap(); | |
9cc50fc6 SL |
299 | let mut err = struct_span_err!( |
300 | infcx.tcx.sess, obligation.cause.span, E0279, | |
e9174d1e SL |
301 | "the requirement `{}` is not satisfied (`{}`)", |
302 | predicate, | |
303 | err); | |
9cc50fc6 SL |
304 | note_obligation_cause(infcx, &mut err, obligation); |
305 | err.emit(); | |
e9174d1e | 306 | } |
1a4d82fc | 307 | |
e9174d1e SL |
308 | ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { |
309 | let predicate = | |
310 | infcx.resolve_type_vars_if_possible(&obligation.predicate); | |
9cc50fc6 SL |
311 | let mut err = struct_span_err!( |
312 | infcx.tcx.sess, obligation.cause.span, E0280, | |
e9174d1e SL |
313 | "the requirement `{}` is not satisfied", |
314 | predicate); | |
9cc50fc6 SL |
315 | note_obligation_cause(infcx, &mut err, obligation); |
316 | err.emit(); | |
e9174d1e SL |
317 | } |
318 | ||
319 | ty::Predicate::ObjectSafe(trait_def_id) => { | |
b039eaaf SL |
320 | let violations = object_safety_violations( |
321 | infcx.tcx, trait_def_id); | |
9cc50fc6 SL |
322 | let mut err = report_object_safety_error(infcx.tcx, |
323 | obligation.cause.span, | |
324 | trait_def_id, | |
325 | violations); | |
326 | note_obligation_cause(infcx, &mut err, obligation); | |
327 | err.emit(); | |
e9174d1e SL |
328 | } |
329 | ||
330 | ty::Predicate::WellFormed(ty) => { | |
331 | // WF predicates cannot themselves make | |
332 | // errors. They can only block due to | |
333 | // ambiguity; otherwise, they always | |
334 | // degenerate into other obligations | |
335 | // (which may fail). | |
336 | infcx.tcx.sess.span_bug( | |
337 | obligation.cause.span, | |
338 | &format!("WF predicate not satisfied for {:?}", ty)); | |
85aaf69f | 339 | } |
1a4d82fc JJ |
340 | } |
341 | } | |
342 | } | |
85aaf69f | 343 | |
1a4d82fc JJ |
344 | OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => { |
345 | let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref); | |
346 | let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref); | |
c1a9b12d | 347 | if !actual_trait_ref.self_ty().references_error() { |
9cc50fc6 SL |
348 | let mut err = struct_span_err!( |
349 | infcx.tcx.sess, obligation.cause.span, E0281, | |
e9174d1e SL |
350 | "type mismatch: the type `{}` implements the trait `{}`, \ |
351 | but the trait `{}` is required ({})", | |
352 | expected_trait_ref.self_ty(), | |
353 | expected_trait_ref, | |
354 | actual_trait_ref, | |
355 | e); | |
9cc50fc6 SL |
356 | note_obligation_cause(infcx, &mut err, obligation); |
357 | err.emit(); | |
1a4d82fc JJ |
358 | } |
359 | } | |
d9579d0f AL |
360 | |
361 | TraitNotObjectSafe(did) => { | |
b039eaaf | 362 | let violations = object_safety_violations(infcx.tcx, did); |
9cc50fc6 SL |
363 | let mut err = report_object_safety_error(infcx.tcx, obligation.cause.span, did, |
364 | violations); | |
365 | note_obligation_cause(infcx, &mut err, obligation); | |
366 | err.emit(); | |
e9174d1e SL |
367 | } |
368 | } | |
369 | } | |
d9579d0f | 370 | |
e9174d1e SL |
371 | pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>, |
372 | span: Span, | |
373 | trait_def_id: DefId, | |
9cc50fc6 SL |
374 | violations: Vec<ObjectSafetyViolation>) |
375 | -> DiagnosticBuilder<'tcx> | |
e9174d1e | 376 | { |
9cc50fc6 SL |
377 | let mut err = struct_span_err!( |
378 | tcx.sess, span, E0038, | |
e9174d1e SL |
379 | "the trait `{}` cannot be made into an object", |
380 | tcx.item_path_str(trait_def_id)); | |
d9579d0f | 381 | |
e9174d1e | 382 | let mut reported_violations = FnvHashSet(); |
b039eaaf | 383 | for violation in violations { |
e9174d1e SL |
384 | if !reported_violations.insert(violation.clone()) { |
385 | continue; | |
386 | } | |
387 | match violation { | |
388 | ObjectSafetyViolation::SizedSelf => { | |
9cc50fc6 | 389 | err.fileline_note( |
e9174d1e SL |
390 | span, |
391 | "the trait cannot require that `Self : Sized`"); | |
392 | } | |
d9579d0f | 393 | |
e9174d1e | 394 | ObjectSafetyViolation::SupertraitSelf => { |
9cc50fc6 | 395 | err.fileline_note( |
e9174d1e SL |
396 | span, |
397 | "the trait cannot use `Self` as a type parameter \ | |
398 | in the supertrait listing"); | |
399 | } | |
d9579d0f | 400 | |
e9174d1e SL |
401 | ObjectSafetyViolation::Method(method, |
402 | MethodViolationCode::StaticMethod) => { | |
9cc50fc6 | 403 | err.fileline_note( |
e9174d1e SL |
404 | span, |
405 | &format!("method `{}` has no receiver", | |
406 | method.name)); | |
407 | } | |
408 | ||
409 | ObjectSafetyViolation::Method(method, | |
410 | MethodViolationCode::ReferencesSelf) => { | |
9cc50fc6 | 411 | err.fileline_note( |
e9174d1e SL |
412 | span, |
413 | &format!("method `{}` references the `Self` type \ | |
414 | in its arguments or return type", | |
415 | method.name)); | |
416 | } | |
417 | ||
418 | ObjectSafetyViolation::Method(method, | |
419 | MethodViolationCode::Generic) => { | |
9cc50fc6 | 420 | err.fileline_note( |
e9174d1e SL |
421 | span, |
422 | &format!("method `{}` has generic type parameters", | |
423 | method.name)); | |
d9579d0f AL |
424 | } |
425 | } | |
1a4d82fc | 426 | } |
9cc50fc6 | 427 | err |
1a4d82fc JJ |
428 | } |
429 | ||
430 | pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, | |
431 | obligation: &PredicateObligation<'tcx>) { | |
432 | // Unable to successfully determine, probably means | |
433 | // insufficient type information, but could mean | |
434 | // ambiguous impls. The latter *ought* to be a | |
435 | // coherence violation, so we don't report it here. | |
436 | ||
437 | let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate); | |
438 | ||
62682a34 SL |
439 | debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", |
440 | predicate, | |
441 | obligation); | |
1a4d82fc JJ |
442 | |
443 | match predicate { | |
444 | ty::Predicate::Trait(ref data) => { | |
445 | let trait_ref = data.to_poly_trait_ref(); | |
446 | let self_ty = trait_ref.self_ty(); | |
447 | let all_types = &trait_ref.substs().types; | |
c1a9b12d | 448 | if all_types.references_error() { |
9cc50fc6 SL |
449 | } else { |
450 | // Typically, this ambiguity should only happen if | |
451 | // there are unresolved type inference variables | |
452 | // (otherwise it would suggest a coherence | |
453 | // failure). But given #21974 that is not necessarily | |
454 | // the case -- we can have multiple where clauses that | |
455 | // are only distinguished by a region, which results | |
456 | // in an ambiguity even when all types are fully | |
457 | // known, since we don't dispatch based on region | |
458 | // relationships. | |
459 | ||
1a4d82fc JJ |
460 | // This is kind of a hack: it frequently happens that some earlier |
461 | // error prevents types from being fully inferred, and then we get | |
462 | // a bunch of uninteresting errors saying something like "<generic | |
463 | // #0> doesn't implement Sized". It may even be true that we | |
464 | // could just skip over all checks where the self-ty is an | |
465 | // inference variable, but I was afraid that there might be an | |
466 | // inference variable created, registered as an obligation, and | |
467 | // then never forced by writeback, and hence by skipping here we'd | |
468 | // be ignoring the fact that we don't KNOW the type works | |
469 | // out. Though even that would probably be harmless, given that | |
470 | // we're only talking about builtin traits, which are known to be | |
471 | // inhabited. But in any case I just threw in this check for | |
472 | // has_errors() to be sure that compilation isn't happening | |
473 | // anyway. In that case, why inundate the user. | |
474 | if !infcx.tcx.sess.has_errors() { | |
475 | if | |
476 | infcx.tcx.lang_items.sized_trait() | |
477 | .map_or(false, |sized_id| sized_id == trait_ref.def_id()) | |
478 | { | |
e9174d1e | 479 | need_type_info(infcx, obligation.cause.span, self_ty); |
1a4d82fc | 480 | } else { |
9cc50fc6 SL |
481 | let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0283, |
482 | "type annotations required: \ | |
483 | cannot resolve `{}`", | |
484 | predicate); | |
485 | note_obligation_cause(infcx, &mut err, obligation); | |
486 | err.emit(); | |
1a4d82fc JJ |
487 | } |
488 | } | |
1a4d82fc JJ |
489 | } |
490 | } | |
491 | ||
e9174d1e SL |
492 | ty::Predicate::WellFormed(ty) => { |
493 | // Same hacky approach as above to avoid deluging user | |
494 | // with error messages. | |
495 | if !ty.references_error() && !infcx.tcx.sess.has_errors() { | |
496 | need_type_info(infcx, obligation.cause.span, ty); | |
497 | } | |
498 | } | |
499 | ||
1a4d82fc JJ |
500 | _ => { |
501 | if !infcx.tcx.sess.has_errors() { | |
9cc50fc6 SL |
502 | let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0284, |
503 | "type annotations required: cannot resolve `{}`", | |
504 | predicate); | |
505 | note_obligation_cause(infcx, &mut err, obligation); | |
506 | err.emit(); | |
1a4d82fc JJ |
507 | } |
508 | } | |
509 | } | |
510 | } | |
511 | ||
e9174d1e SL |
512 | fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, |
513 | span: Span, | |
514 | ty: Ty<'tcx>) | |
515 | { | |
516 | span_err!(infcx.tcx.sess, span, E0282, | |
517 | "unable to infer enough type information about `{}`; \ | |
518 | type annotations or generic parameter binding required", | |
519 | ty); | |
520 | } | |
521 | ||
c34b1796 | 522 | fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, |
9cc50fc6 | 523 | err: &mut DiagnosticBuilder, |
c34b1796 | 524 | obligation: &Obligation<'tcx, T>) |
62682a34 | 525 | where T: fmt::Display |
1a4d82fc JJ |
526 | { |
527 | note_obligation_cause_code(infcx, | |
9cc50fc6 | 528 | err, |
1a4d82fc JJ |
529 | &obligation.predicate, |
530 | obligation.cause.span, | |
531 | &obligation.cause.code); | |
532 | } | |
533 | ||
c34b1796 | 534 | fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, |
9cc50fc6 | 535 | err: &mut DiagnosticBuilder, |
c34b1796 AL |
536 | predicate: &T, |
537 | cause_span: Span, | |
538 | cause_code: &ObligationCauseCode<'tcx>) | |
62682a34 | 539 | where T: fmt::Display |
1a4d82fc JJ |
540 | { |
541 | let tcx = infcx.tcx; | |
542 | match *cause_code { | |
543 | ObligationCauseCode::MiscObligation => { } | |
e9174d1e | 544 | ObligationCauseCode::SliceOrArrayElem => { |
9cc50fc6 | 545 | err.fileline_note( |
e9174d1e | 546 | cause_span, |
92a42be0 | 547 | "slice and array elements must have `Sized` type"); |
e9174d1e SL |
548 | } |
549 | ObligationCauseCode::ProjectionWf(data) => { | |
9cc50fc6 | 550 | err.fileline_note( |
e9174d1e SL |
551 | cause_span, |
552 | &format!("required so that the projection `{}` is well-formed", | |
553 | data)); | |
554 | } | |
555 | ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { | |
9cc50fc6 | 556 | err.fileline_note( |
e9174d1e SL |
557 | cause_span, |
558 | &format!("required so that reference `{}` does not outlive its referent", | |
559 | ref_ty)); | |
560 | } | |
1a4d82fc | 561 | ObligationCauseCode::ItemObligation(item_def_id) => { |
c1a9b12d | 562 | let item_name = tcx.item_path_str(item_def_id); |
9cc50fc6 | 563 | err.fileline_note( |
1a4d82fc | 564 | cause_span, |
85aaf69f | 565 | &format!("required by `{}`", item_name)); |
1a4d82fc JJ |
566 | } |
567 | ObligationCauseCode::ObjectCastObligation(object_ty) => { | |
9cc50fc6 | 568 | err.fileline_note( |
1a4d82fc | 569 | cause_span, |
85aaf69f | 570 | &format!( |
1a4d82fc | 571 | "required for the cast to the object type `{}`", |
85aaf69f | 572 | infcx.ty_to_string(object_ty))); |
1a4d82fc JJ |
573 | } |
574 | ObligationCauseCode::RepeatVec => { | |
9cc50fc6 | 575 | err.fileline_note( |
1a4d82fc JJ |
576 | cause_span, |
577 | "the `Copy` trait is required because the \ | |
578 | repeated element will be copied"); | |
579 | } | |
580 | ObligationCauseCode::VariableType(_) => { | |
9cc50fc6 | 581 | err.fileline_note( |
1a4d82fc JJ |
582 | cause_span, |
583 | "all local variables must have a statically known size"); | |
584 | } | |
585 | ObligationCauseCode::ReturnType => { | |
9cc50fc6 | 586 | err.fileline_note( |
1a4d82fc JJ |
587 | cause_span, |
588 | "the return type of a function must have a \ | |
589 | statically known size"); | |
590 | } | |
591 | ObligationCauseCode::AssignmentLhsSized => { | |
9cc50fc6 | 592 | err.fileline_note( |
1a4d82fc JJ |
593 | cause_span, |
594 | "the left-hand-side of an assignment must have a statically known size"); | |
595 | } | |
596 | ObligationCauseCode::StructInitializerSized => { | |
9cc50fc6 | 597 | err.fileline_note( |
1a4d82fc JJ |
598 | cause_span, |
599 | "structs must have a statically known size to be initialized"); | |
600 | } | |
e9174d1e | 601 | ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => { |
1a4d82fc | 602 | let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap(); |
c1a9b12d SL |
603 | let trait_name = tcx.item_path_str(def_id); |
604 | let name = tcx.local_var_name_str(var_id); | |
9cc50fc6 | 605 | err.fileline_note( |
e9174d1e SL |
606 | cause_span, |
607 | &format!("the closure that captures `{}` requires that all captured variables \ | |
608 | implement the trait `{}`", | |
609 | name, | |
610 | trait_name)); | |
1a4d82fc JJ |
611 | } |
612 | ObligationCauseCode::FieldSized => { | |
9cc50fc6 | 613 | err.fileline_note( |
e9174d1e SL |
614 | cause_span, |
615 | "only the last field of a struct or enum variant \ | |
616 | may have a dynamically sized type"); | |
1a4d82fc | 617 | } |
1a4d82fc | 618 | ObligationCauseCode::SharedStatic => { |
9cc50fc6 | 619 | err.fileline_note( |
e9174d1e SL |
620 | cause_span, |
621 | "shared static variables must have a type that implements `Sync`"); | |
1a4d82fc JJ |
622 | } |
623 | ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
624 | let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
9cc50fc6 | 625 | err.fileline_note( |
e9174d1e SL |
626 | cause_span, |
627 | &format!("required because it appears within the type `{}`", | |
628 | parent_trait_ref.0.self_ty())); | |
c1a9b12d | 629 | let parent_predicate = parent_trait_ref.to_predicate(); |
9cc50fc6 SL |
630 | note_obligation_cause_code(infcx, |
631 | err, | |
632 | &parent_predicate, | |
633 | cause_span, | |
634 | &*data.parent_code); | |
1a4d82fc JJ |
635 | } |
636 | ObligationCauseCode::ImplDerivedObligation(ref data) => { | |
637 | let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
9cc50fc6 | 638 | err.fileline_note( |
e9174d1e SL |
639 | cause_span, |
640 | &format!("required because of the requirements on the impl of `{}` for `{}`", | |
641 | parent_trait_ref, | |
642 | parent_trait_ref.0.self_ty())); | |
c1a9b12d | 643 | let parent_predicate = parent_trait_ref.to_predicate(); |
9cc50fc6 SL |
644 | note_obligation_cause_code(infcx, |
645 | err, | |
646 | &parent_predicate, | |
647 | cause_span, | |
648 | &*data.parent_code); | |
1a4d82fc | 649 | } |
85aaf69f | 650 | ObligationCauseCode::CompareImplMethodObligation => { |
9cc50fc6 | 651 | err.fileline_note( |
e9174d1e SL |
652 | cause_span, |
653 | &format!("the requirement `{}` appears on the impl method \ | |
654 | but not on the corresponding trait method", | |
655 | predicate)); | |
85aaf69f | 656 | } |
1a4d82fc JJ |
657 | } |
658 | } | |
659 | ||
9cc50fc6 | 660 | fn suggest_new_overflow_limit(tcx: &ty::ctxt, err:&mut DiagnosticBuilder, span: Span) { |
1a4d82fc JJ |
661 | let current_limit = tcx.sess.recursion_limit.get(); |
662 | let suggested_limit = current_limit * 2; | |
9cc50fc6 | 663 | err.fileline_note( |
1a4d82fc JJ |
664 | span, |
665 | &format!( | |
666 | "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", | |
c34b1796 | 667 | suggested_limit)); |
1a4d82fc | 668 | } |