Skip to content

Commit f6715d4

Browse files
committed
On obligation errors point at the unfulfilled binding when possible
1 parent 2c0931e commit f6715d4

File tree

141 files changed

+589
-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

+589
-512
lines changed

src/librustc/hir/mod.rs

Lines changed: 13 additions & 0 deletions
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

Lines changed: 18 additions & 4 deletions
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>,
@@ -1623,6 +1625,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16231625
err.note(&msg);
16241626
}
16251627
}
1628+
ObligationCauseCode::BindingObligation(item_def_id, span) => {
1629+
let item_name = tcx.def_path_str(item_def_id);
1630+
let msg = format!("required by this bound in `{}`", item_name);
1631+
if let Some(ident) = tcx.opt_item_name(item_def_id) {
1632+
err.span_label(ident.span, "");
1633+
}
1634+
if span != DUMMY_SP {
1635+
err.span_label(span, &msg);
1636+
} else {
1637+
err.note(&msg);
1638+
}
1639+
}
16261640
ObligationCauseCode::ObjectCastObligation(object_ty) => {
16271641
err.note(&format!("required for the cast to the object type `{}`",
16281642
self.ty_to_string(object_ty)));

src/librustc/traits/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,9 @@ pub enum ObligationCauseCode<'tcx> {
171171
/// also implement all supertraits of `X`.
172172
ItemObligation(DefId),
173173

174+
/// Like `ItemObligation`, but with extra detail on the source of the obligation.
175+
BindingObligation(DefId, Span),
176+
174177
/// A type like `&'a T` is WF only if `T: 'a`.
175178
ReferenceOutlivesReferent(Ty<'tcx>),
176179

src/librustc/traits/structural_impls.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,6 +2791,10 @@ impl<'tcx> TyCtxt<'tcx> {
27912791
})
27922792
}
27932793

2794+
pub fn opt_item_name(self, def_id: DefId) -> Option<Ident> {
2795+
self.hir().as_local_hir_id(def_id).and_then(|hir_id| self.hir().get(hir_id).ident())
2796+
}
2797+
27942798
pub fn opt_associated_item(self, def_id: DefId) -> Option<AssocItem> {
27952799
let is_associated_item = if let Some(hir_id) = self.hir().as_local_hir_id(def_id) {
27962800
match self.hir().get(hir_id) {

src/librustc_typeck/check/mod.rs

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,16 +2548,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25482548

25492549
/// As `instantiate_type_scheme`, but for the bounds found in a
25502550
/// generic type scheme.
2551-
fn instantiate_bounds(&self, span: Span, def_id: DefId, substs: SubstsRef<'tcx>)
2552-
-> ty::InstantiatedPredicates<'tcx> {
2551+
fn instantiate_bounds(
2552+
&self,
2553+
span: Span,
2554+
def_id: DefId,
2555+
substs: SubstsRef<'tcx>,
2556+
) -> (ty::InstantiatedPredicates<'tcx>, Vec<Span>) {
25532557
let bounds = self.tcx.predicates_of(def_id);
2558+
let spans: Vec<Span> = bounds.predicates.iter().map(|(_, span)| *span).collect();
25542559
let result = bounds.instantiate(self.tcx, substs);
25552560
let result = self.normalize_associated_types_in(span, &result);
2556-
debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}",
2561+
debug!(
2562+
"instantiate_bounds(bounds={:?}, substs={:?}) = {:?}, {:?}",
25572563
bounds,
25582564
substs,
2559-
result);
2560-
result
2565+
result,
2566+
spans,
2567+
);
2568+
(result, spans)
25612569
}
25622570

25632571
/// Replaces the opaque types from the given value with type variables,
@@ -3120,8 +3128,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
31203128

31213129
// All the input types from the fn signature must outlive the call
31223130
// so as to validate implied bounds.
3123-
for &fn_input_ty in fn_inputs {
3124-
self.register_wf_obligation(fn_input_ty, sp, traits::MiscObligation);
3131+
for (fn_input_ty, arg_expr) in fn_inputs.iter().zip(args.iter()) {
3132+
self.register_wf_obligation(fn_input_ty, arg_expr.span, traits::MiscObligation);
31253133
}
31263134

31273135
let expected_arg_count = fn_inputs.len();
@@ -3482,7 +3490,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
34823490
self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
34833491

34843492
// Check bounds on type arguments used in the path.
3485-
let bounds = self.instantiate_bounds(path_span, did, substs);
3493+
let (bounds, _) = self.instantiate_bounds(path_span, did, substs);
34863494
let cause = traits::ObligationCause::new(path_span, self.body_id,
34873495
traits::ItemObligation(did));
34883496
self.add_obligations_for_parameters(cause, &bounds);
@@ -4605,10 +4613,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
46054613

46064614
// Add all the obligations that are required, substituting and
46074615
// normalized appropriately.
4608-
let bounds = self.instantiate_bounds(span, def_id, &substs);
4609-
self.add_obligations_for_parameters(
4610-
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
4611-
&bounds);
4616+
let (bounds, spans) = self.instantiate_bounds(span, def_id, &substs);
4617+
4618+
for (i, mut obligation) in traits::predicates_for_generics(
4619+
traits::ObligationCause::new(
4620+
span,
4621+
self.body_id,
4622+
traits::ItemObligation(def_id),
4623+
),
4624+
self.param_env,
4625+
&bounds,
4626+
).into_iter().enumerate() {
4627+
// This makes the error point at the bound, but we want to point at the argument
4628+
if let Some(span) = spans.get(i) {
4629+
obligation.cause.code = traits::BindingObligation(def_id, *span);
4630+
}
4631+
self.register_predicate(obligation);
4632+
}
46124633

46134634
// Substitute the values for the type parameters into the type of
46144635
// the referenced item.

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

Lines changed: 22 additions & 22 deletions
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

Lines changed: 2 additions & 2 deletions
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

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

0 commit comments

Comments
 (0)