Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

librustc error_reporting.rs cleanup. #39977

Merged
merged 8 commits into from
Feb 28, 2017
246 changes: 106 additions & 140 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,34 +359,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
}

fn report_similar_impl_candidates(&self,
trait_ref: ty::PolyTraitRef<'tcx>,
impl_candidates: Vec<ty::TraitRef<'tcx>>,
err: &mut DiagnosticBuilder)
{
let simp = fast_reject::simplify_type(self.tcx,
trait_ref.skip_binder().self_ty(),
true);
let mut impl_candidates = Vec::new();
let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id());

match simp {
Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
let imp_simp = fast_reject::simplify_type(self.tcx,
imp.self_ty(),
true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return;
}
}
impl_candidates.push(imp);
}),
None => trait_def.for_each_impl(self.tcx, |def_id| {
impl_candidates.push(
self.tcx.impl_trait_ref(def_id).unwrap());
})
};

if impl_candidates.is_empty() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was all of this duplicated from find_similar_impl_candidates? 😆

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeeeppppppp

return;
}
Expand Down Expand Up @@ -525,127 +500,118 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
lint_id)
.emit();
return;
} else {
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
let trait_predicate =
self.resolve_type_vars_if_possible(trait_predicate);

if self.tcx.sess.has_errors() && trait_predicate.references_error() {
return;
} else {
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message) = match self.get_parent_trait_ref(
&obligation.cause.code)
{
Some(t) => {
(format!(" in `{}`", t), format!("within `{}`, ", t))
}
None => (String::new(), String::new()),
};
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0277,
"the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(),
post_message);
err.span_label(span,
&format!("{}the trait `{}` is not \
implemented for `{}`",
pre_message,
trait_ref,
trait_ref.self_ty()));

// Try to report a help message

if !trait_ref.has_infer_types() &&
self.predicate_can_apply(trait_ref) {
// If a where-clause may be useful, remind the
// user that they can add it.
//
// don't display an on-unimplemented note, as
// these notes will often be of the form
// "the type `T` can't be frobnicated"
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
} else if let Some(s) = self.on_unimplemented_note(trait_ref,
obligation) {
// If it has a custom "#[rustc_on_unimplemented]"
// error message, let's display it!
err.note(&s);
} else {
// If we can't show anything useful, try to find
// similar impls.
let impl_candidates =
self.find_similar_impl_candidates(trait_ref);
if impl_candidates.len() > 0 {
self.report_similar_impl_candidates(trait_ref, &mut err);
}
}
err
}
}
}
match obligation.predicate {
ty::Predicate::Trait(ref trait_predicate) => {
let trait_predicate =
self.resolve_type_vars_if_possible(trait_predicate);

ty::Predicate::Equate(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.equality_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
if self.tcx.sess.has_errors() && trait_predicate.references_error() {
return;
}

ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.region_outlives_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
let trait_ref = trait_predicate.to_poly_trait_ref();
let (post_message, pre_message) =
self.get_parent_trait_ref(&obligation.cause.code)
.map(|t| (format!(" in `{}`", t), format!("within `{}`, ", t)))
.unwrap_or((String::new(), String::new()));
let mut err = struct_span_err!(
self.tcx.sess,
span,
E0277,
"the trait bound `{}` is not satisfied{}",
trait_ref.to_predicate(),
post_message);
err.span_label(span,
&format!("{}the trait `{}` is not \
implemented for `{}`",
pre_message,
trait_ref,
trait_ref.self_ty()));

// Try to report a help message

if !trait_ref.has_infer_types() &&
self.predicate_can_apply(trait_ref) {
// If a where-clause may be useful, remind the
// user that they can add it.
//
// don't display an on-unimplemented note, as
// these notes will often be of the form
// "the type `T` can't be frobnicated"
// which is somewhat confusing.
err.help(&format!("consider adding a `where {}` bound",
trait_ref.to_predicate()));
} else if let Some(s) = self.on_unimplemented_note(trait_ref,
obligation) {
// If it has a custom "#[rustc_on_unimplemented]"
// error message, let's display it!
err.note(&s);
} else {
// If we can't show anything useful, try to find
// similar impls.
let impl_candidates = self.find_similar_impl_candidates(trait_ref);
self.report_similar_impl_candidates(impl_candidates, &mut err);
}
err
}

ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
self.resolve_type_vars_if_possible(&obligation.predicate);
struct_span_err!(self.tcx.sess, span, E0280,
"the requirement `{}` is not satisfied",
predicate)
}
ty::Predicate::Equate(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.equality_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0278,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
}

ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
self.tcx.report_object_safety_error(span,
trait_def_id,
violations)
}
ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = self.resolve_type_vars_if_possible(predicate);
let err = self.region_outlives_predicate(&obligation.cause,
&predicate).err().unwrap();
struct_span_err!(self.tcx.sess, span, E0279,
"the requirement `{}` is not satisfied (`{}`)",
predicate, err)
}

ty::Predicate::ClosureKind(closure_def_id, kind) => {
let found_kind = self.closure_kind(closure_def_id).unwrap();
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
let mut err = struct_span_err!(
self.tcx.sess, closure_span, E0525,
"expected a closure that implements the `{}` trait, \
but this closure only implements `{}`",
kind,
found_kind);
err.span_note(
obligation.cause.span,
&format!("the requirement to implement \
`{}` derives from here", kind));
err.emit();
return;
}
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
let predicate =
self.resolve_type_vars_if_possible(&obligation.predicate);
struct_span_err!(self.tcx.sess, span, E0280,
"the requirement `{}` is not satisfied",
predicate)
}

ty::Predicate::WellFormed(ty) => {
// WF predicates cannot themselves make
// errors. They can only block due to
// ambiguity; otherwise, they always
// degenerate into other obligations
// (which may fail).
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
}
ty::Predicate::ObjectSafe(trait_def_id) => {
let violations = self.tcx.object_safety_violations(trait_def_id);
self.tcx.report_object_safety_error(span,
trait_def_id,
violations)
}

ty::Predicate::ClosureKind(closure_def_id, kind) => {
let found_kind = self.closure_kind(closure_def_id).unwrap();
let closure_span = self.tcx.hir.span_if_local(closure_def_id).unwrap();
let mut err = struct_span_err!(
self.tcx.sess, closure_span, E0525,
"expected a closure that implements the `{}` trait, \
but this closure only implements `{}`",
kind,
found_kind);
err.span_note(
obligation.cause.span,
&format!("the requirement to implement \
`{}` derives from here", kind));
err.emit();
return;
}

ty::Predicate::WellFormed(ty) => {
// WF predicates cannot themselves make
// errors. They can only block due to
// ambiguity; otherwise, they always
// degenerate into other obligations
// (which may fail).
span_bug!(span, "WF predicate not satisfied for {:?}", ty);
}
}
}
Expand Down