Skip to content

Commit 9fa8d87

Browse files
committed
Add more context to E0599 errors
Point at the intermediary unfullfilled trait bounds.
1 parent 187f3d7 commit 9fa8d87

27 files changed

+203
-56
lines changed

src/librustc_infer/infer/error_reporting/note.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,8 +645,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
645645
self.tcx.sess,
646646
span,
647647
E0491,
648-
"in type `{}`, reference has a longer lifetime \
649-
than the data it references",
648+
"in type `{}`, reference has a longer lifetime than the data it references",
650649
self.ty_to_string(ty)
651650
);
652651
note_and_explain_region(

src/librustc_typeck/check/method/probe.rs

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,15 +1404,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
14041404
// `potentially_unsatisfied_predicates`.
14051405
return ProbeResult::NoMatch;
14061406
} else {
1407-
// Some nested subobligation of this predicate
1408-
// failed.
1409-
//
1410-
// FIXME: try to find the exact nested subobligation
1411-
// and point at it rather than reporting the entire
1412-
// trait-ref?
1413-
result = ProbeResult::NoMatch;
1414-
let trait_ref = self.resolve_vars_if_possible(&trait_ref);
1415-
possibly_unsatisfied_predicates.push(trait_ref);
1407+
self.probe(|_| {
1408+
match self.select_trait_candidate(trait_ref) {
1409+
Ok(Some(traits::VtableImpl(traits::VtableImplData {
1410+
nested,
1411+
..
1412+
}))) if !nested.is_empty() => {
1413+
for obligation in nested {
1414+
// Determine exactly which obligation wasn't met, so
1415+
// that we can give more context in the error.
1416+
if !self.predicate_may_hold(&obligation) {
1417+
result = ProbeResult::NoMatch;
1418+
if let Some(poly_trait_ref) =
1419+
obligation.predicate.to_opt_poly_trait_ref()
1420+
{
1421+
let trait_ref = poly_trait_ref.clone();
1422+
let trait_ref = trait_ref.skip_binder();
1423+
possibly_unsatisfied_predicates
1424+
.push(*trait_ref);
1425+
}
1426+
}
1427+
}
1428+
}
1429+
_ => {}
1430+
}
1431+
// Some nested subobligation of this predicate
1432+
// failed.
1433+
//
1434+
// FIXME: try to find the exact nested subobligation
1435+
// and point at it rather than reporting the entire
1436+
// trait-ref?
1437+
result = ProbeResult::NoMatch;
1438+
let trait_ref = self.resolve_vars_if_possible(&trait_ref);
1439+
possibly_unsatisfied_predicates.push(trait_ref);
1440+
});
14161441
}
14171442
}
14181443
vec![]

src/librustc_typeck/check/method/suggest.rs

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394394
tcx.sess.diagnostic().struct_dummy()
395395
};
396396

397+
// FIXME: Unify with unmet bound label.
397398
if let Some(def) = actual.ty_adt_def() {
398399
if let Some(full_sp) = tcx.hir().span_if_local(def.did) {
399400
let def_sp = tcx.sess.source_map().def_span(full_sp);
@@ -535,16 +536,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
535536
}
536537

537538
if !unsatisfied_predicates.is_empty() {
539+
let mut bound_spans = vec![];
538540
let mut bound_list = unsatisfied_predicates
539541
.iter()
540-
.map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path()))
542+
.map(|p| {
543+
let self_ty = p.self_ty();
544+
match &self_ty.kind {
545+
ty::Adt(def, _) => bound_spans.push((
546+
self.tcx.sess.source_map().def_span(self.tcx.def_span(def.did)),
547+
format!(
548+
"this type doesn't satisfy the bound `{}`",
549+
p.print_only_trait_path()
550+
),
551+
)),
552+
ty::Dynamic(preds, _) => {
553+
for pred in *preds.skip_binder() {
554+
match pred {
555+
ty::ExistentialPredicate::Trait(tr) => bound_spans
556+
.push((
557+
self.tcx
558+
.sess
559+
.source_map()
560+
.def_span(self.tcx.def_span(tr.def_id)),
561+
format!(
562+
"this trait doesn't satisfy the bound `{}`",
563+
p.print_only_trait_path()
564+
),
565+
)),
566+
ty::ExistentialPredicate::Projection(_)
567+
| ty::ExistentialPredicate::AutoTrait(_) => {}
568+
}
569+
}
570+
}
571+
_ => {}
572+
};
573+
format!("`{}: {}`", p.self_ty(), p.print_only_trait_path())
574+
})
541575
.collect::<Vec<_>>();
542576
bound_list.sort();
543577
bound_list.dedup(); // #35677
578+
bound_spans.sort();
579+
bound_spans.dedup(); // #35677
580+
for (span, msg) in bound_spans.into_iter() {
581+
err.span_label(span, &msg);
582+
}
544583
let bound_list = bound_list.join("\n");
545584
err.note(&format!(
546-
"the method `{}` exists but the following trait bounds \
547-
were not satisfied:\n{}",
585+
"the method `{}` exists but the following trait bounds were not \
586+
satisfied:\n{}",
548587
item_name, bound_list
549588
));
550589
}

src/test/ui/consts/too_generic_eval_ice.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ LL | [5; Self::HOST_SIZE] == [6; 0]
88
| ^^^^^^^^^ associated item not found in `Foo<A, B>`
99
|
1010
= note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied:
11-
`A : std::marker::Sized`
12-
`B : std::marker::Sized`
11+
`A: std::marker::Sized`
12+
`B: std::marker::Sized`
1313

1414
error[E0277]: the size for values of type `A` cannot be known at compilation time
1515
--> $DIR/too_generic_eval_ice.rs:7:13

src/test/ui/derives/derive-assoc-type-not-impl.stderr

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,20 @@ error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the cu
22
--> $DIR/derive-assoc-type-not-impl.rs:18:30
33
|
44
LL | struct Bar<T: Foo> {
5-
| ------------------ method `clone` not found for this
5+
| ------------------
6+
| |
7+
| method `clone` not found for this
8+
| this type doesn't satisfy the bound `std::clone::Clone`
9+
...
10+
LL | struct NotClone;
11+
| ---------------- this type doesn't satisfy the bound `std::clone::Clone`
612
...
713
LL | Bar::<NotClone> { x: 1 }.clone();
814
| ^^^^^ method not found in `Bar<NotClone>`
915
|
1016
= note: the method `clone` exists but the following trait bounds were not satisfied:
11-
`Bar<NotClone> : std::clone::Clone`
17+
`Bar<NotClone>: std::clone::Clone`
18+
`NotClone: std::clone::Clone`
1219
= help: items from traits can only be used if the trait is implemented and in scope
1320
= note: the following trait defines an item `clone`, perhaps you need to implement it:
1421
candidate #1: `std::clone::Clone`

src/test/ui/issues/issue-21596.stderr

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ LL | println!("{}", z.to_string());
77
= note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref
88
= note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
99
= note: the method `to_string` exists but the following trait bounds were not satisfied:
10-
`*const u8 : std::string::ToString`
10+
`*const u8: std::fmt::Display`
11+
`*const u8: std::string::ToString`
1112

1213
error: aborting due to previous error
1314

src/test/ui/issues/issue-31173.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// FIXME: missing sysroot spans (#53081)
2+
// ignore-i586-unknown-linux-gnu
3+
// ignore-i586-unknown-linux-musl
4+
// ignore-i686-unknown-linux-musl
15
use std::vec::IntoIter;
26

37
pub fn get_tok(it: &mut IntoIter<u8>) {

src/test/ui/issues/issue-31173.stderr

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
1-
error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_`
2-
--> $DIR/issue-31173.rs:10:10
1+
error[E0271]: type mismatch resolving `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item == &_`
2+
--> $DIR/issue-31173.rs:14:10
33
|
44
LL | .cloned()
55
| ^^^^^^ expected `u8`, found reference
66
|
77
= note: expected type `u8`
88
found reference `&_`
99

10-
error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope
11-
--> $DIR/issue-31173.rs:14:10
10+
error[E0599]: no method named `collect` found for struct `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` in the current scope
11+
--> $DIR/issue-31173.rs:18:10
1212
|
1313
LL | .collect();
14-
| ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>`
14+
| ^^^^^^^ method not found in `std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>`
15+
|
16+
::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL
17+
|
18+
LL | pub struct Cloned<I> {
19+
| -------------------- this type doesn't satisfy the bound `std::iter::Iterator`
1520
|
1621
= note: the method `collect` exists but the following trait bounds were not satisfied:
17-
`&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
18-
`std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator`
22+
`&mut std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`
23+
`std::iter::Cloned<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator`
1924

2025
error: aborting due to 2 previous errors
2126

src/test/ui/issues/issue-35677.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ LL | this.is_subset(other)
55
| ^^^^^^^^^ method not found in `&std::collections::HashSet<T>`
66
|
77
= note: the method `is_subset` exists but the following trait bounds were not satisfied:
8-
`T : std::cmp::Eq`
9-
`T : std::hash::Hash`
8+
`T: std::cmp::Eq`
9+
`T: std::hash::Hash`
1010

1111
error: aborting due to previous error
1212

src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &Some(42).as_deref();
55
| ^^^^^^^^ help: there is a method with a similar name: `as_ref`
66
|
77
= note: the method `as_deref` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::Deref`
8+
`{integer}: std::ops::Deref`
99

1010
error: aborting due to previous error
1111

src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut();
55
| ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>`
66
|
77
= note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::DerefMut`
8+
`{integer}: std::ops::DerefMut`
99

1010
error: aborting due to previous error
1111

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &Ok(42).as_deref();
55
| ^^^^^^^^ help: there is a method with a similar name: `as_ref`
66
|
77
= note: the method `as_deref` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::Deref`
8+
`{integer}: std::ops::Deref`
99

1010
error: aborting due to previous error
1111

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &Err(41).as_deref_err();
55
| ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
66
|
77
= note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::Deref`
8+
`{integer}: std::ops::Deref`
99

1010
error: aborting due to previous error
1111

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut();
55
| ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err`
66
|
77
= note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::DerefMut`
8+
`{integer}: std::ops::DerefMut`
99

1010
error: aborting due to previous error
1111

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err();
55
| ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut`
66
|
77
= note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied:
8-
`{integer} : std::ops::DerefMut`
8+
`{integer}: std::ops::DerefMut`
99

1010
error: aborting due to previous error
1111

src/test/ui/methods/method-call-err-msg.stderr

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,17 @@ error[E0599]: no method named `take` found for struct `Foo` in the current scope
3535
--> $DIR/method-call-err-msg.rs:19:7
3636
|
3737
LL | pub struct Foo;
38-
| --------------- method `take` not found for this
38+
| ---------------
39+
| |
40+
| method `take` not found for this
41+
| this type doesn't satisfy the bound `std::iter::Iterator`
3942
...
4043
LL | .take()
4144
| ^^^^ method not found in `Foo`
4245
|
4346
= note: the method `take` exists but the following trait bounds were not satisfied:
44-
`&mut Foo : std::iter::Iterator`
47+
`&mut Foo: std::iter::Iterator`
48+
`Foo: std::iter::Iterator`
4549
= help: items from traits can only be used if the trait is implemented and in scope
4650
= note: the following traits define an item `take`, perhaps you need to implement one of them:
4751
candidate #1: `std::io::Read`

src/test/ui/mismatched_types/issue-36053-2.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// FIXME: missing sysroot spans (#53081)
2+
// ignore-i586-unknown-linux-gnu
3+
// ignore-i586-unknown-linux-musl
4+
// ignore-i686-unknown-linux-musl
15
// Regression test for #36053. ICE was caused due to obligations
26
// being added to a special, dedicated fulfillment cx during
37
// a probe.

src/test/ui/mismatched_types/issue-36053-2.stderr

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope
2-
--> $DIR/issue-36053-2.rs:7:55
1+
error[E0599]: no method named `count` found for struct `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` in the current scope
2+
--> $DIR/issue-36053-2.rs:11:55
33
|
44
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
5-
| ^^^^^ method not found in `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>`
5+
| ^^^^^ method not found in `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>`
6+
|
7+
::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL
8+
|
9+
LL | pub struct Filter<I, P> {
10+
| ----------------------- this type doesn't satisfy the bound `std::iter::Iterator`
611
|
712
= note: the method `count` exists but the following trait bounds were not satisfied:
8-
`&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
9-
`std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator`
13+
`&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
14+
`[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>`
15+
`std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
1016

1117
error[E0631]: type mismatch in closure arguments
12-
--> $DIR/issue-36053-2.rs:7:32
18+
--> $DIR/issue-36053-2.rs:11:32
1319
|
1420
LL | once::<&str>("str").fuse().filter(|a: &str| true).count();
1521
| ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _`

src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope
22
--> $DIR/method-help-unsatisfied-bound.rs:5:7
33
|
4+
LL | struct Foo;
5+
| ----------- this type doesn't satisfy the bound `std::fmt::Debug`
6+
...
47
LL | a.unwrap();
58
| ^^^^^^ method not found in `std::result::Result<(), Foo>`
69
|
710
= note: the method `unwrap` exists but the following trait bounds were not satisfied:
8-
`Foo : std::fmt::Debug`
11+
`Foo: std::fmt::Debug`
912

1013
error: aborting due to previous error
1114

src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,16 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre
22
--> $DIR/specialization-trait-not-implemented.rs:22:29
33
|
44
LL | struct MyStruct;
5-
| ---------------- method `foo_one` not found for this
5+
| ----------------
6+
| |
7+
| method `foo_one` not found for this
8+
| this type doesn't satisfy the bound `Foo`
69
...
710
LL | println!("{}", MyStruct.foo_one());
811
| ^^^^^^^ method not found in `MyStruct`
912
|
1013
= note: the method `foo_one` exists but the following trait bounds were not satisfied:
11-
`MyStruct : Foo`
14+
`MyStruct: Foo`
1215
= help: items from traits can only be used if the trait is implemented and in scope
1316
= note: the following trait defines an item `foo_one`, perhaps you need to implement it:
1417
candidate #1: `Foo`

src/test/ui/suggestions/mut-borrow-needed-by-trait.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// FIXME: missing sysroot spans (#53081)
2+
// ignore-i586-unknown-linux-gnu
3+
// ignore-i586-unknown-linux-musl
4+
// ignore-i686-unknown-linux-musl
15
use std::env::args;
26
use std::fs::File;
37
use std::io::{stdout, Write, BufWriter};

0 commit comments

Comments
 (0)