Skip to content

Commit b370c11

Browse files
committed
On obligation errors point at the unfulfilled binding when possible
1 parent 4ff32c0 commit b370c11

File tree

141 files changed

+588
-512
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+588
-512
lines changed

src/librustc/hir/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -2750,3 +2750,16 @@ pub enum Node<'hir> {
27502750

27512751
Crate,
27522752
}
2753+
2754+
impl<'hir> Node<'hir> {
2755+
pub fn ident(&self) -> Option<Ident> {
2756+
2757+
match self {
2758+
Node::TraitItem(TraitItem { ident, .. }) |
2759+
Node::ImplItem(ImplItem { ident, .. }) |
2760+
Node::ForeignItem(ForeignItem { ident, .. }) |
2761+
Node::Item(Item { ident, .. }) => Some(*ident),
2762+
_ => None,
2763+
}
2764+
}
2765+
}

src/librustc/traits/error_reporting.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,12 @@ use syntax::symbol::{sym, kw};
4040
use syntax_pos::{DUMMY_SP, Span, ExpnKind};
4141

4242
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
43-
pub fn report_fulfillment_errors(&self,
44-
errors: &[FulfillmentError<'tcx>],
45-
body_id: Option<hir::BodyId>,
46-
fallback_has_occurred: bool) {
43+
pub fn report_fulfillment_errors(
44+
&self,
45+
errors: &[FulfillmentError<'tcx>],
46+
body_id: Option<hir::BodyId>,
47+
fallback_has_occurred: bool,
48+
) {
4749
#[derive(Debug)]
4850
struct ErrorDescriptor<'tcx> {
4951
predicate: ty::Predicate<'tcx>,
@@ -1651,6 +1653,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16511653
err.note(&msg);
16521654
}
16531655
}
1656+
ObligationCauseCode::BindingObligation(item_def_id, span) => {
1657+
let item_name = tcx.def_path_str(item_def_id);
1658+
let msg = format!("required by this bound in `{}`", item_name);
1659+
if let Some(ident) = tcx.opt_item_name(item_def_id) {
1660+
err.span_label(ident.span, "");
1661+
}
1662+
if span != DUMMY_SP {
1663+
err.span_label(span, &msg);
1664+
} else {
1665+
err.note(&msg);
1666+
}
1667+
}
16541668
ObligationCauseCode::ObjectCastObligation(object_ty) => {
16551669
err.note(&format!("required for the cast to the object type `{}`",
16561670
self.ty_to_string(object_ty)));

src/librustc/traits/mod.rs

+3
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ pub enum ObligationCauseCode<'tcx> {
176176
/// also implement all supertraits of `X`.
177177
ItemObligation(DefId),
178178

179+
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
180+
BindingObligation(DefId, Span),
181+
179182
/// A type like `&'a T` is WF only if `T: 'a`.
180183
ReferenceOutlivesReferent(Ty<'tcx>),
181184

src/librustc/traits/structural_impls.rs

+1
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> {
472472
super::TupleElem => Some(super::TupleElem),
473473
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf),
474474
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)),
475+
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)),
475476
super::ReferenceOutlivesReferent(ty) => {
476477
tcx.lift(&ty).map(super::ReferenceOutlivesReferent)
477478
}

src/librustc/ty/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -2797,6 +2797,10 @@ impl<'tcx> TyCtxt<'tcx> {
27972797
})
27982798
}
27992799

2800+
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
2801+
self.hir().as_local_hir_id(def_id).and_then(|hir_id| self.hir().get(hir_id).ident())
2802+
}
2803+
28002804
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
28012805
let is_associated_item = if let Some(hir_id) = self.hir().as_local_hir_id(def_id) {
28022806
match self.hir().get(hir_id) {

src/librustc_typeck/check/mod.rs

+32-12
Original file line numberDiff line numberDiff line change
@@ -2617,16 +2617,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
26172617

26182618
/// As `instantiate_type_scheme`, but for the bounds found in a
26192619
/// generic type scheme.
2620-
fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: SubstsRef<'tcx>)
2621-
-> ty::InstantiatedPredicates<'tcx> {
2620+
fn instantiate_bounds(
2621+
&self,
2622+
span: Span,
2623+
def_id: DefId,
2624+
substs: SubstsRef<'tcx>,
2625+
) -> (ty::InstantiatedPredicates<'tcx>, Vec<Span>) {
26222626
let bounds = self.tcx.predicates_of(def_id);
2627+
let spans: Vec<Span> = bounds.predicates.iter().map(|(_, span)| *span).collect();
26232628
let result = bounds.instantiate(self.tcx, substs);
26242629
let result = self.normalize_associated_types_in(span, &result);
2625-
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
2630+
debug!(
2631+
"instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}",
26262632
bounds,
26272633
substs,
2628-
result);
2629-
result
2634+
result,
2635+
spans,
2636+
);
2637+
(result, spans)
26302638
}
26312639

26322640
/// Replaces the opaque types from the given value with type variables,
@@ -3194,8 +3202,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31943202

31953203
// All the input types from the fn signature must outlive the call
31963204
// so as to validate implied bounds.
3197-
for &fn_input_ty in fn_inputs {
3198-
self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
3205+
for (fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) {
3206+
self.register_wf_obligation(fn_input_ty, arg_expr.span, traits::MiscObligation);
31993207
}
32003208

32013209
let expected_arg_count = fn_inputs.len();
@@ -3604,7 +3612,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
36043612
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
36053613

36063614
// Check bounds on type arguments used in the path.
3607-
let bounds = self.instantiate_bounds(path_span, did, substs);
3615+
let (bounds, _) = self.instantiate_bounds(path_span, did, substs);
36083616
let cause = traits::ObligationCause::new(
36093617
path_span,
36103618
self.body_id,
@@ -4730,11 +4738,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
47304738

47314739
// Add all the obligations that are required, substituting and
47324740
// normalized appropriately.
4733-
let bounds = self.instantiate_bounds(span, def_id, &substs);
4734-
self.add_obligations_for_parameters(
4735-
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
4741+
let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs);
4742+
4743+
for (i, mut obligation) in traits::predicates_for_generics(
4744+
traits::ObligationCause::new(
4745+
span,
4746+
self.body_id,
4747+
traits::ItemObligation(def_id),
4748+
),
4749+
self.param_env,
47364750
&bounds,
4737-
);
4751+
).into_iter().enumerate() {
4752+
// This makes the error point at the bound, but we want to point at the argument
4753+
if let Some(span) = spans.get(i) {
4754+
obligation.cause.code = traits::BindingObligation(def_id, *span);
4755+
}
4756+
self.register_predicate(obligation);
4757+
}
47384758

47394759
// Substitute the values for the type parameters into the type of
47404760
// the referenced item.

src/test/ui/anonymous-higher-ranked-lifetime.stderr

+22-22
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ LL | f1(|_: (), _: ()| {});
77
| expected signature of `for<'r, 's> fn(&'r (), &'s ()) -> _`
88
...
99
LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
10-
| ------------------------------------ required by `f1`
10+
| -- ------------ required by this bound in `f1`
1111

1212
error[E0631]: type mismatch in closure arguments
1313
--> $DIR/anonymous-higher-ranked-lifetime.rs:2:5
@@ -18,7 +18,7 @@ LL | f1(|_: (), _: ()| {});
1818
| expected signature of `fn(&(), &()) -> _`
1919
...
2020
LL | fn f1<F>(_: F) where F: Fn(&(), &()) {}
21-
| ------------------------------------ required by `f1`
21+
| -- ---------- required by this bound in `f1`
2222

2323
error[E0631]: type mismatch in closure arguments
2424
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -29,7 +29,7 @@ LL | f2(|_: (), _: ()| {});
2929
| expected signature of `for<'a, 'r> fn(&'a (), &'r ()) -> _`
3030
...
3131
LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
32-
| ----------------------------------------------- required by `f2`
32+
| -- ----------------------- required by this bound in `f2`
3333

3434
error[E0631]: type mismatch in closure arguments
3535
--> $DIR/anonymous-higher-ranked-lifetime.rs:4:5
@@ -40,7 +40,7 @@ LL | f2(|_: (), _: ()| {});
4040
| expected signature of `fn(&'a (), &()) -> _`
4141
...
4242
LL | fn f2<F>(_: F) where F: for<'a> Fn(&'a (), &()) {}
43-
| ----------------------------------------------- required by `f2`
43+
| -- ------------- required by this bound in `f2`
4444

4545
error[E0631]: type mismatch in closure arguments
4646
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -51,7 +51,7 @@ LL | f3(|_: (), _: ()| {});
5151
| expected signature of `for<'r> fn(&(), &'r ()) -> _`
5252
...
5353
LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
54-
| ------------------------------------------- required by `f3`
54+
| -- --------------- required by this bound in `f3`
5555

5656
error[E0631]: type mismatch in closure arguments
5757
--> $DIR/anonymous-higher-ranked-lifetime.rs:6:5
@@ -62,7 +62,7 @@ LL | f3(|_: (), _: ()| {});
6262
| expected signature of `fn(&(), &()) -> _`
6363
...
6464
LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {}
65-
| ------------------------------------------- required by `f3`
65+
| -- ------------- required by this bound in `f3`
6666

6767
error[E0631]: type mismatch in closure arguments
6868
--> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
@@ -73,7 +73,7 @@ LL | f4(|_: (), _: ()| {});
7373
| expected signature of `for<'s, 'r> fn(&'s (), &'r ()) -> _`
7474
...
7575
LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
76-
| ----------------------------------------------- required by `f4`
76+
| -- ----------------------- required by this bound in `f4`
7777

7878
error[E0631]: type mismatch in closure arguments
7979
--> $DIR/anonymous-higher-ranked-lifetime.rs:8:5
@@ -84,7 +84,7 @@ LL | f4(|_: (), _: ()| {});
8484
| expected signature of `fn(&(), &'r ()) -> _`
8585
...
8686
LL | fn f4<F>(_: F) where F: for<'r> Fn(&(), &'r ()) {}
87-
| ----------------------------------------------- required by `f4`
87+
| -- ------------- required by this bound in `f4`
8888

8989
error[E0631]: type mismatch in closure arguments
9090
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
@@ -95,7 +95,7 @@ LL | f5(|_: (), _: ()| {});
9595
| expected signature of `for<'r> fn(&'r (), &'r ()) -> _`
9696
...
9797
LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
98-
| -------------------------------------------------- required by `f5`
98+
| -- -------------------------- required by this bound in `f5`
9999

100100
error[E0631]: type mismatch in closure arguments
101101
--> $DIR/anonymous-higher-ranked-lifetime.rs:10:5
@@ -106,7 +106,7 @@ LL | f5(|_: (), _: ()| {});
106106
| expected signature of `fn(&'r (), &'r ()) -> _`
107107
...
108108
LL | fn f5<F>(_: F) where F: for<'r> Fn(&'r (), &'r ()) {}
109-
| -------------------------------------------------- required by `f5`
109+
| -- ---------------- required by this bound in `f5`
110110

111111
error[E0631]: type mismatch in closure arguments
112112
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -117,7 +117,7 @@ LL | g1(|_: (), _: ()| {});
117117
| expected signature of `for<'r> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>) -> _`
118118
...
119119
LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
120-
| ------------------------------------------------- required by `g1`
120+
| -- ------------------------- required by this bound in `g1`
121121

122122
error[E0631]: type mismatch in closure arguments
123123
--> $DIR/anonymous-higher-ranked-lifetime.rs:12:5
@@ -128,7 +128,7 @@ LL | g1(|_: (), _: ()| {});
128128
| expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
129129
...
130130
LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
131-
| ------------------------------------------------- required by `g1`
131+
| -- ----------------------- required by this bound in `g1`
132132

133133
error[E0631]: type mismatch in closure arguments
134134
--> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
@@ -139,7 +139,7 @@ LL | g2(|_: (), _: ()| {});
139139
| expected signature of `for<'r> fn(&'r (), for<'s> fn(&'s ())) -> _`
140140
...
141141
LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
142-
| ---------------------------------------- required by `g2`
142+
| -- ---------------- required by this bound in `g2`
143143

144144
error[E0631]: type mismatch in closure arguments
145145
--> $DIR/anonymous-higher-ranked-lifetime.rs:14:5
@@ -150,7 +150,7 @@ LL | g2(|_: (), _: ()| {});
150150
| expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
151151
...
152152
LL | fn g2<F>(_: F) where F: Fn(&(), fn(&())) {}
153-
| ---------------------------------------- required by `g2`
153+
| -- -------------- required by this bound in `g2`
154154

155155
error[E0631]: type mismatch in closure arguments
156156
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
@@ -161,7 +161,7 @@ LL | g3(|_: (), _: ()| {});
161161
| expected signature of `for<'s> fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
162162
...
163163
LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
164-
| ------------------------------------------------------------ required by `g3`
164+
| -- ------------------------------------ required by this bound in `g3`
165165

166166
error[E0631]: type mismatch in closure arguments
167167
--> $DIR/anonymous-higher-ranked-lifetime.rs:16:5
@@ -172,7 +172,7 @@ LL | g3(|_: (), _: ()| {});
172172
| expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _`
173173
...
174174
LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
175-
| ------------------------------------------------------------ required by `g3`
175+
| -- -------------------------- required by this bound in `g3`
176176

177177
error[E0631]: type mismatch in closure arguments
178178
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
@@ -183,7 +183,7 @@ LL | g4(|_: (), _: ()| {});
183183
| expected signature of `for<'s> fn(&'s (), for<'r> fn(&'r ())) -> _`
184184
...
185185
LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
186-
| --------------------------------------------------- required by `g4`
186+
| -- --------------------------- required by this bound in `g4`
187187

188188
error[E0631]: type mismatch in closure arguments
189189
--> $DIR/anonymous-higher-ranked-lifetime.rs:18:5
@@ -194,7 +194,7 @@ LL | g4(|_: (), _: ()| {});
194194
| expected signature of `fn(&(), for<'r> fn(&'r ())) -> _`
195195
...
196196
LL | fn g4<F>(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {}
197-
| --------------------------------------------------- required by `g4`
197+
| -- ------------------------- required by this bound in `g4`
198198

199199
error[E0631]: type mismatch in closure arguments
200200
--> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
@@ -205,7 +205,7 @@ LL | h1(|_: (), _: (), _: (), _: ()| {});
205205
| expected signature of `for<'r, 's> fn(&'r (), std::boxed::Box<(dyn for<'t0> std::ops::Fn(&'t0 ()) + 'static)>, &'s (), for<'t0, 't1> fn(&'t0 (), &'t1 ())) -> _`
206206
...
207207
LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
208-
| -------------------------------------------------------------------- required by `h1`
208+
| -- -------------------------------------------- required by this bound in `h1`
209209

210210
error[E0631]: type mismatch in closure arguments
211211
--> $DIR/anonymous-higher-ranked-lifetime.rs:20:5
@@ -216,7 +216,7 @@ LL | h1(|_: (), _: (), _: (), _: ()| {});
216216
| expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _`
217217
...
218218
LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), fn(&(), &())) {}
219-
| -------------------------------------------------------------------- required by `h1`
219+
| -- ------------------------------------------ required by this bound in `h1`
220220

221221
error[E0631]: type mismatch in closure arguments
222222
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
@@ -227,7 +227,7 @@ LL | h2(|_: (), _: (), _: (), _: ()| {});
227227
| expected signature of `for<'r, 't0> fn(&'r (), std::boxed::Box<(dyn for<'s> std::ops::Fn(&'s ()) + 'static)>, &'t0 (), for<'s, 't1> fn(&'s (), &'t1 ())) -> _`
228228
...
229229
LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
230-
| --------------------------------------------------------------------------------- required by `h2`
230+
| -- --------------------------------------------------------- required by this bound in `h2`
231231

232232
error[E0631]: type mismatch in closure arguments
233233
--> $DIR/anonymous-higher-ranked-lifetime.rs:22:5
@@ -238,7 +238,7 @@ LL | h2(|_: (), _: (), _: (), _: ()| {});
238238
| expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _`
239239
...
240240
LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
241-
| --------------------------------------------------------------------------------- required by `h2`
241+
| -- ---------------------------------------------- required by this bound in `h2`
242242

243243
error: aborting due to 22 previous errors
244244

src/test/ui/associated-types/associated-types-binding-to-type-defined-in-supertrait.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0271]: type mismatch resolving `<ModelT as Vehicle>::Color == Blue`
22
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:31:10
33
|
44
LL | fn blue_car<C:Car<Color=Blue>>(c: C) {
5-
| ------------------------------------ required by `blue_car`
5+
| -------- ---------- required by this bound in `blue_car`
66
...
77
LL | fn b() { blue_car(ModelT); }
88
| ^^^^^^^^ expected struct `Black`, found struct `Blue`
@@ -14,7 +14,7 @@ error[E0271]: type mismatch resolving `<ModelU as Vehicle>::Color == Black`
1414
--> $DIR/associated-types-binding-to-type-defined-in-supertrait.rs:32:10
1515
|
1616
LL | fn black_car<C:Car<Color=Black>>(c: C) {
17-
| -------------------------------------- required by `black_car`
17+
| --------- ----------- required by this bound in `black_car`
1818
...
1919
LL | fn c() { black_car(ModelU); }
2020
| ^^^^^^^^^ expected struct `Blue`, found struct `Black`

src/test/ui/associated-types/associated-types-eq-3.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
1313
--> $DIR/associated-types-eq-3.rs:38:5
1414
|
1515
LL | fn foo1<I: Foo<A=Bar>>(x: I) {
16-
| ---------------------------- required by `foo1`
16+
| ---- ----- required by this bound in `foo1`
1717
...
1818
LL | foo1(a);
1919
| ^^^^ expected usize, found struct `Bar`

0 commit comments

Comments
 (0)