about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/check/method/mod.rs4
-rw-r--r--src/librustc_typeck/check/method/probe.rs31
-rw-r--r--src/librustc_typeck/check/method/suggest.rs82
-rw-r--r--src/test/ui/derives/derive-assoc-type-not-impl.stderr7
-rw-r--r--src/test/ui/issues/issue-21596.stderr2
-rw-r--r--src/test/ui/issues/issue-31173.stderr7
-rw-r--r--src/test/ui/methods/method-call-err-msg.stderr2
-rw-r--r--src/test/ui/mismatched_types/issue-36053-2.stderr6
-rw-r--r--src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr7
-rw-r--r--src/test/ui/union/union-derive-clone.stderr7
-rw-r--r--src/test/ui/unique-object-noncopyable.stderr9
-rw-r--r--src/test/ui/unique-pinned-nocopy.stderr7
12 files changed, 111 insertions, 60 deletions
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index fd85397760a..b09522bbd33 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -67,7 +67,7 @@ pub enum MethodError<'tcx> {
 // could lead to matches if satisfied, and a list of not-in-scope traits which may work.
 pub struct NoMatchData<'tcx> {
     pub static_candidates: Vec<CandidateSource>,
-    pub unsatisfied_predicates: Vec<ty::Predicate<'tcx>>,
+    pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
     pub out_of_scope_traits: Vec<DefId>,
     pub lev_candidate: Option<ty::AssocItem>,
     pub mode: probe::Mode,
@@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> {
 impl<'tcx> NoMatchData<'tcx> {
     pub fn new(
         static_candidates: Vec<CandidateSource>,
-        unsatisfied_predicates: Vec<ty::Predicate<'tcx>>,
+        unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
         out_of_scope_traits: Vec<DefId>,
         lev_candidate: Option<ty::AssocItem>,
         mode: probe::Mode,
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 4f729c593cb..3e2826907b8 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -77,7 +77,7 @@ struct ProbeContext<'a, 'tcx> {
 
     /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used
     /// for error reporting
-    unsatisfied_predicates: Vec<ty::Predicate<'tcx>>,
+    unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option<ty::Predicate<'tcx>>)>,
 
     is_suggestion: IsSuggestion,
 }
@@ -1223,7 +1223,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         self_ty: Ty<'tcx>,
         probes: ProbesIter,
-        possibly_unsatisfied_predicates: &mut Vec<ty::Predicate<'tcx>>,
+        possibly_unsatisfied_predicates: &mut Vec<(
+            ty::Predicate<'tcx>,
+            Option<ty::Predicate<'tcx>>,
+        )>,
         unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>,
     ) -> Option<PickResult<'tcx>>
     where
@@ -1342,7 +1345,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         &self,
         self_ty: Ty<'tcx>,
         probe: &Candidate<'tcx>,
-        possibly_unsatisfied_predicates: &mut Vec<ty::Predicate<'tcx>>,
+        possibly_unsatisfied_predicates: &mut Vec<(
+            ty::Predicate<'tcx>,
+            Option<ty::Predicate<'tcx>>,
+        )>,
     ) -> ProbeResult {
         debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe);
 
@@ -1409,20 +1415,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                                         if !self.predicate_may_hold(&obligation) {
                                             result = ProbeResult::NoMatch;
                                             let o = self.resolve_vars_if_possible(obligation);
-                                            possibly_unsatisfied_predicates.push(o.predicate);
+                                            let predicate =
+                                                self.resolve_vars_if_possible(&predicate);
+                                            let p = if predicate == o.predicate {
+                                                // Avoid "`MyStruct: Foo` which is required by
+                                                // `MyStruct: Foo`" in E0599.
+                                                None
+                                            } else {
+                                                Some(predicate)
+                                            };
+                                            possibly_unsatisfied_predicates.push((o.predicate, p));
                                         }
                                     }
                                 }
                                 _ => {
                                     // Some nested subobligation of this predicate
                                     // failed.
-                                    //
-                                    // FIXME: try to find the exact nested subobligation
-                                    // and point at it rather than reporting the entire
-                                    // trait-ref?
                                     result = ProbeResult::NoMatch;
                                     let predicate = self.resolve_vars_if_possible(&predicate);
-                                    possibly_unsatisfied_predicates.push(predicate);
+                                    possibly_unsatisfied_predicates.push((predicate, None));
                                 }
                             }
                             false
@@ -1447,7 +1458,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                 let o = self.resolve_vars_if_possible(&o);
                 if !self.predicate_may_hold(&o) {
                     result = ProbeResult::NoMatch;
-                    possibly_unsatisfied_predicates.push(o.predicate);
+                    possibly_unsatisfied_predicates.push((o.predicate, None));
                 }
             }
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 6edceeb15b3..973f8208f16 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -538,9 +538,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let def_span =
                         |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id));
                     let mut bound_spans = vec![];
-                    let mut bound_list = unsatisfied_predicates
-                        .iter()
-                        .filter_map(|pred| match pred {
+                    let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str| {
+                        match &self_ty.kind {
+                            ty::Adt(def, _) => {
+                                // Point at the type that couldn't satisfy the bound.
+                                bound_spans.push((
+                                    def_span(def.did),
+                                    format!("doesn't satisfy {}", obligation),
+                                ));
+                            }
+                            ty::Dynamic(preds, _) => {
+                                // Point at the trait object that couldn't satisfy the bound.
+                                for pred in *preds.skip_binder() {
+                                    match pred {
+                                        ty::ExistentialPredicate::Trait(tr) => bound_spans.push((
+                                            def_span(tr.def_id),
+                                            format!("doesn't satisfy {}", obligation),
+                                        )),
+                                        ty::ExistentialPredicate::Projection(_)
+                                        | ty::ExistentialPredicate::AutoTrait(_) => {}
+                                    }
+                                }
+                            }
+                            _ => {}
+                        }
+                    };
+                    let mut format_pred = |pred| {
+                        match pred {
                             ty::Predicate::Projection(pred) => {
                                 // `<Foo as Iterator>::Item = String`.
                                 let trait_ref =
@@ -549,44 +573,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                     .tcx
                                     .associated_item(pred.skip_binder().projection_ty.item_def_id);
                                 let ty = pred.skip_binder().ty;
-                                Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty))
+                                let obligation =
+                                    format!("`{}::{} = {}`", trait_ref, assoc.ident, ty);
+                                bound_span_label(trait_ref.self_ty(), &obligation);
+                                Some(obligation)
                             }
                             ty::Predicate::Trait(poly_trait_ref, _) => {
                                 let p = poly_trait_ref.skip_binder().trait_ref;
                                 let self_ty = p.self_ty();
                                 let path = p.print_only_trait_path();
-                                match &self_ty.kind {
-                                    ty::Adt(def, _) => {
-                                        // Point at the type that couldn't satisfy the bound.
-                                        bound_spans.push((
-                                            def_span(def.did),
-                                            format!("doesn't satisfy `{}: {}`", self_ty, path),
-                                        ));
-                                    }
-                                    ty::Dynamic(preds, _) => {
-                                        // Point at the trait object that couldn't satisfy the bound.
-                                        for pred in *preds.skip_binder() {
-                                            match pred {
-                                                ty::ExistentialPredicate::Trait(tr) => bound_spans
-                                                    .push((
-                                                        def_span(tr.def_id),
-                                                        format!(
-                                                            "doesn't satisfy `{}: {}`",
-                                                            self_ty, path
-                                                        ),
-                                                    )),
-                                                ty::ExistentialPredicate::Projection(_)
-                                                | ty::ExistentialPredicate::AutoTrait(_) => {}
-                                            }
-                                        }
-                                    }
-                                    _ => {}
-                                }
-                                Some(format!("`{}: {}`", self_ty, path))
+                                let obligation = format!("`{}: {}`", self_ty, path);
+                                bound_span_label(self_ty, &obligation);
+                                Some(obligation)
                             }
                             _ => None,
+                        }
+                    };
+                    let mut bound_list = unsatisfied_predicates
+                        .iter()
+                        .filter_map(|(pred, parent_pred)| {
+                            format_pred(*pred).map(|pred| match parent_pred {
+                                None => pred,
+                                Some(parent_pred) => match format_pred(*parent_pred) {
+                                    None => pred,
+                                    Some(parent_pred) => {
+                                        format!("{} which is required by {}", pred, parent_pred)
+                                    }
+                                },
+                            })
                         })
-                        .collect::<Vec<_>>();
+                        .collect::<Vec<String>>();
                     bound_list.sort();
                     bound_list.dedup(); // #35677
                     bound_spans.sort();
diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
index 3ed726dea35..e837c7721af 100644
--- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr
@@ -2,7 +2,10 @@ error[E0599]: no method named `clone` found for struct `Bar<NotClone>` in the cu
   --> $DIR/derive-assoc-type-not-impl.rs:18:30
    |
 LL | struct Bar<T: Foo> {
-   | ------------------ method `clone` not found for this
+   | ------------------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `Bar<NotClone>: std::clone::Clone`
 ...
 LL | struct NotClone;
    | ---------------- doesn't satisfy `NotClone: std::clone::Clone`
@@ -11,7 +14,7 @@ LL |     Bar::<NotClone> { x: 1 }.clone();
    |                              ^^^^^ method not found in `Bar<NotClone>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
-           `NotClone: std::clone::Clone`
+           `NotClone: std::clone::Clone` which is required by `Bar<NotClone>: std::clone::Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `std::clone::Clone`
diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr
index 10b634b4603..bbd16618049 100644
--- a/src/test/ui/issues/issue-21596.stderr
+++ b/src/test/ui/issues/issue-21596.stderr
@@ -7,7 +7,7 @@ LL |     println!("{}", z.to_string());
    = 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
    = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior
    = note: the method `to_string` exists but the following trait bounds were not satisfied:
-           `*const u8: std::fmt::Display`
+           `*const u8: std::fmt::Display` which is required by `*const u8: std::string::ToString`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index d5e3cf48f38..9100f2c3a93 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -17,10 +17,13 @@ LL |         .collect();
    |
 LL | pub struct Cloned<I> {
    | -------------------- doesn't satisfy `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`
+...
+LL | pub struct TakeWhile<I, P> {
+   | -------------------------- doesn't satisfy `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_`
    |
    = note: the method `collect` exists but the following trait bounds were not satisfied:
-           `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_`
-           `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`
+           `<std::iter::TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `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`
+           `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` which is required by `&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`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr
index b0d747d201d..b4e54ab7783 100644
--- a/src/test/ui/methods/method-call-err-msg.stderr
+++ b/src/test/ui/methods/method-call-err-msg.stderr
@@ -44,7 +44,7 @@ LL |      .take()
    |       ^^^^ method not found in `Foo`
    |
    = note: the method `take` exists but the following trait bounds were not satisfied:
-           `Foo: std::iter::Iterator`
+           `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following traits define an item `take`, perhaps you need to implement one of them:
            candidate #1: `std::io::Read`
diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr
index 5f3353c89cc..5899dfffa41 100644
--- a/src/test/ui/mismatched_types/issue-36053-2.stderr
+++ b/src/test/ui/mismatched_types/issue-36053-2.stderr
@@ -10,9 +10,9 @@ LL | pub struct Filter<I, P> {
    | ----------------------- doesn't satisfy `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
    |
    = note: the method `count` exists but the following trait bounds were not satisfied:
-           `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool`
-           `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>`
-           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
+           `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
+           `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` which is required by `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
+           `std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` which is required by `&mut std::iter::Filter<std::iter::Fuse<std::iter::Once<&str>>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator`
 
 error[E0631]: type mismatch in closure arguments
   --> $DIR/issue-36053-2.rs:11:32
diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
index 3a9fddc474a..5d297728eca 100644
--- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
+++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr
@@ -30,9 +30,14 @@ error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&
    |
 LL |     writeln!(fp, "hello world").unwrap();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>`
+   | 
+  ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL
+   |
+LL | pub struct BufWriter<W: Write> {
+   | ------------------------------ doesn't satisfy `std::io::BufWriter<&dyn std::io::Write>: std::io::Write`
    |
    = note: the method `write_fmt` exists but the following trait bounds were not satisfied:
-           `&dyn std::io::Write: std::io::Write`
+           `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write`
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 4 previous errors
diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr
index 2051ea33391..456e1cd83ef 100644
--- a/src/test/ui/union/union-derive-clone.stderr
+++ b/src/test/ui/union/union-derive-clone.stderr
@@ -11,7 +11,10 @@ error[E0599]: no method named `clone` found for union `U5<CloneNoCopy>` in the c
   --> $DIR/union-derive-clone.rs:37:15
    |
 LL | union U5<T> {
-   | ----------- method `clone` not found for this
+   | -----------
+   | |
+   | method `clone` not found for this
+   | doesn't satisfy `U5<CloneNoCopy>: std::clone::Clone`
 ...
 LL | struct CloneNoCopy;
    | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy`
@@ -20,7 +23,7 @@ LL |     let w = u.clone();
    |               ^^^^^ method not found in `U5<CloneNoCopy>`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
-           `CloneNoCopy: std::marker::Copy`
+           `CloneNoCopy: std::marker::Copy` which is required by `U5<CloneNoCopy>: std::clone::Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `std::clone::Clone`
diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr
index f230d0d14d2..c3be38e1cf1 100644
--- a/src/test/ui/unique-object-noncopyable.stderr
+++ b/src/test/ui/unique-object-noncopyable.stderr
@@ -9,10 +9,15 @@ LL | trait Foo {
 ...
 LL |     let _z = y.clone();
    |                ^^^^^ method not found in `std::boxed::Box<dyn Foo>`
+   | 
+  ::: $SRC_DIR/liballoc/boxed.rs:LL:COL
+   |
+LL | pub struct Box<T: ?Sized>(Unique<T>);
+   | ------------------------------------- doesn't satisfy `std::boxed::Box<dyn Foo>: std::clone::Clone`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
-           `dyn Foo: std::clone::Clone`
-           `dyn Foo: std::marker::Sized`
+           `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box<dyn Foo>: std::clone::Clone`
+           `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box<dyn Foo>: std::clone::Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `std::clone::Clone`
diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr
index 12d719a1027..fb2f4c01b63 100644
--- a/src/test/ui/unique-pinned-nocopy.stderr
+++ b/src/test/ui/unique-pinned-nocopy.stderr
@@ -6,9 +6,14 @@ LL | struct R {
 ...
 LL |     let _j = i.clone();
    |                ^^^^^ method not found in `std::boxed::Box<R>`
+   | 
+  ::: $SRC_DIR/liballoc/boxed.rs:LL:COL
+   |
+LL | pub struct Box<T: ?Sized>(Unique<T>);
+   | ------------------------------------- doesn't satisfy `std::boxed::Box<R>: std::clone::Clone`
    |
    = note: the method `clone` exists but the following trait bounds were not satisfied:
-           `R: std::clone::Clone`
+           `R: std::clone::Clone` which is required by `std::boxed::Box<R>: std::clone::Clone`
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `clone`, perhaps you need to implement it:
            candidate #1: `std::clone::Clone`