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