]>
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, |
54a0048b | 16 | ObligationCause, |
1a4d82fc JJ |
17 | ObligationCauseCode, |
18 | OutputTypeParameterMismatch, | |
d9579d0f | 19 | TraitNotObjectSafe, |
1a4d82fc | 20 | PredicateObligation, |
54a0048b | 21 | SelectionContext, |
1a4d82fc | 22 | SelectionError, |
d9579d0f AL |
23 | ObjectSafetyViolation, |
24 | MethodViolationCode, | |
1a4d82fc JJ |
25 | }; |
26 | ||
85aaf69f | 27 | use fmt_macros::{Parser, Piece, Position}; |
54a0048b | 28 | use hir::def_id::DefId; |
5bcae85e | 29 | use infer::{self, InferCtxt, TypeOrigin}; |
9e0c209e | 30 | use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; |
5bcae85e | 31 | use ty::error::ExpectedFound; |
54a0048b | 32 | use ty::fast_reject; |
a7813a04 | 33 | use ty::fold::TypeFolder; |
9e0c209e | 34 | use ty::subst::Subst; |
e9174d1e SL |
35 | use util::nodemap::{FnvHashMap, FnvHashSet}; |
36 | ||
9cc50fc6 | 37 | use std::cmp; |
62682a34 | 38 | use std::fmt; |
3157f602 XL |
39 | use syntax_pos::Span; |
40 | use errors::DiagnosticBuilder; | |
e9174d1e SL |
41 | |
42 | #[derive(Debug, PartialEq, Eq, Hash)] | |
43 | pub struct TraitErrorKey<'tcx> { | |
e9174d1e SL |
44 | span: Span, |
45 | predicate: ty::Predicate<'tcx> | |
46 | } | |
47 | ||
a7813a04 XL |
48 | impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> { |
49 | fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
9e0c209e | 50 | e: &FulfillmentError<'tcx>) -> Self { |
e9174d1e SL |
51 | let predicate = |
52 | infcx.resolve_type_vars_if_possible(&e.obligation.predicate); | |
53 | TraitErrorKey { | |
e9174d1e | 54 | span: e.obligation.cause.span, |
9e0c209e | 55 | predicate: infcx.tcx.erase_regions(&predicate) |
e9174d1e SL |
56 | } |
57 | } | |
58 | } | |
1a4d82fc | 59 | |
a7813a04 XL |
60 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
61 | pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) { | |
62 | for error in errors { | |
9e0c209e | 63 | self.report_fulfillment_error(error); |
a7813a04 | 64 | } |
e9174d1e | 65 | } |
a7813a04 XL |
66 | |
67 | fn report_fulfillment_error(&self, | |
9e0c209e SL |
68 | error: &FulfillmentError<'tcx>) { |
69 | let error_key = TraitErrorKey::from_error(self, error); | |
a7813a04 XL |
70 | debug!("report_fulfillment_errors({:?}) - key={:?}", |
71 | error, error_key); | |
72 | if !self.reported_trait_errors.borrow_mut().insert(error_key) { | |
73 | debug!("report_fulfillment_errors: skipping duplicate"); | |
74 | return; | |
75 | } | |
76 | match error.code { | |
77 | FulfillmentErrorCode::CodeSelectionError(ref e) => { | |
9e0c209e | 78 | self.report_selection_error(&error.obligation, e); |
a7813a04 XL |
79 | } |
80 | FulfillmentErrorCode::CodeProjectionError(ref e) => { | |
9e0c209e | 81 | self.report_projection_error(&error.obligation, e); |
a7813a04 XL |
82 | } |
83 | FulfillmentErrorCode::CodeAmbiguity => { | |
84 | self.maybe_report_ambiguity(&error.obligation); | |
85 | } | |
1a4d82fc | 86 | } |
a7813a04 XL |
87 | } |
88 | ||
89 | fn report_projection_error(&self, | |
90 | obligation: &PredicateObligation<'tcx>, | |
9e0c209e | 91 | error: &MismatchedProjectionTypes<'tcx>) |
a7813a04 XL |
92 | { |
93 | let predicate = | |
94 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
95 | ||
5bcae85e SL |
96 | if predicate.references_error() { |
97 | return | |
98 | } | |
9e0c209e | 99 | |
5bcae85e SL |
100 | self.probe(|_| { |
101 | let origin = TypeOrigin::Misc(obligation.cause.span); | |
102 | let err_buf; | |
103 | let mut err = &error.err; | |
104 | let mut values = None; | |
105 | ||
106 | // try to find the mismatched types to report the error with. | |
107 | // | |
108 | // this can fail if the problem was higher-ranked, in which | |
109 | // cause I have no idea for a good error message. | |
110 | if let ty::Predicate::Projection(ref data) = predicate { | |
111 | let mut selcx = SelectionContext::new(self); | |
112 | let (data, _) = self.replace_late_bound_regions_with_fresh_var( | |
a7813a04 | 113 | obligation.cause.span, |
5bcae85e SL |
114 | infer::LateBoundRegionConversionTime::HigherRankedType, |
115 | data); | |
116 | let normalized = super::normalize_projection_type( | |
117 | &mut selcx, | |
118 | data.projection_ty, | |
119 | obligation.cause.clone(), | |
120 | 0 | |
121 | ); | |
122 | let origin = TypeOrigin::Misc(obligation.cause.span); | |
123 | if let Err(error) = self.eq_types( | |
124 | false, origin, | |
125 | data.ty, normalized.value | |
126 | ) { | |
127 | values = Some(infer::ValuePairs::Types(ExpectedFound { | |
128 | expected: normalized.value, | |
129 | found: data.ty, | |
130 | })); | |
131 | err_buf = error; | |
132 | err = &err_buf; | |
133 | } | |
a7813a04 | 134 | } |
5bcae85e SL |
135 | |
136 | let mut diag = struct_span_err!( | |
137 | self.tcx.sess, origin.span(), E0271, | |
138 | "type mismatch resolving `{}`", predicate | |
139 | ); | |
9e0c209e | 140 | self.note_type_err(&mut diag, origin, None, values, err); |
5bcae85e SL |
141 | self.note_obligation_cause(&mut diag, obligation); |
142 | diag.emit(); | |
143 | }); | |
a7813a04 XL |
144 | } |
145 | ||
a7813a04 XL |
146 | fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { |
147 | /// returns the fuzzy category of a given type, or None | |
148 | /// if the type can be equated to any type. | |
149 | fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> { | |
150 | match t.sty { | |
151 | ty::TyBool => Some(0), | |
152 | ty::TyChar => Some(1), | |
153 | ty::TyStr => Some(2), | |
9e0c209e | 154 | ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3), |
a7813a04 | 155 | ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4), |
9e0c209e SL |
156 | ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), |
157 | ty::TyArray(..) | ty::TySlice(..) => Some(6), | |
158 | ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), | |
159 | ty::TyTrait(..) => Some(8), | |
160 | ty::TyClosure(..) => Some(9), | |
161 | ty::TyTuple(..) => Some(10), | |
162 | ty::TyProjection(..) => Some(11), | |
163 | ty::TyParam(..) => Some(12), | |
164 | ty::TyAnon(..) => Some(13), | |
165 | ty::TyNever => Some(14), | |
166 | ty::TyAdt(adt, ..) => match adt.adt_kind() { | |
167 | AdtKind::Struct => Some(15), | |
168 | AdtKind::Union => Some(16), | |
169 | AdtKind::Enum => Some(17), | |
170 | }, | |
a7813a04 XL |
171 | ty::TyInfer(..) | ty::TyError => None |
172 | } | |
173 | } | |
174 | ||
175 | match (type_category(a), type_category(b)) { | |
176 | (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { | |
9e0c209e | 177 | (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b, |
a7813a04 XL |
178 | _ => cat_a == cat_b |
179 | }, | |
180 | // infer and error can be equated to all types | |
181 | _ => true | |
1a4d82fc JJ |
182 | } |
183 | } | |
1a4d82fc | 184 | |
a7813a04 XL |
185 | fn impl_similar_to(&self, |
186 | trait_ref: ty::PolyTraitRef<'tcx>, | |
187 | obligation: &PredicateObligation<'tcx>) | |
188 | -> Option<DefId> | |
189 | { | |
190 | let tcx = self.tcx; | |
191 | ||
192 | let trait_ref = tcx.erase_late_bound_regions(&trait_ref); | |
193 | let trait_self_ty = trait_ref.self_ty(); | |
194 | ||
195 | let mut self_match_impls = vec![]; | |
196 | let mut fuzzy_match_impls = vec![]; | |
197 | ||
198 | self.tcx.lookup_trait_def(trait_ref.def_id) | |
199 | .for_each_relevant_impl(self.tcx, trait_self_ty, |def_id| { | |
9e0c209e | 200 | let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); |
a7813a04 XL |
201 | let impl_trait_ref = tcx |
202 | .impl_trait_ref(def_id) | |
203 | .unwrap() | |
9e0c209e | 204 | .subst(tcx, impl_substs); |
a7813a04 XL |
205 | |
206 | let impl_self_ty = impl_trait_ref.self_ty(); | |
207 | ||
208 | if let Ok(..) = self.can_equate(&trait_self_ty, &impl_self_ty) { | |
209 | self_match_impls.push(def_id); | |
210 | ||
9e0c209e SL |
211 | if trait_ref.substs.types().skip(1) |
212 | .zip(impl_trait_ref.substs.types().skip(1)) | |
a7813a04 XL |
213 | .all(|(u,v)| self.fuzzy_match_tys(u, v)) |
214 | { | |
215 | fuzzy_match_impls.push(def_id); | |
216 | } | |
217 | } | |
218 | }); | |
219 | ||
220 | let impl_def_id = if self_match_impls.len() == 1 { | |
221 | self_match_impls[0] | |
222 | } else if fuzzy_match_impls.len() == 1 { | |
223 | fuzzy_match_impls[0] | |
224 | } else { | |
225 | return None | |
226 | }; | |
227 | ||
228 | if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") { | |
229 | Some(impl_def_id) | |
230 | } else { | |
231 | None | |
232 | } | |
1a4d82fc | 233 | } |
1a4d82fc | 234 | |
a7813a04 XL |
235 | fn on_unimplemented_note(&self, |
236 | trait_ref: ty::PolyTraitRef<'tcx>, | |
237 | obligation: &PredicateObligation<'tcx>) -> Option<String> { | |
238 | let def_id = self.impl_similar_to(trait_ref, obligation) | |
239 | .unwrap_or(trait_ref.def_id()); | |
240 | let trait_ref = trait_ref.skip_binder(); | |
241 | ||
242 | let span = obligation.cause.span; | |
243 | let mut report = None; | |
244 | for item in self.tcx.get_attrs(def_id).iter() { | |
245 | if item.check_name("rustc_on_unimplemented") { | |
246 | let err_sp = item.meta().span.substitute_dummy(span); | |
247 | let def = self.tcx.lookup_trait_def(trait_ref.def_id); | |
248 | let trait_str = def.trait_ref.to_string(); | |
249 | if let Some(ref istring) = item.value_str() { | |
9e0c209e SL |
250 | let generic_map = def.generics.types.iter().map(|param| { |
251 | (param.name.as_str().to_string(), | |
252 | trait_ref.substs.type_for_def(param).to_string()) | |
253 | }).collect::<FnvHashMap<String, String>>(); | |
a7813a04 XL |
254 | let parser = Parser::new(&istring); |
255 | let mut errored = false; | |
256 | let err: String = parser.filter_map(|p| { | |
257 | match p { | |
258 | Piece::String(s) => Some(s), | |
259 | Piece::NextArgument(a) => match a.position { | |
260 | Position::ArgumentNamed(s) => match generic_map.get(s) { | |
261 | Some(val) => Some(val), | |
262 | None => { | |
263 | span_err!(self.tcx.sess, err_sp, E0272, | |
264 | "the #[rustc_on_unimplemented] \ | |
265 | attribute on \ | |
266 | trait definition for {} refers to \ | |
267 | non-existent type parameter {}", | |
268 | trait_str, s); | |
269 | errored = true; | |
270 | None | |
271 | } | |
272 | }, | |
273 | _ => { | |
274 | span_err!(self.tcx.sess, err_sp, E0273, | |
275 | "the #[rustc_on_unimplemented] attribute \ | |
276 | on trait definition for {} must have \ | |
277 | named format arguments, eg \ | |
278 | `#[rustc_on_unimplemented = \ | |
279 | \"foo {{T}}\"]`", trait_str); | |
85aaf69f SL |
280 | errored = true; |
281 | None | |
282 | } | |
85aaf69f SL |
283 | } |
284 | } | |
a7813a04 XL |
285 | }).collect(); |
286 | // Report only if the format string checks out | |
287 | if !errored { | |
288 | report = Some(err); | |
85aaf69f | 289 | } |
a7813a04 XL |
290 | } else { |
291 | span_err!(self.tcx.sess, err_sp, E0274, | |
292 | "the #[rustc_on_unimplemented] attribute on \ | |
293 | trait definition for {} must have a value, \ | |
294 | eg `#[rustc_on_unimplemented = \"foo\"]`", | |
295 | trait_str); | |
85aaf69f | 296 | } |
a7813a04 | 297 | break; |
85aaf69f | 298 | } |
85aaf69f | 299 | } |
a7813a04 | 300 | report |
85aaf69f | 301 | } |
85aaf69f | 302 | |
a7813a04 XL |
303 | fn find_similar_impl_candidates(&self, |
304 | trait_ref: ty::PolyTraitRef<'tcx>) | |
305 | -> Vec<ty::TraitRef<'tcx>> | |
306 | { | |
307 | let simp = fast_reject::simplify_type(self.tcx, | |
308 | trait_ref.skip_binder().self_ty(), | |
309 | true); | |
310 | let mut impl_candidates = Vec::new(); | |
311 | let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id()); | |
312 | ||
313 | match simp { | |
314 | Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { | |
315 | let imp = self.tcx.impl_trait_ref(def_id).unwrap(); | |
316 | let imp_simp = fast_reject::simplify_type(self.tcx, | |
317 | imp.self_ty(), | |
318 | true); | |
319 | if let Some(imp_simp) = imp_simp { | |
320 | if simp != imp_simp { | |
321 | return; | |
322 | } | |
54a0048b | 323 | } |
a7813a04 XL |
324 | impl_candidates.push(imp); |
325 | }), | |
326 | None => trait_def.for_each_impl(self.tcx, |def_id| { | |
327 | impl_candidates.push( | |
328 | self.tcx.impl_trait_ref(def_id).unwrap()); | |
329 | }) | |
330 | }; | |
331 | impl_candidates | |
332 | } | |
54a0048b | 333 | |
a7813a04 XL |
334 | fn report_similar_impl_candidates(&self, |
335 | trait_ref: ty::PolyTraitRef<'tcx>, | |
336 | err: &mut DiagnosticBuilder) | |
337 | { | |
338 | let simp = fast_reject::simplify_type(self.tcx, | |
339 | trait_ref.skip_binder().self_ty(), | |
340 | true); | |
341 | let mut impl_candidates = Vec::new(); | |
342 | let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id()); | |
343 | ||
344 | match simp { | |
345 | Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| { | |
346 | let imp = self.tcx.impl_trait_ref(def_id).unwrap(); | |
347 | let imp_simp = fast_reject::simplify_type(self.tcx, | |
348 | imp.self_ty(), | |
349 | true); | |
350 | if let Some(imp_simp) = imp_simp { | |
351 | if simp != imp_simp { | |
352 | return; | |
353 | } | |
354 | } | |
355 | impl_candidates.push(imp); | |
356 | }), | |
357 | None => trait_def.for_each_impl(self.tcx, |def_id| { | |
358 | impl_candidates.push( | |
359 | self.tcx.impl_trait_ref(def_id).unwrap()); | |
360 | }) | |
361 | }; | |
54a0048b | 362 | |
a7813a04 XL |
363 | if impl_candidates.is_empty() { |
364 | return; | |
365 | } | |
366 | ||
367 | err.help(&format!("the following implementations were found:")); | |
54a0048b | 368 | |
a7813a04 XL |
369 | let end = cmp::min(4, impl_candidates.len()); |
370 | for candidate in &impl_candidates[0..end] { | |
371 | err.help(&format!(" {:?}", candidate)); | |
372 | } | |
373 | if impl_candidates.len() > 4 { | |
374 | err.help(&format!("and {} others", impl_candidates.len()-4)); | |
375 | } | |
7453a54e | 376 | } |
c34b1796 | 377 | |
a7813a04 XL |
378 | /// Reports that an overflow has occurred and halts compilation. We |
379 | /// halt compilation unconditionally because it is important that | |
380 | /// overflows never be masked -- they basically represent computations | |
381 | /// whose result could not be truly determined and thus we can't say | |
382 | /// if the program type checks or not -- and they are unusual | |
383 | /// occurrences in any case. | |
384 | pub fn report_overflow_error<T>(&self, | |
385 | obligation: &Obligation<'tcx, T>, | |
386 | suggest_increasing_limit: bool) -> ! | |
387 | where T: fmt::Display + TypeFoldable<'tcx> | |
388 | { | |
389 | let predicate = | |
390 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
391 | let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275, | |
392 | "overflow evaluating the requirement `{}`", | |
393 | predicate); | |
c34b1796 | 394 | |
a7813a04 XL |
395 | if suggest_increasing_limit { |
396 | self.suggest_new_overflow_limit(&mut err); | |
397 | } | |
c34b1796 | 398 | |
a7813a04 | 399 | self.note_obligation_cause(&mut err, obligation); |
7453a54e | 400 | |
a7813a04 XL |
401 | err.emit(); |
402 | self.tcx.sess.abort_if_errors(); | |
403 | bug!(); | |
404 | } | |
7453a54e | 405 | |
a7813a04 XL |
406 | /// Reports that a cycle was detected which led to overflow and halts |
407 | /// compilation. This is equivalent to `report_overflow_error` except | |
408 | /// that we can give a more helpful error message (and, in particular, | |
409 | /// we do not suggest increasing the overflow limit, which is not | |
410 | /// going to help). | |
411 | pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { | |
412 | let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned()); | |
413 | assert!(cycle.len() > 0); | |
7453a54e | 414 | |
a7813a04 | 415 | debug!("report_overflow_error_cycle: cycle={:?}", cycle); |
7453a54e | 416 | |
a7813a04 XL |
417 | self.report_overflow_error(&cycle[0], false); |
418 | } | |
7453a54e | 419 | |
a7813a04 XL |
420 | pub fn report_selection_error(&self, |
421 | obligation: &PredicateObligation<'tcx>, | |
9e0c209e | 422 | error: &SelectionError<'tcx>) |
a7813a04 XL |
423 | { |
424 | let span = obligation.cause.span; | |
425 | let mut err = match *error { | |
426 | SelectionError::Unimplemented => { | |
427 | if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code { | |
428 | span_err!( | |
429 | self.tcx.sess, span, E0276, | |
430 | "the requirement `{}` appears on the impl \ | |
431 | method but not on the corresponding trait method", | |
432 | obligation.predicate); | |
433 | return; | |
434 | } else { | |
435 | match obligation.predicate { | |
436 | ty::Predicate::Trait(ref trait_predicate) => { | |
437 | let trait_predicate = | |
438 | self.resolve_type_vars_if_possible(trait_predicate); | |
439 | ||
440 | if self.tcx.sess.has_errors() && trait_predicate.references_error() { | |
441 | return; | |
442 | } else { | |
443 | let trait_ref = trait_predicate.to_poly_trait_ref(); | |
444 | ||
9e0c209e | 445 | let mut err = struct_span_err!(self.tcx.sess, span, E0277, |
a7813a04 XL |
446 | "the trait bound `{}` is not satisfied", |
447 | trait_ref.to_predicate()); | |
9e0c209e SL |
448 | err.span_label(span, &format!("trait `{}` not satisfied", |
449 | trait_ref.to_predicate())); | |
a7813a04 XL |
450 | |
451 | // Try to report a help message | |
452 | ||
453 | if !trait_ref.has_infer_types() && | |
454 | self.predicate_can_apply(trait_ref) { | |
455 | // If a where-clause may be useful, remind the | |
456 | // user that they can add it. | |
457 | // | |
458 | // don't display an on-unimplemented note, as | |
459 | // these notes will often be of the form | |
460 | // "the type `T` can't be frobnicated" | |
461 | // which is somewhat confusing. | |
462 | err.help(&format!("consider adding a `where {}` bound", | |
463 | trait_ref.to_predicate())); | |
464 | } else if let Some(s) = self.on_unimplemented_note(trait_ref, | |
465 | obligation) { | |
466 | // If it has a custom "#[rustc_on_unimplemented]" | |
467 | // error message, let's display it! | |
468 | err.note(&s); | |
469 | } else { | |
470 | // If we can't show anything useful, try to find | |
471 | // similar impls. | |
472 | let impl_candidates = | |
473 | self.find_similar_impl_candidates(trait_ref); | |
474 | if impl_candidates.len() > 0 { | |
475 | self.report_similar_impl_candidates(trait_ref, &mut err); | |
476 | } | |
477 | } | |
478 | err | |
479 | } | |
480 | } | |
7453a54e | 481 | |
a7813a04 XL |
482 | ty::Predicate::Equate(ref predicate) => { |
483 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
484 | let err = self.equality_predicate(span, | |
485 | &predicate).err().unwrap(); | |
486 | struct_span_err!(self.tcx.sess, span, E0278, | |
487 | "the requirement `{}` is not satisfied (`{}`)", | |
488 | predicate, err) | |
489 | } | |
7453a54e | 490 | |
a7813a04 XL |
491 | ty::Predicate::RegionOutlives(ref predicate) => { |
492 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
493 | let err = self.region_outlives_predicate(span, | |
494 | &predicate).err().unwrap(); | |
495 | struct_span_err!(self.tcx.sess, span, E0279, | |
496 | "the requirement `{}` is not satisfied (`{}`)", | |
497 | predicate, err) | |
498 | } | |
7453a54e | 499 | |
a7813a04 XL |
500 | ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { |
501 | let predicate = | |
502 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
503 | struct_span_err!(self.tcx.sess, span, E0280, | |
504 | "the requirement `{}` is not satisfied", | |
505 | predicate) | |
506 | } | |
e9174d1e | 507 | |
a7813a04 XL |
508 | ty::Predicate::ObjectSafe(trait_def_id) => { |
509 | let violations = self.tcx.object_safety_violations(trait_def_id); | |
9e0c209e SL |
510 | self.tcx.report_object_safety_error(span, |
511 | trait_def_id, | |
512 | violations) | |
85aaf69f | 513 | } |
85aaf69f | 514 | |
a7813a04 XL |
515 | ty::Predicate::ClosureKind(closure_def_id, kind) => { |
516 | let found_kind = self.closure_kind(closure_def_id).unwrap(); | |
517 | let closure_span = self.tcx.map.span_if_local(closure_def_id).unwrap(); | |
518 | let mut err = struct_span_err!( | |
519 | self.tcx.sess, closure_span, E0525, | |
520 | "expected a closure that implements the `{}` trait, \ | |
521 | but this closure only implements `{}`", | |
522 | kind, | |
523 | found_kind); | |
524 | err.span_note( | |
525 | obligation.cause.span, | |
526 | &format!("the requirement to implement \ | |
527 | `{}` derives from here", kind)); | |
528 | err.emit(); | |
529 | return; | |
530 | } | |
e9174d1e | 531 | |
a7813a04 XL |
532 | ty::Predicate::WellFormed(ty) => { |
533 | // WF predicates cannot themselves make | |
534 | // errors. They can only block due to | |
535 | // ambiguity; otherwise, they always | |
536 | // degenerate into other obligations | |
537 | // (which may fail). | |
538 | span_bug!(span, "WF predicate not satisfied for {:?}", ty); | |
539 | } | |
85aaf69f | 540 | } |
1a4d82fc JJ |
541 | } |
542 | } | |
85aaf69f | 543 | |
a7813a04 XL |
544 | OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => { |
545 | let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); | |
546 | let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref); | |
547 | if actual_trait_ref.self_ty().references_error() { | |
548 | return; | |
549 | } | |
550 | struct_span_err!(self.tcx.sess, span, E0281, | |
e9174d1e SL |
551 | "type mismatch: the type `{}` implements the trait `{}`, \ |
552 | but the trait `{}` is required ({})", | |
553 | expected_trait_ref.self_ty(), | |
554 | expected_trait_ref, | |
555 | actual_trait_ref, | |
a7813a04 | 556 | e) |
1a4d82fc | 557 | } |
d9579d0f | 558 | |
a7813a04 XL |
559 | TraitNotObjectSafe(did) => { |
560 | let violations = self.tcx.object_safety_violations(did); | |
9e0c209e SL |
561 | self.tcx.report_object_safety_error(span, did, |
562 | violations) | |
a7813a04 XL |
563 | } |
564 | }; | |
565 | self.note_obligation_cause(&mut err, obligation); | |
566 | err.emit(); | |
e9174d1e SL |
567 | } |
568 | } | |
d9579d0f | 569 | |
a7813a04 XL |
570 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
571 | pub fn recursive_type_with_infinite_size_error(self, | |
572 | type_def_id: DefId) | |
573 | -> DiagnosticBuilder<'tcx> | |
574 | { | |
575 | assert!(type_def_id.is_local()); | |
576 | let span = self.map.span_if_local(type_def_id).unwrap(); | |
577 | let mut err = struct_span_err!(self.sess, span, E0072, | |
578 | "recursive type `{}` has infinite size", | |
579 | self.item_path_str(type_def_id)); | |
5bcae85e | 580 | err.span_label(span, &format!("recursive type has infinite size")); |
a7813a04 XL |
581 | err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \ |
582 | at some point to make `{}` representable", | |
583 | self.item_path_str(type_def_id))); | |
584 | err | |
585 | } | |
d9579d0f | 586 | |
a7813a04 XL |
587 | pub fn report_object_safety_error(self, |
588 | span: Span, | |
589 | trait_def_id: DefId, | |
a7813a04 | 590 | violations: Vec<ObjectSafetyViolation>) |
9e0c209e | 591 | -> DiagnosticBuilder<'tcx> |
a7813a04 | 592 | { |
9e0c209e SL |
593 | let trait_str = self.item_path_str(trait_def_id); |
594 | let mut err = struct_span_err!( | |
595 | self.sess, span, E0038, | |
596 | "the trait `{}` cannot be made into an object", | |
597 | trait_str); | |
598 | err.span_label(span, &format!( | |
599 | "the trait `{}` cannot be made into an object", trait_str | |
600 | )); | |
d9579d0f | 601 | |
a7813a04 XL |
602 | let mut reported_violations = FnvHashSet(); |
603 | for violation in violations { | |
604 | if !reported_violations.insert(violation.clone()) { | |
605 | continue; | |
e9174d1e | 606 | } |
a7813a04 XL |
607 | let buf; |
608 | let note = match violation { | |
609 | ObjectSafetyViolation::SizedSelf => { | |
610 | "the trait cannot require that `Self : Sized`" | |
611 | } | |
e9174d1e | 612 | |
a7813a04 XL |
613 | ObjectSafetyViolation::SupertraitSelf => { |
614 | "the trait cannot use `Self` as a type parameter \ | |
615 | in the supertrait listing" | |
616 | } | |
617 | ||
618 | ObjectSafetyViolation::Method(method, | |
619 | MethodViolationCode::StaticMethod) => { | |
620 | buf = format!("method `{}` has no receiver", | |
621 | method.name); | |
622 | &buf | |
623 | } | |
624 | ||
625 | ObjectSafetyViolation::Method(method, | |
626 | MethodViolationCode::ReferencesSelf) => { | |
627 | buf = format!("method `{}` references the `Self` type \ | |
628 | in its arguments or return type", | |
629 | method.name); | |
630 | &buf | |
631 | } | |
e9174d1e | 632 | |
a7813a04 XL |
633 | ObjectSafetyViolation::Method(method, |
634 | MethodViolationCode::Generic) => { | |
635 | buf = format!("method `{}` has generic type parameters", | |
636 | method.name); | |
637 | &buf | |
638 | } | |
639 | }; | |
9e0c209e | 640 | err.note(note); |
d9579d0f | 641 | } |
a7813a04 | 642 | err |
1a4d82fc JJ |
643 | } |
644 | } | |
645 | ||
a7813a04 XL |
646 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
647 | fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) { | |
648 | // Unable to successfully determine, probably means | |
649 | // insufficient type information, but could mean | |
650 | // ambiguous impls. The latter *ought* to be a | |
651 | // coherence violation, so we don't report it here. | |
652 | ||
653 | let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); | |
654 | ||
655 | debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", | |
656 | predicate, | |
657 | obligation); | |
658 | ||
659 | // Ambiguity errors are often caused as fallout from earlier | |
660 | // errors. So just ignore them if this infcx is tainted. | |
661 | if self.is_tainted_by_errors() { | |
662 | return; | |
663 | } | |
664 | ||
665 | match predicate { | |
666 | ty::Predicate::Trait(ref data) => { | |
667 | let trait_ref = data.to_poly_trait_ref(); | |
668 | let self_ty = trait_ref.self_ty(); | |
9e0c209e | 669 | if predicate.references_error() { |
a7813a04 XL |
670 | } else { |
671 | // Typically, this ambiguity should only happen if | |
672 | // there are unresolved type inference variables | |
673 | // (otherwise it would suggest a coherence | |
674 | // failure). But given #21974 that is not necessarily | |
675 | // the case -- we can have multiple where clauses that | |
676 | // are only distinguished by a region, which results | |
677 | // in an ambiguity even when all types are fully | |
678 | // known, since we don't dispatch based on region | |
679 | // relationships. | |
680 | ||
681 | // This is kind of a hack: it frequently happens that some earlier | |
682 | // error prevents types from being fully inferred, and then we get | |
683 | // a bunch of uninteresting errors saying something like "<generic | |
684 | // #0> doesn't implement Sized". It may even be true that we | |
685 | // could just skip over all checks where the self-ty is an | |
686 | // inference variable, but I was afraid that there might be an | |
687 | // inference variable created, registered as an obligation, and | |
688 | // then never forced by writeback, and hence by skipping here we'd | |
689 | // be ignoring the fact that we don't KNOW the type works | |
690 | // out. Though even that would probably be harmless, given that | |
691 | // we're only talking about builtin traits, which are known to be | |
692 | // inhabited. But in any case I just threw in this check for | |
693 | // has_errors() to be sure that compilation isn't happening | |
694 | // anyway. In that case, why inundate the user. | |
695 | if !self.tcx.sess.has_errors() { | |
696 | if | |
697 | self.tcx.lang_items.sized_trait() | |
698 | .map_or(false, |sized_id| sized_id == trait_ref.def_id()) | |
699 | { | |
700 | self.need_type_info(obligation.cause.span, self_ty); | |
701 | } else { | |
702 | let mut err = struct_span_err!(self.tcx.sess, | |
703 | obligation.cause.span, E0283, | |
704 | "type annotations required: \ | |
705 | cannot resolve `{}`", | |
706 | predicate); | |
707 | self.note_obligation_cause(&mut err, obligation); | |
708 | err.emit(); | |
709 | } | |
1a4d82fc JJ |
710 | } |
711 | } | |
1a4d82fc | 712 | } |
1a4d82fc | 713 | |
a7813a04 XL |
714 | ty::Predicate::WellFormed(ty) => { |
715 | // Same hacky approach as above to avoid deluging user | |
716 | // with error messages. | |
717 | if !ty.references_error() && !self.tcx.sess.has_errors() { | |
718 | self.need_type_info(obligation.cause.span, ty); | |
719 | } | |
e9174d1e | 720 | } |
e9174d1e | 721 | |
a7813a04 XL |
722 | _ => { |
723 | if !self.tcx.sess.has_errors() { | |
724 | let mut err = struct_span_err!(self.tcx.sess, | |
725 | obligation.cause.span, E0284, | |
726 | "type annotations required: \ | |
727 | cannot resolve `{}`", | |
728 | predicate); | |
729 | self.note_obligation_cause(&mut err, obligation); | |
730 | err.emit(); | |
731 | } | |
1a4d82fc JJ |
732 | } |
733 | } | |
734 | } | |
1a4d82fc | 735 | |
a7813a04 XL |
736 | /// Returns whether the trait predicate may apply for *some* assignment |
737 | /// to the type parameters. | |
738 | fn predicate_can_apply(&self, pred: ty::PolyTraitRef<'tcx>) -> bool { | |
739 | struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { | |
740 | infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, | |
741 | var_map: FnvHashMap<Ty<'tcx>, Ty<'tcx>> | |
742 | } | |
54a0048b | 743 | |
a7813a04 XL |
744 | impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> { |
745 | fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } | |
54a0048b | 746 | |
a7813a04 XL |
747 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { |
748 | if let ty::TyParam(..) = ty.sty { | |
749 | let infcx = self.infcx; | |
750 | self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var()) | |
751 | } else { | |
752 | ty.super_fold_with(self) | |
753 | } | |
54a0048b SL |
754 | } |
755 | } | |
54a0048b | 756 | |
a7813a04 XL |
757 | self.probe(|_| { |
758 | let mut selcx = SelectionContext::new(self); | |
54a0048b | 759 | |
a7813a04 XL |
760 | let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { |
761 | infcx: self, | |
762 | var_map: FnvHashMap() | |
763 | }); | |
54a0048b | 764 | |
a7813a04 XL |
765 | let cleaned_pred = super::project::normalize( |
766 | &mut selcx, | |
767 | ObligationCause::dummy(), | |
768 | &cleaned_pred | |
769 | ).value; | |
54a0048b | 770 | |
a7813a04 XL |
771 | let obligation = Obligation::new( |
772 | ObligationCause::dummy(), | |
773 | cleaned_pred.to_predicate() | |
774 | ); | |
54a0048b | 775 | |
a7813a04 XL |
776 | selcx.evaluate_obligation(&obligation) |
777 | }) | |
778 | } | |
54a0048b SL |
779 | |
780 | ||
a7813a04 | 781 | fn need_type_info(&self, span: Span, ty: Ty<'tcx>) { |
5bcae85e SL |
782 | let mut err = struct_span_err!(self.tcx.sess, span, E0282, |
783 | "unable to infer enough type information about `{}`", | |
784 | ty); | |
785 | err.note("type annotations or generic parameter binding required"); | |
786 | err.span_label(span, &format!("cannot infer type for `{}`", ty)); | |
787 | err.emit() | |
a7813a04 | 788 | } |
e9174d1e | 789 | |
a7813a04 XL |
790 | fn note_obligation_cause<T>(&self, |
791 | err: &mut DiagnosticBuilder, | |
792 | obligation: &Obligation<'tcx, T>) | |
793 | where T: fmt::Display | |
794 | { | |
795 | self.note_obligation_cause_code(err, | |
796 | &obligation.predicate, | |
797 | &obligation.cause.code); | |
798 | } | |
1a4d82fc | 799 | |
a7813a04 XL |
800 | fn note_obligation_cause_code<T>(&self, |
801 | err: &mut DiagnosticBuilder, | |
802 | predicate: &T, | |
803 | cause_code: &ObligationCauseCode<'tcx>) | |
804 | where T: fmt::Display | |
805 | { | |
806 | let tcx = self.tcx; | |
807 | match *cause_code { | |
808 | ObligationCauseCode::MiscObligation => { } | |
809 | ObligationCauseCode::SliceOrArrayElem => { | |
810 | err.note("slice and array elements must have `Sized` type"); | |
811 | } | |
812 | ObligationCauseCode::TupleElem => { | |
813 | err.note("tuple elements must have `Sized` type"); | |
814 | } | |
815 | ObligationCauseCode::ProjectionWf(data) => { | |
816 | err.note(&format!("required so that the projection `{}` is well-formed", | |
817 | data)); | |
818 | } | |
819 | ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { | |
820 | err.note(&format!("required so that reference `{}` does not outlive its referent", | |
821 | ref_ty)); | |
822 | } | |
823 | ObligationCauseCode::ItemObligation(item_def_id) => { | |
824 | let item_name = tcx.item_path_str(item_def_id); | |
825 | err.note(&format!("required by `{}`", item_name)); | |
826 | } | |
827 | ObligationCauseCode::ObjectCastObligation(object_ty) => { | |
828 | err.note(&format!("required for the cast to the object type `{}`", | |
829 | self.ty_to_string(object_ty))); | |
830 | } | |
831 | ObligationCauseCode::RepeatVec => { | |
832 | err.note("the `Copy` trait is required because the \ | |
833 | repeated element will be copied"); | |
834 | } | |
835 | ObligationCauseCode::VariableType(_) => { | |
836 | err.note("all local variables must have a statically known size"); | |
837 | } | |
838 | ObligationCauseCode::ReturnType => { | |
839 | err.note("the return type of a function must have a \ | |
840 | statically known size"); | |
841 | } | |
842 | ObligationCauseCode::AssignmentLhsSized => { | |
843 | err.note("the left-hand-side of an assignment must have a statically known size"); | |
844 | } | |
845 | ObligationCauseCode::StructInitializerSized => { | |
846 | err.note("structs must have a statically known size to be initialized"); | |
847 | } | |
848 | ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => { | |
849 | let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap(); | |
850 | let trait_name = tcx.item_path_str(def_id); | |
851 | let name = tcx.local_var_name_str(var_id); | |
852 | err.note( | |
853 | &format!("the closure that captures `{}` requires that all captured variables \ | |
854 | implement the trait `{}`", | |
855 | name, | |
856 | trait_name)); | |
857 | } | |
858 | ObligationCauseCode::FieldSized => { | |
859 | err.note("only the last field of a struct or enum variant \ | |
860 | may have a dynamically sized type"); | |
861 | } | |
3157f602 XL |
862 | ObligationCauseCode::ConstSized => { |
863 | err.note("constant expressions must have a statically known size"); | |
864 | } | |
a7813a04 XL |
865 | ObligationCauseCode::SharedStatic => { |
866 | err.note("shared static variables must have a type that implements `Sync`"); | |
867 | } | |
868 | ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
869 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
870 | err.note(&format!("required because it appears within the type `{}`", | |
871 | parent_trait_ref.0.self_ty())); | |
872 | let parent_predicate = parent_trait_ref.to_predicate(); | |
873 | self.note_obligation_cause_code(err, | |
874 | &parent_predicate, | |
875 | &data.parent_code); | |
876 | } | |
877 | ObligationCauseCode::ImplDerivedObligation(ref data) => { | |
878 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
879 | err.note( | |
880 | &format!("required because of the requirements on the impl of `{}` for `{}`", | |
881 | parent_trait_ref, | |
882 | parent_trait_ref.0.self_ty())); | |
883 | let parent_predicate = parent_trait_ref.to_predicate(); | |
884 | self.note_obligation_cause_code(err, | |
885 | &parent_predicate, | |
886 | &data.parent_code); | |
887 | } | |
888 | ObligationCauseCode::CompareImplMethodObligation => { | |
889 | err.note( | |
890 | &format!("the requirement `{}` appears on the impl method \ | |
891 | but not on the corresponding trait method", | |
892 | predicate)); | |
893 | } | |
85aaf69f | 894 | } |
1a4d82fc | 895 | } |
1a4d82fc | 896 | |
a7813a04 XL |
897 | fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { |
898 | let current_limit = self.tcx.sess.recursion_limit.get(); | |
899 | let suggested_limit = current_limit * 2; | |
900 | err.note(&format!( | |
901 | "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", | |
902 | suggested_limit)); | |
903 | } | |
1a4d82fc | 904 | } |