]>
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 | 17 | ObligationCauseCode, |
ea8adc8c XL |
18 | OnUnimplementedDirective, |
19 | OnUnimplementedNote, | |
1a4d82fc | 20 | OutputTypeParameterMismatch, |
d9579d0f | 21 | TraitNotObjectSafe, |
ea8adc8c | 22 | ConstEvalFailure, |
1a4d82fc | 23 | PredicateObligation, |
041b39d2 | 24 | Reveal, |
54a0048b | 25 | SelectionContext, |
1a4d82fc | 26 | SelectionError, |
d9579d0f | 27 | ObjectSafetyViolation, |
1a4d82fc JJ |
28 | }; |
29 | ||
8bb4bdeb | 30 | use errors::DiagnosticBuilder; |
041b39d2 | 31 | use hir; |
54a0048b | 32 | use hir::def_id::DefId; |
476ff2be SL |
33 | use infer::{self, InferCtxt}; |
34 | use infer::type_variable::TypeVariableOrigin; | |
ea8adc8c | 35 | use middle::const_val; |
c30ab7b3 | 36 | use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; |
8bb4bdeb | 37 | use std::fmt; |
041b39d2 XL |
38 | use syntax::ast; |
39 | use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; | |
ea8adc8c | 40 | use ty::error::ExpectedFound; |
54a0048b | 41 | use ty::fast_reject; |
a7813a04 | 42 | use ty::fold::TypeFolder; |
9e0c209e | 43 | use ty::subst::Subst; |
cc61c64b | 44 | use ty::SubtypePredicate; |
476ff2be | 45 | use util::nodemap::{FxHashMap, FxHashSet}; |
e9174d1e | 46 | |
476ff2be | 47 | use syntax_pos::{DUMMY_SP, Span}; |
8bb4bdeb | 48 | |
041b39d2 XL |
49 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
50 | pub fn report_fulfillment_errors(&self, | |
51 | errors: &Vec<FulfillmentError<'tcx>>, | |
52 | body_id: Option<hir::BodyId>) { | |
53 | #[derive(Debug)] | |
54 | struct ErrorDescriptor<'tcx> { | |
55 | predicate: ty::Predicate<'tcx>, | |
56 | index: Option<usize>, // None if this is an old error | |
57 | } | |
e9174d1e | 58 | |
041b39d2 XL |
59 | let mut error_map : FxHashMap<_, _> = |
60 | self.reported_trait_errors.borrow().iter().map(|(&span, predicates)| { | |
61 | (span, predicates.iter().map(|predicate| ErrorDescriptor { | |
62 | predicate: predicate.clone(), | |
63 | index: None | |
64 | }).collect()) | |
65 | }).collect(); | |
66 | ||
67 | for (index, error) in errors.iter().enumerate() { | |
68 | error_map.entry(error.obligation.cause.span).or_insert(Vec::new()).push( | |
69 | ErrorDescriptor { | |
70 | predicate: error.obligation.predicate.clone(), | |
71 | index: Some(index) | |
72 | }); | |
e9174d1e | 73 | |
041b39d2 XL |
74 | self.reported_trait_errors.borrow_mut() |
75 | .entry(error.obligation.cause.span).or_insert(Vec::new()) | |
76 | .push(error.obligation.predicate.clone()); | |
e9174d1e | 77 | } |
1a4d82fc | 78 | |
041b39d2 XL |
79 | // We do this in 2 passes because we want to display errors in order, tho |
80 | // maybe it *is* better to sort errors by span or something. | |
81 | let mut is_suppressed: Vec<bool> = errors.iter().map(|_| false).collect(); | |
82 | for (_, error_set) in error_map.iter() { | |
83 | // We want to suppress "duplicate" errors with the same span. | |
84 | for error in error_set { | |
85 | if let Some(index) = error.index { | |
86 | // Suppress errors that are either: | |
87 | // 1) strictly implied by another error. | |
88 | // 2) implied by an error with a smaller index. | |
89 | for error2 in error_set { | |
90 | if error2.index.map_or(false, |index2| is_suppressed[index2]) { | |
91 | // Avoid errors being suppressed by already-suppressed | |
92 | // errors, to prevent all errors from being suppressed | |
93 | // at once. | |
94 | continue | |
95 | } | |
8bb4bdeb | 96 | |
041b39d2 XL |
97 | if self.error_implies(&error2.predicate, &error.predicate) && |
98 | !(error2.index >= error.index && | |
99 | self.error_implies(&error.predicate, &error2.predicate)) | |
100 | { | |
101 | info!("skipping {:?} (implied by {:?})", error, error2); | |
102 | is_suppressed[index] = true; | |
103 | break | |
cc61c64b | 104 | } |
cc61c64b | 105 | } |
041b39d2 | 106 | } |
cc61c64b | 107 | } |
cc61c64b | 108 | } |
8bb4bdeb | 109 | |
041b39d2 XL |
110 | for (error, suppressed) in errors.iter().zip(is_suppressed) { |
111 | if !suppressed { | |
112 | self.report_fulfillment_error(error, body_id); | |
113 | } | |
114 | } | |
cc61c64b | 115 | } |
8bb4bdeb | 116 | |
3b2f2976 XL |
117 | // returns if `cond` not occurring implies that `error` does not occur - i.e. that |
118 | // `error` occurring implies that `cond` occurs. | |
041b39d2 XL |
119 | fn error_implies(&self, |
120 | cond: &ty::Predicate<'tcx>, | |
121 | error: &ty::Predicate<'tcx>) | |
122 | -> bool | |
123 | { | |
124 | if cond == error { | |
125 | return true | |
8bb4bdeb | 126 | } |
cc61c64b | 127 | |
041b39d2 XL |
128 | let (cond, error) = match (cond, error) { |
129 | (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error)) | |
130 | => (cond, error), | |
131 | _ => { | |
132 | // FIXME: make this work in other cases too. | |
133 | return false | |
cc61c64b | 134 | } |
041b39d2 | 135 | }; |
8bb4bdeb | 136 | |
041b39d2 XL |
137 | for implication in super::elaborate_predicates(self.tcx, vec![cond.clone()]) { |
138 | if let ty::Predicate::Trait(implication) = implication { | |
139 | let error = error.to_poly_trait_ref(); | |
140 | let implication = implication.to_poly_trait_ref(); | |
141 | // FIXME: I'm just not taking associated types at all here. | |
142 | // Eventually I'll need to implement param-env-aware | |
143 | // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. | |
144 | let param_env = ty::ParamEnv::empty(Reveal::UserFacing); | |
145 | if let Ok(_) = self.can_sub(param_env, error, implication) { | |
146 | debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); | |
147 | return true | |
148 | } | |
149 | } | |
a7813a04 | 150 | } |
041b39d2 XL |
151 | |
152 | false | |
e9174d1e | 153 | } |
a7813a04 | 154 | |
041b39d2 XL |
155 | fn report_fulfillment_error(&self, error: &FulfillmentError<'tcx>, |
156 | body_id: Option<hir::BodyId>) { | |
157 | debug!("report_fulfillment_errors({:?})", error); | |
a7813a04 XL |
158 | match error.code { |
159 | FulfillmentErrorCode::CodeSelectionError(ref e) => { | |
9e0c209e | 160 | self.report_selection_error(&error.obligation, e); |
a7813a04 XL |
161 | } |
162 | FulfillmentErrorCode::CodeProjectionError(ref e) => { | |
9e0c209e | 163 | self.report_projection_error(&error.obligation, e); |
a7813a04 XL |
164 | } |
165 | FulfillmentErrorCode::CodeAmbiguity => { | |
041b39d2 | 166 | self.maybe_report_ambiguity(&error.obligation, body_id); |
a7813a04 | 167 | } |
cc61c64b XL |
168 | FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { |
169 | self.report_mismatched_types(&error.obligation.cause, | |
170 | expected_found.expected, | |
171 | expected_found.found, | |
172 | err.clone()) | |
173 | .emit(); | |
174 | } | |
1a4d82fc | 175 | } |
a7813a04 XL |
176 | } |
177 | ||
178 | fn report_projection_error(&self, | |
179 | obligation: &PredicateObligation<'tcx>, | |
9e0c209e | 180 | error: &MismatchedProjectionTypes<'tcx>) |
a7813a04 XL |
181 | { |
182 | let predicate = | |
183 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
184 | ||
5bcae85e SL |
185 | if predicate.references_error() { |
186 | return | |
187 | } | |
9e0c209e | 188 | |
5bcae85e | 189 | self.probe(|_| { |
5bcae85e SL |
190 | let err_buf; |
191 | let mut err = &error.err; | |
192 | let mut values = None; | |
193 | ||
194 | // try to find the mismatched types to report the error with. | |
195 | // | |
196 | // this can fail if the problem was higher-ranked, in which | |
197 | // cause I have no idea for a good error message. | |
198 | if let ty::Predicate::Projection(ref data) = predicate { | |
199 | let mut selcx = SelectionContext::new(self); | |
200 | let (data, _) = self.replace_late_bound_regions_with_fresh_var( | |
a7813a04 | 201 | obligation.cause.span, |
5bcae85e SL |
202 | infer::LateBoundRegionConversionTime::HigherRankedType, |
203 | data); | |
204 | let normalized = super::normalize_projection_type( | |
205 | &mut selcx, | |
7cac9316 | 206 | obligation.param_env, |
5bcae85e SL |
207 | data.projection_ty, |
208 | obligation.cause.clone(), | |
209 | 0 | |
210 | ); | |
7cac9316 XL |
211 | if let Err(error) = self.at(&obligation.cause, obligation.param_env) |
212 | .eq(normalized.value, data.ty) { | |
5bcae85e SL |
213 | values = Some(infer::ValuePairs::Types(ExpectedFound { |
214 | expected: normalized.value, | |
215 | found: data.ty, | |
216 | })); | |
217 | err_buf = error; | |
218 | err = &err_buf; | |
219 | } | |
a7813a04 | 220 | } |
5bcae85e SL |
221 | |
222 | let mut diag = struct_span_err!( | |
476ff2be | 223 | self.tcx.sess, obligation.cause.span, E0271, |
5bcae85e SL |
224 | "type mismatch resolving `{}`", predicate |
225 | ); | |
476ff2be | 226 | self.note_type_err(&mut diag, &obligation.cause, None, values, err); |
5bcae85e SL |
227 | self.note_obligation_cause(&mut diag, obligation); |
228 | diag.emit(); | |
229 | }); | |
a7813a04 XL |
230 | } |
231 | ||
a7813a04 XL |
232 | fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { |
233 | /// returns the fuzzy category of a given type, or None | |
234 | /// if the type can be equated to any type. | |
235 | fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> { | |
236 | match t.sty { | |
237 | ty::TyBool => Some(0), | |
238 | ty::TyChar => Some(1), | |
239 | ty::TyStr => Some(2), | |
9e0c209e | 240 | ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3), |
a7813a04 | 241 | ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4), |
32a655c1 | 242 | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), |
9e0c209e SL |
243 | ty::TyArray(..) | ty::TySlice(..) => Some(6), |
244 | ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), | |
476ff2be | 245 | ty::TyDynamic(..) => Some(8), |
9e0c209e SL |
246 | ty::TyClosure(..) => Some(9), |
247 | ty::TyTuple(..) => Some(10), | |
248 | ty::TyProjection(..) => Some(11), | |
249 | ty::TyParam(..) => Some(12), | |
250 | ty::TyAnon(..) => Some(13), | |
251 | ty::TyNever => Some(14), | |
252 | ty::TyAdt(adt, ..) => match adt.adt_kind() { | |
253 | AdtKind::Struct => Some(15), | |
254 | AdtKind::Union => Some(16), | |
255 | AdtKind::Enum => Some(17), | |
256 | }, | |
ea8adc8c | 257 | ty::TyGenerator(..) => Some(18), |
a7813a04 XL |
258 | ty::TyInfer(..) | ty::TyError => None |
259 | } | |
260 | } | |
261 | ||
262 | match (type_category(a), type_category(b)) { | |
263 | (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { | |
9e0c209e | 264 | (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b, |
a7813a04 XL |
265 | _ => cat_a == cat_b |
266 | }, | |
267 | // infer and error can be equated to all types | |
268 | _ => true | |
1a4d82fc JJ |
269 | } |
270 | } | |
1a4d82fc | 271 | |
a7813a04 XL |
272 | fn impl_similar_to(&self, |
273 | trait_ref: ty::PolyTraitRef<'tcx>, | |
274 | obligation: &PredicateObligation<'tcx>) | |
275 | -> Option<DefId> | |
276 | { | |
277 | let tcx = self.tcx; | |
7cac9316 | 278 | let param_env = obligation.param_env; |
a7813a04 XL |
279 | let trait_ref = tcx.erase_late_bound_regions(&trait_ref); |
280 | let trait_self_ty = trait_ref.self_ty(); | |
281 | ||
282 | let mut self_match_impls = vec![]; | |
283 | let mut fuzzy_match_impls = vec![]; | |
284 | ||
041b39d2 XL |
285 | self.tcx.for_each_relevant_impl( |
286 | trait_ref.def_id, trait_self_ty, |def_id| { | |
9e0c209e | 287 | let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); |
a7813a04 XL |
288 | let impl_trait_ref = tcx |
289 | .impl_trait_ref(def_id) | |
290 | .unwrap() | |
9e0c209e | 291 | .subst(tcx, impl_substs); |
a7813a04 XL |
292 | |
293 | let impl_self_ty = impl_trait_ref.self_ty(); | |
294 | ||
7cac9316 | 295 | if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { |
a7813a04 XL |
296 | self_match_impls.push(def_id); |
297 | ||
9e0c209e SL |
298 | if trait_ref.substs.types().skip(1) |
299 | .zip(impl_trait_ref.substs.types().skip(1)) | |
a7813a04 XL |
300 | .all(|(u,v)| self.fuzzy_match_tys(u, v)) |
301 | { | |
302 | fuzzy_match_impls.push(def_id); | |
303 | } | |
304 | } | |
305 | }); | |
306 | ||
307 | let impl_def_id = if self_match_impls.len() == 1 { | |
308 | self_match_impls[0] | |
309 | } else if fuzzy_match_impls.len() == 1 { | |
310 | fuzzy_match_impls[0] | |
311 | } else { | |
312 | return None | |
313 | }; | |
314 | ||
315 | if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") { | |
316 | Some(impl_def_id) | |
317 | } else { | |
318 | None | |
319 | } | |
1a4d82fc | 320 | } |
1a4d82fc | 321 | |
ea8adc8c XL |
322 | fn on_unimplemented_note( |
323 | &self, | |
324 | trait_ref: ty::PolyTraitRef<'tcx>, | |
325 | obligation: &PredicateObligation<'tcx>) -> | |
326 | OnUnimplementedNote | |
327 | { | |
a7813a04 XL |
328 | let def_id = self.impl_similar_to(trait_ref, obligation) |
329 | .unwrap_or(trait_ref.def_id()); | |
ea8adc8c XL |
330 | let trait_ref = *trait_ref.skip_binder(); |
331 | ||
332 | let desugaring; | |
333 | let method; | |
334 | let mut flags = vec![]; | |
335 | let direct = match obligation.cause.code { | |
336 | ObligationCauseCode::BuiltinDerivedObligation(..) | | |
337 | ObligationCauseCode::ImplDerivedObligation(..) => false, | |
338 | _ => true | |
339 | }; | |
340 | if direct { | |
341 | // this is a "direct", user-specified, rather than derived, | |
342 | // obligation. | |
343 | flags.push(("direct", None)); | |
344 | } | |
a7813a04 | 345 | |
ea8adc8c XL |
346 | if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code { |
347 | // FIXME: maybe also have some way of handling methods | |
348 | // from other traits? That would require name resolution, | |
349 | // which we might want to be some sort of hygienic. | |
350 | // | |
351 | // Currently I'm leaving it for what I need for `try`. | |
352 | if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { | |
353 | method = self.tcx.item_name(item); | |
354 | flags.push(("from_method", None)); | |
355 | flags.push(("from_method", Some(&*method))); | |
85aaf69f | 356 | } |
85aaf69f | 357 | } |
ea8adc8c XL |
358 | |
359 | if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { | |
360 | desugaring = k.as_symbol().as_str(); | |
361 | flags.push(("from_desugaring", None)); | |
362 | flags.push(("from_desugaring", Some(&*desugaring))); | |
363 | } | |
364 | ||
365 | if let Ok(Some(command)) = OnUnimplementedDirective::of_item( | |
366 | self.tcx, trait_ref.def_id, def_id | |
367 | ) { | |
368 | command.evaluate(self.tcx, trait_ref, &flags) | |
369 | } else { | |
370 | OnUnimplementedNote::empty() | |
371 | } | |
85aaf69f | 372 | } |
85aaf69f | 373 | |
a7813a04 XL |
374 | fn find_similar_impl_candidates(&self, |
375 | trait_ref: ty::PolyTraitRef<'tcx>) | |
376 | -> Vec<ty::TraitRef<'tcx>> | |
377 | { | |
378 | let simp = fast_reject::simplify_type(self.tcx, | |
379 | trait_ref.skip_binder().self_ty(), | |
380 | true); | |
381 | let mut impl_candidates = Vec::new(); | |
a7813a04 XL |
382 | |
383 | match simp { | |
041b39d2 | 384 | Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { |
a7813a04 XL |
385 | let imp = self.tcx.impl_trait_ref(def_id).unwrap(); |
386 | let imp_simp = fast_reject::simplify_type(self.tcx, | |
387 | imp.self_ty(), | |
388 | true); | |
389 | if let Some(imp_simp) = imp_simp { | |
390 | if simp != imp_simp { | |
391 | return; | |
392 | } | |
54a0048b | 393 | } |
a7813a04 XL |
394 | impl_candidates.push(imp); |
395 | }), | |
041b39d2 | 396 | None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { |
a7813a04 XL |
397 | impl_candidates.push( |
398 | self.tcx.impl_trait_ref(def_id).unwrap()); | |
399 | }) | |
400 | }; | |
401 | impl_candidates | |
402 | } | |
54a0048b | 403 | |
a7813a04 | 404 | fn report_similar_impl_candidates(&self, |
8bb4bdeb | 405 | impl_candidates: Vec<ty::TraitRef<'tcx>>, |
a7813a04 XL |
406 | err: &mut DiagnosticBuilder) |
407 | { | |
a7813a04 XL |
408 | if impl_candidates.is_empty() { |
409 | return; | |
410 | } | |
411 | ||
8bb4bdeb XL |
412 | let end = if impl_candidates.len() <= 5 { |
413 | impl_candidates.len() | |
414 | } else { | |
415 | 4 | |
416 | }; | |
32a655c1 SL |
417 | err.help(&format!("the following implementations were found:{}{}", |
418 | &impl_candidates[0..end].iter().map(|candidate| { | |
419 | format!("\n {:?}", candidate) | |
420 | }).collect::<String>(), | |
8bb4bdeb | 421 | if impl_candidates.len() > 5 { |
32a655c1 SL |
422 | format!("\nand {} others", impl_candidates.len() - 4) |
423 | } else { | |
424 | "".to_owned() | |
425 | } | |
426 | )); | |
7453a54e | 427 | } |
c34b1796 | 428 | |
a7813a04 XL |
429 | /// Reports that an overflow has occurred and halts compilation. We |
430 | /// halt compilation unconditionally because it is important that | |
431 | /// overflows never be masked -- they basically represent computations | |
432 | /// whose result could not be truly determined and thus we can't say | |
433 | /// if the program type checks or not -- and they are unusual | |
434 | /// occurrences in any case. | |
435 | pub fn report_overflow_error<T>(&self, | |
436 | obligation: &Obligation<'tcx, T>, | |
437 | suggest_increasing_limit: bool) -> ! | |
438 | where T: fmt::Display + TypeFoldable<'tcx> | |
439 | { | |
440 | let predicate = | |
441 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
442 | let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275, | |
443 | "overflow evaluating the requirement `{}`", | |
444 | predicate); | |
c34b1796 | 445 | |
a7813a04 XL |
446 | if suggest_increasing_limit { |
447 | self.suggest_new_overflow_limit(&mut err); | |
448 | } | |
c34b1796 | 449 | |
a7813a04 | 450 | self.note_obligation_cause(&mut err, obligation); |
7453a54e | 451 | |
a7813a04 XL |
452 | err.emit(); |
453 | self.tcx.sess.abort_if_errors(); | |
454 | bug!(); | |
455 | } | |
7453a54e | 456 | |
a7813a04 XL |
457 | /// Reports that a cycle was detected which led to overflow and halts |
458 | /// compilation. This is equivalent to `report_overflow_error` except | |
459 | /// that we can give a more helpful error message (and, in particular, | |
460 | /// we do not suggest increasing the overflow limit, which is not | |
461 | /// going to help). | |
462 | pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { | |
463 | let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned()); | |
464 | assert!(cycle.len() > 0); | |
7453a54e | 465 | |
a7813a04 | 466 | debug!("report_overflow_error_cycle: cycle={:?}", cycle); |
7453a54e | 467 | |
a7813a04 XL |
468 | self.report_overflow_error(&cycle[0], false); |
469 | } | |
7453a54e | 470 | |
c30ab7b3 SL |
471 | pub fn report_extra_impl_obligation(&self, |
472 | error_span: Span, | |
473 | item_name: ast::Name, | |
474 | _impl_item_def_id: DefId, | |
475 | trait_item_def_id: DefId, | |
476 | requirement: &fmt::Display, | |
477 | lint_id: Option<ast::NodeId>) // (*) | |
478 | -> DiagnosticBuilder<'tcx> | |
479 | { | |
480 | // (*) This parameter is temporary and used only for phasing | |
481 | // in the bug fix to #18937. If it is `Some`, it has a kind of | |
482 | // weird effect -- the diagnostic is reported as a lint, and | |
483 | // the builder which is returned is marked as canceled. | |
484 | ||
3b2f2976 XL |
485 | let msg = "impl has stricter requirements than trait"; |
486 | let mut err = match lint_id { | |
487 | Some(node_id) => { | |
488 | self.tcx.struct_span_lint_node(EXTRA_REQUIREMENT_IN_IMPL, | |
489 | node_id, | |
490 | error_span, | |
491 | msg) | |
492 | } | |
493 | None => { | |
494 | struct_span_err!(self.tcx.sess, | |
495 | error_span, | |
496 | E0276, | |
497 | "{}", msg) | |
498 | } | |
499 | }; | |
c30ab7b3 | 500 | |
32a655c1 | 501 | if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { |
cc61c64b | 502 | let span = self.tcx.sess.codemap().def_span(trait_item_span); |
7cac9316 | 503 | err.span_label(span, format!("definition of `{}` from trait", item_name)); |
c30ab7b3 SL |
504 | } |
505 | ||
506 | err.span_label( | |
507 | error_span, | |
7cac9316 | 508 | format!("impl has extra requirement {}", requirement)); |
c30ab7b3 | 509 | |
c30ab7b3 SL |
510 | err |
511 | } | |
512 | ||
32a655c1 SL |
513 | |
514 | /// Get the parent trait chain start | |
515 | fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> { | |
516 | match code { | |
517 | &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
518 | let parent_trait_ref = self.resolve_type_vars_if_possible( | |
519 | &data.parent_trait_ref); | |
520 | match self.get_parent_trait_ref(&data.parent_code) { | |
521 | Some(t) => Some(t), | |
522 | None => Some(format!("{}", parent_trait_ref.0.self_ty())), | |
523 | } | |
524 | } | |
525 | _ => None, | |
526 | } | |
527 | } | |
528 | ||
a7813a04 XL |
529 | pub fn report_selection_error(&self, |
530 | obligation: &PredicateObligation<'tcx>, | |
9e0c209e | 531 | error: &SelectionError<'tcx>) |
a7813a04 XL |
532 | { |
533 | let span = obligation.cause.span; | |
32a655c1 | 534 | |
a7813a04 XL |
535 | let mut err = match *error { |
536 | SelectionError::Unimplemented => { | |
c30ab7b3 SL |
537 | if let ObligationCauseCode::CompareImplMethodObligation { |
538 | item_name, impl_item_def_id, trait_item_def_id, lint_id | |
539 | } = obligation.cause.code { | |
540 | self.report_extra_impl_obligation( | |
541 | span, | |
542 | item_name, | |
543 | impl_item_def_id, | |
544 | trait_item_def_id, | |
545 | &format!("`{}`", obligation.predicate), | |
546 | lint_id) | |
547 | .emit(); | |
a7813a04 | 548 | return; |
8bb4bdeb XL |
549 | } |
550 | match obligation.predicate { | |
551 | ty::Predicate::Trait(ref trait_predicate) => { | |
552 | let trait_predicate = | |
553 | self.resolve_type_vars_if_possible(trait_predicate); | |
7453a54e | 554 | |
8bb4bdeb XL |
555 | if self.tcx.sess.has_errors() && trait_predicate.references_error() { |
556 | return; | |
a7813a04 | 557 | } |
8bb4bdeb XL |
558 | let trait_ref = trait_predicate.to_poly_trait_ref(); |
559 | let (post_message, pre_message) = | |
560 | self.get_parent_trait_ref(&obligation.cause.code) | |
561 | .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) | |
ea8adc8c XL |
562 | .unwrap_or((String::new(), String::new())); |
563 | ||
564 | let OnUnimplementedNote { message, label } | |
565 | = self.on_unimplemented_note(trait_ref, obligation); | |
566 | let have_alt_message = message.is_some() || label.is_some(); | |
567 | ||
8bb4bdeb XL |
568 | let mut err = struct_span_err!( |
569 | self.tcx.sess, | |
570 | span, | |
571 | E0277, | |
ea8adc8c XL |
572 | "{}", |
573 | message.unwrap_or_else(|| { | |
574 | format!("the trait bound `{}` is not satisfied{}", | |
575 | trait_ref.to_predicate(), post_message) | |
576 | })); | |
8bb4bdeb | 577 | |
ea8adc8c | 578 | if let Some(ref s) = label { |
7cac9316 XL |
579 | // If it has a custom "#[rustc_on_unimplemented]" |
580 | // error message, let's display it as the label! | |
581 | err.span_label(span, s.as_str()); | |
582 | err.help(&format!("{}the trait `{}` is not implemented for `{}`", | |
583 | pre_message, | |
584 | trait_ref, | |
585 | trait_ref.self_ty())); | |
586 | } else { | |
587 | err.span_label(span, | |
588 | &*format!("{}the trait `{}` is not implemented for `{}`", | |
589 | pre_message, | |
590 | trait_ref, | |
591 | trait_ref.self_ty())); | |
592 | } | |
593 | ||
8bb4bdeb | 594 | // Try to report a help message |
8bb4bdeb | 595 | if !trait_ref.has_infer_types() && |
7cac9316 | 596 | self.predicate_can_apply(obligation.param_env, trait_ref) { |
8bb4bdeb XL |
597 | // If a where-clause may be useful, remind the |
598 | // user that they can add it. | |
599 | // | |
600 | // don't display an on-unimplemented note, as | |
601 | // these notes will often be of the form | |
602 | // "the type `T` can't be frobnicated" | |
603 | // which is somewhat confusing. | |
604 | err.help(&format!("consider adding a `where {}` bound", | |
605 | trait_ref.to_predicate())); | |
ea8adc8c | 606 | } else if !have_alt_message { |
cc61c64b | 607 | // Can't show anything else useful, try to find similar impls. |
8bb4bdeb XL |
608 | let impl_candidates = self.find_similar_impl_candidates(trait_ref); |
609 | self.report_similar_impl_candidates(impl_candidates, &mut err); | |
a7813a04 | 610 | } |
cc61c64b | 611 | |
8bb4bdeb XL |
612 | err |
613 | } | |
7453a54e | 614 | |
cc61c64b XL |
615 | ty::Predicate::Subtype(ref predicate) => { |
616 | // Errors for Subtype predicates show up as | |
617 | // `FulfillmentErrorCode::CodeSubtypeError`, | |
618 | // not selection error. | |
619 | span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) | |
620 | } | |
621 | ||
8bb4bdeb XL |
622 | ty::Predicate::Equate(ref predicate) => { |
623 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
624 | let err = self.equality_predicate(&obligation.cause, | |
7cac9316 XL |
625 | obligation.param_env, |
626 | &predicate).err().unwrap(); | |
8bb4bdeb XL |
627 | struct_span_err!(self.tcx.sess, span, E0278, |
628 | "the requirement `{}` is not satisfied (`{}`)", | |
629 | predicate, err) | |
630 | } | |
e9174d1e | 631 | |
8bb4bdeb XL |
632 | ty::Predicate::RegionOutlives(ref predicate) => { |
633 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
634 | let err = self.region_outlives_predicate(&obligation.cause, | |
635 | &predicate).err().unwrap(); | |
636 | struct_span_err!(self.tcx.sess, span, E0279, | |
637 | "the requirement `{}` is not satisfied (`{}`)", | |
638 | predicate, err) | |
639 | } | |
85aaf69f | 640 | |
8bb4bdeb XL |
641 | ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { |
642 | let predicate = | |
643 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
644 | struct_span_err!(self.tcx.sess, span, E0280, | |
645 | "the requirement `{}` is not satisfied", | |
646 | predicate) | |
647 | } | |
e9174d1e | 648 | |
8bb4bdeb XL |
649 | ty::Predicate::ObjectSafe(trait_def_id) => { |
650 | let violations = self.tcx.object_safety_violations(trait_def_id); | |
651 | self.tcx.report_object_safety_error(span, | |
652 | trait_def_id, | |
653 | violations) | |
654 | } | |
655 | ||
656 | ty::Predicate::ClosureKind(closure_def_id, kind) => { | |
657 | let found_kind = self.closure_kind(closure_def_id).unwrap(); | |
658 | let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); | |
041b39d2 | 659 | let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); |
8bb4bdeb XL |
660 | let mut err = struct_span_err!( |
661 | self.tcx.sess, closure_span, E0525, | |
662 | "expected a closure that implements the `{}` trait, \ | |
663 | but this closure only implements `{}`", | |
664 | kind, | |
665 | found_kind); | |
041b39d2 XL |
666 | |
667 | err.span_label( | |
8bb4bdeb | 668 | obligation.cause.span, |
041b39d2 XL |
669 | format!("the requirement to implement `{}` derives from here", kind)); |
670 | ||
671 | // Additional context information explaining why the closure only implements | |
672 | // a particular trait. | |
673 | if let Some(tables) = self.in_progress_tables { | |
3b2f2976 XL |
674 | let tables = tables.borrow(); |
675 | let closure_hir_id = self.tcx.hir.node_to_hir_id(node_id); | |
676 | match tables.closure_kinds().get(closure_hir_id) { | |
041b39d2 XL |
677 | Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { |
678 | err.span_note(span, &format!( | |
679 | "closure is `FnOnce` because it moves the \ | |
680 | variable `{}` out of its environment", name)); | |
681 | }, | |
682 | Some(&(ty::ClosureKind::FnMut, Some((span, name)))) => { | |
683 | err.span_note(span, &format!( | |
684 | "closure is `FnMut` because it mutates the \ | |
685 | variable `{}` here", name)); | |
686 | }, | |
687 | _ => {} | |
688 | } | |
689 | } | |
690 | ||
8bb4bdeb XL |
691 | err.emit(); |
692 | return; | |
693 | } | |
694 | ||
695 | ty::Predicate::WellFormed(ty) => { | |
696 | // WF predicates cannot themselves make | |
697 | // errors. They can only block due to | |
698 | // ambiguity; otherwise, they always | |
699 | // degenerate into other obligations | |
700 | // (which may fail). | |
701 | span_bug!(span, "WF predicate not satisfied for {:?}", ty); | |
85aaf69f | 702 | } |
ea8adc8c XL |
703 | |
704 | ty::Predicate::ConstEvaluatable(..) => { | |
705 | // Errors for `ConstEvaluatable` predicates show up as | |
706 | // `SelectionError::ConstEvalFailure`, | |
707 | // not `Unimplemented`. | |
708 | span_bug!(span, | |
709 | "const-evaluatable requirement gave wrong error: `{:?}`", obligation) | |
710 | } | |
1a4d82fc JJ |
711 | } |
712 | } | |
85aaf69f | 713 | |
ea8adc8c | 714 | OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, _) => { |
a7813a04 XL |
715 | let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); |
716 | let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref); | |
717 | if actual_trait_ref.self_ty().references_error() { | |
718 | return; | |
719 | } | |
7cac9316 XL |
720 | let expected_trait_ty = expected_trait_ref.self_ty(); |
721 | let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| { | |
722 | self.tcx.hir.span_if_local(did) | |
723 | }); | |
724 | ||
ea8adc8c XL |
725 | let self_ty_count = |
726 | match expected_trait_ref.skip_binder().substs.type_at(1).sty { | |
727 | ty::TyTuple(ref tys, _) => tys.len(), | |
728 | _ => 1, | |
7cac9316 | 729 | }; |
ea8adc8c XL |
730 | let arg_ty_count = |
731 | match actual_trait_ref.skip_binder().substs.type_at(1).sty { | |
732 | ty::TyTuple(ref tys, _) => tys.len(), | |
733 | _ => 1, | |
7cac9316 | 734 | }; |
ea8adc8c XL |
735 | if self_ty_count == arg_ty_count { |
736 | self.report_closure_arg_mismatch(span, | |
737 | found_span, | |
738 | expected_trait_ref, | |
739 | actual_trait_ref) | |
7cac9316 | 740 | } else { |
ea8adc8c XL |
741 | // Expected `|| { }`, found `|x, y| { }` |
742 | // Expected `fn(x) -> ()`, found `|| { }` | |
743 | self.report_arg_count_mismatch( | |
744 | span, | |
745 | found_span, | |
746 | arg_ty_count, | |
747 | self_ty_count, | |
748 | expected_trait_ty.is_closure() | |
749 | ) | |
7cac9316 | 750 | } |
1a4d82fc | 751 | } |
d9579d0f | 752 | |
a7813a04 XL |
753 | TraitNotObjectSafe(did) => { |
754 | let violations = self.tcx.object_safety_violations(did); | |
9e0c209e SL |
755 | self.tcx.report_object_safety_error(span, did, |
756 | violations) | |
a7813a04 | 757 | } |
ea8adc8c XL |
758 | |
759 | ConstEvalFailure(ref err) => { | |
760 | if let const_val::ErrKind::TypeckError = err.kind { | |
761 | return; | |
762 | } | |
763 | err.struct_error(self.tcx, span, "constant expression") | |
764 | } | |
a7813a04 XL |
765 | }; |
766 | self.note_obligation_cause(&mut err, obligation); | |
767 | err.emit(); | |
e9174d1e | 768 | } |
7cac9316 | 769 | |
7cac9316 XL |
770 | fn report_arg_count_mismatch(&self, |
771 | span: Span, | |
772 | found_span: Option<Span>, | |
773 | expected: usize, | |
774 | found: usize, | |
775 | is_closure: bool) | |
776 | -> DiagnosticBuilder<'tcx> | |
777 | { | |
778 | let mut err = struct_span_err!(self.tcx.sess, span, E0593, | |
779 | "{} takes {} argument{} but {} argument{} {} required", | |
780 | if is_closure { "closure" } else { "function" }, | |
781 | found, | |
782 | if found == 1 { "" } else { "s" }, | |
783 | expected, | |
784 | if expected == 1 { "" } else { "s" }, | |
785 | if expected == 1 { "is" } else { "are" }); | |
786 | ||
787 | err.span_label(span, format!("expected {} that takes {} argument{}", | |
788 | if is_closure { "closure" } else { "function" }, | |
789 | expected, | |
790 | if expected == 1 { "" } else { "s" })); | |
791 | if let Some(span) = found_span { | |
792 | err.span_label(span, format!("takes {} argument{}", | |
793 | found, | |
794 | if found == 1 { "" } else { "s" })); | |
795 | } | |
796 | err | |
797 | } | |
ea8adc8c XL |
798 | |
799 | fn report_closure_arg_mismatch(&self, | |
800 | span: Span, | |
801 | found_span: Option<Span>, | |
802 | expected_ref: ty::PolyTraitRef<'tcx>, | |
803 | found: ty::PolyTraitRef<'tcx>) | |
804 | -> DiagnosticBuilder<'tcx> | |
805 | { | |
806 | fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, | |
807 | trait_ref: &ty::TraitRef<'tcx>) -> String { | |
808 | let inputs = trait_ref.substs.type_at(1); | |
809 | let sig = if let ty::TyTuple(inputs, _) = inputs.sty { | |
810 | tcx.mk_fn_sig( | |
811 | inputs.iter().map(|&x| x), | |
812 | tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), | |
813 | false, | |
814 | hir::Unsafety::Normal, | |
815 | ::syntax::abi::Abi::Rust | |
816 | ) | |
817 | } else { | |
818 | tcx.mk_fn_sig( | |
819 | ::std::iter::once(inputs), | |
820 | tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), | |
821 | false, | |
822 | hir::Unsafety::Normal, | |
823 | ::syntax::abi::Abi::Rust | |
824 | ) | |
825 | }; | |
826 | format!("{}", ty::Binder(sig)) | |
827 | } | |
828 | ||
829 | let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure(); | |
830 | let mut err = struct_span_err!(self.tcx.sess, span, E0631, | |
831 | "type mismatch in {} arguments", | |
832 | if argument_is_closure { "closure" } else { "function" }); | |
833 | ||
834 | let found_str = format!( | |
835 | "expected signature of `{}`", | |
836 | build_fn_sig_string(self.tcx, found.skip_binder()) | |
837 | ); | |
838 | err.span_label(span, found_str); | |
839 | ||
840 | let found_span = found_span.unwrap_or(span); | |
841 | let expected_str = format!( | |
842 | "found signature of `{}`", | |
843 | build_fn_sig_string(self.tcx, expected_ref.skip_binder()) | |
844 | ); | |
845 | err.span_label(found_span, expected_str); | |
846 | ||
847 | err | |
848 | } | |
e9174d1e | 849 | } |
d9579d0f | 850 | |
a7813a04 XL |
851 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
852 | pub fn recursive_type_with_infinite_size_error(self, | |
853 | type_def_id: DefId) | |
854 | -> DiagnosticBuilder<'tcx> | |
855 | { | |
856 | assert!(type_def_id.is_local()); | |
32a655c1 | 857 | let span = self.hir.span_if_local(type_def_id).unwrap(); |
cc61c64b | 858 | let span = self.sess.codemap().def_span(span); |
a7813a04 XL |
859 | let mut err = struct_span_err!(self.sess, span, E0072, |
860 | "recursive type `{}` has infinite size", | |
861 | self.item_path_str(type_def_id)); | |
7cac9316 | 862 | err.span_label(span, "recursive type has infinite size"); |
a7813a04 XL |
863 | err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \ |
864 | at some point to make `{}` representable", | |
865 | self.item_path_str(type_def_id))); | |
866 | err | |
867 | } | |
d9579d0f | 868 | |
a7813a04 XL |
869 | pub fn report_object_safety_error(self, |
870 | span: Span, | |
871 | trait_def_id: DefId, | |
a7813a04 | 872 | violations: Vec<ObjectSafetyViolation>) |
9e0c209e | 873 | -> DiagnosticBuilder<'tcx> |
a7813a04 | 874 | { |
9e0c209e | 875 | let trait_str = self.item_path_str(trait_def_id); |
cc61c64b | 876 | let span = self.sess.codemap().def_span(span); |
9e0c209e SL |
877 | let mut err = struct_span_err!( |
878 | self.sess, span, E0038, | |
879 | "the trait `{}` cannot be made into an object", | |
880 | trait_str); | |
7cac9316 | 881 | err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str)); |
d9579d0f | 882 | |
476ff2be | 883 | let mut reported_violations = FxHashSet(); |
a7813a04 XL |
884 | for violation in violations { |
885 | if !reported_violations.insert(violation.clone()) { | |
886 | continue; | |
e9174d1e | 887 | } |
8bb4bdeb | 888 | err.note(&violation.error_msg()); |
d9579d0f | 889 | } |
a7813a04 | 890 | err |
1a4d82fc JJ |
891 | } |
892 | } | |
893 | ||
a7813a04 | 894 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
041b39d2 XL |
895 | fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, |
896 | body_id: Option<hir::BodyId>) { | |
a7813a04 XL |
897 | // Unable to successfully determine, probably means |
898 | // insufficient type information, but could mean | |
899 | // ambiguous impls. The latter *ought* to be a | |
900 | // coherence violation, so we don't report it here. | |
901 | ||
902 | let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); | |
cc61c64b | 903 | let span = obligation.cause.span; |
a7813a04 XL |
904 | |
905 | debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", | |
906 | predicate, | |
907 | obligation); | |
908 | ||
909 | // Ambiguity errors are often caused as fallout from earlier | |
910 | // errors. So just ignore them if this infcx is tainted. | |
911 | if self.is_tainted_by_errors() { | |
912 | return; | |
913 | } | |
914 | ||
915 | match predicate { | |
916 | ty::Predicate::Trait(ref data) => { | |
917 | let trait_ref = data.to_poly_trait_ref(); | |
918 | let self_ty = trait_ref.self_ty(); | |
9e0c209e | 919 | if predicate.references_error() { |
8bb4bdeb XL |
920 | return; |
921 | } | |
922 | // Typically, this ambiguity should only happen if | |
923 | // there are unresolved type inference variables | |
924 | // (otherwise it would suggest a coherence | |
925 | // failure). But given #21974 that is not necessarily | |
926 | // the case -- we can have multiple where clauses that | |
927 | // are only distinguished by a region, which results | |
928 | // in an ambiguity even when all types are fully | |
929 | // known, since we don't dispatch based on region | |
930 | // relationships. | |
931 | ||
932 | // This is kind of a hack: it frequently happens that some earlier | |
933 | // error prevents types from being fully inferred, and then we get | |
934 | // a bunch of uninteresting errors saying something like "<generic | |
935 | // #0> doesn't implement Sized". It may even be true that we | |
936 | // could just skip over all checks where the self-ty is an | |
937 | // inference variable, but I was afraid that there might be an | |
938 | // inference variable created, registered as an obligation, and | |
939 | // then never forced by writeback, and hence by skipping here we'd | |
940 | // be ignoring the fact that we don't KNOW the type works | |
941 | // out. Though even that would probably be harmless, given that | |
942 | // we're only talking about builtin traits, which are known to be | |
943 | // inhabited. But in any case I just threw in this check for | |
944 | // has_errors() to be sure that compilation isn't happening | |
945 | // anyway. In that case, why inundate the user. | |
946 | if !self.tcx.sess.has_errors() { | |
947 | if | |
ea8adc8c | 948 | self.tcx.lang_items().sized_trait() |
8bb4bdeb XL |
949 | .map_or(false, |sized_id| sized_id == trait_ref.def_id()) |
950 | { | |
cc61c64b | 951 | self.need_type_info(body_id, span, self_ty); |
8bb4bdeb XL |
952 | } else { |
953 | let mut err = struct_span_err!(self.tcx.sess, | |
cc61c64b | 954 | span, E0283, |
8bb4bdeb XL |
955 | "type annotations required: \ |
956 | cannot resolve `{}`", | |
957 | predicate); | |
958 | self.note_obligation_cause(&mut err, obligation); | |
959 | err.emit(); | |
1a4d82fc JJ |
960 | } |
961 | } | |
1a4d82fc | 962 | } |
1a4d82fc | 963 | |
a7813a04 XL |
964 | ty::Predicate::WellFormed(ty) => { |
965 | // Same hacky approach as above to avoid deluging user | |
966 | // with error messages. | |
967 | if !ty.references_error() && !self.tcx.sess.has_errors() { | |
cc61c64b XL |
968 | self.need_type_info(body_id, span, ty); |
969 | } | |
970 | } | |
971 | ||
972 | ty::Predicate::Subtype(ref data) => { | |
973 | if data.references_error() || self.tcx.sess.has_errors() { | |
974 | // no need to overload user in such cases | |
975 | } else { | |
976 | let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); | |
977 | // both must be type variables, or the other would've been instantiated | |
978 | assert!(a.is_ty_var() && b.is_ty_var()); | |
041b39d2 | 979 | self.need_type_info(body_id, |
cc61c64b XL |
980 | obligation.cause.span, |
981 | a); | |
a7813a04 | 982 | } |
e9174d1e | 983 | } |
e9174d1e | 984 | |
a7813a04 XL |
985 | _ => { |
986 | if !self.tcx.sess.has_errors() { | |
987 | let mut err = struct_span_err!(self.tcx.sess, | |
988 | obligation.cause.span, E0284, | |
989 | "type annotations required: \ | |
990 | cannot resolve `{}`", | |
991 | predicate); | |
992 | self.note_obligation_cause(&mut err, obligation); | |
993 | err.emit(); | |
994 | } | |
1a4d82fc JJ |
995 | } |
996 | } | |
997 | } | |
1a4d82fc | 998 | |
a7813a04 XL |
999 | /// Returns whether the trait predicate may apply for *some* assignment |
1000 | /// to the type parameters. | |
7cac9316 XL |
1001 | fn predicate_can_apply(&self, |
1002 | param_env: ty::ParamEnv<'tcx>, | |
1003 | pred: ty::PolyTraitRef<'tcx>) | |
1004 | -> bool { | |
a7813a04 XL |
1005 | struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { |
1006 | infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, | |
476ff2be | 1007 | var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>> |
a7813a04 | 1008 | } |
54a0048b | 1009 | |
a7813a04 XL |
1010 | impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> { |
1011 | fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } | |
54a0048b | 1012 | |
a7813a04 | 1013 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { |
476ff2be | 1014 | if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty { |
a7813a04 | 1015 | let infcx = self.infcx; |
476ff2be SL |
1016 | self.var_map.entry(ty).or_insert_with(|| |
1017 | infcx.next_ty_var( | |
1018 | TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name))) | |
a7813a04 XL |
1019 | } else { |
1020 | ty.super_fold_with(self) | |
1021 | } | |
54a0048b SL |
1022 | } |
1023 | } | |
54a0048b | 1024 | |
a7813a04 XL |
1025 | self.probe(|_| { |
1026 | let mut selcx = SelectionContext::new(self); | |
54a0048b | 1027 | |
a7813a04 XL |
1028 | let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { |
1029 | infcx: self, | |
476ff2be | 1030 | var_map: FxHashMap() |
a7813a04 | 1031 | }); |
54a0048b | 1032 | |
a7813a04 XL |
1033 | let cleaned_pred = super::project::normalize( |
1034 | &mut selcx, | |
7cac9316 | 1035 | param_env, |
a7813a04 XL |
1036 | ObligationCause::dummy(), |
1037 | &cleaned_pred | |
1038 | ).value; | |
54a0048b | 1039 | |
a7813a04 XL |
1040 | let obligation = Obligation::new( |
1041 | ObligationCause::dummy(), | |
7cac9316 | 1042 | param_env, |
a7813a04 XL |
1043 | cleaned_pred.to_predicate() |
1044 | ); | |
54a0048b | 1045 | |
a7813a04 XL |
1046 | selcx.evaluate_obligation(&obligation) |
1047 | }) | |
1048 | } | |
54a0048b | 1049 | |
a7813a04 XL |
1050 | fn note_obligation_cause<T>(&self, |
1051 | err: &mut DiagnosticBuilder, | |
1052 | obligation: &Obligation<'tcx, T>) | |
1053 | where T: fmt::Display | |
1054 | { | |
1055 | self.note_obligation_cause_code(err, | |
1056 | &obligation.predicate, | |
1057 | &obligation.cause.code); | |
1058 | } | |
1a4d82fc | 1059 | |
a7813a04 XL |
1060 | fn note_obligation_cause_code<T>(&self, |
1061 | err: &mut DiagnosticBuilder, | |
1062 | predicate: &T, | |
1063 | cause_code: &ObligationCauseCode<'tcx>) | |
1064 | where T: fmt::Display | |
1065 | { | |
1066 | let tcx = self.tcx; | |
1067 | match *cause_code { | |
476ff2be SL |
1068 | ObligationCauseCode::ExprAssignable | |
1069 | ObligationCauseCode::MatchExpressionArm { .. } | | |
1070 | ObligationCauseCode::IfExpression | | |
1071 | ObligationCauseCode::IfExpressionWithNoElse | | |
1072 | ObligationCauseCode::EquatePredicate | | |
1073 | ObligationCauseCode::MainFunctionType | | |
1074 | ObligationCauseCode::StartFunctionType | | |
1075 | ObligationCauseCode::IntrinsicType | | |
1076 | ObligationCauseCode::MethodReceiver | | |
cc61c64b | 1077 | ObligationCauseCode::ReturnNoExpression | |
476ff2be SL |
1078 | ObligationCauseCode::MiscObligation => { |
1079 | } | |
a7813a04 XL |
1080 | ObligationCauseCode::SliceOrArrayElem => { |
1081 | err.note("slice and array elements must have `Sized` type"); | |
1082 | } | |
1083 | ObligationCauseCode::TupleElem => { | |
041b39d2 | 1084 | err.note("only the last element of a tuple may have a dynamically sized type"); |
a7813a04 XL |
1085 | } |
1086 | ObligationCauseCode::ProjectionWf(data) => { | |
1087 | err.note(&format!("required so that the projection `{}` is well-formed", | |
1088 | data)); | |
1089 | } | |
1090 | ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { | |
1091 | err.note(&format!("required so that reference `{}` does not outlive its referent", | |
1092 | ref_ty)); | |
1093 | } | |
c30ab7b3 SL |
1094 | ObligationCauseCode::ObjectTypeBound(object_ty, region) => { |
1095 | err.note(&format!("required so that the lifetime bound of `{}` for `{}` \ | |
1096 | is satisfied", | |
1097 | region, object_ty)); | |
1098 | } | |
a7813a04 XL |
1099 | ObligationCauseCode::ItemObligation(item_def_id) => { |
1100 | let item_name = tcx.item_path_str(item_def_id); | |
1101 | err.note(&format!("required by `{}`", item_name)); | |
1102 | } | |
1103 | ObligationCauseCode::ObjectCastObligation(object_ty) => { | |
1104 | err.note(&format!("required for the cast to the object type `{}`", | |
1105 | self.ty_to_string(object_ty))); | |
1106 | } | |
1107 | ObligationCauseCode::RepeatVec => { | |
1108 | err.note("the `Copy` trait is required because the \ | |
1109 | repeated element will be copied"); | |
1110 | } | |
1111 | ObligationCauseCode::VariableType(_) => { | |
1112 | err.note("all local variables must have a statically known size"); | |
1113 | } | |
041b39d2 | 1114 | ObligationCauseCode::SizedReturnType => { |
a7813a04 XL |
1115 | err.note("the return type of a function must have a \ |
1116 | statically known size"); | |
1117 | } | |
1118 | ObligationCauseCode::AssignmentLhsSized => { | |
1119 | err.note("the left-hand-side of an assignment must have a statically known size"); | |
1120 | } | |
041b39d2 XL |
1121 | ObligationCauseCode::TupleInitializerSized => { |
1122 | err.note("tuples must have a statically known size to be initialized"); | |
1123 | } | |
a7813a04 XL |
1124 | ObligationCauseCode::StructInitializerSized => { |
1125 | err.note("structs must have a statically known size to be initialized"); | |
1126 | } | |
3b2f2976 XL |
1127 | ObligationCauseCode::FieldSized(ref item) => { |
1128 | match *item { | |
1129 | AdtKind::Struct => { | |
1130 | err.note("only the last field of a struct may have a dynamically \ | |
1131 | sized type"); | |
1132 | } | |
1133 | AdtKind::Union => { | |
1134 | err.note("no field of a union may have a dynamically sized type"); | |
1135 | } | |
1136 | AdtKind::Enum => { | |
1137 | err.note("no field of an enum variant may have a dynamically sized type"); | |
1138 | } | |
1139 | } | |
a7813a04 | 1140 | } |
3157f602 XL |
1141 | ObligationCauseCode::ConstSized => { |
1142 | err.note("constant expressions must have a statically known size"); | |
1143 | } | |
a7813a04 XL |
1144 | ObligationCauseCode::SharedStatic => { |
1145 | err.note("shared static variables must have a type that implements `Sync`"); | |
1146 | } | |
1147 | ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
1148 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
1149 | err.note(&format!("required because it appears within the type `{}`", | |
1150 | parent_trait_ref.0.self_ty())); | |
1151 | let parent_predicate = parent_trait_ref.to_predicate(); | |
1152 | self.note_obligation_cause_code(err, | |
1153 | &parent_predicate, | |
1154 | &data.parent_code); | |
1155 | } | |
1156 | ObligationCauseCode::ImplDerivedObligation(ref data) => { | |
1157 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
1158 | err.note( | |
1159 | &format!("required because of the requirements on the impl of `{}` for `{}`", | |
1160 | parent_trait_ref, | |
1161 | parent_trait_ref.0.self_ty())); | |
1162 | let parent_predicate = parent_trait_ref.to_predicate(); | |
1163 | self.note_obligation_cause_code(err, | |
1164 | &parent_predicate, | |
1165 | &data.parent_code); | |
1166 | } | |
c30ab7b3 | 1167 | ObligationCauseCode::CompareImplMethodObligation { .. } => { |
a7813a04 XL |
1168 | err.note( |
1169 | &format!("the requirement `{}` appears on the impl method \ | |
1170 | but not on the corresponding trait method", | |
1171 | predicate)); | |
1172 | } | |
041b39d2 XL |
1173 | ObligationCauseCode::ReturnType(_) | |
1174 | ObligationCauseCode::BlockTailExpression(_) => (), | |
85aaf69f | 1175 | } |
1a4d82fc | 1176 | } |
1a4d82fc | 1177 | |
a7813a04 XL |
1178 | fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { |
1179 | let current_limit = self.tcx.sess.recursion_limit.get(); | |
1180 | let suggested_limit = current_limit * 2; | |
3b2f2976 | 1181 | err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", |
a7813a04 XL |
1182 | suggested_limit)); |
1183 | } | |
1a4d82fc | 1184 | } |