On obligation errors point at the unfulfilled binding when possible

This commit is contained in:
Esteban Küber 2019-09-04 10:17:59 -07:00
parent 4ff32c07da
commit b370c111fd
141 changed files with 588 additions and 512 deletions

View file

@ -2750,3 +2750,16 @@ pub enum Node<'hir> {
Crate,
}
impl<'hir> Node<'hir> {
pub fn ident(&self) -> Option<Ident> {
match self {
Node::TraitItem(TraitItem { ident, .. }) |
Node::ImplItem(ImplItem { ident, .. }) |
Node::ForeignItem(ForeignItem { ident, .. }) |
Node::Item(Item { ident, .. }) => Some(*ident),
_ => None,
}
}
}

View file

@ -40,10 +40,12 @@ use syntax::symbol::{sym, kw};
use syntax_pos::{DUMMY_SP, Span, ExpnKind};
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn report_fulfillment_errors(&self,
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
fallback_has_occurred: bool) {
pub fn report_fulfillment_errors(
&self,
errors: &[FulfillmentError<'tcx>],
body_id: Option<hir::BodyId>,
fallback_has_occurred: bool,
) {
#[derive(Debug)]
struct ErrorDescriptor<'tcx> {
predicate: ty::Predicate<'tcx>,
@ -1651,6 +1653,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
err.note(&msg);
}
}
ObligationCauseCode::BindingObligation(item_def_id, span) => {
let item_name = tcx.def_path_str(item_def_id);
let msg = format!("required by this bound in `{}`", item_name);
if let Some(ident) = tcx.opt_item_name(item_def_id) {
err.span_label(ident.span, "");
}
if span != DUMMY_SP {
err.span_label(span, &msg);
} else {
err.note(&msg);
}
}
ObligationCauseCode::ObjectCastObligation(object_ty) => {
err.note(&format!("required for the cast to the object type `{}`",
self.ty_to_string(object_ty)));

View file

@ -176,6 +176,9 @@ pub enum ObligationCauseCode<'tcx> {
/// also implement all supertraits of `X`.
ItemObligation(DefId),
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
BindingObligation(DefId, Span),
/// A type like `&'a T` is WF only if `T: 'a`.
ReferenceOutlivesReferent(Ty<'tcx>),

View file

@ -472,6 +472,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
super::TupleElem => Some(super::TupleElem),
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
super::ReferenceOutlivesReferent(ty) => {
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
}

View file

@ -2797,6 +2797,10 @@ impl<'tcx> TyCtxt<'tcx> {
})
}
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
self.hir().as_local_hir_id(def_id).and_then(|hir_id| self.hir().get(hir_id).ident())
}
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
let is_associated_item = if let Some(hir_id) = self.hir().as_local_hir_id(def_id) {
match self.hir().get(hir_id) {