]>
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; |
8bb4bdeb | 36 | use std::fmt; |
041b39d2 | 37 | use syntax::ast; |
abe05a73 | 38 | use session::DiagnosticMessageId; |
041b39d2 | 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 | 221 | |
abe05a73 XL |
222 | let msg = format!("type mismatch resolving `{}`", predicate); |
223 | let error_id = (DiagnosticMessageId::ErrorId(271), | |
224 | Some(obligation.cause.span), msg.clone()); | |
225 | let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); | |
226 | if fresh { | |
227 | let mut diag = struct_span_err!( | |
228 | self.tcx.sess, obligation.cause.span, E0271, | |
229 | "type mismatch resolving `{}`", predicate | |
230 | ); | |
231 | self.note_type_err(&mut diag, &obligation.cause, None, values, err); | |
232 | self.note_obligation_cause(&mut diag, obligation); | |
233 | diag.emit(); | |
234 | } | |
5bcae85e | 235 | }); |
a7813a04 XL |
236 | } |
237 | ||
a7813a04 XL |
238 | fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { |
239 | /// returns the fuzzy category of a given type, or None | |
240 | /// if the type can be equated to any type. | |
241 | fn type_category<'tcx>(t: Ty<'tcx>) -> Option<u32> { | |
242 | match t.sty { | |
243 | ty::TyBool => Some(0), | |
244 | ty::TyChar => Some(1), | |
245 | ty::TyStr => Some(2), | |
9e0c209e | 246 | ty::TyInt(..) | ty::TyUint(..) | ty::TyInfer(ty::IntVar(..)) => Some(3), |
a7813a04 | 247 | ty::TyFloat(..) | ty::TyInfer(ty::FloatVar(..)) => Some(4), |
32a655c1 | 248 | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), |
9e0c209e SL |
249 | ty::TyArray(..) | ty::TySlice(..) => Some(6), |
250 | ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), | |
476ff2be | 251 | ty::TyDynamic(..) => Some(8), |
9e0c209e SL |
252 | ty::TyClosure(..) => Some(9), |
253 | ty::TyTuple(..) => Some(10), | |
254 | ty::TyProjection(..) => Some(11), | |
255 | ty::TyParam(..) => Some(12), | |
256 | ty::TyAnon(..) => Some(13), | |
257 | ty::TyNever => Some(14), | |
258 | ty::TyAdt(adt, ..) => match adt.adt_kind() { | |
259 | AdtKind::Struct => Some(15), | |
260 | AdtKind::Union => Some(16), | |
261 | AdtKind::Enum => Some(17), | |
262 | }, | |
ea8adc8c | 263 | ty::TyGenerator(..) => Some(18), |
abe05a73 | 264 | ty::TyForeign(..) => Some(19), |
a7813a04 XL |
265 | ty::TyInfer(..) | ty::TyError => None |
266 | } | |
267 | } | |
268 | ||
269 | match (type_category(a), type_category(b)) { | |
270 | (Some(cat_a), Some(cat_b)) => match (&a.sty, &b.sty) { | |
9e0c209e | 271 | (&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => def_a == def_b, |
a7813a04 XL |
272 | _ => cat_a == cat_b |
273 | }, | |
274 | // infer and error can be equated to all types | |
275 | _ => true | |
1a4d82fc JJ |
276 | } |
277 | } | |
1a4d82fc | 278 | |
a7813a04 XL |
279 | fn impl_similar_to(&self, |
280 | trait_ref: ty::PolyTraitRef<'tcx>, | |
281 | obligation: &PredicateObligation<'tcx>) | |
282 | -> Option<DefId> | |
283 | { | |
284 | let tcx = self.tcx; | |
7cac9316 | 285 | let param_env = obligation.param_env; |
a7813a04 XL |
286 | let trait_ref = tcx.erase_late_bound_regions(&trait_ref); |
287 | let trait_self_ty = trait_ref.self_ty(); | |
288 | ||
289 | let mut self_match_impls = vec![]; | |
290 | let mut fuzzy_match_impls = vec![]; | |
291 | ||
041b39d2 XL |
292 | self.tcx.for_each_relevant_impl( |
293 | trait_ref.def_id, trait_self_ty, |def_id| { | |
9e0c209e | 294 | let impl_substs = self.fresh_substs_for_item(obligation.cause.span, def_id); |
a7813a04 XL |
295 | let impl_trait_ref = tcx |
296 | .impl_trait_ref(def_id) | |
297 | .unwrap() | |
9e0c209e | 298 | .subst(tcx, impl_substs); |
a7813a04 XL |
299 | |
300 | let impl_self_ty = impl_trait_ref.self_ty(); | |
301 | ||
7cac9316 | 302 | if let Ok(..) = self.can_eq(param_env, trait_self_ty, impl_self_ty) { |
a7813a04 XL |
303 | self_match_impls.push(def_id); |
304 | ||
9e0c209e SL |
305 | if trait_ref.substs.types().skip(1) |
306 | .zip(impl_trait_ref.substs.types().skip(1)) | |
a7813a04 XL |
307 | .all(|(u,v)| self.fuzzy_match_tys(u, v)) |
308 | { | |
309 | fuzzy_match_impls.push(def_id); | |
310 | } | |
311 | } | |
312 | }); | |
313 | ||
314 | let impl_def_id = if self_match_impls.len() == 1 { | |
315 | self_match_impls[0] | |
316 | } else if fuzzy_match_impls.len() == 1 { | |
317 | fuzzy_match_impls[0] | |
318 | } else { | |
319 | return None | |
320 | }; | |
321 | ||
322 | if tcx.has_attr(impl_def_id, "rustc_on_unimplemented") { | |
323 | Some(impl_def_id) | |
324 | } else { | |
325 | None | |
326 | } | |
1a4d82fc | 327 | } |
1a4d82fc | 328 | |
ea8adc8c XL |
329 | fn on_unimplemented_note( |
330 | &self, | |
331 | trait_ref: ty::PolyTraitRef<'tcx>, | |
332 | obligation: &PredicateObligation<'tcx>) -> | |
333 | OnUnimplementedNote | |
334 | { | |
a7813a04 XL |
335 | let def_id = self.impl_similar_to(trait_ref, obligation) |
336 | .unwrap_or(trait_ref.def_id()); | |
ea8adc8c XL |
337 | let trait_ref = *trait_ref.skip_binder(); |
338 | ||
339 | let desugaring; | |
340 | let method; | |
341 | let mut flags = vec![]; | |
342 | let direct = match obligation.cause.code { | |
343 | ObligationCauseCode::BuiltinDerivedObligation(..) | | |
344 | ObligationCauseCode::ImplDerivedObligation(..) => false, | |
345 | _ => true | |
346 | }; | |
347 | if direct { | |
348 | // this is a "direct", user-specified, rather than derived, | |
349 | // obligation. | |
350 | flags.push(("direct", None)); | |
351 | } | |
a7813a04 | 352 | |
ea8adc8c XL |
353 | if let ObligationCauseCode::ItemObligation(item) = obligation.cause.code { |
354 | // FIXME: maybe also have some way of handling methods | |
355 | // from other traits? That would require name resolution, | |
356 | // which we might want to be some sort of hygienic. | |
357 | // | |
358 | // Currently I'm leaving it for what I need for `try`. | |
359 | if self.tcx.trait_of_item(item) == Some(trait_ref.def_id) { | |
360 | method = self.tcx.item_name(item); | |
361 | flags.push(("from_method", None)); | |
362 | flags.push(("from_method", Some(&*method))); | |
85aaf69f | 363 | } |
85aaf69f | 364 | } |
ea8adc8c XL |
365 | |
366 | if let Some(k) = obligation.cause.span.compiler_desugaring_kind() { | |
367 | desugaring = k.as_symbol().as_str(); | |
368 | flags.push(("from_desugaring", None)); | |
369 | flags.push(("from_desugaring", Some(&*desugaring))); | |
370 | } | |
371 | ||
372 | if let Ok(Some(command)) = OnUnimplementedDirective::of_item( | |
373 | self.tcx, trait_ref.def_id, def_id | |
374 | ) { | |
375 | command.evaluate(self.tcx, trait_ref, &flags) | |
376 | } else { | |
377 | OnUnimplementedNote::empty() | |
378 | } | |
85aaf69f | 379 | } |
85aaf69f | 380 | |
a7813a04 XL |
381 | fn find_similar_impl_candidates(&self, |
382 | trait_ref: ty::PolyTraitRef<'tcx>) | |
383 | -> Vec<ty::TraitRef<'tcx>> | |
384 | { | |
385 | let simp = fast_reject::simplify_type(self.tcx, | |
386 | trait_ref.skip_binder().self_ty(), | |
387 | true); | |
388 | let mut impl_candidates = Vec::new(); | |
a7813a04 XL |
389 | |
390 | match simp { | |
041b39d2 | 391 | Some(simp) => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { |
a7813a04 XL |
392 | let imp = self.tcx.impl_trait_ref(def_id).unwrap(); |
393 | let imp_simp = fast_reject::simplify_type(self.tcx, | |
394 | imp.self_ty(), | |
395 | true); | |
396 | if let Some(imp_simp) = imp_simp { | |
397 | if simp != imp_simp { | |
398 | return; | |
399 | } | |
54a0048b | 400 | } |
a7813a04 XL |
401 | impl_candidates.push(imp); |
402 | }), | |
041b39d2 | 403 | None => self.tcx.for_each_impl(trait_ref.def_id(), |def_id| { |
a7813a04 XL |
404 | impl_candidates.push( |
405 | self.tcx.impl_trait_ref(def_id).unwrap()); | |
406 | }) | |
407 | }; | |
408 | impl_candidates | |
409 | } | |
54a0048b | 410 | |
a7813a04 | 411 | fn report_similar_impl_candidates(&self, |
8bb4bdeb | 412 | impl_candidates: Vec<ty::TraitRef<'tcx>>, |
a7813a04 XL |
413 | err: &mut DiagnosticBuilder) |
414 | { | |
a7813a04 XL |
415 | if impl_candidates.is_empty() { |
416 | return; | |
417 | } | |
418 | ||
8bb4bdeb XL |
419 | let end = if impl_candidates.len() <= 5 { |
420 | impl_candidates.len() | |
421 | } else { | |
422 | 4 | |
423 | }; | |
32a655c1 SL |
424 | err.help(&format!("the following implementations were found:{}{}", |
425 | &impl_candidates[0..end].iter().map(|candidate| { | |
426 | format!("\n {:?}", candidate) | |
427 | }).collect::<String>(), | |
8bb4bdeb | 428 | if impl_candidates.len() > 5 { |
32a655c1 SL |
429 | format!("\nand {} others", impl_candidates.len() - 4) |
430 | } else { | |
431 | "".to_owned() | |
432 | } | |
433 | )); | |
7453a54e | 434 | } |
c34b1796 | 435 | |
a7813a04 XL |
436 | /// Reports that an overflow has occurred and halts compilation. We |
437 | /// halt compilation unconditionally because it is important that | |
438 | /// overflows never be masked -- they basically represent computations | |
439 | /// whose result could not be truly determined and thus we can't say | |
440 | /// if the program type checks or not -- and they are unusual | |
441 | /// occurrences in any case. | |
442 | pub fn report_overflow_error<T>(&self, | |
443 | obligation: &Obligation<'tcx, T>, | |
444 | suggest_increasing_limit: bool) -> ! | |
445 | where T: fmt::Display + TypeFoldable<'tcx> | |
446 | { | |
447 | let predicate = | |
448 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
449 | let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275, | |
450 | "overflow evaluating the requirement `{}`", | |
451 | predicate); | |
c34b1796 | 452 | |
a7813a04 XL |
453 | if suggest_increasing_limit { |
454 | self.suggest_new_overflow_limit(&mut err); | |
455 | } | |
c34b1796 | 456 | |
a7813a04 | 457 | self.note_obligation_cause(&mut err, obligation); |
7453a54e | 458 | |
a7813a04 XL |
459 | err.emit(); |
460 | self.tcx.sess.abort_if_errors(); | |
461 | bug!(); | |
462 | } | |
7453a54e | 463 | |
a7813a04 XL |
464 | /// Reports that a cycle was detected which led to overflow and halts |
465 | /// compilation. This is equivalent to `report_overflow_error` except | |
466 | /// that we can give a more helpful error message (and, in particular, | |
467 | /// we do not suggest increasing the overflow limit, which is not | |
468 | /// going to help). | |
469 | pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { | |
470 | let cycle = self.resolve_type_vars_if_possible(&cycle.to_owned()); | |
471 | assert!(cycle.len() > 0); | |
7453a54e | 472 | |
a7813a04 | 473 | debug!("report_overflow_error_cycle: cycle={:?}", cycle); |
7453a54e | 474 | |
a7813a04 XL |
475 | self.report_overflow_error(&cycle[0], false); |
476 | } | |
7453a54e | 477 | |
c30ab7b3 SL |
478 | pub fn report_extra_impl_obligation(&self, |
479 | error_span: Span, | |
480 | item_name: ast::Name, | |
481 | _impl_item_def_id: DefId, | |
482 | trait_item_def_id: DefId, | |
abe05a73 | 483 | requirement: &fmt::Display) |
c30ab7b3 SL |
484 | -> DiagnosticBuilder<'tcx> |
485 | { | |
3b2f2976 | 486 | let msg = "impl has stricter requirements than trait"; |
abe05a73 XL |
487 | let mut err = struct_span_err!(self.tcx.sess, |
488 | error_span, | |
489 | E0276, | |
490 | "{}", msg); | |
c30ab7b3 | 491 | |
32a655c1 | 492 | if let Some(trait_item_span) = self.tcx.hir.span_if_local(trait_item_def_id) { |
cc61c64b | 493 | let span = self.tcx.sess.codemap().def_span(trait_item_span); |
7cac9316 | 494 | err.span_label(span, format!("definition of `{}` from trait", item_name)); |
c30ab7b3 SL |
495 | } |
496 | ||
497 | err.span_label( | |
498 | error_span, | |
7cac9316 | 499 | format!("impl has extra requirement {}", requirement)); |
c30ab7b3 | 500 | |
c30ab7b3 SL |
501 | err |
502 | } | |
503 | ||
32a655c1 SL |
504 | |
505 | /// Get the parent trait chain start | |
506 | fn get_parent_trait_ref(&self, code: &ObligationCauseCode<'tcx>) -> Option<String> { | |
507 | match code { | |
508 | &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
509 | let parent_trait_ref = self.resolve_type_vars_if_possible( | |
510 | &data.parent_trait_ref); | |
511 | match self.get_parent_trait_ref(&data.parent_code) { | |
512 | Some(t) => Some(t), | |
513 | None => Some(format!("{}", parent_trait_ref.0.self_ty())), | |
514 | } | |
515 | } | |
516 | _ => None, | |
517 | } | |
518 | } | |
519 | ||
a7813a04 XL |
520 | pub fn report_selection_error(&self, |
521 | obligation: &PredicateObligation<'tcx>, | |
9e0c209e | 522 | error: &SelectionError<'tcx>) |
a7813a04 XL |
523 | { |
524 | let span = obligation.cause.span; | |
32a655c1 | 525 | |
a7813a04 XL |
526 | let mut err = match *error { |
527 | SelectionError::Unimplemented => { | |
c30ab7b3 | 528 | if let ObligationCauseCode::CompareImplMethodObligation { |
abe05a73 | 529 | item_name, impl_item_def_id, trait_item_def_id, |
c30ab7b3 SL |
530 | } = obligation.cause.code { |
531 | self.report_extra_impl_obligation( | |
532 | span, | |
533 | item_name, | |
534 | impl_item_def_id, | |
535 | trait_item_def_id, | |
abe05a73 | 536 | &format!("`{}`", obligation.predicate)) |
c30ab7b3 | 537 | .emit(); |
a7813a04 | 538 | return; |
8bb4bdeb XL |
539 | } |
540 | match obligation.predicate { | |
541 | ty::Predicate::Trait(ref trait_predicate) => { | |
542 | let trait_predicate = | |
543 | self.resolve_type_vars_if_possible(trait_predicate); | |
7453a54e | 544 | |
8bb4bdeb XL |
545 | if self.tcx.sess.has_errors() && trait_predicate.references_error() { |
546 | return; | |
a7813a04 | 547 | } |
8bb4bdeb XL |
548 | let trait_ref = trait_predicate.to_poly_trait_ref(); |
549 | let (post_message, pre_message) = | |
550 | self.get_parent_trait_ref(&obligation.cause.code) | |
551 | .map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t))) | |
ea8adc8c XL |
552 | .unwrap_or((String::new(), String::new())); |
553 | ||
554 | let OnUnimplementedNote { message, label } | |
555 | = self.on_unimplemented_note(trait_ref, obligation); | |
556 | let have_alt_message = message.is_some() || label.is_some(); | |
557 | ||
8bb4bdeb XL |
558 | let mut err = struct_span_err!( |
559 | self.tcx.sess, | |
560 | span, | |
561 | E0277, | |
ea8adc8c XL |
562 | "{}", |
563 | message.unwrap_or_else(|| { | |
564 | format!("the trait bound `{}` is not satisfied{}", | |
565 | trait_ref.to_predicate(), post_message) | |
566 | })); | |
8bb4bdeb | 567 | |
ea8adc8c | 568 | if let Some(ref s) = label { |
7cac9316 XL |
569 | // If it has a custom "#[rustc_on_unimplemented]" |
570 | // error message, let's display it as the label! | |
571 | err.span_label(span, s.as_str()); | |
572 | err.help(&format!("{}the trait `{}` is not implemented for `{}`", | |
573 | pre_message, | |
574 | trait_ref, | |
575 | trait_ref.self_ty())); | |
576 | } else { | |
577 | err.span_label(span, | |
578 | &*format!("{}the trait `{}` is not implemented for `{}`", | |
579 | pre_message, | |
580 | trait_ref, | |
581 | trait_ref.self_ty())); | |
582 | } | |
583 | ||
8bb4bdeb | 584 | // Try to report a help message |
8bb4bdeb | 585 | if !trait_ref.has_infer_types() && |
7cac9316 | 586 | self.predicate_can_apply(obligation.param_env, trait_ref) { |
8bb4bdeb XL |
587 | // If a where-clause may be useful, remind the |
588 | // user that they can add it. | |
589 | // | |
590 | // don't display an on-unimplemented note, as | |
591 | // these notes will often be of the form | |
592 | // "the type `T` can't be frobnicated" | |
593 | // which is somewhat confusing. | |
594 | err.help(&format!("consider adding a `where {}` bound", | |
595 | trait_ref.to_predicate())); | |
ea8adc8c | 596 | } else if !have_alt_message { |
cc61c64b | 597 | // Can't show anything else useful, try to find similar impls. |
8bb4bdeb XL |
598 | let impl_candidates = self.find_similar_impl_candidates(trait_ref); |
599 | self.report_similar_impl_candidates(impl_candidates, &mut err); | |
a7813a04 | 600 | } |
cc61c64b | 601 | |
8bb4bdeb XL |
602 | err |
603 | } | |
7453a54e | 604 | |
cc61c64b XL |
605 | ty::Predicate::Subtype(ref predicate) => { |
606 | // Errors for Subtype predicates show up as | |
607 | // `FulfillmentErrorCode::CodeSubtypeError`, | |
608 | // not selection error. | |
609 | span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) | |
610 | } | |
611 | ||
8bb4bdeb XL |
612 | ty::Predicate::Equate(ref predicate) => { |
613 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
614 | let err = self.equality_predicate(&obligation.cause, | |
7cac9316 XL |
615 | obligation.param_env, |
616 | &predicate).err().unwrap(); | |
8bb4bdeb XL |
617 | struct_span_err!(self.tcx.sess, span, E0278, |
618 | "the requirement `{}` is not satisfied (`{}`)", | |
619 | predicate, err) | |
620 | } | |
e9174d1e | 621 | |
8bb4bdeb XL |
622 | ty::Predicate::RegionOutlives(ref predicate) => { |
623 | let predicate = self.resolve_type_vars_if_possible(predicate); | |
624 | let err = self.region_outlives_predicate(&obligation.cause, | |
625 | &predicate).err().unwrap(); | |
626 | struct_span_err!(self.tcx.sess, span, E0279, | |
627 | "the requirement `{}` is not satisfied (`{}`)", | |
628 | predicate, err) | |
629 | } | |
85aaf69f | 630 | |
8bb4bdeb XL |
631 | ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { |
632 | let predicate = | |
633 | self.resolve_type_vars_if_possible(&obligation.predicate); | |
634 | struct_span_err!(self.tcx.sess, span, E0280, | |
635 | "the requirement `{}` is not satisfied", | |
636 | predicate) | |
637 | } | |
e9174d1e | 638 | |
8bb4bdeb XL |
639 | ty::Predicate::ObjectSafe(trait_def_id) => { |
640 | let violations = self.tcx.object_safety_violations(trait_def_id); | |
641 | self.tcx.report_object_safety_error(span, | |
642 | trait_def_id, | |
643 | violations) | |
644 | } | |
645 | ||
646 | ty::Predicate::ClosureKind(closure_def_id, kind) => { | |
647 | let found_kind = self.closure_kind(closure_def_id).unwrap(); | |
648 | let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap(); | |
041b39d2 | 649 | let node_id = self.tcx.hir.as_local_node_id(closure_def_id).unwrap(); |
8bb4bdeb XL |
650 | let mut err = struct_span_err!( |
651 | self.tcx.sess, closure_span, E0525, | |
652 | "expected a closure that implements the `{}` trait, \ | |
653 | but this closure only implements `{}`", | |
654 | kind, | |
655 | found_kind); | |
041b39d2 XL |
656 | |
657 | err.span_label( | |
8bb4bdeb | 658 | obligation.cause.span, |
041b39d2 XL |
659 | format!("the requirement to implement `{}` derives from here", kind)); |
660 | ||
661 | // Additional context information explaining why the closure only implements | |
662 | // a particular trait. | |
663 | if let Some(tables) = self.in_progress_tables { | |
3b2f2976 XL |
664 | let tables = tables.borrow(); |
665 | let closure_hir_id = self.tcx.hir.node_to_hir_id(node_id); | |
666 | match tables.closure_kinds().get(closure_hir_id) { | |
041b39d2 XL |
667 | Some(&(ty::ClosureKind::FnOnce, Some((span, name)))) => { |
668 | err.span_note(span, &format!( | |
669 | "closure is `FnOnce` because it moves the \ | |
670 | variable `{}` out of its environment", name)); | |
671 | }, | |
672 | Some(&(ty::ClosureKind::FnMut, Some((span, name)))) => { | |
673 | err.span_note(span, &format!( | |
674 | "closure is `FnMut` because it mutates the \ | |
675 | variable `{}` here", name)); | |
676 | }, | |
677 | _ => {} | |
678 | } | |
679 | } | |
680 | ||
8bb4bdeb XL |
681 | err.emit(); |
682 | return; | |
683 | } | |
684 | ||
685 | ty::Predicate::WellFormed(ty) => { | |
686 | // WF predicates cannot themselves make | |
687 | // errors. They can only block due to | |
688 | // ambiguity; otherwise, they always | |
689 | // degenerate into other obligations | |
690 | // (which may fail). | |
691 | span_bug!(span, "WF predicate not satisfied for {:?}", ty); | |
85aaf69f | 692 | } |
ea8adc8c XL |
693 | |
694 | ty::Predicate::ConstEvaluatable(..) => { | |
695 | // Errors for `ConstEvaluatable` predicates show up as | |
696 | // `SelectionError::ConstEvalFailure`, | |
697 | // not `Unimplemented`. | |
698 | span_bug!(span, | |
699 | "const-evaluatable requirement gave wrong error: `{:?}`", obligation) | |
700 | } | |
1a4d82fc JJ |
701 | } |
702 | } | |
85aaf69f | 703 | |
abe05a73 XL |
704 | OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { |
705 | let found_trait_ref = self.resolve_type_vars_if_possible(&*found_trait_ref); | |
a7813a04 | 706 | let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref); |
abe05a73 | 707 | if expected_trait_ref.self_ty().references_error() { |
a7813a04 XL |
708 | return; |
709 | } | |
abe05a73 XL |
710 | let found_trait_ty = found_trait_ref.self_ty(); |
711 | ||
712 | let found_did = found_trait_ty.ty_to_def_id(); | |
713 | let found_span = found_did.and_then(|did| { | |
7cac9316 XL |
714 | self.tcx.hir.span_if_local(did) |
715 | }); | |
716 | ||
abe05a73 XL |
717 | let found_ty_count = |
718 | match found_trait_ref.skip_binder().substs.type_at(1).sty { | |
ea8adc8c XL |
719 | ty::TyTuple(ref tys, _) => tys.len(), |
720 | _ => 1, | |
7cac9316 | 721 | }; |
abe05a73 XL |
722 | let (expected_tys, expected_ty_count) = |
723 | match expected_trait_ref.skip_binder().substs.type_at(1).sty { | |
724 | ty::TyTuple(ref tys, _) => | |
725 | (tys.iter().map(|t| &t.sty).collect(), tys.len()), | |
726 | ref sty => (vec![sty], 1), | |
7cac9316 | 727 | }; |
abe05a73 | 728 | if found_ty_count == expected_ty_count { |
ea8adc8c XL |
729 | self.report_closure_arg_mismatch(span, |
730 | found_span, | |
abe05a73 XL |
731 | found_trait_ref, |
732 | expected_trait_ref) | |
7cac9316 | 733 | } else { |
abe05a73 XL |
734 | let expected_tuple = if expected_ty_count == 1 { |
735 | expected_tys.first().and_then(|t| { | |
736 | if let &&ty::TyTuple(ref tuptys, _) = t { | |
737 | Some(tuptys.len()) | |
738 | } else { | |
739 | None | |
740 | } | |
741 | }) | |
742 | } else { | |
743 | None | |
744 | }; | |
745 | ||
746 | // FIXME(#44150): Expand this to "N args expected but a N-tuple found." | |
747 | // Type of the 1st expected argument is somehow provided as type of a | |
748 | // found one in that case. | |
749 | // | |
750 | // ``` | |
751 | // [1i32, 2, 3].sort_by(|(a, b)| ..) | |
752 | // // ^^^^^^^^ | |
753 | // // expected_trait_ref: std::ops::FnMut<(&i32, &i32)> | |
754 | // // found_trait_ref: std::ops::FnMut<(&i32,)> | |
755 | // ``` | |
756 | ||
757 | let (closure_span, closure_args) = found_did | |
758 | .and_then(|did| self.tcx.hir.get_if_local(did)) | |
759 | .and_then(|node| { | |
760 | if let hir::map::NodeExpr( | |
761 | &hir::Expr { | |
762 | node: hir::ExprClosure(_, ref decl, id, span, _), | |
763 | .. | |
764 | }) = node | |
765 | { | |
766 | let ty_snips = decl.inputs.iter() | |
767 | .map(|ty| { | |
768 | self.tcx.sess.codemap().span_to_snippet(ty.span).ok() | |
769 | .and_then(|snip| { | |
770 | // filter out dummy spans | |
771 | if snip == "," || snip == "|" { | |
772 | None | |
773 | } else { | |
774 | Some(snip) | |
775 | } | |
776 | }) | |
777 | }) | |
778 | .collect::<Vec<Option<String>>>(); | |
779 | ||
780 | let body = self.tcx.hir.body(id); | |
781 | let pat_snips = body.arguments.iter() | |
782 | .map(|arg| | |
783 | self.tcx.sess.codemap().span_to_snippet(arg.pat.span).ok()) | |
784 | .collect::<Option<Vec<String>>>(); | |
785 | ||
786 | Some((span, pat_snips, ty_snips)) | |
787 | } else { | |
788 | None | |
789 | } | |
790 | }) | |
791 | .map(|(span, pat, ty)| (Some(span), Some((pat, ty)))) | |
792 | .unwrap_or((None, None)); | |
793 | let closure_args = closure_args.and_then(|(pat, ty)| Some((pat?, ty))); | |
794 | ||
ea8adc8c XL |
795 | self.report_arg_count_mismatch( |
796 | span, | |
abe05a73 XL |
797 | closure_span.or(found_span), |
798 | expected_ty_count, | |
799 | expected_tuple, | |
800 | found_ty_count, | |
801 | closure_args, | |
802 | found_trait_ty.is_closure() | |
ea8adc8c | 803 | ) |
7cac9316 | 804 | } |
1a4d82fc | 805 | } |
d9579d0f | 806 | |
a7813a04 XL |
807 | TraitNotObjectSafe(did) => { |
808 | let violations = self.tcx.object_safety_violations(did); | |
9e0c209e SL |
809 | self.tcx.report_object_safety_error(span, did, |
810 | violations) | |
a7813a04 | 811 | } |
ea8adc8c XL |
812 | |
813 | ConstEvalFailure(ref err) => { | |
814 | if let const_val::ErrKind::TypeckError = err.kind { | |
815 | return; | |
816 | } | |
817 | err.struct_error(self.tcx, span, "constant expression") | |
818 | } | |
a7813a04 XL |
819 | }; |
820 | self.note_obligation_cause(&mut err, obligation); | |
821 | err.emit(); | |
e9174d1e | 822 | } |
7cac9316 | 823 | |
abe05a73 XL |
824 | fn report_arg_count_mismatch( |
825 | &self, | |
826 | span: Span, | |
827 | found_span: Option<Span>, | |
828 | expected: usize, | |
829 | expected_tuple: Option<usize>, | |
830 | found: usize, | |
831 | closure_args: Option<(Vec<String>, Vec<Option<String>>)>, | |
832 | is_closure: bool | |
833 | ) -> DiagnosticBuilder<'tcx> { | |
834 | use std::borrow::Cow; | |
835 | ||
836 | let kind = if is_closure { "closure" } else { "function" }; | |
837 | ||
838 | let args_str = |n, distinct| format!( | |
839 | "{} {}argument{}", | |
840 | n, | |
841 | if distinct && n >= 2 { "distinct " } else { "" }, | |
842 | if n == 1 { "" } else { "s" }, | |
843 | ); | |
844 | ||
845 | let expected_str = if let Some(n) = expected_tuple { | |
846 | assert!(expected == 1); | |
847 | if closure_args.as_ref().map(|&(ref pats, _)| pats.len()) == Some(n) { | |
848 | Cow::from("a single tuple as argument") | |
849 | } else { | |
850 | // be verbose when numbers differ | |
851 | Cow::from(format!("a single {}-tuple as argument", n)) | |
852 | } | |
853 | } else { | |
854 | Cow::from(args_str(expected, false)) | |
855 | }; | |
856 | ||
857 | let found_str = if expected_tuple.is_some() { | |
858 | args_str(found, true) | |
859 | } else { | |
860 | args_str(found, false) | |
861 | }; | |
862 | ||
863 | ||
7cac9316 | 864 | let mut err = struct_span_err!(self.tcx.sess, span, E0593, |
abe05a73 XL |
865 | "{} is expected to take {}, but it takes {}", |
866 | kind, | |
867 | expected_str, | |
868 | found_str, | |
869 | ); | |
870 | ||
871 | err.span_label( | |
872 | span, | |
873 | format!( | |
874 | "expected {} that takes {}", | |
875 | kind, | |
876 | expected_str, | |
877 | ) | |
878 | ); | |
879 | ||
7cac9316 | 880 | if let Some(span) = found_span { |
abe05a73 XL |
881 | if let (Some(expected_tuple), Some((pats, tys))) = (expected_tuple, closure_args) { |
882 | if expected_tuple != found || pats.len() != found { | |
883 | err.span_label(span, format!("takes {}", found_str)); | |
884 | } else { | |
885 | let sugg = format!( | |
886 | "|({}){}|", | |
887 | pats.join(", "), | |
888 | ||
889 | // add type annotations if available | |
890 | if tys.iter().any(|ty| ty.is_some()) { | |
891 | Cow::from(format!( | |
892 | ": ({})", | |
893 | tys.into_iter().map(|ty| if let Some(ty) = ty { | |
894 | ty | |
895 | } else { | |
896 | "_".to_string() | |
897 | }).collect::<Vec<String>>().join(", ") | |
898 | )) | |
899 | } else { | |
900 | Cow::from("") | |
901 | }, | |
902 | ); | |
903 | ||
904 | err.span_suggestion( | |
905 | span, | |
906 | "consider changing the closure to accept a tuple", | |
907 | sugg | |
908 | ); | |
909 | } | |
910 | } else { | |
911 | err.span_label(span, format!("takes {}", found_str)); | |
912 | } | |
7cac9316 | 913 | } |
abe05a73 | 914 | |
7cac9316 XL |
915 | err |
916 | } | |
ea8adc8c XL |
917 | |
918 | fn report_closure_arg_mismatch(&self, | |
919 | span: Span, | |
920 | found_span: Option<Span>, | |
921 | expected_ref: ty::PolyTraitRef<'tcx>, | |
922 | found: ty::PolyTraitRef<'tcx>) | |
923 | -> DiagnosticBuilder<'tcx> | |
924 | { | |
925 | fn build_fn_sig_string<'a, 'gcx, 'tcx>(tcx: ty::TyCtxt<'a, 'gcx, 'tcx>, | |
926 | trait_ref: &ty::TraitRef<'tcx>) -> String { | |
927 | let inputs = trait_ref.substs.type_at(1); | |
928 | let sig = if let ty::TyTuple(inputs, _) = inputs.sty { | |
929 | tcx.mk_fn_sig( | |
930 | inputs.iter().map(|&x| x), | |
931 | tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), | |
932 | false, | |
933 | hir::Unsafety::Normal, | |
934 | ::syntax::abi::Abi::Rust | |
935 | ) | |
936 | } else { | |
937 | tcx.mk_fn_sig( | |
938 | ::std::iter::once(inputs), | |
939 | tcx.mk_infer(ty::TyVar(ty::TyVid { index: 0 })), | |
940 | false, | |
941 | hir::Unsafety::Normal, | |
942 | ::syntax::abi::Abi::Rust | |
943 | ) | |
944 | }; | |
945 | format!("{}", ty::Binder(sig)) | |
946 | } | |
947 | ||
948 | let argument_is_closure = expected_ref.skip_binder().substs.type_at(0).is_closure(); | |
949 | let mut err = struct_span_err!(self.tcx.sess, span, E0631, | |
950 | "type mismatch in {} arguments", | |
951 | if argument_is_closure { "closure" } else { "function" }); | |
952 | ||
953 | let found_str = format!( | |
954 | "expected signature of `{}`", | |
955 | build_fn_sig_string(self.tcx, found.skip_binder()) | |
956 | ); | |
957 | err.span_label(span, found_str); | |
958 | ||
959 | let found_span = found_span.unwrap_or(span); | |
960 | let expected_str = format!( | |
961 | "found signature of `{}`", | |
962 | build_fn_sig_string(self.tcx, expected_ref.skip_binder()) | |
963 | ); | |
964 | err.span_label(found_span, expected_str); | |
965 | ||
966 | err | |
967 | } | |
e9174d1e | 968 | } |
d9579d0f | 969 | |
a7813a04 XL |
970 | impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { |
971 | pub fn recursive_type_with_infinite_size_error(self, | |
972 | type_def_id: DefId) | |
973 | -> DiagnosticBuilder<'tcx> | |
974 | { | |
975 | assert!(type_def_id.is_local()); | |
32a655c1 | 976 | let span = self.hir.span_if_local(type_def_id).unwrap(); |
cc61c64b | 977 | let span = self.sess.codemap().def_span(span); |
a7813a04 XL |
978 | let mut err = struct_span_err!(self.sess, span, E0072, |
979 | "recursive type `{}` has infinite size", | |
980 | self.item_path_str(type_def_id)); | |
7cac9316 | 981 | err.span_label(span, "recursive type has infinite size"); |
a7813a04 XL |
982 | err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \ |
983 | at some point to make `{}` representable", | |
984 | self.item_path_str(type_def_id))); | |
985 | err | |
986 | } | |
d9579d0f | 987 | |
a7813a04 XL |
988 | pub fn report_object_safety_error(self, |
989 | span: Span, | |
990 | trait_def_id: DefId, | |
a7813a04 | 991 | violations: Vec<ObjectSafetyViolation>) |
9e0c209e | 992 | -> DiagnosticBuilder<'tcx> |
a7813a04 | 993 | { |
9e0c209e | 994 | let trait_str = self.item_path_str(trait_def_id); |
cc61c64b | 995 | let span = self.sess.codemap().def_span(span); |
9e0c209e SL |
996 | let mut err = struct_span_err!( |
997 | self.sess, span, E0038, | |
998 | "the trait `{}` cannot be made into an object", | |
999 | trait_str); | |
7cac9316 | 1000 | err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str)); |
d9579d0f | 1001 | |
476ff2be | 1002 | let mut reported_violations = FxHashSet(); |
a7813a04 XL |
1003 | for violation in violations { |
1004 | if !reported_violations.insert(violation.clone()) { | |
1005 | continue; | |
e9174d1e | 1006 | } |
8bb4bdeb | 1007 | err.note(&violation.error_msg()); |
d9579d0f | 1008 | } |
a7813a04 | 1009 | err |
1a4d82fc JJ |
1010 | } |
1011 | } | |
1012 | ||
a7813a04 | 1013 | impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { |
041b39d2 XL |
1014 | fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>, |
1015 | body_id: Option<hir::BodyId>) { | |
a7813a04 XL |
1016 | // Unable to successfully determine, probably means |
1017 | // insufficient type information, but could mean | |
1018 | // ambiguous impls. The latter *ought* to be a | |
1019 | // coherence violation, so we don't report it here. | |
1020 | ||
1021 | let predicate = self.resolve_type_vars_if_possible(&obligation.predicate); | |
cc61c64b | 1022 | let span = obligation.cause.span; |
a7813a04 XL |
1023 | |
1024 | debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})", | |
1025 | predicate, | |
1026 | obligation); | |
1027 | ||
1028 | // Ambiguity errors are often caused as fallout from earlier | |
1029 | // errors. So just ignore them if this infcx is tainted. | |
1030 | if self.is_tainted_by_errors() { | |
1031 | return; | |
1032 | } | |
1033 | ||
1034 | match predicate { | |
1035 | ty::Predicate::Trait(ref data) => { | |
1036 | let trait_ref = data.to_poly_trait_ref(); | |
1037 | let self_ty = trait_ref.self_ty(); | |
9e0c209e | 1038 | if predicate.references_error() { |
8bb4bdeb XL |
1039 | return; |
1040 | } | |
1041 | // Typically, this ambiguity should only happen if | |
1042 | // there are unresolved type inference variables | |
1043 | // (otherwise it would suggest a coherence | |
1044 | // failure). But given #21974 that is not necessarily | |
1045 | // the case -- we can have multiple where clauses that | |
1046 | // are only distinguished by a region, which results | |
1047 | // in an ambiguity even when all types are fully | |
1048 | // known, since we don't dispatch based on region | |
1049 | // relationships. | |
1050 | ||
1051 | // This is kind of a hack: it frequently happens that some earlier | |
1052 | // error prevents types from being fully inferred, and then we get | |
1053 | // a bunch of uninteresting errors saying something like "<generic | |
1054 | // #0> doesn't implement Sized". It may even be true that we | |
1055 | // could just skip over all checks where the self-ty is an | |
1056 | // inference variable, but I was afraid that there might be an | |
1057 | // inference variable created, registered as an obligation, and | |
1058 | // then never forced by writeback, and hence by skipping here we'd | |
1059 | // be ignoring the fact that we don't KNOW the type works | |
1060 | // out. Though even that would probably be harmless, given that | |
1061 | // we're only talking about builtin traits, which are known to be | |
1062 | // inhabited. But in any case I just threw in this check for | |
1063 | // has_errors() to be sure that compilation isn't happening | |
1064 | // anyway. In that case, why inundate the user. | |
1065 | if !self.tcx.sess.has_errors() { | |
1066 | if | |
ea8adc8c | 1067 | self.tcx.lang_items().sized_trait() |
8bb4bdeb XL |
1068 | .map_or(false, |sized_id| sized_id == trait_ref.def_id()) |
1069 | { | |
cc61c64b | 1070 | self.need_type_info(body_id, span, self_ty); |
8bb4bdeb XL |
1071 | } else { |
1072 | let mut err = struct_span_err!(self.tcx.sess, | |
cc61c64b | 1073 | span, E0283, |
8bb4bdeb XL |
1074 | "type annotations required: \ |
1075 | cannot resolve `{}`", | |
1076 | predicate); | |
1077 | self.note_obligation_cause(&mut err, obligation); | |
1078 | err.emit(); | |
1a4d82fc JJ |
1079 | } |
1080 | } | |
1a4d82fc | 1081 | } |
1a4d82fc | 1082 | |
a7813a04 XL |
1083 | ty::Predicate::WellFormed(ty) => { |
1084 | // Same hacky approach as above to avoid deluging user | |
1085 | // with error messages. | |
1086 | if !ty.references_error() && !self.tcx.sess.has_errors() { | |
cc61c64b XL |
1087 | self.need_type_info(body_id, span, ty); |
1088 | } | |
1089 | } | |
1090 | ||
1091 | ty::Predicate::Subtype(ref data) => { | |
1092 | if data.references_error() || self.tcx.sess.has_errors() { | |
1093 | // no need to overload user in such cases | |
1094 | } else { | |
1095 | let &SubtypePredicate { a_is_expected: _, a, b } = data.skip_binder(); | |
1096 | // both must be type variables, or the other would've been instantiated | |
1097 | assert!(a.is_ty_var() && b.is_ty_var()); | |
041b39d2 | 1098 | self.need_type_info(body_id, |
cc61c64b XL |
1099 | obligation.cause.span, |
1100 | a); | |
a7813a04 | 1101 | } |
e9174d1e | 1102 | } |
e9174d1e | 1103 | |
a7813a04 XL |
1104 | _ => { |
1105 | if !self.tcx.sess.has_errors() { | |
1106 | let mut err = struct_span_err!(self.tcx.sess, | |
1107 | obligation.cause.span, E0284, | |
1108 | "type annotations required: \ | |
1109 | cannot resolve `{}`", | |
1110 | predicate); | |
1111 | self.note_obligation_cause(&mut err, obligation); | |
1112 | err.emit(); | |
1113 | } | |
1a4d82fc JJ |
1114 | } |
1115 | } | |
1116 | } | |
1a4d82fc | 1117 | |
a7813a04 XL |
1118 | /// Returns whether the trait predicate may apply for *some* assignment |
1119 | /// to the type parameters. | |
7cac9316 XL |
1120 | fn predicate_can_apply(&self, |
1121 | param_env: ty::ParamEnv<'tcx>, | |
1122 | pred: ty::PolyTraitRef<'tcx>) | |
1123 | -> bool { | |
a7813a04 XL |
1124 | struct ParamToVarFolder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { |
1125 | infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, | |
476ff2be | 1126 | var_map: FxHashMap<Ty<'tcx>, Ty<'tcx>> |
a7813a04 | 1127 | } |
54a0048b | 1128 | |
a7813a04 XL |
1129 | impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for ParamToVarFolder<'a, 'gcx, 'tcx> { |
1130 | fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.infcx.tcx } | |
54a0048b | 1131 | |
a7813a04 | 1132 | fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { |
476ff2be | 1133 | if let ty::TyParam(ty::ParamTy {name, ..}) = ty.sty { |
a7813a04 | 1134 | let infcx = self.infcx; |
476ff2be SL |
1135 | self.var_map.entry(ty).or_insert_with(|| |
1136 | infcx.next_ty_var( | |
1137 | TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name))) | |
a7813a04 XL |
1138 | } else { |
1139 | ty.super_fold_with(self) | |
1140 | } | |
54a0048b SL |
1141 | } |
1142 | } | |
54a0048b | 1143 | |
a7813a04 XL |
1144 | self.probe(|_| { |
1145 | let mut selcx = SelectionContext::new(self); | |
54a0048b | 1146 | |
a7813a04 XL |
1147 | let cleaned_pred = pred.fold_with(&mut ParamToVarFolder { |
1148 | infcx: self, | |
476ff2be | 1149 | var_map: FxHashMap() |
a7813a04 | 1150 | }); |
54a0048b | 1151 | |
a7813a04 XL |
1152 | let cleaned_pred = super::project::normalize( |
1153 | &mut selcx, | |
7cac9316 | 1154 | param_env, |
a7813a04 XL |
1155 | ObligationCause::dummy(), |
1156 | &cleaned_pred | |
1157 | ).value; | |
54a0048b | 1158 | |
a7813a04 XL |
1159 | let obligation = Obligation::new( |
1160 | ObligationCause::dummy(), | |
7cac9316 | 1161 | param_env, |
a7813a04 XL |
1162 | cleaned_pred.to_predicate() |
1163 | ); | |
54a0048b | 1164 | |
a7813a04 XL |
1165 | selcx.evaluate_obligation(&obligation) |
1166 | }) | |
1167 | } | |
54a0048b | 1168 | |
a7813a04 XL |
1169 | fn note_obligation_cause<T>(&self, |
1170 | err: &mut DiagnosticBuilder, | |
1171 | obligation: &Obligation<'tcx, T>) | |
1172 | where T: fmt::Display | |
1173 | { | |
1174 | self.note_obligation_cause_code(err, | |
1175 | &obligation.predicate, | |
1176 | &obligation.cause.code); | |
1177 | } | |
1a4d82fc | 1178 | |
a7813a04 XL |
1179 | fn note_obligation_cause_code<T>(&self, |
1180 | err: &mut DiagnosticBuilder, | |
1181 | predicate: &T, | |
1182 | cause_code: &ObligationCauseCode<'tcx>) | |
1183 | where T: fmt::Display | |
1184 | { | |
1185 | let tcx = self.tcx; | |
1186 | match *cause_code { | |
476ff2be SL |
1187 | ObligationCauseCode::ExprAssignable | |
1188 | ObligationCauseCode::MatchExpressionArm { .. } | | |
1189 | ObligationCauseCode::IfExpression | | |
1190 | ObligationCauseCode::IfExpressionWithNoElse | | |
1191 | ObligationCauseCode::EquatePredicate | | |
1192 | ObligationCauseCode::MainFunctionType | | |
1193 | ObligationCauseCode::StartFunctionType | | |
1194 | ObligationCauseCode::IntrinsicType | | |
1195 | ObligationCauseCode::MethodReceiver | | |
cc61c64b | 1196 | ObligationCauseCode::ReturnNoExpression | |
476ff2be SL |
1197 | ObligationCauseCode::MiscObligation => { |
1198 | } | |
a7813a04 XL |
1199 | ObligationCauseCode::SliceOrArrayElem => { |
1200 | err.note("slice and array elements must have `Sized` type"); | |
1201 | } | |
1202 | ObligationCauseCode::TupleElem => { | |
041b39d2 | 1203 | err.note("only the last element of a tuple may have a dynamically sized type"); |
a7813a04 XL |
1204 | } |
1205 | ObligationCauseCode::ProjectionWf(data) => { | |
1206 | err.note(&format!("required so that the projection `{}` is well-formed", | |
1207 | data)); | |
1208 | } | |
1209 | ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => { | |
1210 | err.note(&format!("required so that reference `{}` does not outlive its referent", | |
1211 | ref_ty)); | |
1212 | } | |
c30ab7b3 SL |
1213 | ObligationCauseCode::ObjectTypeBound(object_ty, region) => { |
1214 | err.note(&format!("required so that the lifetime bound of `{}` for `{}` \ | |
1215 | is satisfied", | |
1216 | region, object_ty)); | |
1217 | } | |
a7813a04 XL |
1218 | ObligationCauseCode::ItemObligation(item_def_id) => { |
1219 | let item_name = tcx.item_path_str(item_def_id); | |
1220 | err.note(&format!("required by `{}`", item_name)); | |
1221 | } | |
1222 | ObligationCauseCode::ObjectCastObligation(object_ty) => { | |
1223 | err.note(&format!("required for the cast to the object type `{}`", | |
1224 | self.ty_to_string(object_ty))); | |
1225 | } | |
1226 | ObligationCauseCode::RepeatVec => { | |
1227 | err.note("the `Copy` trait is required because the \ | |
1228 | repeated element will be copied"); | |
1229 | } | |
1230 | ObligationCauseCode::VariableType(_) => { | |
1231 | err.note("all local variables must have a statically known size"); | |
1232 | } | |
041b39d2 | 1233 | ObligationCauseCode::SizedReturnType => { |
a7813a04 XL |
1234 | err.note("the return type of a function must have a \ |
1235 | statically known size"); | |
1236 | } | |
1237 | ObligationCauseCode::AssignmentLhsSized => { | |
1238 | err.note("the left-hand-side of an assignment must have a statically known size"); | |
1239 | } | |
041b39d2 XL |
1240 | ObligationCauseCode::TupleInitializerSized => { |
1241 | err.note("tuples must have a statically known size to be initialized"); | |
1242 | } | |
a7813a04 XL |
1243 | ObligationCauseCode::StructInitializerSized => { |
1244 | err.note("structs must have a statically known size to be initialized"); | |
1245 | } | |
3b2f2976 XL |
1246 | ObligationCauseCode::FieldSized(ref item) => { |
1247 | match *item { | |
1248 | AdtKind::Struct => { | |
1249 | err.note("only the last field of a struct may have a dynamically \ | |
1250 | sized type"); | |
1251 | } | |
1252 | AdtKind::Union => { | |
1253 | err.note("no field of a union may have a dynamically sized type"); | |
1254 | } | |
1255 | AdtKind::Enum => { | |
1256 | err.note("no field of an enum variant may have a dynamically sized type"); | |
1257 | } | |
1258 | } | |
a7813a04 | 1259 | } |
3157f602 XL |
1260 | ObligationCauseCode::ConstSized => { |
1261 | err.note("constant expressions must have a statically known size"); | |
1262 | } | |
a7813a04 XL |
1263 | ObligationCauseCode::SharedStatic => { |
1264 | err.note("shared static variables must have a type that implements `Sync`"); | |
1265 | } | |
1266 | ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | |
1267 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
1268 | err.note(&format!("required because it appears within the type `{}`", | |
1269 | parent_trait_ref.0.self_ty())); | |
1270 | let parent_predicate = parent_trait_ref.to_predicate(); | |
1271 | self.note_obligation_cause_code(err, | |
1272 | &parent_predicate, | |
1273 | &data.parent_code); | |
1274 | } | |
1275 | ObligationCauseCode::ImplDerivedObligation(ref data) => { | |
1276 | let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref); | |
1277 | err.note( | |
1278 | &format!("required because of the requirements on the impl of `{}` for `{}`", | |
1279 | parent_trait_ref, | |
1280 | parent_trait_ref.0.self_ty())); | |
1281 | let parent_predicate = parent_trait_ref.to_predicate(); | |
1282 | self.note_obligation_cause_code(err, | |
1283 | &parent_predicate, | |
1284 | &data.parent_code); | |
1285 | } | |
c30ab7b3 | 1286 | ObligationCauseCode::CompareImplMethodObligation { .. } => { |
a7813a04 XL |
1287 | err.note( |
1288 | &format!("the requirement `{}` appears on the impl method \ | |
1289 | but not on the corresponding trait method", | |
1290 | predicate)); | |
1291 | } | |
041b39d2 XL |
1292 | ObligationCauseCode::ReturnType(_) | |
1293 | ObligationCauseCode::BlockTailExpression(_) => (), | |
85aaf69f | 1294 | } |
1a4d82fc | 1295 | } |
1a4d82fc | 1296 | |
a7813a04 XL |
1297 | fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) { |
1298 | let current_limit = self.tcx.sess.recursion_limit.get(); | |
1299 | let suggested_limit = current_limit * 2; | |
3b2f2976 | 1300 | err.help(&format!("consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate", |
a7813a04 XL |
1301 | suggested_limit)); |
1302 | } | |
1a4d82fc | 1303 | } |