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

On obligation errors point at the unfulfilled binding when possible #64151

Merged
merged 10 commits into from
Sep 23, 2019
2 changes: 2 additions & 0 deletions src/etc/generate-deriving-span-tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
os.path.join(os.path.dirname(__file__), '../test/ui/derives/'))

TEMPLATE = """\
// ignore-x86
// ^ due to stderr output differences
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'

{error_deriving}
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1893,10 +1893,13 @@ impl<'a> LoweringContext<'a> {
if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) {
// Do not suggest going from `Trait()` to `Trait<>`
if data.inputs.len() > 0 {
let split = snippet.find('(').unwrap();
let trait_name = &snippet[0..split];
let args = &snippet[split + 1 .. snippet.len() - 1];
err.span_suggestion(
data.span,
"use angle brackets instead",
format!("<{}>", &snippet[1..snippet.len() - 1]),
format!("{}<{}>", trait_name, args),
Applicability::MaybeIncorrect,
);
}
Expand Down
12 changes: 12 additions & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2750,3 +2750,15 @@ pub enum Node<'hir> {

Crate,
}

impl Node<'_> {
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,
}
}
}
29 changes: 25 additions & 4 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand Down Expand Up @@ -1053,6 +1055,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
.filter(|c| !c.is_whitespace())
.take_while(|c| *c == '&')
.count();
if let Some('\'') = snippet.chars()
.filter(|c| !c.is_whitespace())
.skip(refs_number)
.next()
{ // Do not suggest removal of borrow from type arguments.
return;
}

let mut trait_type = trait_ref.self_ty();

Expand Down Expand Up @@ -1651,6 +1660,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 {
estebank marked this conversation as resolved.
Show resolved Hide resolved
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)));
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>),

Expand Down
1 change: 1 addition & 0 deletions src/librustc/traits/structural_impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
4 changes: 4 additions & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
12 changes: 6 additions & 6 deletions src/librustc_typeck/check/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn confirm_builtin_call(
&self,
call_expr: &hir::Expr,
call_expr: &'tcx hir::Expr,
callee_ty: Ty<'tcx>,
arg_exprs: &'tcx [hir::Expr],
expected: Expectation<'tcx>,
Expand Down Expand Up @@ -425,7 +425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
self.check_argument_types(
call_expr.span,
call_expr.span,
call_expr,
inputs,
&expected_arg_tys[..],
arg_exprs,
Expand All @@ -439,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn confirm_deferred_closure_call(
&self,
call_expr: &hir::Expr,
call_expr: &'tcx hir::Expr,
arg_exprs: &'tcx [hir::Expr],
expected: Expectation<'tcx>,
fn_sig: ty::FnSig<'tcx>,
Expand All @@ -458,7 +458,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

self.check_argument_types(
call_expr.span,
call_expr.span,
call_expr,
fn_sig.inputs(),
&expected_arg_tys,
arg_exprs,
Expand All @@ -472,14 +472,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

fn confirm_overloaded_call(
&self,
call_expr: &hir::Expr,
call_expr: &'tcx hir::Expr,
arg_exprs: &'tcx [hir::Expr],
expected: Expectation<'tcx>,
method_callee: MethodCallee<'tcx>,
) -> Ty<'tcx> {
let output_type = self.check_method_argument_types(
call_expr.span,
call_expr.span,
call_expr,
Ok(method_callee),
arg_exprs,
TupleArgumentsFlag::TupleArguments,
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Call the generic checker.
self.check_method_argument_types(
span,
expr.span,
expr,
method,
&args[1..],
DontTupleArguments,
Expand Down
Loading